UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

413 lines (410 loc) 16.6 kB
import { Emitter } from 'vscode/vscode/vs/base/common/event'; import { DisposableStore } from 'vscode/vscode/vs/base/common/lifecycle'; import { EditorOption, TextEditorCursorStyle, RenderLineNumbersType, cursorStyleToString } from 'vscode/vscode/vs/editor/common/config/editorOptions'; import { Range } from 'vscode/vscode/vs/editor/common/core/range'; import { Selection } from 'vscode/vscode/vs/editor/common/core/selection'; import { ScrollType } from 'vscode/vscode/vs/editor/common/editorCommon'; import { SnippetController2 } from 'vscode/vscode/vs/editor/contrib/snippet/browser/snippetController2'; import { TextEditorRevealType } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol'; import { equals } from 'vscode/vscode/vs/base/common/arrays'; import { EditorState, CodeEditorStateFlag } from 'vscode/vscode/vs/editor/contrib/editorState/browser/editorState'; import { SnippetParser } from 'vscode/vscode/vs/editor/contrib/snippet/browser/snippetParser'; class MainThreadTextEditorProperties { static readFromEditor(previousProperties, model, codeEditor) { const selections = MainThreadTextEditorProperties._readSelectionsFromCodeEditor(previousProperties, codeEditor); const options = MainThreadTextEditorProperties._readOptionsFromCodeEditor(previousProperties, model, codeEditor); const visibleRanges = MainThreadTextEditorProperties._readVisibleRangesFromCodeEditor(previousProperties, codeEditor); return ( new MainThreadTextEditorProperties(selections, options, visibleRanges)); } static _readSelectionsFromCodeEditor(previousProperties, codeEditor) { let result = null; if (codeEditor) { result = codeEditor.getSelections(); } if (!result && previousProperties) { result = previousProperties.selections; } if (!result) { result = [( new Selection(1, 1, 1, 1))]; } return result; } static _readOptionsFromCodeEditor(previousProperties, model, codeEditor) { if (model.isDisposed()) { if (previousProperties) { return previousProperties.options; } else { throw ( new Error('No valid properties')); } } let cursorStyle; let lineNumbers; if (codeEditor) { const options = codeEditor.getOptions(); const lineNumbersOpts = options.get(EditorOption.lineNumbers); cursorStyle = options.get(EditorOption.cursorStyle); lineNumbers = lineNumbersOpts.renderType; } else if (previousProperties) { cursorStyle = previousProperties.options.cursorStyle; lineNumbers = previousProperties.options.lineNumbers; } else { cursorStyle = TextEditorCursorStyle.Line; lineNumbers = RenderLineNumbersType.On; } const modelOptions = model.getOptions(); return { insertSpaces: modelOptions.insertSpaces, tabSize: modelOptions.tabSize, indentSize: modelOptions.indentSize, originalIndentSize: modelOptions.originalIndentSize, cursorStyle: cursorStyle, lineNumbers: lineNumbers }; } static _readVisibleRangesFromCodeEditor(previousProperties, codeEditor) { if (codeEditor) { return codeEditor.getVisibleRanges(); } return []; } constructor(selections, options, visibleRanges) { this.selections = selections; this.options = options; this.visibleRanges = visibleRanges; } generateDelta(oldProps, selectionChangeSource) { const delta = { options: null, selections: null, visibleRanges: null }; if (!oldProps || !MainThreadTextEditorProperties._selectionsEqual(oldProps.selections, this.selections)) { delta.selections = { selections: this.selections, source: selectionChangeSource ?? undefined, }; } if (!oldProps || !MainThreadTextEditorProperties._optionsEqual(oldProps.options, this.options)) { delta.options = this.options; } if (!oldProps || !MainThreadTextEditorProperties._rangesEqual(oldProps.visibleRanges, this.visibleRanges)) { delta.visibleRanges = this.visibleRanges; } if (delta.selections || delta.options || delta.visibleRanges) { return delta; } return null; } static _selectionsEqual(a, b) { return equals(a, b, (aValue, bValue) => aValue.equalsSelection(bValue)); } static _rangesEqual(a, b) { return equals(a, b, (aValue, bValue) => aValue.equalsRange(bValue)); } static _optionsEqual(a, b) { if (a && !b || !a && b) { return false; } if (!a && !b) { return true; } return (a.tabSize === b.tabSize && a.indentSize === b.indentSize && a.insertSpaces === b.insertSpaces && a.cursorStyle === b.cursorStyle && a.lineNumbers === b.lineNumbers); } } class MainThreadTextEditor { constructor(id, model, codeEditor, focusTracker, mainThreadDocuments, modelService, clipboardService) { this._modelListeners = ( new DisposableStore()); this._codeEditorListeners = ( new DisposableStore()); this._id = id; this._model = model; this._codeEditor = null; this._properties = null; this._focusTracker = focusTracker; this._mainThreadDocuments = mainThreadDocuments; this._modelService = modelService; this._clipboardService = clipboardService; this._onPropertiesChanged = ( new Emitter()); this._modelListeners.add(this._model.onDidChangeOptions((e) => { this._updatePropertiesNow(null); })); this.setCodeEditor(codeEditor); this._updatePropertiesNow(null); } dispose() { this._modelListeners.dispose(); this._codeEditor = null; this._codeEditorListeners.dispose(); } _updatePropertiesNow(selectionChangeSource) { this._setProperties(MainThreadTextEditorProperties.readFromEditor(this._properties, this._model, this._codeEditor), selectionChangeSource); } _setProperties(newProperties, selectionChangeSource) { const delta = newProperties.generateDelta(this._properties, selectionChangeSource); this._properties = newProperties; if (delta) { this._onPropertiesChanged.fire(delta); } } getId() { return this._id; } getModel() { return this._model; } getCodeEditor() { return this._codeEditor; } hasCodeEditor(codeEditor) { return (this._codeEditor === codeEditor); } setCodeEditor(codeEditor) { if (this.hasCodeEditor(codeEditor)) { return; } this._codeEditorListeners.clear(); this._codeEditor = codeEditor; if (this._codeEditor) { this._codeEditorListeners.add(this._codeEditor.onDidChangeModel(() => { this.setCodeEditor(null); })); this._codeEditorListeners.add(this._codeEditor.onDidFocusEditorWidget(() => { this._focusTracker.onGainedFocus(); })); this._codeEditorListeners.add(this._codeEditor.onDidBlurEditorWidget(() => { this._focusTracker.onLostFocus(); })); let nextSelectionChangeSource = null; this._codeEditorListeners.add(this._mainThreadDocuments.onIsCaughtUpWithContentChanges((uri) => { if (( uri.toString()) === ( this._model.uri.toString())) { const selectionChangeSource = nextSelectionChangeSource; nextSelectionChangeSource = null; this._updatePropertiesNow(selectionChangeSource); } })); const isValidCodeEditor = () => { return (this._codeEditor && this._codeEditor.getModel() === this._model); }; const updateProperties = (selectionChangeSource) => { if (this._mainThreadDocuments.isCaughtUpWithContentChanges(this._model.uri)) { nextSelectionChangeSource = null; this._updatePropertiesNow(selectionChangeSource); } else { nextSelectionChangeSource = selectionChangeSource; } }; this._codeEditorListeners.add(this._codeEditor.onDidChangeCursorSelection((e) => { if (!isValidCodeEditor()) { return; } updateProperties(e.source); })); this._codeEditorListeners.add(this._codeEditor.onDidChangeConfiguration((e) => { if (!isValidCodeEditor()) { return; } updateProperties(null); })); this._codeEditorListeners.add(this._codeEditor.onDidLayoutChange(() => { if (!isValidCodeEditor()) { return; } updateProperties(null); })); this._codeEditorListeners.add(this._codeEditor.onDidScrollChange(() => { if (!isValidCodeEditor()) { return; } updateProperties(null); })); this._updatePropertiesNow(null); } } isVisible() { return !!this._codeEditor; } getProperties() { return this._properties; } get onPropertiesChanged() { return this._onPropertiesChanged.event; } setSelections(selections) { if (this._codeEditor) { this._codeEditor.setSelections(selections); return; } const newSelections = ( selections.map(Selection.liftSelection)); this._setProperties(( new MainThreadTextEditorProperties(newSelections, this._properties.options, this._properties.visibleRanges)), null); } _setIndentConfiguration(newConfiguration) { const creationOpts = this._modelService.getCreationOptions(this._model.getLanguageId(), this._model.uri, this._model.isForSimpleWidget); if (newConfiguration.tabSize === 'auto' || newConfiguration.insertSpaces === 'auto') { let insertSpaces = creationOpts.insertSpaces; let tabSize = creationOpts.tabSize; if (newConfiguration.insertSpaces !== 'auto' && typeof newConfiguration.insertSpaces !== 'undefined') { insertSpaces = newConfiguration.insertSpaces; } if (newConfiguration.tabSize !== 'auto' && typeof newConfiguration.tabSize !== 'undefined') { tabSize = newConfiguration.tabSize; } this._model.detectIndentation(insertSpaces, tabSize); return; } const newOpts = {}; if (typeof newConfiguration.insertSpaces !== 'undefined') { newOpts.insertSpaces = newConfiguration.insertSpaces; } if (typeof newConfiguration.tabSize !== 'undefined') { newOpts.tabSize = newConfiguration.tabSize; } if (typeof newConfiguration.indentSize !== 'undefined') { newOpts.indentSize = newConfiguration.indentSize; } this._model.updateOptions(newOpts); } setConfiguration(newConfiguration) { this._setIndentConfiguration(newConfiguration); if (!this._codeEditor) { return; } if (newConfiguration.cursorStyle) { const newCursorStyle = cursorStyleToString(newConfiguration.cursorStyle); this._codeEditor.updateOptions({ cursorStyle: newCursorStyle }); } if (typeof newConfiguration.lineNumbers !== 'undefined') { let lineNumbers; switch (newConfiguration.lineNumbers) { case RenderLineNumbersType.On: lineNumbers = 'on'; break; case RenderLineNumbersType.Relative: lineNumbers = 'relative'; break; case RenderLineNumbersType.Interval: lineNumbers = 'interval'; break; default: lineNumbers = 'off'; } this._codeEditor.updateOptions({ lineNumbers: lineNumbers }); } } setDecorations(key, ranges) { if (!this._codeEditor) { return; } this._codeEditor.setDecorationsByType('exthost-api', key, ranges); } setDecorationsFast(key, _ranges) { if (!this._codeEditor) { return; } const ranges = []; for (let i = 0, len = Math.floor(_ranges.length / 4); i < len; i++) { ranges[i] = ( new Range(_ranges[4 * i], _ranges[4 * i + 1], _ranges[4 * i + 2], _ranges[4 * i + 3])); } this._codeEditor.setDecorationsByTypeFast(key, ranges); } revealRange(range, revealType) { if (!this._codeEditor) { return; } switch (revealType) { case TextEditorRevealType.Default: this._codeEditor.revealRange(range, ScrollType.Smooth); break; case TextEditorRevealType.InCenter: this._codeEditor.revealRangeInCenter(range, ScrollType.Smooth); break; case TextEditorRevealType.InCenterIfOutsideViewport: this._codeEditor.revealRangeInCenterIfOutsideViewport(range, ScrollType.Smooth); break; case TextEditorRevealType.AtTop: this._codeEditor.revealRangeAtTop(range, ScrollType.Smooth); break; default: console.warn(`Unknown revealType: ${revealType}`); break; } } isFocused() { if (this._codeEditor) { return this._codeEditor.hasTextFocus(); } return false; } matches(editor) { if (!editor) { return false; } return editor.getControl() === this._codeEditor; } applyEdits(versionIdCheck, edits, opts) { if (this._model.getVersionId() !== versionIdCheck) { return false; } if (!this._codeEditor) { return false; } if (typeof opts.setEndOfLine !== 'undefined') { this._model.pushEOL(opts.setEndOfLine); } const transformedEdits = ( edits.map((edit) => { return { range: Range.lift(edit.range), text: edit.text, forceMoveMarkers: edit.forceMoveMarkers }; })); if (opts.undoStopBefore) { this._codeEditor.pushUndoStop(); } this._codeEditor.executeEdits('MainThreadTextEditor', transformedEdits); if (opts.undoStopAfter) { this._codeEditor.pushUndoStop(); } return true; } async insertSnippet(modelVersionId, template, ranges, opts) { if (!this._codeEditor || !this._codeEditor.hasModel()) { return false; } let clipboardText; const needsTemplate = SnippetParser.guessNeedsClipboard(template); if (needsTemplate) { const state = ( new EditorState(this._codeEditor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position)); clipboardText = await this._clipboardService.readText(); if (!state.validate(this._codeEditor)) { return false; } } if (this._codeEditor.getModel().getVersionId() !== modelVersionId) { return false; } const snippetController = SnippetController2.get(this._codeEditor); if (!snippetController) { return false; } this._codeEditor.focus(); const edits = ( ranges.map(range => ({ range: Range.lift(range), template }))); snippetController.apply(edits, { overwriteBefore: 0, overwriteAfter: 0, undoStopBefore: opts.undoStopBefore, undoStopAfter: opts.undoStopAfter, clipboardText }); return true; } } export { MainThreadTextEditor, MainThreadTextEditorProperties };