monaco-editor
Version:
A browser based code editor
864 lines (863 loc) • 40.7 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import * as nls from '../../../nls.js';
import { RunOnceScheduler } from '../../../base/common/async.js';
import { KeyChord } from '../../../base/common/keyCodes.js';
import { Disposable, dispose } from '../../../base/common/lifecycle.js';
import { EditorAction, registerEditorAction, registerEditorContribution } from '../../browser/editorExtensions.js';
import { CursorMoveCommands } from '../../common/controller/cursorMoveCommands.js';
import { Range } from '../../common/core/range.js';
import { Selection } from '../../common/core/selection.js';
import { EditorContextKeys } from '../../common/editorContextKeys.js';
import { OverviewRulerLane } from '../../common/model.js';
import { ModelDecorationOptions } from '../../common/model/textModel.js';
import { DocumentHighlightProviderRegistry } from '../../common/modes.js';
import { CommonFindController } from '../find/findController.js';
import { MenuId } from '../../../platform/actions/common/actions.js';
import { overviewRulerSelectionHighlightForeground } from '../../../platform/theme/common/colorRegistry.js';
import { themeColorFromId } from '../../../platform/theme/common/themeService.js';
var InsertCursorAbove = /** @class */ (function (_super) {
__extends(InsertCursorAbove, _super);
function InsertCursorAbove() {
return _super.call(this, {
id: 'editor.action.insertCursorAbove',
label: nls.localize('mutlicursor.insertAbove', "Add Cursor Above"),
alias: 'Add Cursor Above',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 2048 /* CtrlCmd */ | 512 /* Alt */ | 16 /* UpArrow */,
linux: {
primary: 1024 /* Shift */ | 512 /* Alt */ | 16 /* UpArrow */,
secondary: [2048 /* CtrlCmd */ | 1024 /* Shift */ | 16 /* UpArrow */]
},
weight: 100 /* EditorContrib */
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miInsertCursorAbove', comment: ['&& denotes a mnemonic'] }, "&&Add Cursor Above"),
order: 2
}
}) || this;
}
InsertCursorAbove.prototype.run = function (accessor, editor, args) {
var useLogicalLine = (args && args.logicalLine === true);
var cursors = editor._getCursors();
var context = cursors.context;
if (context.config.readOnly) {
return;
}
context.model.pushStackElement();
cursors.setStates(args.source, 3 /* Explicit */, CursorMoveCommands.addCursorUp(context, cursors.getAll(), useLogicalLine));
cursors.reveal(true, 1 /* TopMost */, 0 /* Smooth */);
};
return InsertCursorAbove;
}(EditorAction));
export { InsertCursorAbove };
var InsertCursorBelow = /** @class */ (function (_super) {
__extends(InsertCursorBelow, _super);
function InsertCursorBelow() {
return _super.call(this, {
id: 'editor.action.insertCursorBelow',
label: nls.localize('mutlicursor.insertBelow', "Add Cursor Below"),
alias: 'Add Cursor Below',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 2048 /* CtrlCmd */ | 512 /* Alt */ | 18 /* DownArrow */,
linux: {
primary: 1024 /* Shift */ | 512 /* Alt */ | 18 /* DownArrow */,
secondary: [2048 /* CtrlCmd */ | 1024 /* Shift */ | 18 /* DownArrow */]
},
weight: 100 /* EditorContrib */
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miInsertCursorBelow', comment: ['&& denotes a mnemonic'] }, "A&&dd Cursor Below"),
order: 3
}
}) || this;
}
InsertCursorBelow.prototype.run = function (accessor, editor, args) {
var useLogicalLine = (args && args.logicalLine === true);
var cursors = editor._getCursors();
var context = cursors.context;
if (context.config.readOnly) {
return;
}
context.model.pushStackElement();
cursors.setStates(args.source, 3 /* Explicit */, CursorMoveCommands.addCursorDown(context, cursors.getAll(), useLogicalLine));
cursors.reveal(true, 2 /* BottomMost */, 0 /* Smooth */);
};
return InsertCursorBelow;
}(EditorAction));
export { InsertCursorBelow };
var InsertCursorAtEndOfEachLineSelected = /** @class */ (function (_super) {
__extends(InsertCursorAtEndOfEachLineSelected, _super);
function InsertCursorAtEndOfEachLineSelected() {
return _super.call(this, {
id: 'editor.action.insertCursorAtEndOfEachLineSelected',
label: nls.localize('mutlicursor.insertAtEndOfEachLineSelected', "Add Cursors to Line Ends"),
alias: 'Add Cursors to Line Ends',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 1024 /* Shift */ | 512 /* Alt */ | 39 /* KEY_I */,
weight: 100 /* EditorContrib */
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miInsertCursorAtEndOfEachLineSelected', comment: ['&& denotes a mnemonic'] }, "Add C&&ursors to Line Ends"),
order: 4
}
}) || this;
}
InsertCursorAtEndOfEachLineSelected.prototype.getCursorsForSelection = function (selection, model, result) {
if (selection.isEmpty()) {
return;
}
for (var i = selection.startLineNumber; i < selection.endLineNumber; i++) {
var currentLineMaxColumn = model.getLineMaxColumn(i);
result.push(new Selection(i, currentLineMaxColumn, i, currentLineMaxColumn));
}
if (selection.endColumn > 1) {
result.push(new Selection(selection.endLineNumber, selection.endColumn, selection.endLineNumber, selection.endColumn));
}
};
InsertCursorAtEndOfEachLineSelected.prototype.run = function (accessor, editor) {
var _this = this;
var model = editor.getModel();
var selections = editor.getSelections();
var newSelections = [];
selections.forEach(function (sel) { return _this.getCursorsForSelection(sel, model, newSelections); });
if (newSelections.length > 0) {
editor.setSelections(newSelections);
}
};
return InsertCursorAtEndOfEachLineSelected;
}(EditorAction));
var MultiCursorSessionResult = /** @class */ (function () {
function MultiCursorSessionResult(selections, revealRange, revealScrollType) {
this.selections = selections;
this.revealRange = revealRange;
this.revealScrollType = revealScrollType;
}
return MultiCursorSessionResult;
}());
export { MultiCursorSessionResult };
var MultiCursorSession = /** @class */ (function () {
function MultiCursorSession(_editor, findController, isDisconnectedFromFindController, searchText, wholeWord, matchCase, currentMatch) {
this._editor = _editor;
this.findController = findController;
this.isDisconnectedFromFindController = isDisconnectedFromFindController;
this.searchText = searchText;
this.wholeWord = wholeWord;
this.matchCase = matchCase;
this.currentMatch = currentMatch;
}
MultiCursorSession.create = function (editor, findController) {
var findState = findController.getState();
// Find widget owns entirely what we search for if:
// - focus is not in the editor (i.e. it is in the find widget)
// - and the search widget is visible
// - and the search string is non-empty
if (!editor.hasTextFocus() && findState.isRevealed && findState.searchString.length > 0) {
// Find widget owns what is searched for
return new MultiCursorSession(editor, findController, false, findState.searchString, findState.wholeWord, findState.matchCase, null);
}
// Otherwise, the selection gives the search text, and the find widget gives the search settings
// The exception is the find state disassociation case: when beginning with a single, collapsed selection
var isDisconnectedFromFindController = false;
var wholeWord;
var matchCase;
var selections = editor.getSelections();
if (selections.length === 1 && selections[0].isEmpty()) {
isDisconnectedFromFindController = true;
wholeWord = true;
matchCase = true;
}
else {
wholeWord = findState.wholeWord;
matchCase = findState.matchCase;
}
// Selection owns what is searched for
var s = editor.getSelection();
var searchText;
var currentMatch = null;
if (s.isEmpty()) {
// selection is empty => expand to current word
var word = editor.getModel().getWordAtPosition(s.getStartPosition());
if (!word) {
return null;
}
searchText = word.word;
currentMatch = new Selection(s.startLineNumber, word.startColumn, s.startLineNumber, word.endColumn);
}
else {
searchText = editor.getModel().getValueInRange(s).replace(/\r\n/g, '\n');
}
return new MultiCursorSession(editor, findController, isDisconnectedFromFindController, searchText, wholeWord, matchCase, currentMatch);
};
MultiCursorSession.prototype.addSelectionToNextFindMatch = function () {
var nextMatch = this._getNextMatch();
if (!nextMatch) {
return null;
}
var allSelections = this._editor.getSelections();
return new MultiCursorSessionResult(allSelections.concat(nextMatch), nextMatch, 0 /* Smooth */);
};
MultiCursorSession.prototype.moveSelectionToNextFindMatch = function () {
var nextMatch = this._getNextMatch();
if (!nextMatch) {
return null;
}
var allSelections = this._editor.getSelections();
return new MultiCursorSessionResult(allSelections.slice(0, allSelections.length - 1).concat(nextMatch), nextMatch, 0 /* Smooth */);
};
MultiCursorSession.prototype._getNextMatch = function () {
if (this.currentMatch) {
var result = this.currentMatch;
this.currentMatch = null;
return result;
}
this.findController.highlightFindOptions();
var allSelections = this._editor.getSelections();
var lastAddedSelection = allSelections[allSelections.length - 1];
var nextMatch = this._editor.getModel().findNextMatch(this.searchText, lastAddedSelection.getEndPosition(), false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false);
if (!nextMatch) {
return null;
}
return new Selection(nextMatch.range.startLineNumber, nextMatch.range.startColumn, nextMatch.range.endLineNumber, nextMatch.range.endColumn);
};
MultiCursorSession.prototype.addSelectionToPreviousFindMatch = function () {
var previousMatch = this._getPreviousMatch();
if (!previousMatch) {
return null;
}
var allSelections = this._editor.getSelections();
return new MultiCursorSessionResult(allSelections.concat(previousMatch), previousMatch, 0 /* Smooth */);
};
MultiCursorSession.prototype.moveSelectionToPreviousFindMatch = function () {
var previousMatch = this._getPreviousMatch();
if (!previousMatch) {
return null;
}
var allSelections = this._editor.getSelections();
return new MultiCursorSessionResult(allSelections.slice(0, allSelections.length - 1).concat(previousMatch), previousMatch, 0 /* Smooth */);
};
MultiCursorSession.prototype._getPreviousMatch = function () {
if (this.currentMatch) {
var result = this.currentMatch;
this.currentMatch = null;
return result;
}
this.findController.highlightFindOptions();
var allSelections = this._editor.getSelections();
var lastAddedSelection = allSelections[allSelections.length - 1];
var previousMatch = this._editor.getModel().findPreviousMatch(this.searchText, lastAddedSelection.getStartPosition(), false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false);
if (!previousMatch) {
return null;
}
return new Selection(previousMatch.range.startLineNumber, previousMatch.range.startColumn, previousMatch.range.endLineNumber, previousMatch.range.endColumn);
};
MultiCursorSession.prototype.selectAll = function () {
this.findController.highlightFindOptions();
return this._editor.getModel().findMatches(this.searchText, true, false, this.matchCase, this.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, 1073741824 /* MAX_SAFE_SMALL_INTEGER */);
};
return MultiCursorSession;
}());
export { MultiCursorSession };
var MultiCursorSelectionController = /** @class */ (function (_super) {
__extends(MultiCursorSelectionController, _super);
function MultiCursorSelectionController(editor) {
var _this = _super.call(this) || this;
_this._editor = editor;
_this._ignoreSelectionChange = false;
_this._session = null;
_this._sessionDispose = [];
return _this;
}
MultiCursorSelectionController.get = function (editor) {
return editor.getContribution(MultiCursorSelectionController.ID);
};
MultiCursorSelectionController.prototype.dispose = function () {
this._endSession();
_super.prototype.dispose.call(this);
};
MultiCursorSelectionController.prototype.getId = function () {
return MultiCursorSelectionController.ID;
};
MultiCursorSelectionController.prototype._beginSessionIfNeeded = function (findController) {
var _this = this;
if (!this._session) {
// Create a new session
var session = MultiCursorSession.create(this._editor, findController);
if (!session) {
return;
}
this._session = session;
var newState = { searchString: this._session.searchText };
if (this._session.isDisconnectedFromFindController) {
newState.wholeWordOverride = 1 /* True */;
newState.matchCaseOverride = 1 /* True */;
newState.isRegexOverride = 2 /* False */;
}
findController.getState().change(newState, false);
this._sessionDispose = [
this._editor.onDidChangeCursorSelection(function (e) {
if (_this._ignoreSelectionChange) {
return;
}
_this._endSession();
}),
this._editor.onDidBlurEditorText(function () {
_this._endSession();
}),
findController.getState().onFindReplaceStateChange(function (e) {
if (e.matchCase || e.wholeWord) {
_this._endSession();
}
})
];
}
};
MultiCursorSelectionController.prototype._endSession = function () {
this._sessionDispose = dispose(this._sessionDispose);
if (this._session && this._session.isDisconnectedFromFindController) {
var newState = {
wholeWordOverride: 0 /* NotSet */,
matchCaseOverride: 0 /* NotSet */,
isRegexOverride: 0 /* NotSet */,
};
this._session.findController.getState().change(newState, false);
}
this._session = null;
};
MultiCursorSelectionController.prototype._setSelections = function (selections) {
this._ignoreSelectionChange = true;
this._editor.setSelections(selections);
this._ignoreSelectionChange = false;
};
MultiCursorSelectionController.prototype._expandEmptyToWord = function (model, selection) {
if (!selection.isEmpty()) {
return selection;
}
var word = model.getWordAtPosition(selection.getStartPosition());
if (!word) {
return selection;
}
return new Selection(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn);
};
MultiCursorSelectionController.prototype._applySessionResult = function (result) {
if (!result) {
return;
}
this._setSelections(result.selections);
if (result.revealRange) {
this._editor.revealRangeInCenterIfOutsideViewport(result.revealRange, result.revealScrollType);
}
};
MultiCursorSelectionController.prototype.getSession = function (findController) {
return this._session;
};
MultiCursorSelectionController.prototype.addSelectionToNextFindMatch = function (findController) {
if (!this._session) {
// If there are multiple cursors, handle the case where they do not all select the same text.
var allSelections = this._editor.getSelections();
if (allSelections.length > 1) {
var findState = findController.getState();
var matchCase = findState.matchCase;
var selectionsContainSameText = modelRangesContainSameText(this._editor.getModel(), allSelections, matchCase);
if (!selectionsContainSameText) {
var model = this._editor.getModel();
var resultingSelections = [];
for (var i = 0, len = allSelections.length; i < len; i++) {
resultingSelections[i] = this._expandEmptyToWord(model, allSelections[i]);
}
this._editor.setSelections(resultingSelections);
return;
}
}
}
this._beginSessionIfNeeded(findController);
if (this._session) {
this._applySessionResult(this._session.addSelectionToNextFindMatch());
}
};
MultiCursorSelectionController.prototype.addSelectionToPreviousFindMatch = function (findController) {
this._beginSessionIfNeeded(findController);
if (this._session) {
this._applySessionResult(this._session.addSelectionToPreviousFindMatch());
}
};
MultiCursorSelectionController.prototype.moveSelectionToNextFindMatch = function (findController) {
this._beginSessionIfNeeded(findController);
if (this._session) {
this._applySessionResult(this._session.moveSelectionToNextFindMatch());
}
};
MultiCursorSelectionController.prototype.moveSelectionToPreviousFindMatch = function (findController) {
this._beginSessionIfNeeded(findController);
if (this._session) {
this._applySessionResult(this._session.moveSelectionToPreviousFindMatch());
}
};
MultiCursorSelectionController.prototype.selectAll = function (findController) {
var matches = null;
var findState = findController.getState();
// Special case: find widget owns entirely what we search for if:
// - focus is not in the editor (i.e. it is in the find widget)
// - and the search widget is visible
// - and the search string is non-empty
// - and we're searching for a regex
if (findState.isRevealed && findState.searchString.length > 0 && findState.isRegex) {
matches = this._editor.getModel().findMatches(findState.searchString, true, findState.isRegex, findState.matchCase, findState.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false, 1073741824 /* MAX_SAFE_SMALL_INTEGER */);
}
else {
this._beginSessionIfNeeded(findController);
if (!this._session) {
return;
}
matches = this._session.selectAll();
}
if (matches.length > 0) {
var editorSelection = this._editor.getSelection();
// Have the primary cursor remain the one where the action was invoked
for (var i = 0, len = matches.length; i < len; i++) {
var match = matches[i];
var intersection = match.range.intersectRanges(editorSelection);
if (intersection) {
// bingo!
matches[i] = matches[0];
matches[0] = match;
break;
}
}
this._setSelections(matches.map(function (m) { return new Selection(m.range.startLineNumber, m.range.startColumn, m.range.endLineNumber, m.range.endColumn); }));
}
};
MultiCursorSelectionController.ID = 'editor.contrib.multiCursorController';
return MultiCursorSelectionController;
}(Disposable));
export { MultiCursorSelectionController };
var MultiCursorSelectionControllerAction = /** @class */ (function (_super) {
__extends(MultiCursorSelectionControllerAction, _super);
function MultiCursorSelectionControllerAction() {
return _super !== null && _super.apply(this, arguments) || this;
}
MultiCursorSelectionControllerAction.prototype.run = function (accessor, editor) {
var multiCursorController = MultiCursorSelectionController.get(editor);
if (!multiCursorController) {
return;
}
var findController = CommonFindController.get(editor);
if (!findController) {
return null;
}
this._run(multiCursorController, findController);
};
return MultiCursorSelectionControllerAction;
}(EditorAction));
export { MultiCursorSelectionControllerAction };
var AddSelectionToNextFindMatchAction = /** @class */ (function (_super) {
__extends(AddSelectionToNextFindMatchAction, _super);
function AddSelectionToNextFindMatchAction() {
return _super.call(this, {
id: 'editor.action.addSelectionToNextFindMatch',
label: nls.localize('addSelectionToNextFindMatch', "Add Selection To Next Find Match"),
alias: 'Add Selection To Next Find Match',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: 2048 /* CtrlCmd */ | 34 /* KEY_D */,
weight: 100 /* EditorContrib */
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miAddSelectionToNextFindMatch', comment: ['&& denotes a mnemonic'] }, "Add &&Next Occurrence"),
order: 5
}
}) || this;
}
AddSelectionToNextFindMatchAction.prototype._run = function (multiCursorController, findController) {
multiCursorController.addSelectionToNextFindMatch(findController);
};
return AddSelectionToNextFindMatchAction;
}(MultiCursorSelectionControllerAction));
export { AddSelectionToNextFindMatchAction };
var AddSelectionToPreviousFindMatchAction = /** @class */ (function (_super) {
__extends(AddSelectionToPreviousFindMatchAction, _super);
function AddSelectionToPreviousFindMatchAction() {
return _super.call(this, {
id: 'editor.action.addSelectionToPreviousFindMatch',
label: nls.localize('addSelectionToPreviousFindMatch', "Add Selection To Previous Find Match"),
alias: 'Add Selection To Previous Find Match',
precondition: null,
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miAddSelectionToPreviousFindMatch', comment: ['&& denotes a mnemonic'] }, "Add P&&revious Occurrence"),
order: 6
}
}) || this;
}
AddSelectionToPreviousFindMatchAction.prototype._run = function (multiCursorController, findController) {
multiCursorController.addSelectionToPreviousFindMatch(findController);
};
return AddSelectionToPreviousFindMatchAction;
}(MultiCursorSelectionControllerAction));
export { AddSelectionToPreviousFindMatchAction };
var MoveSelectionToNextFindMatchAction = /** @class */ (function (_super) {
__extends(MoveSelectionToNextFindMatchAction, _super);
function MoveSelectionToNextFindMatchAction() {
return _super.call(this, {
id: 'editor.action.moveSelectionToNextFindMatch',
label: nls.localize('moveSelectionToNextFindMatch', "Move Last Selection To Next Find Match"),
alias: 'Move Last Selection To Next Find Match',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KEY_K */, 2048 /* CtrlCmd */ | 34 /* KEY_D */),
weight: 100 /* EditorContrib */
}
}) || this;
}
MoveSelectionToNextFindMatchAction.prototype._run = function (multiCursorController, findController) {
multiCursorController.moveSelectionToNextFindMatch(findController);
};
return MoveSelectionToNextFindMatchAction;
}(MultiCursorSelectionControllerAction));
export { MoveSelectionToNextFindMatchAction };
var MoveSelectionToPreviousFindMatchAction = /** @class */ (function (_super) {
__extends(MoveSelectionToPreviousFindMatchAction, _super);
function MoveSelectionToPreviousFindMatchAction() {
return _super.call(this, {
id: 'editor.action.moveSelectionToPreviousFindMatch',
label: nls.localize('moveSelectionToPreviousFindMatch', "Move Last Selection To Previous Find Match"),
alias: 'Move Last Selection To Previous Find Match',
precondition: null
}) || this;
}
MoveSelectionToPreviousFindMatchAction.prototype._run = function (multiCursorController, findController) {
multiCursorController.moveSelectionToPreviousFindMatch(findController);
};
return MoveSelectionToPreviousFindMatchAction;
}(MultiCursorSelectionControllerAction));
export { MoveSelectionToPreviousFindMatchAction };
var SelectHighlightsAction = /** @class */ (function (_super) {
__extends(SelectHighlightsAction, _super);
function SelectHighlightsAction() {
return _super.call(this, {
id: 'editor.action.selectHighlights',
label: nls.localize('selectAllOccurrencesOfFindMatch', "Select All Occurrences of Find Match"),
alias: 'Select All Occurrences of Find Match',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: 2048 /* CtrlCmd */ | 1024 /* Shift */ | 42 /* KEY_L */,
weight: 100 /* EditorContrib */
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '3_multi',
title: nls.localize({ key: 'miSelectHighlights', comment: ['&& denotes a mnemonic'] }, "Select All &&Occurrences"),
order: 7
}
}) || this;
}
SelectHighlightsAction.prototype._run = function (multiCursorController, findController) {
multiCursorController.selectAll(findController);
};
return SelectHighlightsAction;
}(MultiCursorSelectionControllerAction));
export { SelectHighlightsAction };
var CompatChangeAll = /** @class */ (function (_super) {
__extends(CompatChangeAll, _super);
function CompatChangeAll() {
return _super.call(this, {
id: 'editor.action.changeAll',
label: nls.localize('changeAll.label', "Change All Occurrences"),
alias: 'Change All Occurrences',
precondition: EditorContextKeys.writable,
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 2048 /* CtrlCmd */ | 60 /* F2 */,
weight: 100 /* EditorContrib */
},
menuOpts: {
group: '1_modification',
order: 1.2
}
}) || this;
}
CompatChangeAll.prototype._run = function (multiCursorController, findController) {
multiCursorController.selectAll(findController);
};
return CompatChangeAll;
}(MultiCursorSelectionControllerAction));
export { CompatChangeAll };
var SelectionHighlighterState = /** @class */ (function () {
function SelectionHighlighterState(searchText, matchCase, wordSeparators) {
this.searchText = searchText;
this.matchCase = matchCase;
this.wordSeparators = wordSeparators;
}
/**
* Everything equals except for `lastWordUnderCursor`
*/
SelectionHighlighterState.softEquals = function (a, b) {
if (!a && !b) {
return true;
}
if (!a || !b) {
return false;
}
return (a.searchText === b.searchText
&& a.matchCase === b.matchCase
&& a.wordSeparators === b.wordSeparators);
};
return SelectionHighlighterState;
}());
var SelectionHighlighter = /** @class */ (function (_super) {
__extends(SelectionHighlighter, _super);
function SelectionHighlighter(editor) {
var _this = _super.call(this) || this;
_this.editor = editor;
_this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight;
_this.decorations = [];
_this.updateSoon = _this._register(new RunOnceScheduler(function () { return _this._update(); }, 300));
_this.state = null;
_this._register(editor.onDidChangeConfiguration(function (e) {
_this._isEnabled = editor.getConfiguration().contribInfo.selectionHighlight;
}));
_this._register(editor.onDidChangeCursorSelection(function (e) {
if (!_this._isEnabled) {
// Early exit if nothing needs to be done!
// Leave some form of early exit check here if you wish to continue being a cursor position change listener ;)
return;
}
if (e.selection.isEmpty()) {
if (e.reason === 3 /* Explicit */) {
if (_this.state) {
// no longer valid
_this._setState(null);
}
_this.updateSoon.schedule();
}
else {
_this._setState(null);
}
}
else {
_this._update();
}
}));
_this._register(editor.onDidChangeModel(function (e) {
_this._setState(null);
}));
_this._register(CommonFindController.get(editor).getState().onFindReplaceStateChange(function (e) {
_this._update();
}));
return _this;
}
SelectionHighlighter.prototype.getId = function () {
return SelectionHighlighter.ID;
};
SelectionHighlighter.prototype._update = function () {
this._setState(SelectionHighlighter._createState(this._isEnabled, this.editor));
};
SelectionHighlighter._createState = function (isEnabled, editor) {
if (!isEnabled) {
return null;
}
var model = editor.getModel();
if (!model) {
return null;
}
var s = editor.getSelection();
if (s.startLineNumber !== s.endLineNumber) {
// multiline forbidden for perf reasons
return null;
}
var multiCursorController = MultiCursorSelectionController.get(editor);
if (!multiCursorController) {
return null;
}
var findController = CommonFindController.get(editor);
if (!findController) {
return null;
}
var r = multiCursorController.getSession(findController);
if (!r) {
var allSelections = editor.getSelections();
if (allSelections.length > 1) {
var findState_1 = findController.getState();
var matchCase = findState_1.matchCase;
var selectionsContainSameText = modelRangesContainSameText(editor.getModel(), allSelections, matchCase);
if (!selectionsContainSameText) {
return null;
}
}
r = MultiCursorSession.create(editor, findController);
}
if (!r) {
return null;
}
if (r.currentMatch) {
// This is an empty selection
// Do not interfere with semantic word highlighting in the no selection case
return null;
}
if (/^[ \t]+$/.test(r.searchText)) {
// whitespace only selection
return null;
}
if (r.searchText.length > 200) {
// very long selection
return null;
}
// TODO: better handling of this case
var findState = findController.getState();
var caseSensitive = findState.matchCase;
// Return early if the find widget shows the exact same matches
if (findState.isRevealed) {
var findStateSearchString = findState.searchString;
if (!caseSensitive) {
findStateSearchString = findStateSearchString.toLowerCase();
}
var mySearchString = r.searchText;
if (!caseSensitive) {
mySearchString = mySearchString.toLowerCase();
}
if (findStateSearchString === mySearchString && r.matchCase === findState.matchCase && r.wholeWord === findState.wholeWord && !findState.isRegex) {
return null;
}
}
return new SelectionHighlighterState(r.searchText, r.matchCase, r.wholeWord ? editor.getConfiguration().wordSeparators : null);
};
SelectionHighlighter.prototype._setState = function (state) {
if (SelectionHighlighterState.softEquals(this.state, state)) {
this.state = state;
return;
}
this.state = state;
if (!this.state) {
this.decorations = this.editor.deltaDecorations(this.decorations, []);
return;
}
var model = this.editor.getModel();
if (model.isTooLargeForTokenization()) {
// the file is too large, so searching word under cursor in the whole document takes is blocking the UI.
return;
}
var hasFindOccurrences = DocumentHighlightProviderRegistry.has(model);
var allMatches = model.findMatches(this.state.searchText, true, false, this.state.matchCase, this.state.wordSeparators, false).map(function (m) { return m.range; });
allMatches.sort(Range.compareRangesUsingStarts);
var selections = this.editor.getSelections();
selections.sort(Range.compareRangesUsingStarts);
// do not overlap with selection (issue #64 and #512)
var matches = [];
for (var i = 0, j = 0, len = allMatches.length, lenJ = selections.length; i < len;) {
var match = allMatches[i];
if (j >= lenJ) {
// finished all editor selections
matches.push(match);
i++;
}
else {
var cmp = Range.compareRangesUsingStarts(match, selections[j]);
if (cmp < 0) {
// match is before sel
if (selections[j].isEmpty() || !Range.areIntersecting(match, selections[j])) {
matches.push(match);
}
i++;
}
else if (cmp > 0) {
// sel is before match
j++;
}
else {
// sel is equal to match
i++;
j++;
}
}
}
var decorations = matches.map(function (r) {
return {
range: r,
// Show in overviewRuler only if model has no semantic highlighting
options: (hasFindOccurrences ? SelectionHighlighter._SELECTION_HIGHLIGHT : SelectionHighlighter._SELECTION_HIGHLIGHT_OVERVIEW)
};
});
this.decorations = this.editor.deltaDecorations(this.decorations, decorations);
};
SelectionHighlighter.prototype.dispose = function () {
this._setState(null);
_super.prototype.dispose.call(this);
};
SelectionHighlighter.ID = 'editor.contrib.selectionHighlighter';
SelectionHighlighter._SELECTION_HIGHLIGHT_OVERVIEW = ModelDecorationOptions.register({
stickiness: 1 /* NeverGrowsWhenTypingAtEdges */,
className: 'selectionHighlight',
overviewRuler: {
color: themeColorFromId(overviewRulerSelectionHighlightForeground),
position: OverviewRulerLane.Center
}
});
SelectionHighlighter._SELECTION_HIGHLIGHT = ModelDecorationOptions.register({
stickiness: 1 /* NeverGrowsWhenTypingAtEdges */,
className: 'selectionHighlight',
});
return SelectionHighlighter;
}(Disposable));
export { SelectionHighlighter };
function modelRangesContainSameText(model, ranges, matchCase) {
var selectedText = getValueInRange(model, ranges[0], !matchCase);
for (var i = 1, len = ranges.length; i < len; i++) {
var range = ranges[i];
if (range.isEmpty()) {
return false;
}
var thisSelectedText = getValueInRange(model, range, !matchCase);
if (selectedText !== thisSelectedText) {
return false;
}
}
return true;
}
function getValueInRange(model, range, toLowerCase) {
var text = model.getValueInRange(range);
return (toLowerCase ? text.toLowerCase() : text);
}
registerEditorContribution(MultiCursorSelectionController);
registerEditorContribution(SelectionHighlighter);
registerEditorAction(InsertCursorAbove);
registerEditorAction(InsertCursorBelow);
registerEditorAction(InsertCursorAtEndOfEachLineSelected);
registerEditorAction(AddSelectionToNextFindMatchAction);
registerEditorAction(AddSelectionToPreviousFindMatchAction);
registerEditorAction(MoveSelectionToNextFindMatchAction);
registerEditorAction(MoveSelectionToPreviousFindMatchAction);
registerEditorAction(SelectHighlightsAction);
registerEditorAction(CompatChangeAll);