UNPKG

monaco-editor

Version:
771 lines (770 loc) • 35.2 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var WordHighlighter_1, WordHighlighterContribution_1; import * as nls from '../../../../nls.js'; import * as arrays from '../../../../base/common/arrays.js'; import { alert } from '../../../../base/browser/ui/aria/aria.js'; import { createCancelablePromise, first, timeout } from '../../../../base/common/async.js'; import { CancellationToken } from '../../../../base/common/cancellation.js'; import { onUnexpectedError, onUnexpectedExternalError } from '../../../../base/common/errors.js'; import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js'; import { isDiffEditor } from '../../../browser/editorBrowser.js'; import { EditorAction, registerEditorAction, registerEditorContribution, registerModelAndPositionCommand } from '../../../browser/editorExtensions.js'; import { ICodeEditorService } from '../../../browser/services/codeEditorService.js'; import { Range } from '../../../common/core/range.js'; import { EditorContextKeys } from '../../../common/editorContextKeys.js'; import { DocumentHighlightKind } from '../../../common/languages.js'; import { shouldSynchronizeModel } from '../../../common/model.js'; import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js'; import { getHighlightDecorationOptions } from './highlightDecorations.js'; import { IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js'; import { Schemas } from '../../../../base/common/network.js'; import { ResourceMap } from '../../../../base/common/map.js'; import { score } from '../../../common/languageSelector.js'; // import { TextualMultiDocumentHighlightFeature } from 'vs/editor/contrib/wordHighlighter/browser/textualHighlightProvider'; // import { registerEditorFeature } from 'vs/editor/common/editorFeatures'; const ctxHasWordHighlights = new RawContextKey('hasWordHighlights', false); export function getOccurrencesAtPosition(registry, model, position, token) { const orderedByScore = registry.ordered(model); // in order of score ask the occurrences provider // until someone response with a good result // (good = none empty array) return first(orderedByScore.map(provider => () => { return Promise.resolve(provider.provideDocumentHighlights(model, position, token)) .then(undefined, onUnexpectedExternalError); }), arrays.isNonEmptyArray).then(result => { if (result) { const map = new ResourceMap(); map.set(model.uri, result); return map; } return new ResourceMap(); }); } export function getOccurrencesAcrossMultipleModels(registry, model, position, wordSeparators, token, otherModels) { const orderedByScore = registry.ordered(model); // in order of score ask the occurrences provider // until someone response with a good result // (good = none empty array) return first(orderedByScore.map(provider => () => { const filteredModels = otherModels.filter(otherModel => { return shouldSynchronizeModel(otherModel); }).filter(otherModel => { return score(provider.selector, otherModel.uri, otherModel.getLanguageId(), true, undefined, undefined) > 0; }); return Promise.resolve(provider.provideMultiDocumentHighlights(model, position, filteredModels, token)) .then(undefined, onUnexpectedExternalError); }), (t) => t instanceof ResourceMap && t.size > 0); } class OccurenceAtPositionRequest { constructor(_model, _selection, _wordSeparators) { this._model = _model; this._selection = _selection; this._wordSeparators = _wordSeparators; this._wordRange = this._getCurrentWordRange(_model, _selection); this._result = null; } get result() { if (!this._result) { this._result = createCancelablePromise(token => this._compute(this._model, this._selection, this._wordSeparators, token)); } return this._result; } _getCurrentWordRange(model, selection) { const word = model.getWordAtPosition(selection.getPosition()); if (word) { return new Range(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn); } return null; } isValid(model, selection, decorations) { const lineNumber = selection.startLineNumber; const startColumn = selection.startColumn; const endColumn = selection.endColumn; const currentWordRange = this._getCurrentWordRange(model, selection); let requestIsValid = Boolean(this._wordRange && this._wordRange.equalsRange(currentWordRange)); // Even if we are on a different word, if that word is in the decorations ranges, the request is still valid // (Same symbol) for (let i = 0, len = decorations.length; !requestIsValid && i < len; i++) { const range = decorations.getRange(i); if (range && range.startLineNumber === lineNumber) { if (range.startColumn <= startColumn && range.endColumn >= endColumn) { requestIsValid = true; } } } return requestIsValid; } cancel() { this.result.cancel(); } } class SemanticOccurenceAtPositionRequest extends OccurenceAtPositionRequest { constructor(model, selection, wordSeparators, providers) { super(model, selection, wordSeparators); this._providers = providers; } _compute(model, selection, wordSeparators, token) { return getOccurrencesAtPosition(this._providers, model, selection.getPosition(), token).then(value => { if (!value) { return new ResourceMap(); } return value; }); } } class MultiModelOccurenceRequest extends OccurenceAtPositionRequest { constructor(model, selection, wordSeparators, providers, otherModels) { super(model, selection, wordSeparators); this._providers = providers; this._otherModels = otherModels; } _compute(model, selection, wordSeparators, token) { return getOccurrencesAcrossMultipleModels(this._providers, model, selection.getPosition(), wordSeparators, token, this._otherModels).then(value => { if (!value) { return new ResourceMap(); } return value; }); } } class TextualOccurenceRequest extends OccurenceAtPositionRequest { constructor(model, selection, word, wordSeparators, otherModels) { super(model, selection, wordSeparators); this._otherModels = otherModels; this._selectionIsEmpty = selection.isEmpty(); this._word = word; } _compute(model, selection, wordSeparators, token) { return timeout(250, token).then(() => { const result = new ResourceMap(); let wordResult; if (this._word) { wordResult = this._word; } else { wordResult = model.getWordAtPosition(selection.getPosition()); } if (!wordResult) { return new ResourceMap(); } const allModels = [model, ...this._otherModels]; for (const otherModel of allModels) { if (otherModel.isDisposed()) { continue; } const matches = otherModel.findMatches(wordResult.word, true, false, true, wordSeparators, false); const highlights = matches.map(m => ({ range: m.range, kind: DocumentHighlightKind.Text })); if (highlights) { result.set(otherModel.uri, highlights); } } return result; }); } isValid(model, selection, decorations) { const currentSelectionIsEmpty = selection.isEmpty(); if (this._selectionIsEmpty !== currentSelectionIsEmpty) { return false; } return super.isValid(model, selection, decorations); } } function computeOccurencesAtPosition(registry, model, selection, word, wordSeparators) { if (registry.has(model)) { return new SemanticOccurenceAtPositionRequest(model, selection, wordSeparators, registry); } return new TextualOccurenceRequest(model, selection, word, wordSeparators, []); } function computeOccurencesMultiModel(registry, model, selection, word, wordSeparators, otherModels) { if (registry.has(model)) { return new MultiModelOccurenceRequest(model, selection, wordSeparators, registry, otherModels); } return new TextualOccurenceRequest(model, selection, word, wordSeparators, otherModels); } registerModelAndPositionCommand('_executeDocumentHighlights', async (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); const map = await getOccurrencesAtPosition(languageFeaturesService.documentHighlightProvider, model, position, CancellationToken.None); return map === null || map === void 0 ? void 0 : map.get(model.uri); }); let WordHighlighter = WordHighlighter_1 = class WordHighlighter { constructor(editor, providers, multiProviders, contextKeyService, codeEditorService) { this.toUnhook = new DisposableStore(); this.workerRequestTokenId = 0; this.workerRequestCompleted = false; this.workerRequestValue = new ResourceMap(); this.lastCursorPositionChangeTime = 0; this.renderDecorationsTimer = -1; this.editor = editor; this.providers = providers; this.multiDocumentProviders = multiProviders; this.codeEditorService = codeEditorService; this._hasWordHighlights = ctxHasWordHighlights.bindTo(contextKeyService); this._ignorePositionChangeEvent = false; this.occurrencesHighlight = this.editor.getOption(80 /* EditorOption.occurrencesHighlight */); this.model = this.editor.getModel(); this.toUnhook.add(editor.onDidChangeCursorPosition((e) => { if (this._ignorePositionChangeEvent) { // We are changing the position => ignore this event return; } if (this.occurrencesHighlight === 'off') { // 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; } this._onPositionChanged(e); })); this.toUnhook.add(editor.onDidChangeModelContent((e) => { this._stopAll(); })); this.toUnhook.add(editor.onDidChangeModel((e) => { if (!e.newModelUrl && e.oldModelUrl) { this._stopSingular(); } else { if (WordHighlighter_1.query) { this._run(); } } })); this.toUnhook.add(editor.onDidChangeConfiguration((e) => { const newValue = this.editor.getOption(80 /* EditorOption.occurrencesHighlight */); if (this.occurrencesHighlight !== newValue) { this.occurrencesHighlight = newValue; this._stopAll(); } })); this.decorations = this.editor.createDecorationsCollection(); this.workerRequestTokenId = 0; this.workerRequest = null; this.workerRequestCompleted = false; this.lastCursorPositionChangeTime = 0; this.renderDecorationsTimer = -1; // if there is a query already, highlight off that query if (WordHighlighter_1.query) { this._run(); } } hasDecorations() { return (this.decorations.length > 0); } restore() { if (this.occurrencesHighlight === 'off') { return; } this._run(); } _getSortedHighlights() { return (this.decorations.getRanges() .sort(Range.compareRangesUsingStarts)); } moveNext() { const highlights = this._getSortedHighlights(); const index = highlights.findIndex((range) => range.containsPosition(this.editor.getPosition())); const newIndex = ((index + 1) % highlights.length); const dest = highlights[newIndex]; try { this._ignorePositionChangeEvent = true; this.editor.setPosition(dest.getStartPosition()); this.editor.revealRangeInCenterIfOutsideViewport(dest); const word = this._getWord(); if (word) { const lineContent = this.editor.getModel().getLineContent(dest.startLineNumber); alert(`${lineContent}, ${newIndex + 1} of ${highlights.length} for '${word.word}'`); } } finally { this._ignorePositionChangeEvent = false; } } moveBack() { const highlights = this._getSortedHighlights(); const index = highlights.findIndex((range) => range.containsPosition(this.editor.getPosition())); const newIndex = ((index - 1 + highlights.length) % highlights.length); const dest = highlights[newIndex]; try { this._ignorePositionChangeEvent = true; this.editor.setPosition(dest.getStartPosition()); this.editor.revealRangeInCenterIfOutsideViewport(dest); const word = this._getWord(); if (word) { const lineContent = this.editor.getModel().getLineContent(dest.startLineNumber); alert(`${lineContent}, ${newIndex + 1} of ${highlights.length} for '${word.word}'`); } } finally { this._ignorePositionChangeEvent = false; } } _removeSingleDecorations() { // return if no model if (!this.editor.hasModel()) { return; } const currentDecorationIDs = WordHighlighter_1.storedDecorations.get(this.editor.getModel().uri); if (!currentDecorationIDs) { return; } this.editor.removeDecorations(currentDecorationIDs); WordHighlighter_1.storedDecorations.delete(this.editor.getModel().uri); if (this.decorations.length > 0) { this.decorations.clear(); this._hasWordHighlights.set(false); } } _removeAllDecorations() { const currentEditors = this.codeEditorService.listCodeEditors(); // iterate over editors and store models in currentModels for (const editor of currentEditors) { if (!editor.hasModel()) { continue; } const currentDecorationIDs = WordHighlighter_1.storedDecorations.get(editor.getModel().uri); if (!currentDecorationIDs) { continue; } editor.removeDecorations(currentDecorationIDs); WordHighlighter_1.storedDecorations.delete(editor.getModel().uri); const editorHighlighterContrib = WordHighlighterContribution.get(editor); if (!(editorHighlighterContrib === null || editorHighlighterContrib === void 0 ? void 0 : editorHighlighterContrib.wordHighlighter)) { continue; } if (editorHighlighterContrib.wordHighlighter.decorations.length > 0) { editorHighlighterContrib.wordHighlighter.decorations.clear(); editorHighlighterContrib.wordHighlighter._hasWordHighlights.set(false); } } } _stopSingular() { var _a, _b, _c, _d; // Remove any existing decorations + a possible query, and re - run to update decorations this._removeSingleDecorations(); if (this.editor.hasWidgetFocus()) { if (((_a = this.editor.getModel()) === null || _a === void 0 ? void 0 : _a.uri.scheme) !== Schemas.vscodeNotebookCell && ((_c = (_b = WordHighlighter_1.query) === null || _b === void 0 ? void 0 : _b.modelInfo) === null || _c === void 0 ? void 0 : _c.model.uri.scheme) !== Schemas.vscodeNotebookCell) { // clear query if focused non-nb editor WordHighlighter_1.query = null; this._run(); } else { // remove modelInfo to account for nb cell being disposed if ((_d = WordHighlighter_1.query) === null || _d === void 0 ? void 0 : _d.modelInfo) { WordHighlighter_1.query.modelInfo = null; } } } // Cancel any renderDecorationsTimer if (this.renderDecorationsTimer !== -1) { clearTimeout(this.renderDecorationsTimer); this.renderDecorationsTimer = -1; } // Cancel any worker request if (this.workerRequest !== null) { this.workerRequest.cancel(); this.workerRequest = null; } // Invalidate any worker request callback if (!this.workerRequestCompleted) { this.workerRequestTokenId++; this.workerRequestCompleted = true; } } _stopAll() { // Remove any existing decorations this._removeAllDecorations(); // Cancel any renderDecorationsTimer if (this.renderDecorationsTimer !== -1) { clearTimeout(this.renderDecorationsTimer); this.renderDecorationsTimer = -1; } // Cancel any worker request if (this.workerRequest !== null) { this.workerRequest.cancel(); this.workerRequest = null; } // Invalidate any worker request callback if (!this.workerRequestCompleted) { this.workerRequestTokenId++; this.workerRequestCompleted = true; } } _onPositionChanged(e) { var _a; // disabled if (this.occurrencesHighlight === 'off') { this._stopAll(); return; } // ignore typing & other // need to check if the model is a notebook cell, should not stop if nb if (e.reason !== 3 /* CursorChangeReason.Explicit */ && ((_a = this.editor.getModel()) === null || _a === void 0 ? void 0 : _a.uri.scheme) !== Schemas.vscodeNotebookCell) { this._stopAll(); return; } this._run(); } _getWord() { const editorSelection = this.editor.getSelection(); const lineNumber = editorSelection.startLineNumber; const startColumn = editorSelection.startColumn; if (this.model.isDisposed()) { return null; } return this.model.getWordAtPosition({ lineNumber: lineNumber, column: startColumn }); } getOtherModelsToHighlight(model) { if (!model) { return []; } // notebook case const isNotebookEditor = model.uri.scheme === Schemas.vscodeNotebookCell; if (isNotebookEditor) { const currentModels = []; const currentEditors = this.codeEditorService.listCodeEditors(); for (const editor of currentEditors) { const tempModel = editor.getModel(); if (tempModel && tempModel !== model && tempModel.uri.scheme === Schemas.vscodeNotebookCell) { currentModels.push(tempModel); } } return currentModels; } // inline case // ? current works when highlighting outside of an inline diff, highlighting in. // ? broken when highlighting within a diff editor. highlighting the main editor does not work // ? editor group service could be useful here const currentModels = []; const currentEditors = this.codeEditorService.listCodeEditors(); for (const editor of currentEditors) { if (!isDiffEditor(editor)) { continue; } const diffModel = editor.getModel(); if (!diffModel) { continue; } if (model === diffModel.modified) { // embedded inline chat diff would pass this, allowing highlights //? currentModels.push(diffModel.original); currentModels.push(diffModel.modified); } } if (currentModels.length) { // no matching editors have been found return currentModels; } // multi-doc OFF if (this.occurrencesHighlight === 'singleFile') { return []; } // multi-doc ON for (const editor of currentEditors) { const tempModel = editor.getModel(); const isValidModel = tempModel && tempModel !== model; if (isValidModel) { currentModels.push(tempModel); } } return currentModels; } _run() { var _a, _b; let workerRequestIsValid; if (!this.editor.hasWidgetFocus()) { // no focus (new nb cell, etc) if (WordHighlighter_1.query === null) { // no previous query, nothing to highlight return; } } else { const editorSelection = this.editor.getSelection(); // ignore multiline selection if (!editorSelection || editorSelection.startLineNumber !== editorSelection.endLineNumber) { this._stopAll(); return; } const startColumn = editorSelection.startColumn; const endColumn = editorSelection.endColumn; const word = this._getWord(); // The selection must be inside a word or surround one word at most if (!word || word.startColumn > startColumn || word.endColumn < endColumn) { // no previous query, nothing to highlight WordHighlighter_1.query = null; this._stopAll(); return; } // All the effort below is trying to achieve this: // - when cursor is moved to a word, trigger immediately a findOccurrences request // - 250ms later after the last cursor move event, render the occurrences // - no flickering! workerRequestIsValid = (this.workerRequest && this.workerRequest.isValid(this.model, editorSelection, this.decorations)); WordHighlighter_1.query = { modelInfo: { model: this.model, selection: editorSelection, }, word: word }; } // There are 4 cases: // a) old workerRequest is valid & completed, renderDecorationsTimer fired // b) old workerRequest is valid & completed, renderDecorationsTimer not fired // c) old workerRequest is valid, but not completed // d) old workerRequest is not valid // For a) no action is needed // For c), member 'lastCursorPositionChangeTime' will be used when installing the timer so no action is needed this.lastCursorPositionChangeTime = (new Date()).getTime(); if (workerRequestIsValid) { if (this.workerRequestCompleted && this.renderDecorationsTimer !== -1) { // case b) // Delay the firing of renderDecorationsTimer by an extra 250 ms clearTimeout(this.renderDecorationsTimer); this.renderDecorationsTimer = -1; this._beginRenderDecorations(); } } else { // case d) // Stop all previous actions and start fresh this._stopAll(); const myRequestId = ++this.workerRequestTokenId; this.workerRequestCompleted = false; const otherModelsToHighlight = this.getOtherModelsToHighlight(this.editor.getModel()); // 2 cases where we want to send the word // a) there is no stored query model, but there is a word. This signals the editor that drove the highlight is disposed (cell out of viewport, etc) // b) the queried model is not the current model. This signals that the editor that drove the highlight is still in the viewport, but we are highlighting a different cell // otherwise, we send null in place of the word, and the model and selection are used to compute the word const sendWord = (!WordHighlighter_1.query.modelInfo && WordHighlighter_1.query.word) || (((_a = WordHighlighter_1.query.modelInfo) === null || _a === void 0 ? void 0 : _a.model.uri) !== this.model.uri) ? true : false; if (!WordHighlighter_1.query.modelInfo || (WordHighlighter_1.query.modelInfo.model.uri !== this.model.uri)) { // use this.model this.workerRequest = this.computeWithModel(this.model, this.editor.getSelection(), sendWord ? WordHighlighter_1.query.word : null, otherModelsToHighlight); } else { // use stored query model + selection this.workerRequest = this.computeWithModel(WordHighlighter_1.query.modelInfo.model, WordHighlighter_1.query.modelInfo.selection, WordHighlighter_1.query.word, otherModelsToHighlight); } (_b = this.workerRequest) === null || _b === void 0 ? void 0 : _b.result.then(data => { if (myRequestId === this.workerRequestTokenId) { this.workerRequestCompleted = true; this.workerRequestValue = data || []; this._beginRenderDecorations(); } }, onUnexpectedError); } } computeWithModel(model, selection, word, otherModels) { if (!otherModels.length) { return computeOccurencesAtPosition(this.providers, model, selection, word, this.editor.getOption(129 /* EditorOption.wordSeparators */)); } else { return computeOccurencesMultiModel(this.multiDocumentProviders, model, selection, word, this.editor.getOption(129 /* EditorOption.wordSeparators */), otherModels); } } _beginRenderDecorations() { const currentTime = (new Date()).getTime(); const minimumRenderTime = this.lastCursorPositionChangeTime + 250; if (currentTime >= minimumRenderTime) { // Synchronous this.renderDecorationsTimer = -1; this.renderDecorations(); } else { // Asynchronous this.renderDecorationsTimer = setTimeout(() => { this.renderDecorations(); }, (minimumRenderTime - currentTime)); } } renderDecorations() { var _a, _b, _c; this.renderDecorationsTimer = -1; // create new loop, iterate over current editors using this.codeEditorService.listCodeEditors(), // if the URI of that codeEditor is in the map, then add the decorations to the decorations array // then set the decorations for the editor const currentEditors = this.codeEditorService.listCodeEditors(); for (const editor of currentEditors) { const editorHighlighterContrib = WordHighlighterContribution.get(editor); if (!editorHighlighterContrib) { continue; } const newDecorations = []; const uri = (_a = editor.getModel()) === null || _a === void 0 ? void 0 : _a.uri; if (uri && this.workerRequestValue.has(uri)) { const oldDecorationIDs = WordHighlighter_1.storedDecorations.get(uri); const newDocumentHighlights = this.workerRequestValue.get(uri); if (newDocumentHighlights) { for (const highlight of newDocumentHighlights) { newDecorations.push({ range: highlight.range, options: getHighlightDecorationOptions(highlight.kind) }); } } let newDecorationIDs = []; editor.changeDecorations((changeAccessor) => { newDecorationIDs = changeAccessor.deltaDecorations(oldDecorationIDs !== null && oldDecorationIDs !== void 0 ? oldDecorationIDs : [], newDecorations); }); WordHighlighter_1.storedDecorations = WordHighlighter_1.storedDecorations.set(uri, newDecorationIDs); if (newDecorations.length > 0) { (_b = editorHighlighterContrib.wordHighlighter) === null || _b === void 0 ? void 0 : _b.decorations.set(newDecorations); (_c = editorHighlighterContrib.wordHighlighter) === null || _c === void 0 ? void 0 : _c._hasWordHighlights.set(true); } } } } dispose() { this._stopSingular(); this.toUnhook.dispose(); } }; WordHighlighter.storedDecorations = new ResourceMap(); WordHighlighter.query = null; WordHighlighter = WordHighlighter_1 = __decorate([ __param(4, ICodeEditorService) ], WordHighlighter); let WordHighlighterContribution = WordHighlighterContribution_1 = class WordHighlighterContribution extends Disposable { static get(editor) { return editor.getContribution(WordHighlighterContribution_1.ID); } constructor(editor, contextKeyService, languageFeaturesService, codeEditorService) { super(); this._wordHighlighter = null; const createWordHighlighterIfPossible = () => { if (editor.hasModel() && !editor.getModel().isTooLargeForTokenization()) { this._wordHighlighter = new WordHighlighter(editor, languageFeaturesService.documentHighlightProvider, languageFeaturesService.multiDocumentHighlightProvider, contextKeyService, codeEditorService); } }; this._register(editor.onDidChangeModel((e) => { if (this._wordHighlighter) { this._wordHighlighter.dispose(); this._wordHighlighter = null; } createWordHighlighterIfPossible(); })); createWordHighlighterIfPossible(); } get wordHighlighter() { return this._wordHighlighter; } saveViewState() { if (this._wordHighlighter && this._wordHighlighter.hasDecorations()) { return true; } return false; } moveNext() { var _a; (_a = this._wordHighlighter) === null || _a === void 0 ? void 0 : _a.moveNext(); } moveBack() { var _a; (_a = this._wordHighlighter) === null || _a === void 0 ? void 0 : _a.moveBack(); } restoreViewState(state) { if (this._wordHighlighter && state) { this._wordHighlighter.restore(); } } dispose() { if (this._wordHighlighter) { this._wordHighlighter.dispose(); this._wordHighlighter = null; } super.dispose(); } }; WordHighlighterContribution.ID = 'editor.contrib.wordHighlighter'; WordHighlighterContribution = WordHighlighterContribution_1 = __decorate([ __param(1, IContextKeyService), __param(2, ILanguageFeaturesService), __param(3, ICodeEditorService) ], WordHighlighterContribution); export { WordHighlighterContribution }; class WordHighlightNavigationAction extends EditorAction { constructor(next, opts) { super(opts); this._isNext = next; } run(accessor, editor) { const controller = WordHighlighterContribution.get(editor); if (!controller) { return; } if (this._isNext) { controller.moveNext(); } else { controller.moveBack(); } } } class NextWordHighlightAction extends WordHighlightNavigationAction { constructor() { super(true, { id: 'editor.action.wordHighlight.next', label: nls.localize('wordHighlight.next.label', "Go to Next Symbol Highlight"), alias: 'Go to Next Symbol Highlight', precondition: ctxHasWordHighlights, kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: 65 /* KeyCode.F7 */, weight: 100 /* KeybindingWeight.EditorContrib */ } }); } } class PrevWordHighlightAction extends WordHighlightNavigationAction { constructor() { super(false, { id: 'editor.action.wordHighlight.prev', label: nls.localize('wordHighlight.previous.label', "Go to Previous Symbol Highlight"), alias: 'Go to Previous Symbol Highlight', precondition: ctxHasWordHighlights, kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: 1024 /* KeyMod.Shift */ | 65 /* KeyCode.F7 */, weight: 100 /* KeybindingWeight.EditorContrib */ } }); } } class TriggerWordHighlightAction extends EditorAction { constructor() { super({ id: 'editor.action.wordHighlight.trigger', label: nls.localize('wordHighlight.trigger.label', "Trigger Symbol Highlight"), alias: 'Trigger Symbol Highlight', precondition: ctxHasWordHighlights.toNegated(), kbOpts: { kbExpr: EditorContextKeys.editorTextFocus, primary: 0, weight: 100 /* KeybindingWeight.EditorContrib */ } }); } run(accessor, editor, args) { const controller = WordHighlighterContribution.get(editor); if (!controller) { return; } controller.restoreViewState(true); } } registerEditorContribution(WordHighlighterContribution.ID, WordHighlighterContribution, 0 /* EditorContributionInstantiation.Eager */); // eager because it uses `saveViewState`/`restoreViewState` registerEditorAction(NextWordHighlightAction); registerEditorAction(PrevWordHighlightAction); registerEditorAction(TriggerWordHighlightAction); // registerEditorFeature(TextualMultiDocumentHighlightFeature);