From 0b90eb2c25202d6379ec180d0d29514c2ee607ef Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 10 Dec 2015 17:20:22 +0100 Subject: [PATCH] Fixes #259: Add shortcuts & commands for find modifiers --- src/vs/base/browser/ui/findinput/findInput.ts | 21 +++- .../editor/common/editorCommonExtensions.ts | 21 ++-- src/vs/editor/contrib/find/browser/find.ts | 114 ++++++++++++++---- .../editor/contrib/find/browser/findWidget.ts | 46 ++++--- .../editor/contrib/find/common/findModel.ts | 13 +- 5 files changed, 154 insertions(+), 61 deletions(-) diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 180e23447a4..e05585ac8df 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -20,8 +20,17 @@ export interface IOptions { width?:number; validation?:InputBox.IInputValidator; label:string; + + appendCaseSensitiveLabel?: string; + appendWholeWordsLabel?: string; + appendRegexLabel?: string; } +const NLS_REGEX_CHECKBOX_LABEL = nls.localize('regexDescription', "Use Regular Expression"); +const NLS_WHOLE_WORD_CHECKBOX_LABEL = nls.localize('wordsDescription', "Match Whole Word"); +const NLS_CASE_SENSITIVE_CHECKBOX_LABEL = nls.localize('caseDescription', "Match Case"); +const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); + export class FindInput { static OPTION_CHANGE:string = 'optionChange'; @@ -48,7 +57,7 @@ export class FindInput { this.width = options.width || 100; this.placeholder = options.placeholder || ''; this.validation = options.validation; - this.label = options.label || nls.localize('defaultLabel', "input"); + this.label = options.label || NLS_DEFAULT_LABEL; this.listenersToRemove = []; this.regex = null; @@ -59,7 +68,7 @@ export class FindInput { this.inputBox = null; this.validationNode = null; - this.buildDomNode(); + this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || ''); if(Boolean(parent)) { parent.appendChild(this.domNode); @@ -172,7 +181,7 @@ export class FindInput { this.inputBox.width = w; } - private buildDomNode(): void { + private buildDomNode(appendCaseSensitiveLabel:string, appendWholeWordsLabel: string, appendRegexLabel: string): void { this.domNode = document.createElement('div'); this.domNode.style.width = this.width + 'px'; $(this.domNode).addClass('monaco-findInput'); @@ -186,19 +195,19 @@ export class FindInput { } }); - this.regex = new Checkbox.Checkbox('regex', nls.localize('regexDescription', "Use Regular Expression"), false, () => { + this.regex = new Checkbox.Checkbox('regex', NLS_REGEX_CHECKBOX_LABEL + appendRegexLabel, false, () => { this.onOptionChange(null); this.inputBox.focus(); this.setInputWidth(); this.validate(); }); - this.wholeWords = new Checkbox.Checkbox('whole-word', nls.localize('wordsDescription', "Match Whole Word"), false, () => { + this.wholeWords = new Checkbox.Checkbox('whole-word', NLS_WHOLE_WORD_CHECKBOX_LABEL + appendWholeWordsLabel, false, () => { this.onOptionChange(null); this.inputBox.focus(); this.setInputWidth(); this.validate(); }); - this.caseSensitive = new Checkbox.Checkbox('case-sensitive', nls.localize('caseDescription', "Match Case"), false, () => { + this.caseSensitive = new Checkbox.Checkbox('case-sensitive', NLS_CASE_SENSITIVE_CHECKBOX_LABEL + appendCaseSensitiveLabel, false, () => { this.onOptionChange(null); this.inputBox.focus(); this.setInputWidth(); diff --git a/src/vs/editor/common/editorCommonExtensions.ts b/src/vs/editor/common/editorCommonExtensions.ts index 4fce04b71b5..b349e297832 100644 --- a/src/vs/editor/common/editorCommonExtensions.ts +++ b/src/vs/editor/common/editorCommonExtensions.ts @@ -236,17 +236,20 @@ function triggerEditorActionGlobal(actionId: string, accessor: ServicesAccessor, var defaultEditorActionKeybindingOptions:IEditorActionKeybindingOptions = { primary: null, context: ContextKey.EditorTextFocus }; -function contextRule(needsTextFocus: boolean, needsKey: string): IKeybindingContextRule[]{ +function contextRule(needsTextFocus: boolean, needsKey: string): IKeybindingContextRule[] { + let result: IKeybindingContextRule[] = []; + if (needsTextFocus) { - return [ - { key: EditorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS }, - { key: needsKey } - ]; + result.push({ key: EditorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS }); + } else { + result.push({ key: EditorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS }); + } + + if (needsKey) { + result.push({ key: needsKey }); } - return [ - { key: EditorCommon.KEYBINDING_CONTEXT_EDITOR_FOCUS }, - { key: needsKey } - ]; + + return result; } function createCommandHandler(commandId: string, handler: IEditorCommandHandler): ICommandHandler { diff --git a/src/vs/editor/contrib/find/browser/find.ts b/src/vs/editor/contrib/find/browser/find.ts index f8aba53a001..b83395b7ee3 100644 --- a/src/vs/editor/contrib/find/browser/find.ts +++ b/src/vs/editor/contrib/find/browser/find.ts @@ -17,7 +17,7 @@ import Lifecycle = require('vs/base/common/lifecycle'); import config = require('vs/editor/common/config/config'); import EditorCommon = require('vs/editor/common/editorCommon'); import {Selection} from 'vs/editor/common/core/selection'; -import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService'; +import {IKeybindingService, IKeybindingContextKey, IKeybindings} from 'vs/platform/keybinding/common/keybindingService'; import {IContextViewService} from 'vs/platform/contextview/browser/contextView'; import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; @@ -29,16 +29,19 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid static ID = 'editor.contrib.findController'; + private static _STATE_CHANGED_EVENT = 'stateChanged'; + private editor:EditorBrowser.ICodeEditor; private _findWidgetVisible: IKeybindingContextKey; private model:FindModel.IFindModel; - private widget:FindWidget.IFindWidget; + private widget:FindWidget.FindWidget; private widgetIsVisible:boolean; private widgetListeners:Lifecycle.IDisposable[]; private editorListeners:EventEmitter.ListenerUnbind[]; private lastState:FindModel.IFindState; + private _eventEmitter: EventEmitter.EventEmitter; static getFindController(editor:EditorCommon.ICommonCodeEditor): FindController { return editor.getContribution(FindController.ID); @@ -71,6 +74,8 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid }); this.editorListeners = []; })); + + this._eventEmitter = new EventEmitter.EventEmitter([FindController._STATE_CHANGED_EVENT]); } public getId(): string { @@ -84,6 +89,11 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid this.widget = null; } this.disposeBindingAndModel(); + this._eventEmitter.dispose(); + } + + public onStateChanged(listener:()=>void): Lifecycle.IDisposable { + return this._eventEmitter.addListener2(FindController._STATE_CHANGED_EVENT, listener); } private disposeBindingAndModel(): void { @@ -103,6 +113,51 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid this.editor.focus(); } + private _ensureHasState(): void { + if (!this.lastState) { + this.lastState = { + isReplaceRevealed: false, + properties: { + isRegex: false, + matchCase: false, + wholeWord: false + }, + replaceString: '', + searchString: '' + }; + } + } + + public toggleCaseSensitive(): void { + if (this.widget) { + this.widget.toggleCaseSensitive(); + } else { + this._ensureHasState(); + this.lastState.properties.matchCase = !this.lastState.properties.matchCase; + this._eventEmitter.emit(FindController._STATE_CHANGED_EVENT); + } + } + + public toggleWholeWords(): void { + if (this.widget) { + this.widget.toggleWholeWords(); + } else { + this._ensureHasState(); + this.lastState.properties.wholeWord = !this.lastState.properties.wholeWord; + this._eventEmitter.emit(FindController._STATE_CHANGED_EVENT); + } + } + + public toggleRegex(): void { + if (this.widget) { + this.widget.toggleRegex(); + } else { + this._ensureHasState(); + this.lastState.properties.isRegex = !this.lastState.properties.isRegex; + this._eventEmitter.emit(FindController._STATE_CHANGED_EVENT); + } + } + private onWidgetClosed(): void { this.widgetIsVisible = false; this.disposeBindingAndModel(); @@ -114,10 +169,6 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid public setSearchString(searchString:string): void { this.widget.setSearchString(searchString); - this.lastState = this.widget.getState(); - if (this.model) { - this.model.recomputeMatches(this.lastState, false); - } } private onWidgetUserInput(e:FindWidget.IUserInputEvent): void { @@ -125,6 +176,7 @@ export class FindController implements EditorCommon.IEditorContribution, FindWid if (this.model) { this.model.recomputeMatches(this.lastState, e.jumpToNextMatch); } + this._eventEmitter.emit(FindController._STATE_CHANGED_EVENT); } private _start(forceRevealReplace:boolean, seedSearchStringFromSelection:boolean, seedSearchScopeFromSelection:boolean, shouldFocus:boolean): void { @@ -287,7 +339,7 @@ export class StartFindReplaceAction extends BaseStartFindAction { } public getId(): string { - return FindModel.START_FIND_REPLACE_ID; + return FindModel.START_FIND_REPLACE_ACTION_ID; } _startController(controller:FindController): void { @@ -463,19 +515,20 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution { private editor:EditorCommon.ICommonCodeEditor; private model:EditorCommon.IModel; private decorations:string[]; - private toUnhook:EventEmitter.ListenerUnbind[]; + private toDispose:Lifecycle.IDisposable[]; constructor(editor:EditorCommon.ICommonCodeEditor, @INullService ns) { this.editor = editor; this.model = this.editor.getModel(); this.decorations = []; - this.toUnhook = []; + this.toDispose = []; - this.toUnhook.push(editor.addListener(EditorCommon.EventType.CursorPositionChanged, e => this.onPositionChanged(e))); - this.toUnhook.push(editor.addListener(EditorCommon.EventType.ModelChanged, (e) => { + this.toDispose.push(editor.addListener2(EditorCommon.EventType.CursorPositionChanged, _ => this._update())); + this.toDispose.push(editor.addListener2(EditorCommon.EventType.ModelChanged, (e) => { this.removeDecorations(); this.model = this.editor.getModel(); })); + this.toDispose.push(FindController.getFindController(editor).onStateChanged(() => this._update())); } public getId(): string { @@ -488,7 +541,7 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution { } } - private onPositionChanged(e:EditorCommon.ICursorPositionChangedEvent): void { + private _update(): void { if (!this.editor.getConfiguration().selectionHighlight) { return; } @@ -541,9 +594,7 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution { public dispose(): void { this.removeDecorations(); - while(this.toUnhook.length > 0) { - this.toUnhook.pop()(); - } + this.toDispose = Lifecycle.disposeAll(this.toDispose); } } @@ -556,22 +607,22 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(SelectHighl var CONTEXT_FIND_WIDGET_VISIBLE = 'findWidgetVisible'; // register actions -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(StartFindAction, FindModel.START_FIND_ID, nls.localize('startFindAction',"Find"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(StartFindAction, FindModel.START_FIND_ACTION_ID, nls.localize('startFindAction',"Find"), { context: ContextKey.None, primary: KeyMod.CtrlCmd | KeyCode.KEY_F, secondary: [KeyMod.CtrlCmd | KeyCode.F3] })); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(NextMatchFindAction, FindModel.NEXT_MATCH_FIND_ID, nls.localize('findNextMatchAction', "Find Next"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(NextMatchFindAction, FindModel.NEXT_MATCH_FIND_ACTION_ID, nls.localize('findNextMatchAction', "Find Next"), { context: ContextKey.EditorFocus, primary: KeyCode.F3, mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] } })); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(PreviousMatchFindAction, FindModel.PREVIOUS_MATCH_FIND_ID, nls.localize('findPreviousMatchAction', "Find Previous"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(PreviousMatchFindAction, FindModel.PREVIOUS_MATCH_FIND_ACTION_ID, nls.localize('findPreviousMatchAction', "Find Previous"), { context: ContextKey.EditorFocus, primary: KeyMod.Shift | KeyCode.F3, mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G, secondary: [KeyMod.Shift | KeyCode.F3] } })); -CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(StartFindReplaceAction, FindModel.START_FIND_REPLACE_ID, nls.localize('startReplace', "Replace"), { +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(StartFindReplaceAction, FindModel.START_FIND_REPLACE_ACTION_ID, nls.localize('startReplace', "Replace"), { context: ContextKey.None, primary: KeyMod.CtrlCmd | KeyCode.KEY_H, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_F } @@ -586,6 +637,25 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(AddSelectio })); EditorBrowserRegistry.registerEditorContribution(FindController); EditorBrowserRegistry.registerEditorContribution(SelectionHighlighter); -CommonEditorRegistry.registerEditorCommand('closeFindWidget', CommonEditorRegistry.commandWeight(5), { primary: KeyCode.Escape }, false, CONTEXT_FIND_WIDGET_VISIBLE, (ctx, editor, args) => { - FindController.getFindController(editor).closeFindWidget(); -}); \ No newline at end of file + +function registerFindCommand(id:string, callback:(controller:FindController)=>void, keybindings:IKeybindings, needsKey:string = null): void { + CommonEditorRegistry.registerEditorCommand(id, CommonEditorRegistry.commandWeight(5), keybindings, false, needsKey, (ctx, editor, args) => { + callback(FindController.getFindController(editor)); + }); +} + +registerFindCommand(FindModel.CLOSE_FIND_WIDGET_COMMAND_ID, x => x.closeFindWidget(), { + primary: KeyCode.Escape +}, CONTEXT_FIND_WIDGET_VISIBLE); +registerFindCommand(FindModel.TOGGLE_CASE_SENSITIVE_COMMAND_ID, x => x.toggleCaseSensitive(), { + primary: KeyMod.Alt | KeyCode.KEY_C, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } +}); +registerFindCommand(FindModel.TOGGLE_WHOLE_WORD_COMMAND_ID, x => x.toggleWholeWords(), { + primary: KeyMod.Alt | KeyCode.KEY_W, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } +}); +registerFindCommand(FindModel.TOGGLE_REGEX_COMMAND_ID, x => x.toggleRegex(), { + primary: KeyMod.Alt | KeyCode.KEY_R, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } +}); diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index b66a7f01a4b..2840244a8d6 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -26,17 +26,6 @@ export interface IUserInputEvent { jumpToNextMatch: boolean; } -export interface IFindWidget { - dispose(): void; - - setModel(newFindModel:FindModel.IFindModel): void; - setSearchString(searchString:string): void; - getState(): FindModel.IFindState; - - addUserInputEventListener(callback:(e:IUserInputEvent)=>void): Lifecycle.IDisposable; - addClosedEventListener(callback:()=>void): Lifecycle.IDisposable; -} - export interface IFindController { enableSelectionFind(): void; disableSelectionFind(): void; @@ -56,7 +45,7 @@ const NLS_REPLACE_BTN_LABEL = nls.localize('label.replaceButton', "Replace"); const NLS_REPLACE_ALL_BTN_LABEL = nls.localize('label.replaceAllButton', "Replace All"); const NLS_TOGGLE_REPLACE_MODE_BTN_LABEL = nls.localize('label.toggleReplaceButton', "Toggle Replace mode"); -export class FindWidget extends EventEmitter.EventEmitter implements EditorBrowser.IOverlayWidget, IFindWidget { +export class FindWidget extends EventEmitter.EventEmitter implements EditorBrowser.IOverlayWidget { private static _USER_CLOSED_EVENT = 'close'; private static _USER_INPUT_EVENT = 'userInputEvent'; @@ -161,6 +150,7 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows public setSearchString(searchString:string): void { this._findInput.setValue(searchString); + this._emitUserInputEvent(false); } private _setState(state:FindModel.IFindState, selectionFindEnabled:boolean): void { @@ -263,10 +253,10 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows var handled = false; if (e.equals(CommonKeybindings.ENTER)) { - this._codeEditor.getAction(FindModel.NEXT_MATCH_FIND_ID).run().done(null, Errors.onUnexpectedError); + this._codeEditor.getAction(FindModel.NEXT_MATCH_FIND_ACTION_ID).run().done(null, Errors.onUnexpectedError); handled = true; } else if (e.equals(CommonKeybindings.SHIFT_ENTER)) { - this._codeEditor.getAction(FindModel.PREVIOUS_MATCH_FIND_ID).run().done(null, Errors.onUnexpectedError); + this._codeEditor.getAction(FindModel.PREVIOUS_MATCH_FIND_ACTION_ID).run().done(null, Errors.onUnexpectedError); handled = true; } else if (e.equals(CommonKeybindings.TAB)) { if (this._isReplaceVisible) { @@ -334,6 +324,9 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows width: FindWidget.FIND_INPUT_AREA_WIDTH, label: NLS_FIND_INPUT_LABEL, placeholder: NLS_FIND_INPUT_PLACEHOLDER, + appendCaseSensitiveLabel: this._keybindingLabelFor(FindModel.TOGGLE_CASE_SENSITIVE_COMMAND_ID), + appendWholeWordsLabel: this._keybindingLabelFor(FindModel.TOGGLE_WHOLE_WORD_COMMAND_ID), + appendRegexLabel: this._keybindingLabelFor(FindModel.TOGGLE_REGEX_COMMAND_ID), validation: (value:string): InputBox.IMessage => { if (value.length === 0) { return null; @@ -358,19 +351,19 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows // Previous button this._prevBtn = new SimpleButton( - NLS_PREVIOUS_MATCH_BTN_LABEL + this._keybindingLabelFor(FindModel.PREVIOUS_MATCH_FIND_ID), + NLS_PREVIOUS_MATCH_BTN_LABEL + this._keybindingLabelFor(FindModel.PREVIOUS_MATCH_FIND_ACTION_ID), 'previous' ).onTrigger(() => { - this._codeEditor.getAction(FindModel.PREVIOUS_MATCH_FIND_ID).run().done(null, Errors.onUnexpectedError); + this._codeEditor.getAction(FindModel.PREVIOUS_MATCH_FIND_ACTION_ID).run().done(null, Errors.onUnexpectedError); }); this._toDispose.push(this._prevBtn); // Next button this._nextBtn = new SimpleButton( - NLS_NEXT_MATCH_BTN_LABEL + this._keybindingLabelFor(FindModel.NEXT_MATCH_FIND_ID), + NLS_NEXT_MATCH_BTN_LABEL + this._keybindingLabelFor(FindModel.NEXT_MATCH_FIND_ACTION_ID), 'next' ).onTrigger(() => { - this._codeEditor.getAction(FindModel.NEXT_MATCH_FIND_ID).run().done(null, Errors.onUnexpectedError); + this._codeEditor.getAction(FindModel.NEXT_MATCH_FIND_ACTION_ID).run().done(null, Errors.onUnexpectedError); }); this._toDispose.push(this._nextBtn); @@ -399,7 +392,7 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows // Close button this._closeBtn = new SimpleButton( - NLS_CLOSE_BTN_LABEL + ' (Escape)', + NLS_CLOSE_BTN_LABEL + this._keybindingLabelFor(FindModel.CLOSE_FIND_WIDGET_COMMAND_ID), 'close-fw' ).onTrigger(() => { this._hide(true); @@ -581,6 +574,21 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows private _emitClosedEvent(): void { this.emit(FindWidget._USER_CLOSED_EVENT); } + + public toggleCaseSensitive(): void { + this._findInput.setCaseSensitive(!this._findInput.getCaseSensitive()); + this._emitUserInputEvent(false); + } + + public toggleWholeWords(): void { + this._findInput.setWholeWords(!this._findInput.getWholeWords()); + this._emitUserInputEvent(false); + } + + public toggleRegex(): void { + this._findInput.setRegex(!this._findInput.getRegex()); + this._emitUserInputEvent(false); + } } export class Checkbox implements Lifecycle.IDisposable { diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 17247c4b871..7f771cee3ec 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -13,11 +13,14 @@ import {Range} from 'vs/editor/common/core/range'; import {Position} from 'vs/editor/common/core/position'; import {ReplaceCommand} from 'vs/editor/common/commands/replaceCommand'; -export var START_FIND_ID = 'actions.find'; -export var NEXT_MATCH_FIND_ID = 'editor.action.nextMatchFindAction'; -export var PREVIOUS_MATCH_FIND_ID = 'editor.action.previousMatchFindAction'; - -export var START_FIND_REPLACE_ID = 'editor.action.startFindReplaceAction'; +export const START_FIND_ACTION_ID = 'actions.find'; +export const NEXT_MATCH_FIND_ACTION_ID = 'editor.action.nextMatchFindAction'; +export const PREVIOUS_MATCH_FIND_ACTION_ID = 'editor.action.previousMatchFindAction'; +export const START_FIND_REPLACE_ACTION_ID = 'editor.action.startFindReplaceAction'; +export const CLOSE_FIND_WIDGET_COMMAND_ID = 'closeFindWidget'; +export const TOGGLE_CASE_SENSITIVE_COMMAND_ID = 'toggleFindCaseSensitive'; +export const TOGGLE_WHOLE_WORD_COMMAND_ID = 'toggleFindWholeWord'; +export const TOGGLE_REGEX_COMMAND_ID = 'toggleFindRegex'; export interface IFindMatchesEvent { position: number; -- GitLab