e725f672310fc59d3cd47383f663e80ad23bfee5dab67bbf5782c5dcd5af568067671574420c86409918af3332f30dfcc5939d7cc9dae2a37634be3e58a803 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. import { EditorCommand, registerEditorCommand } from '../../../browser/editorExtensions.js';
  6. import { IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
  7. import { CancellationTokenSource } from '../../../../base/common/cancellation.js';
  8. import { LinkedList } from '../../../../base/common/linkedList.js';
  9. import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
  10. import { registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
  11. import { localize } from '../../../../nls.js';
  12. const IEditorCancellationTokens = createDecorator('IEditorCancelService');
  13. const ctxCancellableOperation = new RawContextKey('cancellableOperation', false, localize('cancellableOperation', 'Whether the editor runs a cancellable operation, e.g. like \'Peek References\''));
  14. registerSingleton(IEditorCancellationTokens, class {
  15. constructor() {
  16. this._tokens = new WeakMap();
  17. }
  18. add(editor, cts) {
  19. let data = this._tokens.get(editor);
  20. if (!data) {
  21. data = editor.invokeWithinContext(accessor => {
  22. const key = ctxCancellableOperation.bindTo(accessor.get(IContextKeyService));
  23. const tokens = new LinkedList();
  24. return { key, tokens };
  25. });
  26. this._tokens.set(editor, data);
  27. }
  28. let removeFn;
  29. data.key.set(true);
  30. removeFn = data.tokens.push(cts);
  31. return () => {
  32. // remove w/o cancellation
  33. if (removeFn) {
  34. removeFn();
  35. data.key.set(!data.tokens.isEmpty());
  36. removeFn = undefined;
  37. }
  38. };
  39. }
  40. cancel(editor) {
  41. const data = this._tokens.get(editor);
  42. if (!data) {
  43. return;
  44. }
  45. // remove with cancellation
  46. const cts = data.tokens.pop();
  47. if (cts) {
  48. cts.cancel();
  49. data.key.set(!data.tokens.isEmpty());
  50. }
  51. }
  52. }, true);
  53. export class EditorKeybindingCancellationTokenSource extends CancellationTokenSource {
  54. constructor(editor, parent) {
  55. super(parent);
  56. this.editor = editor;
  57. this._unregister = editor.invokeWithinContext(accessor => accessor.get(IEditorCancellationTokens).add(editor, this));
  58. }
  59. dispose() {
  60. this._unregister();
  61. super.dispose();
  62. }
  63. }
  64. registerEditorCommand(new class extends EditorCommand {
  65. constructor() {
  66. super({
  67. id: 'editor.cancelOperation',
  68. kbOpts: {
  69. weight: 100 /* KeybindingWeight.EditorContrib */,
  70. primary: 9 /* KeyCode.Escape */
  71. },
  72. precondition: ctxCancellableOperation
  73. });
  74. }
  75. runEditorCommand(accessor, editor) {
  76. accessor.get(IEditorCancellationTokens).cancel(editor);
  77. }
  78. });