Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/editorState/browser/keybindingCancellation.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { KeyCode } from '../../../../base/common/keyCodes.js';
7
import { EditorCommand, registerEditorCommand } from '../../../browser/editorExtensions.js';
8
import { ICodeEditor } from '../../../browser/editorBrowser.js';
9
import { IContextKeyService, RawContextKey, IContextKey } from '../../../../platform/contextkey/common/contextkey.js';
10
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
11
import { CancellationTokenSource, CancellationToken } from '../../../../base/common/cancellation.js';
12
import { LinkedList } from '../../../../base/common/linkedList.js';
13
import { createDecorator, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
14
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
15
import { localize } from '../../../../nls.js';
16
17
18
const IEditorCancellationTokens = createDecorator<IEditorCancellationTokens>('IEditorCancelService');
19
20
interface IEditorCancellationTokens {
21
readonly _serviceBrand: undefined;
22
add(editor: ICodeEditor, cts: CancellationTokenSource): () => void;
23
cancel(editor: ICodeEditor): void;
24
}
25
26
const ctxCancellableOperation = new RawContextKey('cancellableOperation', false, localize('cancellableOperation', 'Whether the editor runs a cancellable operation, e.g. like \'Peek References\''));
27
28
registerSingleton(IEditorCancellationTokens, class implements IEditorCancellationTokens {
29
30
declare readonly _serviceBrand: undefined;
31
32
private readonly _tokens = new WeakMap<ICodeEditor, { key: IContextKey<boolean>; tokens: LinkedList<CancellationTokenSource> }>();
33
34
add(editor: ICodeEditor, cts: CancellationTokenSource): () => void {
35
let data = this._tokens.get(editor);
36
if (!data) {
37
data = editor.invokeWithinContext(accessor => {
38
const key = ctxCancellableOperation.bindTo(accessor.get(IContextKeyService));
39
const tokens = new LinkedList<CancellationTokenSource>();
40
return { key, tokens };
41
});
42
this._tokens.set(editor, data);
43
}
44
45
let removeFn: Function | undefined;
46
47
data.key.set(true);
48
removeFn = data.tokens.push(cts);
49
50
return () => {
51
// remove w/o cancellation
52
if (removeFn) {
53
removeFn();
54
data.key.set(!data.tokens.isEmpty());
55
removeFn = undefined;
56
}
57
};
58
}
59
60
cancel(editor: ICodeEditor): void {
61
const data = this._tokens.get(editor);
62
if (!data) {
63
return;
64
}
65
// remove with cancellation
66
const cts = data.tokens.pop();
67
if (cts) {
68
cts.cancel();
69
data.key.set(!data.tokens.isEmpty());
70
}
71
}
72
73
}, InstantiationType.Delayed);
74
75
export class EditorKeybindingCancellationTokenSource extends CancellationTokenSource {
76
77
private readonly _unregister: Function;
78
79
constructor(readonly editor: ICodeEditor, parent?: CancellationToken) {
80
super(parent);
81
this._unregister = editor.invokeWithinContext(accessor => accessor.get(IEditorCancellationTokens).add(editor, this));
82
}
83
84
override dispose(): void {
85
this._unregister();
86
super.dispose();
87
}
88
}
89
90
registerEditorCommand(new class extends EditorCommand {
91
92
constructor() {
93
super({
94
id: 'editor.cancelOperation',
95
kbOpts: {
96
weight: KeybindingWeight.EditorContrib,
97
primary: KeyCode.Escape
98
},
99
precondition: ctxCancellableOperation
100
});
101
}
102
103
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void {
104
accessor.get(IEditorCancellationTokens).cancel(editor);
105
}
106
});
107
108