Path: blob/main/src/vs/editor/contrib/editorState/browser/keybindingCancellation.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { KeyCode } from '../../../../base/common/keyCodes.js';6import { EditorCommand, registerEditorCommand } from '../../../browser/editorExtensions.js';7import { ICodeEditor } from '../../../browser/editorBrowser.js';8import { IContextKeyService, RawContextKey, IContextKey } from '../../../../platform/contextkey/common/contextkey.js';9import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';10import { CancellationTokenSource, CancellationToken } from '../../../../base/common/cancellation.js';11import { LinkedList } from '../../../../base/common/linkedList.js';12import { createDecorator, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';13import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';14import { localize } from '../../../../nls.js';151617const IEditorCancellationTokens = createDecorator<IEditorCancellationTokens>('IEditorCancelService');1819interface IEditorCancellationTokens {20readonly _serviceBrand: undefined;21add(editor: ICodeEditor, cts: CancellationTokenSource): () => void;22cancel(editor: ICodeEditor): void;23}2425const ctxCancellableOperation = new RawContextKey('cancellableOperation', false, localize('cancellableOperation', 'Whether the editor runs a cancellable operation, e.g. like \'Peek References\''));2627registerSingleton(IEditorCancellationTokens, class implements IEditorCancellationTokens {2829declare readonly _serviceBrand: undefined;3031private readonly _tokens = new WeakMap<ICodeEditor, { key: IContextKey<boolean>; tokens: LinkedList<CancellationTokenSource> }>();3233add(editor: ICodeEditor, cts: CancellationTokenSource): () => void {34let data = this._tokens.get(editor);35if (!data) {36data = editor.invokeWithinContext(accessor => {37const key = ctxCancellableOperation.bindTo(accessor.get(IContextKeyService));38const tokens = new LinkedList<CancellationTokenSource>();39return { key, tokens };40});41this._tokens.set(editor, data);42}4344let removeFn: Function | undefined;4546data.key.set(true);47removeFn = data.tokens.push(cts);4849return () => {50// remove w/o cancellation51if (removeFn) {52removeFn();53data.key.set(!data.tokens.isEmpty());54removeFn = undefined;55}56};57}5859cancel(editor: ICodeEditor): void {60const data = this._tokens.get(editor);61if (!data) {62return;63}64// remove with cancellation65const cts = data.tokens.pop();66if (cts) {67cts.cancel();68data.key.set(!data.tokens.isEmpty());69}70}7172}, InstantiationType.Delayed);7374export class EditorKeybindingCancellationTokenSource extends CancellationTokenSource {7576private readonly _unregister: Function;7778constructor(readonly editor: ICodeEditor, parent?: CancellationToken) {79super(parent);80this._unregister = editor.invokeWithinContext(accessor => accessor.get(IEditorCancellationTokens).add(editor, this));81}8283override dispose(): void {84this._unregister();85super.dispose();86}87}8889registerEditorCommand(new class extends EditorCommand {9091constructor() {92super({93id: 'editor.cancelOperation',94kbOpts: {95weight: KeybindingWeight.EditorContrib,96primary: KeyCode.Escape97},98precondition: ctxCancellableOperation99});100}101102runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void {103accessor.get(IEditorCancellationTokens).cancel(editor);104}105});106107108