awa
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { addDisposableListener } from '../../../base/browser/dom.js';
|
||||
import { mainWindow } from '../../../base/browser/window.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../common/accessibility.js';
|
||||
import { IConfigurationService } from '../../configuration/common/configuration.js';
|
||||
import { IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { ILayoutService } from '../../layout/browser/layoutService.js';
|
||||
let AccessibilityService = class AccessibilityService extends Disposable {
|
||||
constructor(_contextKeyService, _layoutService, _configurationService) {
|
||||
super();
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this._layoutService = _layoutService;
|
||||
this._configurationService = _configurationService;
|
||||
this._accessibilitySupport = 0 /* AccessibilitySupport.Unknown */;
|
||||
this._onDidChangeScreenReaderOptimized = new Emitter();
|
||||
this._onDidChangeReducedMotion = new Emitter();
|
||||
this._onDidChangeLinkUnderline = new Emitter();
|
||||
this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);
|
||||
const updateContextKey = () => this._accessibilityModeEnabledContext.set(this.isScreenReaderOptimized());
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.accessibilitySupport')) {
|
||||
updateContextKey();
|
||||
this._onDidChangeScreenReaderOptimized.fire();
|
||||
}
|
||||
if (e.affectsConfiguration('workbench.reduceMotion')) {
|
||||
this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');
|
||||
this._onDidChangeReducedMotion.fire();
|
||||
}
|
||||
}));
|
||||
updateContextKey();
|
||||
this._register(this.onDidChangeScreenReaderOptimized(() => updateContextKey()));
|
||||
const reduceMotionMatcher = mainWindow.matchMedia(`(prefers-reduced-motion: reduce)`);
|
||||
this._systemMotionReduced = reduceMotionMatcher.matches;
|
||||
this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');
|
||||
this._linkUnderlinesEnabled = this._configurationService.getValue('accessibility.underlineLinks');
|
||||
this.initReducedMotionListeners(reduceMotionMatcher);
|
||||
this.initLinkUnderlineListeners();
|
||||
}
|
||||
initReducedMotionListeners(reduceMotionMatcher) {
|
||||
this._register(addDisposableListener(reduceMotionMatcher, 'change', () => {
|
||||
this._systemMotionReduced = reduceMotionMatcher.matches;
|
||||
if (this._configMotionReduced === 'auto') {
|
||||
this._onDidChangeReducedMotion.fire();
|
||||
}
|
||||
}));
|
||||
const updateRootClasses = () => {
|
||||
const reduce = this.isMotionReduced();
|
||||
this._layoutService.mainContainer.classList.toggle('reduce-motion', reduce);
|
||||
this._layoutService.mainContainer.classList.toggle('enable-motion', !reduce);
|
||||
};
|
||||
updateRootClasses();
|
||||
this._register(this.onDidChangeReducedMotion(() => updateRootClasses()));
|
||||
}
|
||||
initLinkUnderlineListeners() {
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('accessibility.underlineLinks')) {
|
||||
const linkUnderlinesEnabled = this._configurationService.getValue('accessibility.underlineLinks');
|
||||
this._linkUnderlinesEnabled = linkUnderlinesEnabled;
|
||||
this._onDidChangeLinkUnderline.fire();
|
||||
}
|
||||
}));
|
||||
const updateLinkUnderlineClasses = () => {
|
||||
const underlineLinks = this._linkUnderlinesEnabled;
|
||||
this._layoutService.mainContainer.classList.toggle('underline-links', underlineLinks);
|
||||
};
|
||||
updateLinkUnderlineClasses();
|
||||
this._register(this.onDidChangeLinkUnderlines(() => updateLinkUnderlineClasses()));
|
||||
}
|
||||
onDidChangeLinkUnderlines(listener) {
|
||||
return this._onDidChangeLinkUnderline.event(listener);
|
||||
}
|
||||
get onDidChangeScreenReaderOptimized() {
|
||||
return this._onDidChangeScreenReaderOptimized.event;
|
||||
}
|
||||
isScreenReaderOptimized() {
|
||||
const config = this._configurationService.getValue('editor.accessibilitySupport');
|
||||
return config === 'on' || (config === 'auto' && this._accessibilitySupport === 2 /* AccessibilitySupport.Enabled */);
|
||||
}
|
||||
get onDidChangeReducedMotion() {
|
||||
return this._onDidChangeReducedMotion.event;
|
||||
}
|
||||
isMotionReduced() {
|
||||
const config = this._configMotionReduced;
|
||||
return config === 'on' || (config === 'auto' && this._systemMotionReduced);
|
||||
}
|
||||
getAccessibilitySupport() {
|
||||
return this._accessibilitySupport;
|
||||
}
|
||||
};
|
||||
AccessibilityService = __decorate([
|
||||
__param(0, IContextKeyService),
|
||||
__param(1, ILayoutService),
|
||||
__param(2, IConfigurationService)
|
||||
], AccessibilityService);
|
||||
export { AccessibilityService };
|
||||
//# sourceMappingURL=accessibilityService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export const AccessibleViewRegistry = new class AccessibleViewRegistry {
|
||||
constructor() {
|
||||
this._implementations = [];
|
||||
}
|
||||
register(implementation) {
|
||||
this._implementations.push(implementation);
|
||||
return {
|
||||
dispose: () => {
|
||||
const idx = this._implementations.indexOf(implementation);
|
||||
if (idx !== -1) {
|
||||
this._implementations.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
getImplementations() {
|
||||
return this._implementations;
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=accessibleViewRegistry.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/accessibility/browser/accessibleViewRegistry.ts","vs/platform/accessibility/browser/accessibleViewRegistry.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAOhG,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,MAAM,sBAAsB;IAA5B;QACzC,qBAAgB,GAAoC,EAAE,CAAC;IAiBxD,CAAC;IAfA,QAAQ,CAAC,cAA6C;QACrD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3C,OAAO;YACN,OAAO,EAAE,GAAG,EAAE;gBACb,MAAM,GAAG,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;gBAC1D,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;oBAChB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBACtC,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC;IAED,kBAAkB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC9B,CAAC;CACD,CAAC","file":"accessibleViewRegistry.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from '../../../base/common/lifecycle.js';\n\nexport interface IAccessibleViewImplementation {\n}\n\nexport const AccessibleViewRegistry = new class AccessibleViewRegistry {\n\t_implementations: IAccessibleViewImplementation[] = [];\n\n\tregister(implementation: IAccessibleViewImplementation): IDisposable {\n\t\tthis._implementations.push(implementation);\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tconst idx = this._implementations.indexOf(implementation);\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\tthis._implementations.splice(idx, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tgetImplementations(): IAccessibleViewImplementation[] {\n\t\treturn this._implementations;\n\t}\n};\n\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from '../../../base/common/lifecycle.js';\n\nexport interface IAccessibleViewImplementation {\n}\n\nexport const AccessibleViewRegistry = new class AccessibleViewRegistry {\n\t_implementations: IAccessibleViewImplementation[] = [];\n\n\tregister(implementation: IAccessibleViewImplementation): IDisposable {\n\t\tthis._implementations.push(implementation);\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tconst idx = this._implementations.indexOf(implementation);\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\tthis._implementations.splice(idx, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tgetImplementations(): IAccessibleViewImplementation[] {\n\t\treturn this._implementations;\n\t}\n};\n\n"]}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { RawContextKey } from '../../contextkey/common/contextkey.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IAccessibilityService = createDecorator('accessibilityService');
|
||||
export const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey('accessibilityModeEnabled', false);
|
||||
//# sourceMappingURL=accessibility.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/accessibility/common/accessibility.ts","vs/platform/accessibility/common/accessibility.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAE9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAwB,sBAAsB,CAAC,CAAC;AAsBpG,MAAM,CAAC,MAAM,kCAAkC,GAAG,IAAI,aAAa,CAAU,0BAA0B,EAAE,KAAK,CAAC,CAAC","file":"accessibility.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from '../../../base/common/event.js';\nimport { RawContextKey } from '../../contextkey/common/contextkey.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IAccessibilityService = createDecorator<IAccessibilityService>('accessibilityService');\n\nexport interface IAccessibilityService {\n\treadonly _serviceBrand: undefined;\n\n\treadonly onDidChangeScreenReaderOptimized: Event<void>;\n\tisScreenReaderOptimized(): boolean;\n\tisMotionReduced(): boolean;\n\tgetAccessibilitySupport(): AccessibilitySupport;\n}\n\nexport const enum AccessibilitySupport {\n\t/**\n\t * This should be the browser case where it is not known if a screen reader is attached or no.\n\t */\n\tUnknown = 0,\n\n\tDisabled = 1,\n\n\tEnabled = 2\n}\n\nexport const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey<boolean>('accessibilityModeEnabled', false);\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Event } from '../../../base/common/event.js';\nimport { RawContextKey } from '../../contextkey/common/contextkey.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IAccessibilityService = createDecorator<IAccessibilityService>('accessibilityService');\n\nexport interface IAccessibilityService {\n\treadonly _serviceBrand: undefined;\n\n\treadonly onDidChangeScreenReaderOptimized: Event<void>;\n\tisScreenReaderOptimized(): boolean;\n\tisMotionReduced(): boolean;\n\tgetAccessibilitySupport(): AccessibilitySupport;\n}\n\nexport const enum AccessibilitySupport {\n\t/**\n\t * This should be the browser case where it is not known if a screen reader is attached or no.\n\t */\n\tUnknown = 0,\n\n\tDisabled = 1,\n\n\tEnabled = 2\n}\n\nexport const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey<boolean>('accessibilityModeEnabled', false);\n"]}
|
||||
@@ -0,0 +1,331 @@
|
||||
import { localize } from '../../../nls.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IAccessibilitySignalService = createDecorator('accessibilitySignalService');
|
||||
/** Make sure you understand the doc comments of the method you want to call when using this token! */
|
||||
export const AcknowledgeDocCommentsToken = Symbol('AcknowledgeDocCommentsToken');
|
||||
/**
|
||||
* Corresponds to the audio files in ./media.
|
||||
*/
|
||||
export class Sound {
|
||||
static register(options) {
|
||||
const sound = new Sound(options.fileName);
|
||||
return sound;
|
||||
}
|
||||
static { this.error = Sound.register({ fileName: 'error.mp3' }); }
|
||||
static { this.warning = Sound.register({ fileName: 'warning.mp3' }); }
|
||||
static { this.success = Sound.register({ fileName: 'success.mp3' }); }
|
||||
static { this.foldedArea = Sound.register({ fileName: 'foldedAreas.mp3' }); }
|
||||
static { this.break = Sound.register({ fileName: 'break.mp3' }); }
|
||||
static { this.quickFixes = Sound.register({ fileName: 'quickFixes.mp3' }); }
|
||||
static { this.taskCompleted = Sound.register({ fileName: 'taskCompleted.mp3' }); }
|
||||
static { this.taskFailed = Sound.register({ fileName: 'taskFailed.mp3' }); }
|
||||
static { this.terminalBell = Sound.register({ fileName: 'terminalBell.mp3' }); }
|
||||
static { this.diffLineInserted = Sound.register({ fileName: 'diffLineInserted.mp3' }); }
|
||||
static { this.diffLineDeleted = Sound.register({ fileName: 'diffLineDeleted.mp3' }); }
|
||||
static { this.diffLineModified = Sound.register({ fileName: 'diffLineModified.mp3' }); }
|
||||
static { this.requestSent = Sound.register({ fileName: 'requestSent.mp3' }); }
|
||||
static { this.responseReceived1 = Sound.register({ fileName: 'responseReceived1.mp3' }); }
|
||||
static { this.responseReceived2 = Sound.register({ fileName: 'responseReceived2.mp3' }); }
|
||||
static { this.responseReceived3 = Sound.register({ fileName: 'responseReceived3.mp3' }); }
|
||||
static { this.responseReceived4 = Sound.register({ fileName: 'responseReceived4.mp3' }); }
|
||||
static { this.clear = Sound.register({ fileName: 'clear.mp3' }); }
|
||||
static { this.save = Sound.register({ fileName: 'save.mp3' }); }
|
||||
static { this.format = Sound.register({ fileName: 'format.mp3' }); }
|
||||
static { this.voiceRecordingStarted = Sound.register({ fileName: 'voiceRecordingStarted.mp3' }); }
|
||||
static { this.voiceRecordingStopped = Sound.register({ fileName: 'voiceRecordingStopped.mp3' }); }
|
||||
static { this.progress = Sound.register({ fileName: 'progress.mp3' }); }
|
||||
static { this.chatEditModifiedFile = Sound.register({ fileName: 'chatEditModifiedFile.mp3' }); }
|
||||
static { this.editsKept = Sound.register({ fileName: 'editsKept.mp3' }); }
|
||||
static { this.editsUndone = Sound.register({ fileName: 'editsUndone.mp3' }); }
|
||||
static { this.nextEditSuggestion = Sound.register({ fileName: 'nextEditSuggestion.mp3' }); }
|
||||
static { this.terminalCommandSucceeded = Sound.register({ fileName: 'terminalCommandSucceeded.mp3' }); }
|
||||
static { this.chatUserActionRequired = Sound.register({ fileName: 'chatUserActionRequired.mp3' }); }
|
||||
static { this.codeActionTriggered = Sound.register({ fileName: 'codeActionTriggered.mp3' }); }
|
||||
static { this.codeActionApplied = Sound.register({ fileName: 'codeActionApplied.mp3' }); }
|
||||
constructor(fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
}
|
||||
export class SoundSource {
|
||||
constructor(randomOneOf) {
|
||||
this.randomOneOf = randomOneOf;
|
||||
}
|
||||
}
|
||||
export class AccessibilitySignal {
|
||||
constructor(sound, name, legacySoundSettingsKey, settingsKey, legacyAnnouncementSettingsKey, announcementMessage, managesOwnEnablement = false) {
|
||||
this.sound = sound;
|
||||
this.name = name;
|
||||
this.legacySoundSettingsKey = legacySoundSettingsKey;
|
||||
this.settingsKey = settingsKey;
|
||||
this.legacyAnnouncementSettingsKey = legacyAnnouncementSettingsKey;
|
||||
this.announcementMessage = announcementMessage;
|
||||
this.managesOwnEnablement = managesOwnEnablement;
|
||||
}
|
||||
static { this._signals = new Set(); }
|
||||
static register(options) {
|
||||
const soundSource = new SoundSource('randomOneOf' in options.sound ? options.sound.randomOneOf : [options.sound]);
|
||||
const signal = new AccessibilitySignal(soundSource, options.name, options.legacySoundSettingsKey, options.settingsKey, options.legacyAnnouncementSettingsKey, options.announcementMessage, options.managesOwnEnablement);
|
||||
AccessibilitySignal._signals.add(signal);
|
||||
return signal;
|
||||
}
|
||||
static { this.errorAtPosition = AccessibilitySignal.register({
|
||||
name: localize(1561, 'Error at Position'),
|
||||
sound: Sound.error,
|
||||
announcementMessage: localize(1562, 'Error'),
|
||||
settingsKey: 'accessibility.signals.positionHasError',
|
||||
delaySettingsKey: 'accessibility.signalOptions.delays.errorAtPosition'
|
||||
}); }
|
||||
static { this.warningAtPosition = AccessibilitySignal.register({
|
||||
name: localize(1563, 'Warning at Position'),
|
||||
sound: Sound.warning,
|
||||
announcementMessage: localize(1564, 'Warning'),
|
||||
settingsKey: 'accessibility.signals.positionHasWarning',
|
||||
delaySettingsKey: 'accessibility.signalOptions.delays.warningAtPosition'
|
||||
}); }
|
||||
static { this.errorOnLine = AccessibilitySignal.register({
|
||||
name: localize(1565, 'Error on Line'),
|
||||
sound: Sound.error,
|
||||
legacySoundSettingsKey: 'audioCues.lineHasError',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.error',
|
||||
announcementMessage: localize(1566, 'Error on Line'),
|
||||
settingsKey: 'accessibility.signals.lineHasError',
|
||||
}); }
|
||||
static { this.warningOnLine = AccessibilitySignal.register({
|
||||
name: localize(1567, 'Warning on Line'),
|
||||
sound: Sound.warning,
|
||||
legacySoundSettingsKey: 'audioCues.lineHasWarning',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.warning',
|
||||
announcementMessage: localize(1568, 'Warning on Line'),
|
||||
settingsKey: 'accessibility.signals.lineHasWarning',
|
||||
}); }
|
||||
static { this.foldedArea = AccessibilitySignal.register({
|
||||
name: localize(1569, 'Folded Area on Line'),
|
||||
sound: Sound.foldedArea,
|
||||
legacySoundSettingsKey: 'audioCues.lineHasFoldedArea',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.foldedArea',
|
||||
announcementMessage: localize(1570, 'Folded'),
|
||||
settingsKey: 'accessibility.signals.lineHasFoldedArea',
|
||||
}); }
|
||||
static { this.break = AccessibilitySignal.register({
|
||||
name: localize(1571, 'Breakpoint on Line'),
|
||||
sound: Sound.break,
|
||||
legacySoundSettingsKey: 'audioCues.lineHasBreakpoint',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.breakpoint',
|
||||
announcementMessage: localize(1572, 'Breakpoint'),
|
||||
settingsKey: 'accessibility.signals.lineHasBreakpoint',
|
||||
}); }
|
||||
static { this.inlineSuggestion = AccessibilitySignal.register({
|
||||
name: localize(1573, 'Inline Suggestion on Line'),
|
||||
sound: Sound.quickFixes,
|
||||
legacySoundSettingsKey: 'audioCues.lineHasInlineSuggestion',
|
||||
settingsKey: 'accessibility.signals.lineHasInlineSuggestion',
|
||||
}); }
|
||||
static { this.nextEditSuggestion = AccessibilitySignal.register({
|
||||
name: localize(1574, 'Next Edit Suggestion on Line'),
|
||||
sound: Sound.nextEditSuggestion,
|
||||
legacySoundSettingsKey: 'audioCues.nextEditSuggestion',
|
||||
settingsKey: 'accessibility.signals.nextEditSuggestion',
|
||||
announcementMessage: localize(1575, 'Next Edit Suggestion'),
|
||||
}); }
|
||||
static { this.terminalQuickFix = AccessibilitySignal.register({
|
||||
name: localize(1576, 'Terminal Quick Fix'),
|
||||
sound: Sound.quickFixes,
|
||||
legacySoundSettingsKey: 'audioCues.terminalQuickFix',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.terminalQuickFix',
|
||||
announcementMessage: localize(1577, 'Quick Fix'),
|
||||
settingsKey: 'accessibility.signals.terminalQuickFix',
|
||||
}); }
|
||||
static { this.onDebugBreak = AccessibilitySignal.register({
|
||||
name: localize(1578, 'Debugger Stopped on Breakpoint'),
|
||||
sound: Sound.break,
|
||||
legacySoundSettingsKey: 'audioCues.onDebugBreak',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.onDebugBreak',
|
||||
announcementMessage: localize(1579, 'Breakpoint'),
|
||||
settingsKey: 'accessibility.signals.onDebugBreak',
|
||||
}); }
|
||||
static { this.noInlayHints = AccessibilitySignal.register({
|
||||
name: localize(1580, 'No Inlay Hints on Line'),
|
||||
sound: Sound.error,
|
||||
legacySoundSettingsKey: 'audioCues.noInlayHints',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.noInlayHints',
|
||||
announcementMessage: localize(1581, 'No Inlay Hints'),
|
||||
settingsKey: 'accessibility.signals.noInlayHints',
|
||||
}); }
|
||||
static { this.taskCompleted = AccessibilitySignal.register({
|
||||
name: localize(1582, 'Task Completed'),
|
||||
sound: Sound.taskCompleted,
|
||||
legacySoundSettingsKey: 'audioCues.taskCompleted',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.taskCompleted',
|
||||
announcementMessage: localize(1583, 'Task Completed'),
|
||||
settingsKey: 'accessibility.signals.taskCompleted',
|
||||
}); }
|
||||
static { this.taskFailed = AccessibilitySignal.register({
|
||||
name: localize(1584, 'Task Failed'),
|
||||
sound: Sound.taskFailed,
|
||||
legacySoundSettingsKey: 'audioCues.taskFailed',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.taskFailed',
|
||||
announcementMessage: localize(1585, 'Task Failed'),
|
||||
settingsKey: 'accessibility.signals.taskFailed',
|
||||
}); }
|
||||
static { this.terminalCommandFailed = AccessibilitySignal.register({
|
||||
name: localize(1586, 'Terminal Command Failed'),
|
||||
sound: Sound.error,
|
||||
legacySoundSettingsKey: 'audioCues.terminalCommandFailed',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.terminalCommandFailed',
|
||||
announcementMessage: localize(1587, 'Command Failed'),
|
||||
settingsKey: 'accessibility.signals.terminalCommandFailed',
|
||||
}); }
|
||||
static { this.terminalCommandSucceeded = AccessibilitySignal.register({
|
||||
name: localize(1588, 'Terminal Command Succeeded'),
|
||||
sound: Sound.terminalCommandSucceeded,
|
||||
announcementMessage: localize(1589, 'Command Succeeded'),
|
||||
settingsKey: 'accessibility.signals.terminalCommandSucceeded',
|
||||
}); }
|
||||
static { this.terminalBell = AccessibilitySignal.register({
|
||||
name: localize(1590, 'Terminal Bell'),
|
||||
sound: Sound.terminalBell,
|
||||
legacySoundSettingsKey: 'audioCues.terminalBell',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.terminalBell',
|
||||
announcementMessage: localize(1591, 'Terminal Bell'),
|
||||
settingsKey: 'accessibility.signals.terminalBell',
|
||||
}); }
|
||||
static { this.notebookCellCompleted = AccessibilitySignal.register({
|
||||
name: localize(1592, 'Notebook Cell Completed'),
|
||||
sound: Sound.taskCompleted,
|
||||
legacySoundSettingsKey: 'audioCues.notebookCellCompleted',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.notebookCellCompleted',
|
||||
announcementMessage: localize(1593, 'Notebook Cell Completed'),
|
||||
settingsKey: 'accessibility.signals.notebookCellCompleted',
|
||||
}); }
|
||||
static { this.notebookCellFailed = AccessibilitySignal.register({
|
||||
name: localize(1594, 'Notebook Cell Failed'),
|
||||
sound: Sound.taskFailed,
|
||||
legacySoundSettingsKey: 'audioCues.notebookCellFailed',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.notebookCellFailed',
|
||||
announcementMessage: localize(1595, 'Notebook Cell Failed'),
|
||||
settingsKey: 'accessibility.signals.notebookCellFailed',
|
||||
}); }
|
||||
static { this.diffLineInserted = AccessibilitySignal.register({
|
||||
name: localize(1596, 'Diff Line Inserted'),
|
||||
sound: Sound.diffLineInserted,
|
||||
legacySoundSettingsKey: 'audioCues.diffLineInserted',
|
||||
settingsKey: 'accessibility.signals.diffLineInserted',
|
||||
}); }
|
||||
static { this.diffLineDeleted = AccessibilitySignal.register({
|
||||
name: localize(1597, 'Diff Line Deleted'),
|
||||
sound: Sound.diffLineDeleted,
|
||||
legacySoundSettingsKey: 'audioCues.diffLineDeleted',
|
||||
settingsKey: 'accessibility.signals.diffLineDeleted',
|
||||
}); }
|
||||
static { this.diffLineModified = AccessibilitySignal.register({
|
||||
name: localize(1598, 'Diff Line Modified'),
|
||||
sound: Sound.diffLineModified,
|
||||
legacySoundSettingsKey: 'audioCues.diffLineModified',
|
||||
settingsKey: 'accessibility.signals.diffLineModified',
|
||||
}); }
|
||||
static { this.chatEditModifiedFile = AccessibilitySignal.register({
|
||||
name: localize(1599, 'Chat Edit Modified File'),
|
||||
sound: Sound.chatEditModifiedFile,
|
||||
announcementMessage: localize(1600, 'File Modified from Chat Edits'),
|
||||
settingsKey: 'accessibility.signals.chatEditModifiedFile',
|
||||
}); }
|
||||
static { this.chatRequestSent = AccessibilitySignal.register({
|
||||
name: localize(1601, 'Chat Request Sent'),
|
||||
sound: Sound.requestSent,
|
||||
legacySoundSettingsKey: 'audioCues.chatRequestSent',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.chatRequestSent',
|
||||
announcementMessage: localize(1602, 'Chat Request Sent'),
|
||||
settingsKey: 'accessibility.signals.chatRequestSent',
|
||||
}); }
|
||||
static { this.chatResponseReceived = AccessibilitySignal.register({
|
||||
name: localize(1603, 'Chat Response Received'),
|
||||
legacySoundSettingsKey: 'audioCues.chatResponseReceived',
|
||||
sound: {
|
||||
randomOneOf: [
|
||||
Sound.responseReceived1,
|
||||
Sound.responseReceived2,
|
||||
Sound.responseReceived3,
|
||||
Sound.responseReceived4
|
||||
]
|
||||
},
|
||||
settingsKey: 'accessibility.signals.chatResponseReceived'
|
||||
}); }
|
||||
static { this.codeActionTriggered = AccessibilitySignal.register({
|
||||
name: localize(1604, 'Code Action Request Triggered'),
|
||||
sound: Sound.codeActionTriggered,
|
||||
legacySoundSettingsKey: 'audioCues.codeActionRequestTriggered',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.codeActionRequestTriggered',
|
||||
announcementMessage: localize(1605, 'Code Action Request Triggered'),
|
||||
settingsKey: 'accessibility.signals.codeActionTriggered',
|
||||
}); }
|
||||
static { this.codeActionApplied = AccessibilitySignal.register({
|
||||
name: localize(1606, 'Code Action Applied'),
|
||||
legacySoundSettingsKey: 'audioCues.codeActionApplied',
|
||||
sound: Sound.codeActionApplied,
|
||||
settingsKey: 'accessibility.signals.codeActionApplied'
|
||||
}); }
|
||||
static { this.progress = AccessibilitySignal.register({
|
||||
name: localize(1607, 'Progress'),
|
||||
sound: Sound.progress,
|
||||
legacySoundSettingsKey: 'audioCues.chatResponsePending',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.progress',
|
||||
announcementMessage: localize(1608, 'Progress'),
|
||||
settingsKey: 'accessibility.signals.progress'
|
||||
}); }
|
||||
static { this.clear = AccessibilitySignal.register({
|
||||
name: localize(1609, 'Clear'),
|
||||
sound: Sound.clear,
|
||||
legacySoundSettingsKey: 'audioCues.clear',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.clear',
|
||||
announcementMessage: localize(1610, 'Clear'),
|
||||
settingsKey: 'accessibility.signals.clear'
|
||||
}); }
|
||||
static { this.save = AccessibilitySignal.register({
|
||||
name: localize(1611, 'Save'),
|
||||
sound: Sound.save,
|
||||
legacySoundSettingsKey: 'audioCues.save',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.save',
|
||||
announcementMessage: localize(1612, 'Save'),
|
||||
settingsKey: 'accessibility.signals.save'
|
||||
}); }
|
||||
static { this.format = AccessibilitySignal.register({
|
||||
name: localize(1613, 'Format'),
|
||||
sound: Sound.format,
|
||||
legacySoundSettingsKey: 'audioCues.format',
|
||||
legacyAnnouncementSettingsKey: 'accessibility.alert.format',
|
||||
announcementMessage: localize(1614, 'Format'),
|
||||
settingsKey: 'accessibility.signals.format'
|
||||
}); }
|
||||
static { this.voiceRecordingStarted = AccessibilitySignal.register({
|
||||
name: localize(1615, 'Voice Recording Started'),
|
||||
sound: Sound.voiceRecordingStarted,
|
||||
legacySoundSettingsKey: 'audioCues.voiceRecordingStarted',
|
||||
settingsKey: 'accessibility.signals.voiceRecordingStarted'
|
||||
}); }
|
||||
static { this.voiceRecordingStopped = AccessibilitySignal.register({
|
||||
name: localize(1616, 'Voice Recording Stopped'),
|
||||
sound: Sound.voiceRecordingStopped,
|
||||
legacySoundSettingsKey: 'audioCues.voiceRecordingStopped',
|
||||
settingsKey: 'accessibility.signals.voiceRecordingStopped'
|
||||
}); }
|
||||
static { this.editsKept = AccessibilitySignal.register({
|
||||
name: localize(1617, 'Edits Kept'),
|
||||
sound: Sound.editsKept,
|
||||
announcementMessage: localize(1618, 'Edits Kept'),
|
||||
settingsKey: 'accessibility.signals.editsKept',
|
||||
}); }
|
||||
static { this.editsUndone = AccessibilitySignal.register({
|
||||
name: localize(1619, 'Undo Edits'),
|
||||
sound: Sound.editsUndone,
|
||||
announcementMessage: localize(1620, 'Edits Undone'),
|
||||
settingsKey: 'accessibility.signals.editsUndone',
|
||||
}); }
|
||||
static { this.chatUserActionRequired = AccessibilitySignal.register({
|
||||
name: localize(1621, 'Chat User Action Required'),
|
||||
sound: Sound.chatUserActionRequired,
|
||||
announcementMessage: localize(1622, 'Chat User Action Required'),
|
||||
settingsKey: 'accessibility.signals.chatUserActionRequired',
|
||||
managesOwnEnablement: true
|
||||
}); }
|
||||
}
|
||||
//# sourceMappingURL=accessibilitySignalService.js.map
|
||||
File diff suppressed because one or more lines are too long
14
_internal/editor/esm/vs/platform/action/common/action.js
Normal file
14
_internal/editor/esm/vs/platform/action/common/action.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export function isLocalizedString(thing) {
|
||||
return thing
|
||||
&& typeof thing === 'object'
|
||||
&& typeof thing.original === 'string'
|
||||
&& typeof thing.value === 'string';
|
||||
}
|
||||
export function isICommandActionToggleInfo(thing) {
|
||||
return thing ? thing.condition !== undefined : false;
|
||||
}
|
||||
//# sourceMappingURL=action.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { localize2 } from '../../../nls.js';
|
||||
export const Categories = Object.freeze({
|
||||
View: localize2(1623, 'View'),
|
||||
Help: localize2(1624, 'Help'),
|
||||
Test: localize2(1625, 'Test'),
|
||||
File: localize2(1626, 'File'),
|
||||
Preferences: localize2(1627, 'Preferences'),
|
||||
Developer: localize2(1628, "Developer"),
|
||||
});
|
||||
//# sourceMappingURL=actionCommonCategories.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["vs/platform/action/common/actionCommonCategories.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,SAAS,CAAC,IAAM,EAAE,MAAM,CAAC;IAC/B,IAAI,EAAE,SAAS,CAAC,IAAM,EAAE,MAAM,CAAC;IAC/B,IAAI,EAAE,SAAS,CAAC,IAAM,EAAE,MAAM,CAAC;IAC/B,IAAI,EAAE,SAAS,CAAC,IAAM,EAAE,MAAM,CAAC;IAC/B,WAAW,EAAE,SAAS,CAAC,IAAa,EAAE,aAAa,CAAC;IACpD,SAAS,EAAE,SAAS,CAAC,EAAE,EAAgG,CAA7F,CAA+F,CAA7F,UAAwG,CAA7F,AAA8F,EAA5F,OAAO,EAAE,CAAC,iEAAiE,CAAC;CACrH,CAAC,CAAC","file":"actionCommonCategories.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { localize2 } from '../../../nls.js';\n\nexport const Categories = Object.freeze({\n\tView: localize2('view', 'View'),\n\tHelp: localize2('help', 'Help'),\n\tTest: localize2('test', 'Test'),\n\tFile: localize2('file', 'File'),\n\tPreferences: localize2('preferences', 'Preferences'),\n\tDeveloper: localize2({ key: 'developer', comment: ['A developer on Code itself or someone diagnosing issues in Code'] }, \"Developer\"),\n});\n"]}
|
||||
@@ -0,0 +1,336 @@
|
||||
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); }
|
||||
};
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as dom from '../../../base/browser/dom.js';
|
||||
import { KeybindingLabel } from '../../../base/browser/ui/keybindingLabel/keybindingLabel.js';
|
||||
import { List } from '../../../base/browser/ui/list/listWidget.js';
|
||||
import { CancellationTokenSource } from '../../../base/common/cancellation.js';
|
||||
import { Codicon } from '../../../base/common/codicons.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { OS } from '../../../base/common/platform.js';
|
||||
import { ThemeIcon } from '../../../base/common/themables.js';
|
||||
import './actionWidget.css';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IContextViewService } from '../../contextview/browser/contextView.js';
|
||||
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
|
||||
import { defaultListStyles } from '../../theme/browser/defaultStyles.js';
|
||||
import { asCssVariable } from '../../theme/common/colorRegistry.js';
|
||||
import { ILayoutService } from '../../layout/browser/layoutService.js';
|
||||
export const acceptSelectedActionCommand = 'acceptSelectedCodeAction';
|
||||
export const previewSelectedActionCommand = 'previewSelectedCodeAction';
|
||||
class HeaderRenderer {
|
||||
get templateId() { return "header" /* ActionListItemKind.Header */; }
|
||||
renderTemplate(container) {
|
||||
container.classList.add('group-header');
|
||||
const text = document.createElement('span');
|
||||
container.append(text);
|
||||
return { container, text };
|
||||
}
|
||||
renderElement(element, _index, templateData) {
|
||||
templateData.text.textContent = element.group?.title ?? element.label ?? '';
|
||||
}
|
||||
disposeTemplate(_templateData) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
class SeparatorRenderer {
|
||||
get templateId() { return "separator" /* ActionListItemKind.Separator */; }
|
||||
renderTemplate(container) {
|
||||
container.classList.add('separator');
|
||||
const text = document.createElement('span');
|
||||
container.append(text);
|
||||
return { container, text };
|
||||
}
|
||||
renderElement(element, _index, templateData) {
|
||||
templateData.text.textContent = element.label ?? '';
|
||||
}
|
||||
disposeTemplate(_templateData) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
let ActionItemRenderer = class ActionItemRenderer {
|
||||
get templateId() { return "action" /* ActionListItemKind.Action */; }
|
||||
constructor(_supportsPreview, _keybindingService) {
|
||||
this._supportsPreview = _supportsPreview;
|
||||
this._keybindingService = _keybindingService;
|
||||
}
|
||||
renderTemplate(container) {
|
||||
container.classList.add(this.templateId);
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'icon';
|
||||
container.append(icon);
|
||||
const text = document.createElement('span');
|
||||
text.className = 'title';
|
||||
container.append(text);
|
||||
const description = document.createElement('span');
|
||||
description.className = 'description';
|
||||
container.append(description);
|
||||
const keybinding = new KeybindingLabel(container, OS);
|
||||
return { container, icon, text, description, keybinding };
|
||||
}
|
||||
renderElement(element, _index, data) {
|
||||
if (element.group?.icon) {
|
||||
data.icon.className = ThemeIcon.asClassName(element.group.icon);
|
||||
if (element.group.icon.color) {
|
||||
data.icon.style.color = asCssVariable(element.group.icon.color.id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
data.icon.className = ThemeIcon.asClassName(Codicon.lightBulb);
|
||||
data.icon.style.color = 'var(--vscode-editorLightBulb-foreground)';
|
||||
}
|
||||
if (!element.item || !element.label) {
|
||||
return;
|
||||
}
|
||||
dom.setVisibility(!element.hideIcon, data.icon);
|
||||
data.text.textContent = stripNewlines(element.label);
|
||||
// if there is a keybinding, prioritize over description for now
|
||||
if (element.keybinding) {
|
||||
data.description.textContent = element.keybinding.getLabel();
|
||||
data.description.style.display = 'inline';
|
||||
data.description.style.letterSpacing = '0.5px';
|
||||
}
|
||||
else if (element.description) {
|
||||
data.description.textContent = stripNewlines(element.description);
|
||||
data.description.style.display = 'inline';
|
||||
}
|
||||
else {
|
||||
data.description.textContent = '';
|
||||
data.description.style.display = 'none';
|
||||
}
|
||||
const actionTitle = this._keybindingService.lookupKeybinding(acceptSelectedActionCommand)?.getLabel();
|
||||
const previewTitle = this._keybindingService.lookupKeybinding(previewSelectedActionCommand)?.getLabel();
|
||||
data.container.classList.toggle('option-disabled', element.disabled);
|
||||
if (element.tooltip) {
|
||||
data.container.title = element.tooltip;
|
||||
}
|
||||
else if (element.disabled) {
|
||||
data.container.title = element.label;
|
||||
}
|
||||
else if (actionTitle && previewTitle) {
|
||||
if (this._supportsPreview && element.canPreview) {
|
||||
data.container.title = localize(1638, "{0} to Apply, {1} to Preview", actionTitle, previewTitle);
|
||||
}
|
||||
else {
|
||||
data.container.title = localize(1639, "{0} to Apply", actionTitle);
|
||||
}
|
||||
}
|
||||
else {
|
||||
data.container.title = '';
|
||||
}
|
||||
}
|
||||
disposeTemplate(templateData) {
|
||||
templateData.keybinding.dispose();
|
||||
}
|
||||
};
|
||||
ActionItemRenderer = __decorate([
|
||||
__param(1, IKeybindingService)
|
||||
], ActionItemRenderer);
|
||||
class AcceptSelectedEvent extends UIEvent {
|
||||
constructor() { super('acceptSelectedAction'); }
|
||||
}
|
||||
class PreviewSelectedEvent extends UIEvent {
|
||||
constructor() { super('previewSelectedAction'); }
|
||||
}
|
||||
function getKeyboardNavigationLabel(item) {
|
||||
// Filter out header vs. action vs. separator
|
||||
if (item.kind === 'action') {
|
||||
return item.label;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
let ActionList = class ActionList extends Disposable {
|
||||
constructor(user, preview, items, _delegate, accessibilityProvider, _contextViewService, _keybindingService, _layoutService) {
|
||||
super();
|
||||
this._delegate = _delegate;
|
||||
this._contextViewService = _contextViewService;
|
||||
this._keybindingService = _keybindingService;
|
||||
this._layoutService = _layoutService;
|
||||
this._actionLineHeight = 28;
|
||||
this._headerLineHeight = 28;
|
||||
this._separatorLineHeight = 8;
|
||||
this.cts = this._register(new CancellationTokenSource());
|
||||
this.domNode = document.createElement('div');
|
||||
this.domNode.classList.add('actionList');
|
||||
const virtualDelegate = {
|
||||
getHeight: element => {
|
||||
switch (element.kind) {
|
||||
case "header" /* ActionListItemKind.Header */:
|
||||
return this._headerLineHeight;
|
||||
case "separator" /* ActionListItemKind.Separator */:
|
||||
return this._separatorLineHeight;
|
||||
default:
|
||||
return this._actionLineHeight;
|
||||
}
|
||||
},
|
||||
getTemplateId: element => element.kind
|
||||
};
|
||||
this._list = this._register(new List(user, this.domNode, virtualDelegate, [
|
||||
new ActionItemRenderer(preview, this._keybindingService),
|
||||
new HeaderRenderer(),
|
||||
new SeparatorRenderer(),
|
||||
], {
|
||||
keyboardSupport: false,
|
||||
typeNavigationEnabled: true,
|
||||
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel },
|
||||
accessibilityProvider: {
|
||||
getAriaLabel: element => {
|
||||
if (element.kind === "action" /* ActionListItemKind.Action */) {
|
||||
let label = element.label ? stripNewlines(element?.label) : '';
|
||||
if (element.description) {
|
||||
label = label + ', ' + stripNewlines(element.description);
|
||||
}
|
||||
if (element.disabled) {
|
||||
label = localize(1640, "{0}, Disabled Reason: {1}", label, element.disabled);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getWidgetAriaLabel: () => localize(1641, "Action Widget"),
|
||||
getRole: (e) => {
|
||||
switch (e.kind) {
|
||||
case "action" /* ActionListItemKind.Action */:
|
||||
return 'option';
|
||||
case "separator" /* ActionListItemKind.Separator */:
|
||||
return 'separator';
|
||||
default:
|
||||
return 'separator';
|
||||
}
|
||||
},
|
||||
getWidgetRole: () => 'listbox',
|
||||
...accessibilityProvider
|
||||
},
|
||||
}));
|
||||
this._list.style(defaultListStyles);
|
||||
this._register(this._list.onMouseClick(e => this.onListClick(e)));
|
||||
this._register(this._list.onMouseOver(e => this.onListHover(e)));
|
||||
this._register(this._list.onDidChangeFocus(() => this.onFocus()));
|
||||
this._register(this._list.onDidChangeSelection(e => this.onListSelection(e)));
|
||||
this._allMenuItems = items;
|
||||
this._list.splice(0, this._list.length, this._allMenuItems);
|
||||
if (this._list.length) {
|
||||
this.focusNext();
|
||||
}
|
||||
}
|
||||
focusCondition(element) {
|
||||
return !element.disabled && element.kind === "action" /* ActionListItemKind.Action */;
|
||||
}
|
||||
hide(didCancel) {
|
||||
this._delegate.onHide(didCancel);
|
||||
this.cts.cancel();
|
||||
this._contextViewService.hideContextView();
|
||||
}
|
||||
layout(minWidth) {
|
||||
// Updating list height, depending on how many separators and headers there are.
|
||||
const numHeaders = this._allMenuItems.filter(item => item.kind === 'header').length;
|
||||
const numSeparators = this._allMenuItems.filter(item => item.kind === 'separator').length;
|
||||
const itemsHeight = this._allMenuItems.length * this._actionLineHeight;
|
||||
const heightWithHeaders = itemsHeight + numHeaders * this._headerLineHeight - numHeaders * this._actionLineHeight;
|
||||
const heightWithSeparators = heightWithHeaders + numSeparators * this._separatorLineHeight - numSeparators * this._actionLineHeight;
|
||||
this._list.layout(heightWithSeparators);
|
||||
let maxWidth = minWidth;
|
||||
if (this._allMenuItems.length >= 50) {
|
||||
maxWidth = 380;
|
||||
}
|
||||
else {
|
||||
// For finding width dynamically (not using resize observer)
|
||||
const itemWidths = this._allMenuItems.map((_, index) => {
|
||||
const element = this.domNode.ownerDocument.getElementById(this._list.getElementID(index));
|
||||
if (element) {
|
||||
element.style.width = 'auto';
|
||||
const width = element.getBoundingClientRect().width;
|
||||
element.style.width = '';
|
||||
return width;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
// resize observer - can be used in the future since list widget supports dynamic height but not width
|
||||
maxWidth = Math.max(...itemWidths, minWidth);
|
||||
}
|
||||
const maxVhPrecentage = 0.7;
|
||||
const height = Math.min(heightWithSeparators, this._layoutService.getContainer(dom.getWindow(this.domNode)).clientHeight * maxVhPrecentage);
|
||||
this._list.layout(height, maxWidth);
|
||||
this.domNode.style.height = `${height}px`;
|
||||
this._list.domFocus();
|
||||
return maxWidth;
|
||||
}
|
||||
focusPrevious() {
|
||||
this._list.focusPrevious(1, true, undefined, this.focusCondition);
|
||||
}
|
||||
focusNext() {
|
||||
this._list.focusNext(1, true, undefined, this.focusCondition);
|
||||
}
|
||||
acceptSelected(preview) {
|
||||
const focused = this._list.getFocus();
|
||||
if (focused.length === 0) {
|
||||
return;
|
||||
}
|
||||
const focusIndex = focused[0];
|
||||
const element = this._list.element(focusIndex);
|
||||
if (!this.focusCondition(element)) {
|
||||
return;
|
||||
}
|
||||
const event = preview ? new PreviewSelectedEvent() : new AcceptSelectedEvent();
|
||||
this._list.setSelection([focusIndex], event);
|
||||
}
|
||||
onListSelection(e) {
|
||||
if (!e.elements.length) {
|
||||
return;
|
||||
}
|
||||
const element = e.elements[0];
|
||||
if (element.item && this.focusCondition(element)) {
|
||||
this._delegate.onSelect(element.item, e.browserEvent instanceof PreviewSelectedEvent);
|
||||
}
|
||||
else {
|
||||
this._list.setSelection([]);
|
||||
}
|
||||
}
|
||||
onFocus() {
|
||||
const focused = this._list.getFocus();
|
||||
if (focused.length === 0) {
|
||||
return;
|
||||
}
|
||||
const focusIndex = focused[0];
|
||||
const element = this._list.element(focusIndex);
|
||||
this._delegate.onFocus?.(element.item);
|
||||
}
|
||||
async onListHover(e) {
|
||||
const element = e.element;
|
||||
if (element && element.item && this.focusCondition(element)) {
|
||||
if (this._delegate.onHover && !element.disabled && element.kind === "action" /* ActionListItemKind.Action */) {
|
||||
const result = await this._delegate.onHover(element.item, this.cts.token);
|
||||
element.canPreview = result ? result.canPreview : undefined;
|
||||
}
|
||||
if (e.index) {
|
||||
this._list.splice(e.index, 1, [element]);
|
||||
}
|
||||
}
|
||||
this._list.setFocus(typeof e.index === 'number' ? [e.index] : []);
|
||||
}
|
||||
onListClick(e) {
|
||||
if (e.element && this.focusCondition(e.element)) {
|
||||
this._list.setFocus([]);
|
||||
}
|
||||
}
|
||||
};
|
||||
ActionList = __decorate([
|
||||
__param(5, IContextViewService),
|
||||
__param(6, IKeybindingService),
|
||||
__param(7, ILayoutService)
|
||||
], ActionList);
|
||||
export { ActionList };
|
||||
function stripNewlines(str) {
|
||||
return str.replace(/\r\n|\r|\n/g, ' ');
|
||||
}
|
||||
//# sourceMappingURL=actionList.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,197 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.action-widget {
|
||||
font-size: 13px;
|
||||
border-radius: 0;
|
||||
min-width: 100px;
|
||||
max-width: 80vw;
|
||||
z-index: 40;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: 1px solid var(--vscode-menu-border) !important;
|
||||
border-radius: 5px;
|
||||
background-color: var(--vscode-menu-background);
|
||||
color: var(--vscode-menu-foreground);
|
||||
padding: 4px;
|
||||
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
|
||||
}
|
||||
|
||||
.context-view-block {
|
||||
position: fixed;
|
||||
cursor: initial;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.context-view-pointerBlock {
|
||||
position: fixed;
|
||||
cursor: initial;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
border: none !important;
|
||||
border-width: 0 !important;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list:focus:before {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list .monaco-scrollable-element {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/** Styles for each row in the list element **/
|
||||
.action-widget .monaco-list .monaco-list-row {
|
||||
padding: 0 4px 0 4px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
touch-action: none;
|
||||
width: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list .monaco-list-row.action.focused:not(.option-disabled) {
|
||||
background-color: var(--vscode-list-activeSelectionBackground) !important;
|
||||
color: var(--vscode-list-activeSelectionForeground);
|
||||
outline: 1px solid var(--vscode-menu-selectionBorder, transparent);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.group-header {
|
||||
color: var(--vscode-descriptionForeground) !important;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.group-header:not(:first-of-type) {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.action-widget .monaco-scrollable-element .monaco-list-rows .monaco-list-row.separator {
|
||||
border-top: 1px solid var(--vscode-editorHoverWidget-border);
|
||||
color: var(--vscode-descriptionForeground);
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
margin: 4px 0 0 0;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.action-widget .monaco-scrollable-element .monaco-list-rows .monaco-list-row.separator.focused {
|
||||
outline: 0 solid;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.separator:first-of-type {
|
||||
border-top: none;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list .group-header,
|
||||
.action-widget .monaco-list .option-disabled,
|
||||
.action-widget .monaco-list .option-disabled:before,
|
||||
.action-widget .monaco-list .option-disabled .focused,
|
||||
.action-widget .monaco-list .option-disabled .focused:before {
|
||||
cursor: default !important;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent !important;
|
||||
outline: 0 solid !important;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.action {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.action.option-disabled,
|
||||
.action-widget .monaco-list:focus .monaco-list-row.focused.action.option-disabled,
|
||||
.action-widget .monaco-list-row.action.option-disabled .codicon,
|
||||
.action-widget .monaco-list:not(.drop-target):not(.dragging) .monaco-list-row:hover:not(.selected):not(.focused).option-disabled {
|
||||
color: var(--vscode-disabledForeground);
|
||||
}
|
||||
|
||||
|
||||
.action-widget .monaco-list-row.action:not(.option-disabled) .codicon {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.action .title {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list-row.action .monaco-keybinding > .monaco-keybinding-key {
|
||||
background-color: var(--vscode-keybindingLabel-background);
|
||||
color: var(--vscode-keybindingLabel-foreground);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 3px;
|
||||
border-color: var(--vscode-keybindingLabel-border);
|
||||
border-bottom-color: var(--vscode-keybindingLabel-bottomBorder);
|
||||
box-shadow: inset 0 -1px 0 var(--vscode-widget-shadow);
|
||||
}
|
||||
|
||||
/* Action bar */
|
||||
|
||||
.action-widget .action-widget-action-bar {
|
||||
background-color: var(--vscode-menu-background);
|
||||
border-top: 1px solid var(--vscode-menu-border);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.action-widget .action-widget-action-bar::before {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action-widget .action-widget-action-bar .actions-container {
|
||||
padding: 4px 8px 2px 24px;
|
||||
}
|
||||
|
||||
.action-widget-action-bar .action-label {
|
||||
color: var(--vscode-textLink-activeForeground);
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
padding: 0;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.action-widget-action-bar .action-item {
|
||||
margin-right: 16px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.action-widget-action-bar .action-label:hover {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.monaco-action-bar .actions-container.highlight-toggled .action-label.checked {
|
||||
/* The important gives this rule precedence over the hover rule. */
|
||||
background: var(--vscode-actionBar-toggledBackground) !important;
|
||||
}
|
||||
|
||||
.action-widget .monaco-list .monaco-list-row .description {
|
||||
opacity: 0.7;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
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); }
|
||||
};
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as dom from '../../../base/browser/dom.js';
|
||||
import { ActionBar } from '../../../base/browser/ui/actionbar/actionbar.js';
|
||||
import { Disposable, DisposableStore, MutableDisposable } from '../../../base/common/lifecycle.js';
|
||||
import './actionWidget.css';
|
||||
import { localize, localize2 } from '../../../nls.js';
|
||||
import { acceptSelectedActionCommand, ActionList, previewSelectedActionCommand } from './actionList.js';
|
||||
import { Action2, registerAction2 } from '../../actions/common/actions.js';
|
||||
import { IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';
|
||||
import { IContextViewService } from '../../contextview/browser/contextView.js';
|
||||
import { registerSingleton } from '../../instantiation/common/extensions.js';
|
||||
import { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation.js';
|
||||
import { inputActiveOptionBackground, registerColor } from '../../theme/common/colorRegistry.js';
|
||||
registerColor('actionBar.toggledBackground', inputActiveOptionBackground, localize(1642, 'Background color for toggled action items in action bar.'));
|
||||
const ActionWidgetContextKeys = {
|
||||
Visible: new RawContextKey('codeActionMenuVisible', false, localize(1643, "Whether the action widget list is visible"))
|
||||
};
|
||||
export const IActionWidgetService = createDecorator('actionWidgetService');
|
||||
let ActionWidgetService = class ActionWidgetService extends Disposable {
|
||||
get isVisible() {
|
||||
return ActionWidgetContextKeys.Visible.getValue(this._contextKeyService) || false;
|
||||
}
|
||||
constructor(_contextViewService, _contextKeyService, _instantiationService) {
|
||||
super();
|
||||
this._contextViewService = _contextViewService;
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this._instantiationService = _instantiationService;
|
||||
this._list = this._register(new MutableDisposable());
|
||||
}
|
||||
show(user, supportsPreview, items, delegate, anchor, container, actionBarActions, accessibilityProvider) {
|
||||
const visibleContext = ActionWidgetContextKeys.Visible.bindTo(this._contextKeyService);
|
||||
const list = this._instantiationService.createInstance(ActionList, user, supportsPreview, items, delegate, accessibilityProvider);
|
||||
this._contextViewService.showContextView({
|
||||
getAnchor: () => anchor,
|
||||
render: (container) => {
|
||||
visibleContext.set(true);
|
||||
return this._renderWidget(container, list, actionBarActions ?? []);
|
||||
},
|
||||
onHide: (didCancel) => {
|
||||
visibleContext.reset();
|
||||
this._onWidgetClosed(didCancel);
|
||||
},
|
||||
}, container, false);
|
||||
}
|
||||
acceptSelected(preview) {
|
||||
this._list.value?.acceptSelected(preview);
|
||||
}
|
||||
focusPrevious() {
|
||||
this._list?.value?.focusPrevious();
|
||||
}
|
||||
focusNext() {
|
||||
this._list?.value?.focusNext();
|
||||
}
|
||||
hide(didCancel) {
|
||||
this._list.value?.hide(didCancel);
|
||||
this._list.clear();
|
||||
}
|
||||
_renderWidget(element, list, actionBarActions) {
|
||||
const widget = document.createElement('div');
|
||||
widget.classList.add('action-widget');
|
||||
element.appendChild(widget);
|
||||
this._list.value = list;
|
||||
if (this._list.value) {
|
||||
widget.appendChild(this._list.value.domNode);
|
||||
}
|
||||
else {
|
||||
throw new Error('List has no value');
|
||||
}
|
||||
const renderDisposables = new DisposableStore();
|
||||
// Invisible div to block mouse interaction in the rest of the UI
|
||||
const menuBlock = document.createElement('div');
|
||||
const block = element.appendChild(menuBlock);
|
||||
block.classList.add('context-view-block');
|
||||
renderDisposables.add(dom.addDisposableListener(block, dom.EventType.MOUSE_DOWN, e => e.stopPropagation()));
|
||||
// Invisible div to block mouse interaction with the menu
|
||||
const pointerBlockDiv = document.createElement('div');
|
||||
const pointerBlock = element.appendChild(pointerBlockDiv);
|
||||
pointerBlock.classList.add('context-view-pointerBlock');
|
||||
// Removes block on click INSIDE widget or ANY mouse movement
|
||||
renderDisposables.add(dom.addDisposableListener(pointerBlock, dom.EventType.POINTER_MOVE, () => pointerBlock.remove()));
|
||||
renderDisposables.add(dom.addDisposableListener(pointerBlock, dom.EventType.MOUSE_DOWN, () => pointerBlock.remove()));
|
||||
// Action bar
|
||||
let actionBarWidth = 0;
|
||||
if (actionBarActions.length) {
|
||||
const actionBar = this._createActionBar('.action-widget-action-bar', actionBarActions);
|
||||
if (actionBar) {
|
||||
widget.appendChild(actionBar.getContainer().parentElement);
|
||||
renderDisposables.add(actionBar);
|
||||
actionBarWidth = actionBar.getContainer().offsetWidth;
|
||||
}
|
||||
}
|
||||
const width = this._list.value?.layout(actionBarWidth);
|
||||
widget.style.width = `${width}px`;
|
||||
const focusTracker = renderDisposables.add(dom.trackFocus(element));
|
||||
renderDisposables.add(focusTracker.onDidBlur(() => this.hide(true)));
|
||||
return renderDisposables;
|
||||
}
|
||||
_createActionBar(className, actions) {
|
||||
if (!actions.length) {
|
||||
return undefined;
|
||||
}
|
||||
const container = dom.$(className);
|
||||
const actionBar = new ActionBar(container);
|
||||
actionBar.push(actions, { icon: false, label: true });
|
||||
return actionBar;
|
||||
}
|
||||
_onWidgetClosed(didCancel) {
|
||||
this._list.value?.hide(didCancel);
|
||||
}
|
||||
};
|
||||
ActionWidgetService = __decorate([
|
||||
__param(0, IContextViewService),
|
||||
__param(1, IContextKeyService),
|
||||
__param(2, IInstantiationService)
|
||||
], ActionWidgetService);
|
||||
registerSingleton(IActionWidgetService, ActionWidgetService, 1 /* InstantiationType.Delayed */);
|
||||
const weight = 100 /* KeybindingWeight.EditorContrib */ + 1000;
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'hideCodeActionWidget',
|
||||
title: localize2(1644, "Hide action widget"),
|
||||
precondition: ActionWidgetContextKeys.Visible,
|
||||
keybinding: {
|
||||
weight,
|
||||
primary: 9 /* KeyCode.Escape */,
|
||||
secondary: [1024 /* KeyMod.Shift */ | 9 /* KeyCode.Escape */]
|
||||
},
|
||||
});
|
||||
}
|
||||
run(accessor) {
|
||||
accessor.get(IActionWidgetService).hide(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'selectPrevCodeAction',
|
||||
title: localize2(1645, "Select previous action"),
|
||||
precondition: ActionWidgetContextKeys.Visible,
|
||||
keybinding: {
|
||||
weight,
|
||||
primary: 16 /* KeyCode.UpArrow */,
|
||||
secondary: [2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */],
|
||||
mac: { primary: 16 /* KeyCode.UpArrow */, secondary: [2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */, 256 /* KeyMod.WinCtrl */ | 46 /* KeyCode.KeyP */] },
|
||||
}
|
||||
});
|
||||
}
|
||||
run(accessor) {
|
||||
const widgetService = accessor.get(IActionWidgetService);
|
||||
if (widgetService instanceof ActionWidgetService) {
|
||||
widgetService.focusPrevious();
|
||||
}
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'selectNextCodeAction',
|
||||
title: localize2(1646, "Select next action"),
|
||||
precondition: ActionWidgetContextKeys.Visible,
|
||||
keybinding: {
|
||||
weight,
|
||||
primary: 18 /* KeyCode.DownArrow */,
|
||||
secondary: [2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */],
|
||||
mac: { primary: 18 /* KeyCode.DownArrow */, secondary: [2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */, 256 /* KeyMod.WinCtrl */ | 44 /* KeyCode.KeyN */] }
|
||||
}
|
||||
});
|
||||
}
|
||||
run(accessor) {
|
||||
const widgetService = accessor.get(IActionWidgetService);
|
||||
if (widgetService instanceof ActionWidgetService) {
|
||||
widgetService.focusNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: acceptSelectedActionCommand,
|
||||
title: localize2(1647, "Accept selected action"),
|
||||
precondition: ActionWidgetContextKeys.Visible,
|
||||
keybinding: {
|
||||
weight,
|
||||
primary: 3 /* KeyCode.Enter */,
|
||||
secondary: [2048 /* KeyMod.CtrlCmd */ | 89 /* KeyCode.Period */],
|
||||
}
|
||||
});
|
||||
}
|
||||
run(accessor) {
|
||||
const widgetService = accessor.get(IActionWidgetService);
|
||||
if (widgetService instanceof ActionWidgetService) {
|
||||
widgetService.acceptSelected();
|
||||
}
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: previewSelectedActionCommand,
|
||||
title: localize2(1648, "Preview selected action"),
|
||||
precondition: ActionWidgetContextKeys.Visible,
|
||||
keybinding: {
|
||||
weight,
|
||||
primary: 2048 /* KeyMod.CtrlCmd */ | 3 /* KeyCode.Enter */,
|
||||
}
|
||||
});
|
||||
}
|
||||
run(accessor) {
|
||||
const widgetService = accessor.get(IActionWidgetService);
|
||||
if (widgetService instanceof ActionWidgetService) {
|
||||
widgetService.acceptSelected(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=actionWidget.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export {};
|
||||
//# sourceMappingURL=actionWidget.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/actionWidget/common/actionWidget.ts","vs/platform/actionWidget/common/actionWidget.ts"],"names":[],"mappings":"AAAA;;;gGAGgG","file":"actionWidget.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from '../../../base/common/lifecycle.js';\n\nexport interface ActionSet<T> extends IDisposable {\n\treadonly hasAutoFix: boolean;\n\treadonly hasAIFix: boolean;\n\treadonly allAIFixes: boolean;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IDisposable } from '../../../base/common/lifecycle.js';\n\nexport interface ActionSet<T> extends IDisposable {\n\treadonly hasAutoFix: boolean;\n\treadonly hasAIFix: boolean;\n\treadonly allAIFixes: boolean;\n}\n"]}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { registerSingleton } from '../../instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { MenuId } from '../common/actions.js';
|
||||
export const IActionViewItemService = createDecorator('IActionViewItemService');
|
||||
class ActionViewItemService {
|
||||
constructor() {
|
||||
this._providers = new Map();
|
||||
this._onDidChange = new Emitter();
|
||||
this.onDidChange = this._onDidChange.event;
|
||||
}
|
||||
dispose() {
|
||||
this._onDidChange.dispose();
|
||||
}
|
||||
lookUp(menu, commandOrMenuId) {
|
||||
return this._providers.get(this._makeKey(menu, commandOrMenuId));
|
||||
}
|
||||
_makeKey(menu, commandOrMenuId) {
|
||||
return `${menu.id}/${(commandOrMenuId instanceof MenuId ? commandOrMenuId.id : commandOrMenuId)}`;
|
||||
}
|
||||
}
|
||||
registerSingleton(IActionViewItemService, ActionViewItemService, 1 /* InstantiationType.Delayed */);
|
||||
//# sourceMappingURL=actionViewItemService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,63 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-action-bar .action-item.menu-entry .action-label.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50%;
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item.menu-entry.text-only .action-label {
|
||||
color: var(--vscode-descriptionForeground);
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item.menu-entry.text-only.use-comma:not(:last-of-type) .action-label::after {
|
||||
content: ', ';
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item.menu-entry.text-only + .action-item:not(.text-only) > .monaco-dropdown .action-label {
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default {
|
||||
display: flex !important;
|
||||
flex-direction: row;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default > .action-container > .action-label {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default > .action-container.menu-entry > .action-label.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50%;
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default:hover {
|
||||
background-color: var(--vscode-toolbar-hoverBackground);
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default > .dropdown-action-container > .monaco-dropdown > .dropdown-label .codicon[class*='codicon-'] {
|
||||
font-size: 12px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
line-height: 16px;
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
.monaco-dropdown-with-default > .dropdown-action-container > .monaco-dropdown > .dropdown-label > .action-label {
|
||||
display: block;
|
||||
background-size: 16px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { asCSSUrl } from '../../../base/browser/cssValue.js';
|
||||
import { $, addDisposableListener, append, EventType, ModifierKeyEmitter, prepend } from '../../../base/browser/dom.js';
|
||||
import { StandardKeyboardEvent } from '../../../base/browser/keyboardEvent.js';
|
||||
import { ActionViewItem, BaseActionViewItem, SelectActionViewItem } from '../../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
import { DropdownMenuActionViewItem } from '../../../base/browser/ui/dropdown/dropdownActionViewItem.js';
|
||||
import { ActionRunner, Separator, SubmenuAction } from '../../../base/common/actions.js';
|
||||
import { UILabelProvider } from '../../../base/common/keybindingLabels.js';
|
||||
import { combinedDisposable, DisposableStore, MutableDisposable, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { isLinux, isWindows, OS } from '../../../base/common/platform.js';
|
||||
import { ThemeIcon } from '../../../base/common/themables.js';
|
||||
import { assertType } from '../../../base/common/types.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IAccessibilityService } from '../../accessibility/common/accessibility.js';
|
||||
import { isICommandActionToggleInfo } from '../../action/common/action.js';
|
||||
import { IConfigurationService } from '../../configuration/common/configuration.js';
|
||||
import { IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { IContextMenuService, IContextViewService } from '../../contextview/browser/contextView.js';
|
||||
import { IInstantiationService } from '../../instantiation/common/instantiation.js';
|
||||
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
|
||||
import { INotificationService } from '../../notification/common/notification.js';
|
||||
import { IStorageService } from '../../storage/common/storage.js';
|
||||
import { defaultSelectBoxStyles } from '../../theme/browser/defaultStyles.js';
|
||||
import { asCssVariable, selectBorder } from '../../theme/common/colorRegistry.js';
|
||||
import { isDark } from '../../theme/common/theme.js';
|
||||
import { IThemeService } from '../../theme/common/themeService.js';
|
||||
import { hasNativeContextMenu } from '../../window/common/window.js';
|
||||
import { IMenuService, MenuItemAction, SubmenuItemAction } from '../common/actions.js';
|
||||
import './menuEntryActionViewItem.css';
|
||||
export function getFlatContextMenuActions(groups, primaryGroup) {
|
||||
const target = [];
|
||||
getContextMenuActionsImpl(groups, target, primaryGroup);
|
||||
return target;
|
||||
}
|
||||
function getContextMenuActionsImpl(groups, target, primaryGroup) {
|
||||
const modifierKeyEmitter = ModifierKeyEmitter.getInstance();
|
||||
const useAlternativeActions = modifierKeyEmitter.keyStatus.altKey || ((isWindows || isLinux) && modifierKeyEmitter.keyStatus.shiftKey);
|
||||
fillInActions(groups, target, useAlternativeActions, primaryGroup ? actionGroup => actionGroup === primaryGroup : actionGroup => actionGroup === 'navigation');
|
||||
}
|
||||
export function getActionBarActions(groups, primaryGroup, shouldInlineSubmenu, useSeparatorsInPrimaryActions) {
|
||||
const target = { primary: [], secondary: [] };
|
||||
fillInActionBarActions(groups, target, primaryGroup, shouldInlineSubmenu, useSeparatorsInPrimaryActions);
|
||||
return target;
|
||||
}
|
||||
export function getFlatActionBarActions(groups, primaryGroup, shouldInlineSubmenu, useSeparatorsInPrimaryActions) {
|
||||
const target = [];
|
||||
fillInActionBarActions(groups, target, primaryGroup, shouldInlineSubmenu, useSeparatorsInPrimaryActions);
|
||||
return target;
|
||||
}
|
||||
export function fillInActionBarActions(groups, target, primaryGroup, shouldInlineSubmenu, useSeparatorsInPrimaryActions) {
|
||||
const isPrimaryAction = typeof primaryGroup === 'string' ? (actionGroup) => actionGroup === primaryGroup : primaryGroup;
|
||||
// Action bars handle alternative actions on their own so the alternative actions should be ignored
|
||||
fillInActions(groups, target, false, isPrimaryAction, shouldInlineSubmenu, useSeparatorsInPrimaryActions);
|
||||
}
|
||||
function fillInActions(groups, target, useAlternativeActions, isPrimaryAction = actionGroup => actionGroup === 'navigation', shouldInlineSubmenu = () => false, useSeparatorsInPrimaryActions = false) {
|
||||
let primaryBucket;
|
||||
let secondaryBucket;
|
||||
if (Array.isArray(target)) {
|
||||
primaryBucket = target;
|
||||
secondaryBucket = target;
|
||||
}
|
||||
else {
|
||||
primaryBucket = target.primary;
|
||||
secondaryBucket = target.secondary;
|
||||
}
|
||||
const submenuInfo = new Set();
|
||||
for (const [group, actions] of groups) {
|
||||
let target;
|
||||
if (isPrimaryAction(group)) {
|
||||
target = primaryBucket;
|
||||
if (target.length > 0 && useSeparatorsInPrimaryActions) {
|
||||
target.push(new Separator());
|
||||
}
|
||||
}
|
||||
else {
|
||||
target = secondaryBucket;
|
||||
if (target.length > 0) {
|
||||
target.push(new Separator());
|
||||
}
|
||||
}
|
||||
for (let action of actions) {
|
||||
if (useAlternativeActions) {
|
||||
action = action instanceof MenuItemAction && action.alt ? action.alt : action;
|
||||
}
|
||||
const newLen = target.push(action);
|
||||
// keep submenu info for later inlining
|
||||
if (action instanceof SubmenuAction) {
|
||||
submenuInfo.add({ group, action, index: newLen - 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
// ask the outside if submenu should be inlined or not. only ask when
|
||||
// there would be enough space
|
||||
for (const { group, action, index } of submenuInfo) {
|
||||
const target = isPrimaryAction(group) ? primaryBucket : secondaryBucket;
|
||||
// inlining submenus with length 0 or 1 is easy,
|
||||
// larger submenus need to be checked with the overall limit
|
||||
const submenuActions = action.actions;
|
||||
if (shouldInlineSubmenu(action, group, target.length)) {
|
||||
target.splice(index, 1, ...submenuActions);
|
||||
}
|
||||
}
|
||||
}
|
||||
let MenuEntryActionViewItem = class MenuEntryActionViewItem extends ActionViewItem {
|
||||
constructor(action, _options, _keybindingService, _notificationService, _contextKeyService, _themeService, _contextMenuService, _accessibilityService) {
|
||||
super(undefined, action, { icon: !!(action.class || action.item.icon), label: !action.class && !action.item.icon, draggable: _options?.draggable, keybinding: _options?.keybinding, hoverDelegate: _options?.hoverDelegate, keybindingNotRenderedWithLabel: _options?.keybindingNotRenderedWithLabel });
|
||||
this._options = _options;
|
||||
this._keybindingService = _keybindingService;
|
||||
this._notificationService = _notificationService;
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this._themeService = _themeService;
|
||||
this._contextMenuService = _contextMenuService;
|
||||
this._accessibilityService = _accessibilityService;
|
||||
this._wantsAltCommand = false;
|
||||
this._itemClassDispose = this._register(new MutableDisposable());
|
||||
this._altKey = ModifierKeyEmitter.getInstance();
|
||||
}
|
||||
get _menuItemAction() {
|
||||
return this._action;
|
||||
}
|
||||
get _commandAction() {
|
||||
return this._wantsAltCommand && this._menuItemAction.alt || this._menuItemAction;
|
||||
}
|
||||
async onClick(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
try {
|
||||
await this.actionRunner.run(this._commandAction, this._context);
|
||||
}
|
||||
catch (err) {
|
||||
this._notificationService.error(err);
|
||||
}
|
||||
}
|
||||
render(container) {
|
||||
super.render(container);
|
||||
container.classList.add('menu-entry');
|
||||
if (this.options.icon) {
|
||||
this._updateItemClass(this._menuItemAction.item);
|
||||
}
|
||||
if (this._menuItemAction.alt) {
|
||||
let isMouseOver = false;
|
||||
const updateAltState = () => {
|
||||
const wantsAltCommand = !!this._menuItemAction.alt?.enabled &&
|
||||
(!this._accessibilityService.isMotionReduced() || isMouseOver) && (this._altKey.keyStatus.altKey ||
|
||||
(this._altKey.keyStatus.shiftKey && isMouseOver));
|
||||
if (wantsAltCommand !== this._wantsAltCommand) {
|
||||
this._wantsAltCommand = wantsAltCommand;
|
||||
this.updateLabel();
|
||||
this.updateTooltip();
|
||||
this.updateClass();
|
||||
}
|
||||
};
|
||||
this._register(this._altKey.event(updateAltState));
|
||||
this._register(addDisposableListener(container, 'mouseleave', _ => {
|
||||
isMouseOver = false;
|
||||
updateAltState();
|
||||
}));
|
||||
this._register(addDisposableListener(container, 'mouseenter', _ => {
|
||||
isMouseOver = true;
|
||||
updateAltState();
|
||||
}));
|
||||
updateAltState();
|
||||
}
|
||||
}
|
||||
updateLabel() {
|
||||
if (this.options.label && this.label) {
|
||||
this.label.textContent = this._commandAction.label;
|
||||
}
|
||||
}
|
||||
getTooltip() {
|
||||
const keybinding = this._keybindingService.lookupKeybinding(this._commandAction.id, this._contextKeyService);
|
||||
const keybindingLabel = keybinding && keybinding.getLabel();
|
||||
const tooltip = this._commandAction.tooltip || this._commandAction.label;
|
||||
let title = keybindingLabel
|
||||
? localize(1629, "{0} ({1})", tooltip, keybindingLabel)
|
||||
: tooltip;
|
||||
if (!this._wantsAltCommand && this._menuItemAction.alt?.enabled) {
|
||||
const altTooltip = this._menuItemAction.alt.tooltip || this._menuItemAction.alt.label;
|
||||
const altKeybinding = this._keybindingService.lookupKeybinding(this._menuItemAction.alt.id, this._contextKeyService);
|
||||
const altKeybindingLabel = altKeybinding && altKeybinding.getLabel();
|
||||
const altTitleSection = altKeybindingLabel
|
||||
? localize(1630, "{0} ({1})", altTooltip, altKeybindingLabel)
|
||||
: altTooltip;
|
||||
title = localize(1631, "{0}\n[{1}] {2}", title, UILabelProvider.modifierLabels[OS].altKey, altTitleSection);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
updateClass() {
|
||||
if (this.options.icon) {
|
||||
if (this._commandAction !== this._menuItemAction) {
|
||||
if (this._menuItemAction.alt) {
|
||||
this._updateItemClass(this._menuItemAction.alt.item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._updateItemClass(this._menuItemAction.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
_updateItemClass(item) {
|
||||
this._itemClassDispose.value = undefined;
|
||||
const { element, label } = this;
|
||||
if (!element || !label) {
|
||||
return;
|
||||
}
|
||||
const icon = this._commandAction.checked && isICommandActionToggleInfo(item.toggled) && item.toggled.icon ? item.toggled.icon : item.icon;
|
||||
if (!icon) {
|
||||
return;
|
||||
}
|
||||
if (ThemeIcon.isThemeIcon(icon)) {
|
||||
// theme icons
|
||||
const iconClasses = ThemeIcon.asClassNameArray(icon);
|
||||
label.classList.add(...iconClasses);
|
||||
this._itemClassDispose.value = toDisposable(() => {
|
||||
label.classList.remove(...iconClasses);
|
||||
});
|
||||
}
|
||||
else {
|
||||
// icon path/url
|
||||
label.style.backgroundImage = (isDark(this._themeService.getColorTheme().type)
|
||||
? asCSSUrl(icon.dark)
|
||||
: asCSSUrl(icon.light));
|
||||
label.classList.add('icon');
|
||||
this._itemClassDispose.value = combinedDisposable(toDisposable(() => {
|
||||
label.style.backgroundImage = '';
|
||||
label.classList.remove('icon');
|
||||
}), this._themeService.onDidColorThemeChange(() => {
|
||||
// refresh when the theme changes in case we go between dark <-> light
|
||||
this.updateClass();
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
MenuEntryActionViewItem = __decorate([
|
||||
__param(2, IKeybindingService),
|
||||
__param(3, INotificationService),
|
||||
__param(4, IContextKeyService),
|
||||
__param(5, IThemeService),
|
||||
__param(6, IContextMenuService),
|
||||
__param(7, IAccessibilityService)
|
||||
], MenuEntryActionViewItem);
|
||||
export { MenuEntryActionViewItem };
|
||||
export class TextOnlyMenuEntryActionViewItem extends MenuEntryActionViewItem {
|
||||
render(container) {
|
||||
this.options.label = true;
|
||||
this.options.icon = false;
|
||||
super.render(container);
|
||||
container.classList.add('text-only');
|
||||
container.classList.toggle('use-comma', this._options?.useComma ?? false);
|
||||
}
|
||||
updateLabel() {
|
||||
const kb = this._keybindingService.lookupKeybinding(this._action.id, this._contextKeyService);
|
||||
if (!kb) {
|
||||
return super.updateLabel();
|
||||
}
|
||||
if (this.label) {
|
||||
const kb2 = TextOnlyMenuEntryActionViewItem._symbolPrintEnter(kb);
|
||||
if (this._options?.conversational) {
|
||||
this.label.textContent = localize(1632, '{1} to {0}', this._action.label, kb2);
|
||||
}
|
||||
else {
|
||||
this.label.textContent = localize(1633, '{0} ({1})', this._action.label, kb2);
|
||||
}
|
||||
}
|
||||
}
|
||||
static _symbolPrintEnter(kb) {
|
||||
return kb.getLabel()
|
||||
?.replace(/\benter\b/gi, '\u23CE')
|
||||
.replace(/\bEscape\b/gi, 'Esc');
|
||||
}
|
||||
}
|
||||
let SubmenuEntryActionViewItem = class SubmenuEntryActionViewItem extends DropdownMenuActionViewItem {
|
||||
constructor(action, options, _keybindingService, _contextMenuService, _themeService) {
|
||||
const dropdownOptions = {
|
||||
...options,
|
||||
menuAsChild: options?.menuAsChild ?? false,
|
||||
classNames: options?.classNames ?? (ThemeIcon.isThemeIcon(action.item.icon) ? ThemeIcon.asClassName(action.item.icon) : undefined),
|
||||
keybindingProvider: options?.keybindingProvider ?? (action => _keybindingService.lookupKeybinding(action.id))
|
||||
};
|
||||
super(action, { getActions: () => action.actions }, _contextMenuService, dropdownOptions);
|
||||
this._keybindingService = _keybindingService;
|
||||
this._contextMenuService = _contextMenuService;
|
||||
this._themeService = _themeService;
|
||||
}
|
||||
render(container) {
|
||||
super.render(container);
|
||||
assertType(this.element);
|
||||
container.classList.add('menu-entry');
|
||||
const action = this._action;
|
||||
const { icon } = action.item;
|
||||
if (icon && !ThemeIcon.isThemeIcon(icon)) {
|
||||
this.element.classList.add('icon');
|
||||
const setBackgroundImage = () => {
|
||||
if (this.element) {
|
||||
this.element.style.backgroundImage = (isDark(this._themeService.getColorTheme().type)
|
||||
? asCSSUrl(icon.dark)
|
||||
: asCSSUrl(icon.light));
|
||||
}
|
||||
};
|
||||
setBackgroundImage();
|
||||
this._register(this._themeService.onDidColorThemeChange(() => {
|
||||
// refresh when the theme changes in case we go between dark <-> light
|
||||
setBackgroundImage();
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
SubmenuEntryActionViewItem = __decorate([
|
||||
__param(2, IKeybindingService),
|
||||
__param(3, IContextMenuService),
|
||||
__param(4, IThemeService)
|
||||
], SubmenuEntryActionViewItem);
|
||||
export { SubmenuEntryActionViewItem };
|
||||
let DropdownWithDefaultActionViewItem = class DropdownWithDefaultActionViewItem extends BaseActionViewItem {
|
||||
constructor(submenuAction, options, _keybindingService, _notificationService, _contextMenuService, _menuService, _instaService, _storageService) {
|
||||
super(null, submenuAction);
|
||||
this._keybindingService = _keybindingService;
|
||||
this._notificationService = _notificationService;
|
||||
this._contextMenuService = _contextMenuService;
|
||||
this._menuService = _menuService;
|
||||
this._instaService = _instaService;
|
||||
this._storageService = _storageService;
|
||||
this._defaultActionDisposables = this._register(new DisposableStore());
|
||||
this._container = null;
|
||||
this._options = options;
|
||||
this._storageKey = `${submenuAction.item.submenu.id}_lastActionId`;
|
||||
// determine default action
|
||||
let defaultAction;
|
||||
const defaultActionId = options?.persistLastActionId ? _storageService.get(this._storageKey, 1 /* StorageScope.WORKSPACE */) : undefined;
|
||||
if (defaultActionId) {
|
||||
defaultAction = submenuAction.actions.find(a => defaultActionId === a.id);
|
||||
}
|
||||
if (!defaultAction) {
|
||||
defaultAction = submenuAction.actions[0];
|
||||
}
|
||||
this._defaultAction = this._defaultActionDisposables.add(this._instaService.createInstance(MenuEntryActionViewItem, defaultAction, { keybinding: this._getDefaultActionKeybindingLabel(defaultAction) }));
|
||||
const dropdownOptions = {
|
||||
keybindingProvider: action => this._keybindingService.lookupKeybinding(action.id),
|
||||
...options,
|
||||
menuAsChild: options?.menuAsChild ?? true,
|
||||
classNames: options?.classNames ?? ['codicon', 'codicon-chevron-down'],
|
||||
actionRunner: options?.actionRunner ?? this._register(new ActionRunner()),
|
||||
};
|
||||
this._dropdown = this._register(new DropdownMenuActionViewItem(submenuAction, submenuAction.actions, this._contextMenuService, dropdownOptions));
|
||||
this._register(this._dropdown.actionRunner.onDidRun((e) => {
|
||||
if (e.action instanceof MenuItemAction) {
|
||||
this.update(e.action);
|
||||
}
|
||||
}));
|
||||
}
|
||||
update(lastAction) {
|
||||
if (this._options?.persistLastActionId) {
|
||||
this._storageService.store(this._storageKey, lastAction.id, 1 /* StorageScope.WORKSPACE */, 1 /* StorageTarget.MACHINE */);
|
||||
}
|
||||
this._defaultActionDisposables.clear();
|
||||
this._defaultAction = this._defaultActionDisposables.add(this._instaService.createInstance(MenuEntryActionViewItem, lastAction, { keybinding: this._getDefaultActionKeybindingLabel(lastAction) }));
|
||||
this._defaultAction.actionRunner = this._defaultActionDisposables.add(new class extends ActionRunner {
|
||||
async runAction(action, context) {
|
||||
await action.run(undefined);
|
||||
}
|
||||
}());
|
||||
if (this._container) {
|
||||
this._defaultAction.render(prepend(this._container, $('.action-container')));
|
||||
}
|
||||
}
|
||||
_getDefaultActionKeybindingLabel(defaultAction) {
|
||||
let defaultActionKeybinding;
|
||||
if (this._options?.renderKeybindingWithDefaultActionLabel) {
|
||||
const kb = this._keybindingService.lookupKeybinding(defaultAction.id);
|
||||
if (kb) {
|
||||
defaultActionKeybinding = `(${kb.getLabel()})`;
|
||||
}
|
||||
}
|
||||
return defaultActionKeybinding;
|
||||
}
|
||||
setActionContext(newContext) {
|
||||
super.setActionContext(newContext);
|
||||
this._defaultAction.setActionContext(newContext);
|
||||
this._dropdown.setActionContext(newContext);
|
||||
}
|
||||
render(container) {
|
||||
this._container = container;
|
||||
super.render(this._container);
|
||||
this._container.classList.add('monaco-dropdown-with-default');
|
||||
const primaryContainer = $('.action-container');
|
||||
this._defaultAction.render(append(this._container, primaryContainer));
|
||||
this._register(addDisposableListener(primaryContainer, EventType.KEY_DOWN, (e) => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
if (event.equals(17 /* KeyCode.RightArrow */)) {
|
||||
this._defaultAction.element.tabIndex = -1;
|
||||
this._dropdown.focus();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}));
|
||||
const dropdownContainer = $('.dropdown-action-container');
|
||||
this._dropdown.render(append(this._container, dropdownContainer));
|
||||
this._register(addDisposableListener(dropdownContainer, EventType.KEY_DOWN, (e) => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
if (event.equals(15 /* KeyCode.LeftArrow */)) {
|
||||
this._defaultAction.element.tabIndex = 0;
|
||||
this._dropdown.setFocusable(false);
|
||||
this._defaultAction.element?.focus();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}));
|
||||
}
|
||||
focus(fromRight) {
|
||||
if (fromRight) {
|
||||
this._dropdown.focus();
|
||||
}
|
||||
else {
|
||||
this._defaultAction.element.tabIndex = 0;
|
||||
this._defaultAction.element.focus();
|
||||
}
|
||||
}
|
||||
blur() {
|
||||
this._defaultAction.element.tabIndex = -1;
|
||||
this._dropdown.blur();
|
||||
this._container.blur();
|
||||
}
|
||||
setFocusable(focusable) {
|
||||
if (focusable) {
|
||||
this._defaultAction.element.tabIndex = 0;
|
||||
}
|
||||
else {
|
||||
this._defaultAction.element.tabIndex = -1;
|
||||
this._dropdown.setFocusable(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
DropdownWithDefaultActionViewItem = __decorate([
|
||||
__param(2, IKeybindingService),
|
||||
__param(3, INotificationService),
|
||||
__param(4, IContextMenuService),
|
||||
__param(5, IMenuService),
|
||||
__param(6, IInstantiationService),
|
||||
__param(7, IStorageService)
|
||||
], DropdownWithDefaultActionViewItem);
|
||||
export { DropdownWithDefaultActionViewItem };
|
||||
let SubmenuEntrySelectActionViewItem = class SubmenuEntrySelectActionViewItem extends SelectActionViewItem {
|
||||
constructor(action, contextViewService, configurationService) {
|
||||
super(null, action, action.actions.map(a => ({
|
||||
text: a.id === Separator.ID ? '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500' : a.label,
|
||||
isDisabled: !a.enabled,
|
||||
})), 0, contextViewService, defaultSelectBoxStyles, { ariaLabel: action.tooltip, optionsAsChildren: true, useCustomDrawn: !hasNativeContextMenu(configurationService) });
|
||||
this.select(Math.max(0, action.actions.findIndex(a => a.checked)));
|
||||
}
|
||||
render(container) {
|
||||
super.render(container);
|
||||
container.style.borderColor = asCssVariable(selectBorder);
|
||||
}
|
||||
runAction(option, index) {
|
||||
const action = this.action.actions[index];
|
||||
if (action) {
|
||||
this.actionRunner.run(action);
|
||||
}
|
||||
}
|
||||
};
|
||||
SubmenuEntrySelectActionViewItem = __decorate([
|
||||
__param(1, IContextViewService),
|
||||
__param(2, IConfigurationService)
|
||||
], SubmenuEntrySelectActionViewItem);
|
||||
/**
|
||||
* Creates action view items for menu actions or submenu actions.
|
||||
*/
|
||||
export function createActionViewItem(instaService, action, options) {
|
||||
if (action instanceof MenuItemAction) {
|
||||
return instaService.createInstance(MenuEntryActionViewItem, action, options);
|
||||
}
|
||||
else if (action instanceof SubmenuItemAction) {
|
||||
if (action.item.isSelection) {
|
||||
return instaService.createInstance(SubmenuEntrySelectActionViewItem, action);
|
||||
}
|
||||
else {
|
||||
if (action.item.rememberDefaultAction) {
|
||||
return instaService.createInstance(DropdownWithDefaultActionViewItem, action, { ...options, persistLastActionId: true });
|
||||
}
|
||||
else {
|
||||
return instaService.createInstance(SubmenuEntryActionViewItem, action, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=menuEntryActionViewItem.js.map
|
||||
File diff suppressed because one or more lines are too long
280
_internal/editor/esm/vs/platform/actions/browser/toolbar.js
Normal file
280
_internal/editor/esm/vs/platform/actions/browser/toolbar.js
Normal file
@@ -0,0 +1,280 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { addDisposableListener, getWindow } from '../../../base/browser/dom.js';
|
||||
import { StandardMouseEvent } from '../../../base/browser/mouseEvent.js';
|
||||
import { ToggleMenuAction, ToolBar } from '../../../base/browser/ui/toolbar/toolbar.js';
|
||||
import { Separator, toAction } from '../../../base/common/actions.js';
|
||||
import { coalesceInPlace } from '../../../base/common/arrays.js';
|
||||
import { intersection } from '../../../base/common/collections.js';
|
||||
import { BugIndicatingError } from '../../../base/common/errors.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Iterable } from '../../../base/common/iterator.js';
|
||||
import { DisposableStore } from '../../../base/common/lifecycle.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { createActionViewItem, getActionBarActions } from './menuEntryActionViewItem.js';
|
||||
import { IMenuService, MenuItemAction, SubmenuItemAction } from '../common/actions.js';
|
||||
import { createConfigureKeybindingAction } from '../common/menuService.js';
|
||||
import { ICommandService } from '../../commands/common/commands.js';
|
||||
import { IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { IContextMenuService } from '../../contextview/browser/contextView.js';
|
||||
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
|
||||
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
|
||||
import { IActionViewItemService } from './actionViewItemService.js';
|
||||
import { IInstantiationService } from '../../instantiation/common/instantiation.js';
|
||||
/**
|
||||
* The `WorkbenchToolBar` does
|
||||
* - support hiding of menu items
|
||||
* - lookup keybindings for each actions automatically
|
||||
* - send `workbenchActionExecuted`-events for each action
|
||||
*
|
||||
* See {@link MenuWorkbenchToolBar} for a toolbar that is backed by a menu.
|
||||
*/
|
||||
let WorkbenchToolBar = class WorkbenchToolBar extends ToolBar {
|
||||
constructor(container, _options, _menuService, _contextKeyService, _contextMenuService, _keybindingService, _commandService, telemetryService) {
|
||||
super(container, _contextMenuService, {
|
||||
// defaults
|
||||
getKeyBinding: (action) => _keybindingService.lookupKeybinding(action.id) ?? undefined,
|
||||
// options (override defaults)
|
||||
..._options,
|
||||
// mandatory (overide options)
|
||||
allowContextMenu: true,
|
||||
skipTelemetry: typeof _options?.telemetrySource === 'string',
|
||||
});
|
||||
this._options = _options;
|
||||
this._menuService = _menuService;
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this._contextMenuService = _contextMenuService;
|
||||
this._keybindingService = _keybindingService;
|
||||
this._commandService = _commandService;
|
||||
this._sessionDisposables = this._store.add(new DisposableStore());
|
||||
// telemetry logic
|
||||
const telemetrySource = _options?.telemetrySource;
|
||||
if (telemetrySource) {
|
||||
this._store.add(this.actionBar.onDidRun(e => telemetryService.publicLog2('workbenchActionExecuted', { id: e.action.id, from: telemetrySource })));
|
||||
}
|
||||
}
|
||||
setActions(_primary, _secondary = [], menuIds) {
|
||||
this._sessionDisposables.clear();
|
||||
const primary = _primary.slice(); // for hiding and overflow we set some items to undefined
|
||||
const secondary = _secondary.slice();
|
||||
const toggleActions = [];
|
||||
let toggleActionsCheckedCount = 0;
|
||||
const extraSecondary = [];
|
||||
let someAreHidden = false;
|
||||
// unless disabled, move all hidden items to secondary group or ignore them
|
||||
if (this._options?.hiddenItemStrategy !== -1 /* HiddenItemStrategy.NoHide */) {
|
||||
for (let i = 0; i < primary.length; i++) {
|
||||
const action = primary[i];
|
||||
if (!(action instanceof MenuItemAction) && !(action instanceof SubmenuItemAction)) {
|
||||
// console.warn(`Action ${action.id}/${action.label} is not a MenuItemAction`);
|
||||
continue;
|
||||
}
|
||||
if (!action.hideActions) {
|
||||
continue;
|
||||
}
|
||||
// collect all toggle actions
|
||||
toggleActions.push(action.hideActions.toggle);
|
||||
if (action.hideActions.toggle.checked) {
|
||||
toggleActionsCheckedCount++;
|
||||
}
|
||||
// hidden items move into overflow or ignore
|
||||
if (action.hideActions.isHidden) {
|
||||
someAreHidden = true;
|
||||
primary[i] = undefined;
|
||||
if (this._options?.hiddenItemStrategy !== 0 /* HiddenItemStrategy.Ignore */) {
|
||||
extraSecondary[i] = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// count for max
|
||||
if (this._options?.overflowBehavior !== undefined) {
|
||||
const exemptedIds = intersection(new Set(this._options.overflowBehavior.exempted), Iterable.map(primary, a => a?.id));
|
||||
const maxItems = this._options.overflowBehavior.maxItems - exemptedIds.size;
|
||||
let count = 0;
|
||||
for (let i = 0; i < primary.length; i++) {
|
||||
const action = primary[i];
|
||||
if (!action) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
if (exemptedIds.has(action.id)) {
|
||||
continue;
|
||||
}
|
||||
if (count >= maxItems) {
|
||||
primary[i] = undefined;
|
||||
extraSecondary[i] = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
// coalesce turns Array<IAction|undefined> into IAction[]
|
||||
coalesceInPlace(primary);
|
||||
coalesceInPlace(extraSecondary);
|
||||
super.setActions(primary, Separator.join(extraSecondary, secondary));
|
||||
// add context menu for toggle and configure keybinding actions
|
||||
if (toggleActions.length > 0 || primary.length > 0) {
|
||||
this._sessionDisposables.add(addDisposableListener(this.getElement(), 'contextmenu', e => {
|
||||
const event = new StandardMouseEvent(getWindow(this.getElement()), e);
|
||||
const action = this.getItemAction(event.target);
|
||||
if (!(action)) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const primaryActions = [];
|
||||
// -- Configure Keybinding Action --
|
||||
if (action instanceof MenuItemAction && action.menuKeybinding) {
|
||||
primaryActions.push(action.menuKeybinding);
|
||||
}
|
||||
else if (!(action instanceof SubmenuItemAction || action instanceof ToggleMenuAction)) {
|
||||
// only enable the configure keybinding action for actions that support keybindings
|
||||
const supportsKeybindings = !!this._keybindingService.lookupKeybinding(action.id);
|
||||
primaryActions.push(createConfigureKeybindingAction(this._commandService, this._keybindingService, action.id, undefined, supportsKeybindings));
|
||||
}
|
||||
// -- Hide Actions --
|
||||
if (toggleActions.length > 0) {
|
||||
let noHide = false;
|
||||
// last item cannot be hidden when using ignore strategy
|
||||
if (toggleActionsCheckedCount === 1 && this._options?.hiddenItemStrategy === 0 /* HiddenItemStrategy.Ignore */) {
|
||||
noHide = true;
|
||||
for (let i = 0; i < toggleActions.length; i++) {
|
||||
if (toggleActions[i].checked) {
|
||||
toggleActions[i] = toAction({
|
||||
id: action.id,
|
||||
label: action.label,
|
||||
checked: true,
|
||||
enabled: false,
|
||||
run() { }
|
||||
});
|
||||
break; // there is only one
|
||||
}
|
||||
}
|
||||
}
|
||||
// add "hide foo" actions
|
||||
if (!noHide && (action instanceof MenuItemAction || action instanceof SubmenuItemAction)) {
|
||||
if (!action.hideActions) {
|
||||
// no context menu for MenuItemAction instances that support no hiding
|
||||
// those are fake actions and need to be cleaned up
|
||||
return;
|
||||
}
|
||||
primaryActions.push(action.hideActions.hide);
|
||||
}
|
||||
else {
|
||||
primaryActions.push(toAction({
|
||||
id: 'label',
|
||||
label: localize(1634, "Hide"),
|
||||
enabled: false,
|
||||
run() { }
|
||||
}));
|
||||
}
|
||||
}
|
||||
const actions = Separator.join(primaryActions, toggleActions);
|
||||
// add "Reset Menu" action
|
||||
if (this._options?.resetMenu && !menuIds) {
|
||||
menuIds = [this._options.resetMenu];
|
||||
}
|
||||
if (someAreHidden && menuIds) {
|
||||
actions.push(new Separator());
|
||||
actions.push(toAction({
|
||||
id: 'resetThisMenu',
|
||||
label: localize(1635, "Reset Menu"),
|
||||
run: () => this._menuService.resetHiddenStates(menuIds)
|
||||
}));
|
||||
}
|
||||
if (actions.length === 0) {
|
||||
return;
|
||||
}
|
||||
this._contextMenuService.showContextMenu({
|
||||
getAnchor: () => event,
|
||||
getActions: () => actions,
|
||||
// add context menu actions (iff appicable)
|
||||
menuId: this._options?.contextMenu,
|
||||
menuActionOptions: { renderShortTitle: true, ...this._options?.menuOptions },
|
||||
skipTelemetry: typeof this._options?.telemetrySource === 'string',
|
||||
contextKeyService: this._contextKeyService,
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
WorkbenchToolBar = __decorate([
|
||||
__param(2, IMenuService),
|
||||
__param(3, IContextKeyService),
|
||||
__param(4, IContextMenuService),
|
||||
__param(5, IKeybindingService),
|
||||
__param(6, ICommandService),
|
||||
__param(7, ITelemetryService)
|
||||
], WorkbenchToolBar);
|
||||
export { WorkbenchToolBar };
|
||||
/**
|
||||
* A {@link WorkbenchToolBar workbench toolbar} that is purely driven from a {@link MenuId menu}-identifier.
|
||||
*
|
||||
* *Note* that Manual updates via `setActions` are NOT supported.
|
||||
*/
|
||||
let MenuWorkbenchToolBar = class MenuWorkbenchToolBar extends WorkbenchToolBar {
|
||||
get onDidChangeMenuItems() { return this._onDidChangeMenuItems.event; }
|
||||
constructor(container, menuId, options, menuService, contextKeyService, contextMenuService, keybindingService, commandService, telemetryService, actionViewService, instantiationService) {
|
||||
super(container, {
|
||||
resetMenu: menuId,
|
||||
...options,
|
||||
actionViewItemProvider: (action, opts) => {
|
||||
let provider = actionViewService.lookUp(menuId, action instanceof SubmenuItemAction ? action.item.submenu.id : action.id);
|
||||
if (!provider) {
|
||||
provider = options?.actionViewItemProvider;
|
||||
}
|
||||
const viewItem = provider?.(action, opts, instantiationService, getWindow(container).vscodeWindowId);
|
||||
if (viewItem) {
|
||||
return viewItem;
|
||||
}
|
||||
return createActionViewItem(instantiationService, action, opts);
|
||||
}
|
||||
}, menuService, contextKeyService, contextMenuService, keybindingService, commandService, telemetryService);
|
||||
this._onDidChangeMenuItems = this._store.add(new Emitter());
|
||||
// update logic
|
||||
const menu = this._store.add(menuService.createMenu(menuId, contextKeyService, { emitEventsForSubmenuChanges: true, eventDebounceDelay: options?.eventDebounceDelay }));
|
||||
const updateToolbar = () => {
|
||||
const { primary, secondary } = getActionBarActions(menu.getActions(options?.menuOptions), options?.toolbarOptions?.primaryGroup, options?.toolbarOptions?.shouldInlineSubmenu, options?.toolbarOptions?.useSeparatorsInPrimaryActions);
|
||||
container.classList.toggle('has-no-actions', primary.length === 0 && secondary.length === 0);
|
||||
super.setActions(primary, secondary);
|
||||
};
|
||||
this._store.add(menu.onDidChange(() => {
|
||||
updateToolbar();
|
||||
this._onDidChangeMenuItems.fire(this);
|
||||
}));
|
||||
this._store.add(actionViewService.onDidChange(e => {
|
||||
if (e === menuId) {
|
||||
updateToolbar();
|
||||
}
|
||||
}));
|
||||
updateToolbar();
|
||||
}
|
||||
/**
|
||||
* @deprecated The WorkbenchToolBar does not support this method because it works with menus.
|
||||
*/
|
||||
setActions() {
|
||||
throw new BugIndicatingError('This toolbar is populated from a menu.');
|
||||
}
|
||||
};
|
||||
MenuWorkbenchToolBar = __decorate([
|
||||
__param(3, IMenuService),
|
||||
__param(4, IContextKeyService),
|
||||
__param(5, IContextMenuService),
|
||||
__param(6, IKeybindingService),
|
||||
__param(7, ICommandService),
|
||||
__param(8, ITelemetryService),
|
||||
__param(9, IActionViewItemService),
|
||||
__param(10, IInstantiationService)
|
||||
], MenuWorkbenchToolBar);
|
||||
export { MenuWorkbenchToolBar };
|
||||
//# sourceMappingURL=toolbar.js.map
|
||||
File diff suppressed because one or more lines are too long
478
_internal/editor/esm/vs/platform/actions/common/actions.js
Normal file
478
_internal/editor/esm/vs/platform/actions/common/actions.js
Normal file
@@ -0,0 +1,478 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 MenuItemAction_1;
|
||||
import { SubmenuAction } from '../../../base/common/actions.js';
|
||||
import { MicrotaskEmitter } from '../../../base/common/event.js';
|
||||
import { DisposableStore, dispose, markAsSingleton, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { LinkedList } from '../../../base/common/linkedList.js';
|
||||
import { ThemeIcon } from '../../../base/common/themables.js';
|
||||
import { CommandsRegistry, ICommandService } from '../../commands/common/commands.js';
|
||||
import { ContextKeyExpr, IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { KeybindingsRegistry } from '../../keybinding/common/keybindingsRegistry.js';
|
||||
export function isIMenuItem(item) {
|
||||
return item.command !== undefined;
|
||||
}
|
||||
export function isISubmenuItem(item) {
|
||||
return item.submenu !== undefined;
|
||||
}
|
||||
export class MenuId {
|
||||
static { this._instances = new Map(); }
|
||||
static { this.CommandPalette = new MenuId('CommandPalette'); }
|
||||
static { this.DebugBreakpointsContext = new MenuId('DebugBreakpointsContext'); }
|
||||
static { this.DebugCallStackContext = new MenuId('DebugCallStackContext'); }
|
||||
static { this.DebugConsoleContext = new MenuId('DebugConsoleContext'); }
|
||||
static { this.DebugVariablesContext = new MenuId('DebugVariablesContext'); }
|
||||
static { this.NotebookVariablesContext = new MenuId('NotebookVariablesContext'); }
|
||||
static { this.DebugHoverContext = new MenuId('DebugHoverContext'); }
|
||||
static { this.DebugWatchContext = new MenuId('DebugWatchContext'); }
|
||||
static { this.DebugToolBar = new MenuId('DebugToolBar'); }
|
||||
static { this.DebugToolBarStop = new MenuId('DebugToolBarStop'); }
|
||||
static { this.DebugDisassemblyContext = new MenuId('DebugDisassemblyContext'); }
|
||||
static { this.DebugCallStackToolbar = new MenuId('DebugCallStackToolbar'); }
|
||||
static { this.DebugCreateConfiguration = new MenuId('DebugCreateConfiguration'); }
|
||||
static { this.EditorContext = new MenuId('EditorContext'); }
|
||||
static { this.SimpleEditorContext = new MenuId('SimpleEditorContext'); }
|
||||
static { this.EditorContent = new MenuId('EditorContent'); }
|
||||
static { this.EditorLineNumberContext = new MenuId('EditorLineNumberContext'); }
|
||||
static { this.EditorContextCopy = new MenuId('EditorContextCopy'); }
|
||||
static { this.EditorContextPeek = new MenuId('EditorContextPeek'); }
|
||||
static { this.EditorContextShare = new MenuId('EditorContextShare'); }
|
||||
static { this.EditorTitle = new MenuId('EditorTitle'); }
|
||||
static { this.CompactWindowEditorTitle = new MenuId('CompactWindowEditorTitle'); }
|
||||
static { this.EditorTitleRun = new MenuId('EditorTitleRun'); }
|
||||
static { this.EditorTitleContext = new MenuId('EditorTitleContext'); }
|
||||
static { this.EditorTitleContextShare = new MenuId('EditorTitleContextShare'); }
|
||||
static { this.EmptyEditorGroup = new MenuId('EmptyEditorGroup'); }
|
||||
static { this.EmptyEditorGroupContext = new MenuId('EmptyEditorGroupContext'); }
|
||||
static { this.EditorTabsBarContext = new MenuId('EditorTabsBarContext'); }
|
||||
static { this.EditorTabsBarShowTabsSubmenu = new MenuId('EditorTabsBarShowTabsSubmenu'); }
|
||||
static { this.EditorTabsBarShowTabsZenModeSubmenu = new MenuId('EditorTabsBarShowTabsZenModeSubmenu'); }
|
||||
static { this.EditorActionsPositionSubmenu = new MenuId('EditorActionsPositionSubmenu'); }
|
||||
static { this.EditorSplitMoveSubmenu = new MenuId('EditorSplitMoveSubmenu'); }
|
||||
static { this.ExplorerContext = new MenuId('ExplorerContext'); }
|
||||
static { this.ExplorerContextShare = new MenuId('ExplorerContextShare'); }
|
||||
static { this.ExtensionContext = new MenuId('ExtensionContext'); }
|
||||
static { this.ExtensionEditorContextMenu = new MenuId('ExtensionEditorContextMenu'); }
|
||||
static { this.GlobalActivity = new MenuId('GlobalActivity'); }
|
||||
static { this.CommandCenter = new MenuId('CommandCenter'); }
|
||||
static { this.CommandCenterCenter = new MenuId('CommandCenterCenter'); }
|
||||
static { this.LayoutControlMenuSubmenu = new MenuId('LayoutControlMenuSubmenu'); }
|
||||
static { this.LayoutControlMenu = new MenuId('LayoutControlMenu'); }
|
||||
static { this.MenubarMainMenu = new MenuId('MenubarMainMenu'); }
|
||||
static { this.MenubarAppearanceMenu = new MenuId('MenubarAppearanceMenu'); }
|
||||
static { this.MenubarDebugMenu = new MenuId('MenubarDebugMenu'); }
|
||||
static { this.MenubarEditMenu = new MenuId('MenubarEditMenu'); }
|
||||
static { this.MenubarCopy = new MenuId('MenubarCopy'); }
|
||||
static { this.MenubarFileMenu = new MenuId('MenubarFileMenu'); }
|
||||
static { this.MenubarGoMenu = new MenuId('MenubarGoMenu'); }
|
||||
static { this.MenubarHelpMenu = new MenuId('MenubarHelpMenu'); }
|
||||
static { this.MenubarLayoutMenu = new MenuId('MenubarLayoutMenu'); }
|
||||
static { this.MenubarNewBreakpointMenu = new MenuId('MenubarNewBreakpointMenu'); }
|
||||
static { this.PanelAlignmentMenu = new MenuId('PanelAlignmentMenu'); }
|
||||
static { this.PanelPositionMenu = new MenuId('PanelPositionMenu'); }
|
||||
static { this.ActivityBarPositionMenu = new MenuId('ActivityBarPositionMenu'); }
|
||||
static { this.MenubarPreferencesMenu = new MenuId('MenubarPreferencesMenu'); }
|
||||
static { this.MenubarRecentMenu = new MenuId('MenubarRecentMenu'); }
|
||||
static { this.MenubarSelectionMenu = new MenuId('MenubarSelectionMenu'); }
|
||||
static { this.MenubarShare = new MenuId('MenubarShare'); }
|
||||
static { this.MenubarSwitchEditorMenu = new MenuId('MenubarSwitchEditorMenu'); }
|
||||
static { this.MenubarSwitchGroupMenu = new MenuId('MenubarSwitchGroupMenu'); }
|
||||
static { this.MenubarTerminalMenu = new MenuId('MenubarTerminalMenu'); }
|
||||
static { this.MenubarTerminalSuggestStatusMenu = new MenuId('MenubarTerminalSuggestStatusMenu'); }
|
||||
static { this.MenubarViewMenu = new MenuId('MenubarViewMenu'); }
|
||||
static { this.MenubarHomeMenu = new MenuId('MenubarHomeMenu'); }
|
||||
static { this.OpenEditorsContext = new MenuId('OpenEditorsContext'); }
|
||||
static { this.OpenEditorsContextShare = new MenuId('OpenEditorsContextShare'); }
|
||||
static { this.ProblemsPanelContext = new MenuId('ProblemsPanelContext'); }
|
||||
static { this.SCMInputBox = new MenuId('SCMInputBox'); }
|
||||
static { this.SCMChangeContext = new MenuId('SCMChangeContext'); }
|
||||
static { this.SCMResourceContext = new MenuId('SCMResourceContext'); }
|
||||
static { this.SCMResourceContextShare = new MenuId('SCMResourceContextShare'); }
|
||||
static { this.SCMResourceFolderContext = new MenuId('SCMResourceFolderContext'); }
|
||||
static { this.SCMResourceGroupContext = new MenuId('SCMResourceGroupContext'); }
|
||||
static { this.SCMSourceControl = new MenuId('SCMSourceControl'); }
|
||||
static { this.SCMSourceControlInline = new MenuId('SCMSourceControlInline'); }
|
||||
static { this.SCMSourceControlTitle = new MenuId('SCMSourceControlTitle'); }
|
||||
static { this.SCMHistoryTitle = new MenuId('SCMHistoryTitle'); }
|
||||
static { this.SCMHistoryItemContext = new MenuId('SCMHistoryItemContext'); }
|
||||
static { this.SCMHistoryItemChangeContext = new MenuId('SCMHistoryItemChangeContext'); }
|
||||
static { this.SCMHistoryItemHover = new MenuId('SCMHistoryItemHover'); }
|
||||
static { this.SCMHistoryItemRefContext = new MenuId('SCMHistoryItemRefContext'); }
|
||||
static { this.SCMQuickDiffDecorations = new MenuId('SCMQuickDiffDecorations'); }
|
||||
static { this.SCMTitle = new MenuId('SCMTitle'); }
|
||||
static { this.SearchContext = new MenuId('SearchContext'); }
|
||||
static { this.SearchActionMenu = new MenuId('SearchActionContext'); }
|
||||
static { this.StatusBarWindowIndicatorMenu = new MenuId('StatusBarWindowIndicatorMenu'); }
|
||||
static { this.StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu'); }
|
||||
static { this.StickyScrollContext = new MenuId('StickyScrollContext'); }
|
||||
static { this.TestItem = new MenuId('TestItem'); }
|
||||
static { this.TestItemGutter = new MenuId('TestItemGutter'); }
|
||||
static { this.TestProfilesContext = new MenuId('TestProfilesContext'); }
|
||||
static { this.TestMessageContext = new MenuId('TestMessageContext'); }
|
||||
static { this.TestMessageContent = new MenuId('TestMessageContent'); }
|
||||
static { this.TestPeekElement = new MenuId('TestPeekElement'); }
|
||||
static { this.TestPeekTitle = new MenuId('TestPeekTitle'); }
|
||||
static { this.TestCallStack = new MenuId('TestCallStack'); }
|
||||
static { this.TestCoverageFilterItem = new MenuId('TestCoverageFilterItem'); }
|
||||
static { this.TouchBarContext = new MenuId('TouchBarContext'); }
|
||||
static { this.TitleBar = new MenuId('TitleBar'); }
|
||||
static { this.TitleBarContext = new MenuId('TitleBarContext'); }
|
||||
static { this.TitleBarTitleContext = new MenuId('TitleBarTitleContext'); }
|
||||
static { this.TunnelContext = new MenuId('TunnelContext'); }
|
||||
static { this.TunnelPrivacy = new MenuId('TunnelPrivacy'); }
|
||||
static { this.TunnelProtocol = new MenuId('TunnelProtocol'); }
|
||||
static { this.TunnelPortInline = new MenuId('TunnelInline'); }
|
||||
static { this.TunnelTitle = new MenuId('TunnelTitle'); }
|
||||
static { this.TunnelLocalAddressInline = new MenuId('TunnelLocalAddressInline'); }
|
||||
static { this.TunnelOriginInline = new MenuId('TunnelOriginInline'); }
|
||||
static { this.ViewItemContext = new MenuId('ViewItemContext'); }
|
||||
static { this.ViewContainerTitle = new MenuId('ViewContainerTitle'); }
|
||||
static { this.ViewContainerTitleContext = new MenuId('ViewContainerTitleContext'); }
|
||||
static { this.ViewTitle = new MenuId('ViewTitle'); }
|
||||
static { this.ViewTitleContext = new MenuId('ViewTitleContext'); }
|
||||
static { this.CommentEditorActions = new MenuId('CommentEditorActions'); }
|
||||
static { this.CommentThreadTitle = new MenuId('CommentThreadTitle'); }
|
||||
static { this.CommentThreadActions = new MenuId('CommentThreadActions'); }
|
||||
static { this.CommentThreadAdditionalActions = new MenuId('CommentThreadAdditionalActions'); }
|
||||
static { this.CommentThreadTitleContext = new MenuId('CommentThreadTitleContext'); }
|
||||
static { this.CommentThreadCommentContext = new MenuId('CommentThreadCommentContext'); }
|
||||
static { this.CommentTitle = new MenuId('CommentTitle'); }
|
||||
static { this.CommentActions = new MenuId('CommentActions'); }
|
||||
static { this.CommentsViewThreadActions = new MenuId('CommentsViewThreadActions'); }
|
||||
static { this.InteractiveToolbar = new MenuId('InteractiveToolbar'); }
|
||||
static { this.InteractiveCellTitle = new MenuId('InteractiveCellTitle'); }
|
||||
static { this.InteractiveCellDelete = new MenuId('InteractiveCellDelete'); }
|
||||
static { this.InteractiveCellExecute = new MenuId('InteractiveCellExecute'); }
|
||||
static { this.InteractiveInputExecute = new MenuId('InteractiveInputExecute'); }
|
||||
static { this.InteractiveInputConfig = new MenuId('InteractiveInputConfig'); }
|
||||
static { this.ReplInputExecute = new MenuId('ReplInputExecute'); }
|
||||
static { this.IssueReporter = new MenuId('IssueReporter'); }
|
||||
static { this.NotebookToolbar = new MenuId('NotebookToolbar'); }
|
||||
static { this.NotebookToolbarContext = new MenuId('NotebookToolbarContext'); }
|
||||
static { this.NotebookStickyScrollContext = new MenuId('NotebookStickyScrollContext'); }
|
||||
static { this.NotebookCellTitle = new MenuId('NotebookCellTitle'); }
|
||||
static { this.NotebookCellDelete = new MenuId('NotebookCellDelete'); }
|
||||
static { this.NotebookCellInsert = new MenuId('NotebookCellInsert'); }
|
||||
static { this.NotebookCellBetween = new MenuId('NotebookCellBetween'); }
|
||||
static { this.NotebookCellListTop = new MenuId('NotebookCellTop'); }
|
||||
static { this.NotebookCellExecute = new MenuId('NotebookCellExecute'); }
|
||||
static { this.NotebookCellExecuteGoTo = new MenuId('NotebookCellExecuteGoTo'); }
|
||||
static { this.NotebookCellExecutePrimary = new MenuId('NotebookCellExecutePrimary'); }
|
||||
static { this.NotebookDiffCellInputTitle = new MenuId('NotebookDiffCellInputTitle'); }
|
||||
static { this.NotebookDiffDocumentMetadata = new MenuId('NotebookDiffDocumentMetadata'); }
|
||||
static { this.NotebookDiffCellMetadataTitle = new MenuId('NotebookDiffCellMetadataTitle'); }
|
||||
static { this.NotebookDiffCellOutputsTitle = new MenuId('NotebookDiffCellOutputsTitle'); }
|
||||
static { this.NotebookOutputToolbar = new MenuId('NotebookOutputToolbar'); }
|
||||
static { this.NotebookOutlineFilter = new MenuId('NotebookOutlineFilter'); }
|
||||
static { this.NotebookOutlineActionMenu = new MenuId('NotebookOutlineActionMenu'); }
|
||||
static { this.NotebookEditorLayoutConfigure = new MenuId('NotebookEditorLayoutConfigure'); }
|
||||
static { this.NotebookKernelSource = new MenuId('NotebookKernelSource'); }
|
||||
static { this.BulkEditTitle = new MenuId('BulkEditTitle'); }
|
||||
static { this.BulkEditContext = new MenuId('BulkEditContext'); }
|
||||
static { this.TimelineItemContext = new MenuId('TimelineItemContext'); }
|
||||
static { this.TimelineTitle = new MenuId('TimelineTitle'); }
|
||||
static { this.TimelineTitleContext = new MenuId('TimelineTitleContext'); }
|
||||
static { this.TimelineFilterSubMenu = new MenuId('TimelineFilterSubMenu'); }
|
||||
static { this.AccountsContext = new MenuId('AccountsContext'); }
|
||||
static { this.SidebarTitle = new MenuId('SidebarTitle'); }
|
||||
static { this.PanelTitle = new MenuId('PanelTitle'); }
|
||||
static { this.AuxiliaryBarTitle = new MenuId('AuxiliaryBarTitle'); }
|
||||
static { this.TerminalInstanceContext = new MenuId('TerminalInstanceContext'); }
|
||||
static { this.TerminalEditorInstanceContext = new MenuId('TerminalEditorInstanceContext'); }
|
||||
static { this.TerminalNewDropdownContext = new MenuId('TerminalNewDropdownContext'); }
|
||||
static { this.TerminalTabContext = new MenuId('TerminalTabContext'); }
|
||||
static { this.TerminalTabEmptyAreaContext = new MenuId('TerminalTabEmptyAreaContext'); }
|
||||
static { this.TerminalStickyScrollContext = new MenuId('TerminalStickyScrollContext'); }
|
||||
static { this.WebviewContext = new MenuId('WebviewContext'); }
|
||||
static { this.InlineCompletionsActions = new MenuId('InlineCompletionsActions'); }
|
||||
static { this.InlineEditsActions = new MenuId('InlineEditsActions'); }
|
||||
static { this.NewFile = new MenuId('NewFile'); }
|
||||
static { this.MergeInput1Toolbar = new MenuId('MergeToolbar1Toolbar'); }
|
||||
static { this.MergeInput2Toolbar = new MenuId('MergeToolbar2Toolbar'); }
|
||||
static { this.MergeBaseToolbar = new MenuId('MergeBaseToolbar'); }
|
||||
static { this.MergeInputResultToolbar = new MenuId('MergeToolbarResultToolbar'); }
|
||||
static { this.InlineSuggestionToolbar = new MenuId('InlineSuggestionToolbar'); }
|
||||
static { this.InlineEditToolbar = new MenuId('InlineEditToolbar'); }
|
||||
static { this.ChatContext = new MenuId('ChatContext'); }
|
||||
static { this.ChatCodeBlock = new MenuId('ChatCodeblock'); }
|
||||
static { this.ChatCompareBlock = new MenuId('ChatCompareBlock'); }
|
||||
static { this.ChatMessageTitle = new MenuId('ChatMessageTitle'); }
|
||||
static { this.ChatHistory = new MenuId('ChatHistory'); }
|
||||
static { this.ChatWelcomeHistoryContext = new MenuId('ChatWelcomeHistoryContext'); }
|
||||
static { this.ChatMessageFooter = new MenuId('ChatMessageFooter'); }
|
||||
static { this.ChatExecute = new MenuId('ChatExecute'); }
|
||||
static { this.ChatExecuteSecondary = new MenuId('ChatExecuteSecondary'); }
|
||||
static { this.ChatInput = new MenuId('ChatInput'); }
|
||||
static { this.ChatInputSide = new MenuId('ChatInputSide'); }
|
||||
static { this.ChatModePicker = new MenuId('ChatModePicker'); }
|
||||
static { this.ChatEditingWidgetToolbar = new MenuId('ChatEditingWidgetToolbar'); }
|
||||
static { this.ChatEditingEditorContent = new MenuId('ChatEditingEditorContent'); }
|
||||
static { this.ChatEditingEditorHunk = new MenuId('ChatEditingEditorHunk'); }
|
||||
static { this.ChatEditingDeletedNotebookCell = new MenuId('ChatEditingDeletedNotebookCell'); }
|
||||
static { this.ChatInputAttachmentToolbar = new MenuId('ChatInputAttachmentToolbar'); }
|
||||
static { this.ChatEditingWidgetModifiedFilesToolbar = new MenuId('ChatEditingWidgetModifiedFilesToolbar'); }
|
||||
static { this.ChatInputResourceAttachmentContext = new MenuId('ChatInputResourceAttachmentContext'); }
|
||||
static { this.ChatInputSymbolAttachmentContext = new MenuId('ChatInputSymbolAttachmentContext'); }
|
||||
static { this.ChatInlineResourceAnchorContext = new MenuId('ChatInlineResourceAnchorContext'); }
|
||||
static { this.ChatInlineSymbolAnchorContext = new MenuId('ChatInlineSymbolAnchorContext'); }
|
||||
static { this.ChatMessageCheckpoint = new MenuId('ChatMessageCheckpoint'); }
|
||||
static { this.ChatMessageRestoreCheckpoint = new MenuId('ChatMessageRestoreCheckpoint'); }
|
||||
static { this.ChatEditingCodeBlockContext = new MenuId('ChatEditingCodeBlockContext'); }
|
||||
static { this.ChatTitleBarMenu = new MenuId('ChatTitleBarMenu'); }
|
||||
static { this.ChatAttachmentsContext = new MenuId('ChatAttachmentsContext'); }
|
||||
static { this.ChatToolOutputResourceToolbar = new MenuId('ChatToolOutputResourceToolbar'); }
|
||||
static { this.ChatTextEditorMenu = new MenuId('ChatTextEditorMenu'); }
|
||||
static { this.ChatToolOutputResourceContext = new MenuId('ChatToolOutputResourceContext'); }
|
||||
static { this.ChatMultiDiffContext = new MenuId('ChatMultiDiffContext'); }
|
||||
static { this.ChatSessionsMenu = new MenuId('ChatSessionsMenu'); }
|
||||
static { this.ChatConfirmationMenu = new MenuId('ChatConfirmationMenu'); }
|
||||
static { this.AccessibleView = new MenuId('AccessibleView'); }
|
||||
static { this.MultiDiffEditorFileToolbar = new MenuId('MultiDiffEditorFileToolbar'); }
|
||||
static { this.DiffEditorHunkToolbar = new MenuId('DiffEditorHunkToolbar'); }
|
||||
static { this.DiffEditorSelectionToolbar = new MenuId('DiffEditorSelectionToolbar'); }
|
||||
/**
|
||||
* Create a new `MenuId` with the unique identifier. Will throw if a menu
|
||||
* with the identifier already exists, use `MenuId.for(ident)` or a unique
|
||||
* identifier
|
||||
*/
|
||||
constructor(identifier) {
|
||||
if (MenuId._instances.has(identifier)) {
|
||||
throw new TypeError(`MenuId with identifier '${identifier}' already exists. Use MenuId.for(ident) or a unique identifier`);
|
||||
}
|
||||
MenuId._instances.set(identifier, this);
|
||||
this.id = identifier;
|
||||
}
|
||||
}
|
||||
export const IMenuService = createDecorator('menuService');
|
||||
class MenuRegistryChangeEvent {
|
||||
static { this._all = new Map(); }
|
||||
static for(id) {
|
||||
let value = this._all.get(id);
|
||||
if (!value) {
|
||||
value = new MenuRegistryChangeEvent(id);
|
||||
this._all.set(id, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
static merge(events) {
|
||||
const ids = new Set();
|
||||
for (const item of events) {
|
||||
if (item instanceof MenuRegistryChangeEvent) {
|
||||
ids.add(item.id);
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
this.has = candidate => candidate === id;
|
||||
}
|
||||
}
|
||||
export const MenuRegistry = new class {
|
||||
constructor() {
|
||||
this._commands = new Map();
|
||||
this._menuItems = new Map();
|
||||
this._onDidChangeMenu = new MicrotaskEmitter({
|
||||
merge: MenuRegistryChangeEvent.merge
|
||||
});
|
||||
this.onDidChangeMenu = this._onDidChangeMenu.event;
|
||||
}
|
||||
addCommand(command) {
|
||||
this._commands.set(command.id, command);
|
||||
this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(MenuId.CommandPalette));
|
||||
return markAsSingleton(toDisposable(() => {
|
||||
if (this._commands.delete(command.id)) {
|
||||
this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(MenuId.CommandPalette));
|
||||
}
|
||||
}));
|
||||
}
|
||||
getCommand(id) {
|
||||
return this._commands.get(id);
|
||||
}
|
||||
getCommands() {
|
||||
const map = new Map();
|
||||
this._commands.forEach((value, key) => map.set(key, value));
|
||||
return map;
|
||||
}
|
||||
appendMenuItem(id, item) {
|
||||
let list = this._menuItems.get(id);
|
||||
if (!list) {
|
||||
list = new LinkedList();
|
||||
this._menuItems.set(id, list);
|
||||
}
|
||||
const rm = list.push(item);
|
||||
this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(id));
|
||||
return markAsSingleton(toDisposable(() => {
|
||||
rm();
|
||||
this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(id));
|
||||
}));
|
||||
}
|
||||
appendMenuItems(items) {
|
||||
const result = new DisposableStore();
|
||||
for (const { id, item } of items) {
|
||||
result.add(this.appendMenuItem(id, item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
getMenuItems(id) {
|
||||
let result;
|
||||
if (this._menuItems.has(id)) {
|
||||
result = [...this._menuItems.get(id)];
|
||||
}
|
||||
else {
|
||||
result = [];
|
||||
}
|
||||
if (id === MenuId.CommandPalette) {
|
||||
// CommandPalette is special because it shows
|
||||
// all commands by default
|
||||
this._appendImplicitItems(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
_appendImplicitItems(result) {
|
||||
const set = new Set();
|
||||
for (const item of result) {
|
||||
if (isIMenuItem(item)) {
|
||||
set.add(item.command.id);
|
||||
if (item.alt) {
|
||||
set.add(item.alt.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._commands.forEach((command, id) => {
|
||||
if (!set.has(id)) {
|
||||
result.push({ command });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
export class SubmenuItemAction extends SubmenuAction {
|
||||
constructor(item, hideActions, actions) {
|
||||
super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, actions, 'submenu');
|
||||
this.item = item;
|
||||
this.hideActions = hideActions;
|
||||
}
|
||||
}
|
||||
// implements IAction, does NOT extend Action, so that no one
|
||||
// subscribes to events of Action or modified properties
|
||||
let MenuItemAction = MenuItemAction_1 = class MenuItemAction {
|
||||
static label(action, options) {
|
||||
return options?.renderShortTitle && action.shortTitle
|
||||
? (typeof action.shortTitle === 'string' ? action.shortTitle : action.shortTitle.value)
|
||||
: (typeof action.title === 'string' ? action.title : action.title.value);
|
||||
}
|
||||
constructor(item, alt, options, hideActions, menuKeybinding, contextKeyService, _commandService) {
|
||||
this.hideActions = hideActions;
|
||||
this.menuKeybinding = menuKeybinding;
|
||||
this._commandService = _commandService;
|
||||
this.id = item.id;
|
||||
this.label = MenuItemAction_1.label(item, options);
|
||||
this.tooltip = (typeof item.tooltip === 'string' ? item.tooltip : item.tooltip?.value) ?? '';
|
||||
this.enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition);
|
||||
this.checked = undefined;
|
||||
let icon;
|
||||
if (item.toggled) {
|
||||
const toggled = (item.toggled.condition ? item.toggled : { condition: item.toggled });
|
||||
this.checked = contextKeyService.contextMatchesRules(toggled.condition);
|
||||
if (this.checked && toggled.tooltip) {
|
||||
this.tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value;
|
||||
}
|
||||
if (this.checked && ThemeIcon.isThemeIcon(toggled.icon)) {
|
||||
icon = toggled.icon;
|
||||
}
|
||||
if (this.checked && toggled.title) {
|
||||
this.label = typeof toggled.title === 'string' ? toggled.title : toggled.title.value;
|
||||
}
|
||||
}
|
||||
if (!icon) {
|
||||
icon = ThemeIcon.isThemeIcon(item.icon) ? item.icon : undefined;
|
||||
}
|
||||
this.item = item;
|
||||
this.alt = alt ? new MenuItemAction_1(alt, undefined, options, hideActions, undefined, contextKeyService, _commandService) : undefined;
|
||||
this._options = options;
|
||||
this.class = icon && ThemeIcon.asClassName(icon);
|
||||
}
|
||||
run(...args) {
|
||||
let runArgs = [];
|
||||
if (this._options?.arg) {
|
||||
runArgs = [...runArgs, this._options.arg];
|
||||
}
|
||||
if (this._options?.shouldForwardArgs) {
|
||||
runArgs = [...runArgs, ...args];
|
||||
}
|
||||
return this._commandService.executeCommand(this.id, ...runArgs);
|
||||
}
|
||||
};
|
||||
MenuItemAction = MenuItemAction_1 = __decorate([
|
||||
__param(5, IContextKeyService),
|
||||
__param(6, ICommandService)
|
||||
], MenuItemAction);
|
||||
export { MenuItemAction };
|
||||
export class Action2 {
|
||||
constructor(desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
export function registerAction2(ctor) {
|
||||
const disposables = []; // not using `DisposableStore` to reduce startup perf cost
|
||||
const action = new ctor();
|
||||
const { f1, menu, keybinding, ...command } = action.desc;
|
||||
if (CommandsRegistry.getCommand(command.id)) {
|
||||
throw new Error(`Cannot register two commands with the same id: ${command.id}`);
|
||||
}
|
||||
// command
|
||||
disposables.push(CommandsRegistry.registerCommand({
|
||||
id: command.id,
|
||||
handler: (accessor, ...args) => action.run(accessor, ...args),
|
||||
metadata: command.metadata ?? { description: action.desc.title }
|
||||
}));
|
||||
// menu
|
||||
if (Array.isArray(menu)) {
|
||||
for (const item of menu) {
|
||||
disposables.push(MenuRegistry.appendMenuItem(item.id, { command: { ...command, precondition: item.precondition === null ? undefined : command.precondition }, ...item }));
|
||||
}
|
||||
}
|
||||
else if (menu) {
|
||||
disposables.push(MenuRegistry.appendMenuItem(menu.id, { command: { ...command, precondition: menu.precondition === null ? undefined : command.precondition }, ...menu }));
|
||||
}
|
||||
if (f1) {
|
||||
disposables.push(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command, when: command.precondition }));
|
||||
disposables.push(MenuRegistry.addCommand(command));
|
||||
}
|
||||
// keybinding
|
||||
if (Array.isArray(keybinding)) {
|
||||
for (const item of keybinding) {
|
||||
disposables.push(KeybindingsRegistry.registerKeybindingRule({
|
||||
...item,
|
||||
id: command.id,
|
||||
when: command.precondition ? ContextKeyExpr.and(command.precondition, item.when) : item.when
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if (keybinding) {
|
||||
disposables.push(KeybindingsRegistry.registerKeybindingRule({
|
||||
...keybinding,
|
||||
id: command.id,
|
||||
when: command.precondition ? ContextKeyExpr.and(command.precondition, keybinding.when) : keybinding.when
|
||||
}));
|
||||
}
|
||||
return {
|
||||
dispose() {
|
||||
dispose(disposables);
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
//# sourceMappingURL=actions.js.map
|
||||
File diff suppressed because one or more lines are too long
435
_internal/editor/esm/vs/platform/actions/common/menuService.js
Normal file
435
_internal/editor/esm/vs/platform/actions/common/menuService.js
Normal file
@@ -0,0 +1,435 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 PersistedMenuHideState_1, MenuInfo_1;
|
||||
import { RunOnceScheduler } from '../../../base/common/async.js';
|
||||
import { DebounceEmitter, Emitter } from '../../../base/common/event.js';
|
||||
import { DisposableStore } from '../../../base/common/lifecycle.js';
|
||||
import { isIMenuItem, isISubmenuItem, MenuItemAction, MenuRegistry, SubmenuItemAction } from './actions.js';
|
||||
import { ICommandService } from '../../commands/common/commands.js';
|
||||
import { IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { Separator, toAction } from '../../../base/common/actions.js';
|
||||
import { IStorageService } from '../../storage/common/storage.js';
|
||||
import { removeFastWithoutKeepingOrder } from '../../../base/common/arrays.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
|
||||
let MenuService = class MenuService {
|
||||
constructor(_commandService, _keybindingService, storageService) {
|
||||
this._commandService = _commandService;
|
||||
this._keybindingService = _keybindingService;
|
||||
this._hiddenStates = new PersistedMenuHideState(storageService);
|
||||
}
|
||||
createMenu(id, contextKeyService, options) {
|
||||
return new MenuImpl(id, this._hiddenStates, { emitEventsForSubmenuChanges: false, eventDebounceDelay: 50, ...options }, this._commandService, this._keybindingService, contextKeyService);
|
||||
}
|
||||
getMenuActions(id, contextKeyService, options) {
|
||||
const menu = new MenuImpl(id, this._hiddenStates, { emitEventsForSubmenuChanges: false, eventDebounceDelay: 50, ...options }, this._commandService, this._keybindingService, contextKeyService);
|
||||
const actions = menu.getActions(options);
|
||||
menu.dispose();
|
||||
return actions;
|
||||
}
|
||||
resetHiddenStates(ids) {
|
||||
this._hiddenStates.reset(ids);
|
||||
}
|
||||
};
|
||||
MenuService = __decorate([
|
||||
__param(0, ICommandService),
|
||||
__param(1, IKeybindingService),
|
||||
__param(2, IStorageService)
|
||||
], MenuService);
|
||||
export { MenuService };
|
||||
let PersistedMenuHideState = class PersistedMenuHideState {
|
||||
static { PersistedMenuHideState_1 = this; }
|
||||
static { this._key = 'menu.hiddenCommands'; }
|
||||
constructor(_storageService) {
|
||||
this._storageService = _storageService;
|
||||
this._disposables = new DisposableStore();
|
||||
this._onDidChange = new Emitter();
|
||||
this.onDidChange = this._onDidChange.event;
|
||||
this._ignoreChangeEvent = false;
|
||||
this._hiddenByDefaultCache = new Map();
|
||||
try {
|
||||
const raw = _storageService.get(PersistedMenuHideState_1._key, 0 /* StorageScope.PROFILE */, '{}');
|
||||
this._data = JSON.parse(raw);
|
||||
}
|
||||
catch (err) {
|
||||
this._data = Object.create(null);
|
||||
}
|
||||
this._disposables.add(_storageService.onDidChangeValue(0 /* StorageScope.PROFILE */, PersistedMenuHideState_1._key, this._disposables)(() => {
|
||||
if (!this._ignoreChangeEvent) {
|
||||
try {
|
||||
const raw = _storageService.get(PersistedMenuHideState_1._key, 0 /* StorageScope.PROFILE */, '{}');
|
||||
this._data = JSON.parse(raw);
|
||||
}
|
||||
catch (err) {
|
||||
console.log('FAILED to read storage after UPDATE', err);
|
||||
}
|
||||
}
|
||||
this._onDidChange.fire();
|
||||
}));
|
||||
}
|
||||
dispose() {
|
||||
this._onDidChange.dispose();
|
||||
this._disposables.dispose();
|
||||
}
|
||||
_isHiddenByDefault(menu, commandId) {
|
||||
return this._hiddenByDefaultCache.get(`${menu.id}/${commandId}`) ?? false;
|
||||
}
|
||||
setDefaultState(menu, commandId, hidden) {
|
||||
this._hiddenByDefaultCache.set(`${menu.id}/${commandId}`, hidden);
|
||||
}
|
||||
isHidden(menu, commandId) {
|
||||
const hiddenByDefault = this._isHiddenByDefault(menu, commandId);
|
||||
const state = this._data[menu.id]?.includes(commandId) ?? false;
|
||||
return hiddenByDefault ? !state : state;
|
||||
}
|
||||
updateHidden(menu, commandId, hidden) {
|
||||
const hiddenByDefault = this._isHiddenByDefault(menu, commandId);
|
||||
if (hiddenByDefault) {
|
||||
hidden = !hidden;
|
||||
}
|
||||
const entries = this._data[menu.id];
|
||||
if (!hidden) {
|
||||
// remove and cleanup
|
||||
if (entries) {
|
||||
const idx = entries.indexOf(commandId);
|
||||
if (idx >= 0) {
|
||||
removeFastWithoutKeepingOrder(entries, idx);
|
||||
}
|
||||
if (entries.length === 0) {
|
||||
delete this._data[menu.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// add unless already added
|
||||
if (!entries) {
|
||||
this._data[menu.id] = [commandId];
|
||||
}
|
||||
else {
|
||||
const idx = entries.indexOf(commandId);
|
||||
if (idx < 0) {
|
||||
entries.push(commandId);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._persist();
|
||||
}
|
||||
reset(menus) {
|
||||
if (menus === undefined) {
|
||||
// reset all
|
||||
this._data = Object.create(null);
|
||||
this._persist();
|
||||
}
|
||||
else {
|
||||
// reset only for a specific menu
|
||||
for (const { id } of menus) {
|
||||
if (this._data[id]) {
|
||||
delete this._data[id];
|
||||
}
|
||||
}
|
||||
this._persist();
|
||||
}
|
||||
}
|
||||
_persist() {
|
||||
try {
|
||||
this._ignoreChangeEvent = true;
|
||||
const raw = JSON.stringify(this._data);
|
||||
this._storageService.store(PersistedMenuHideState_1._key, raw, 0 /* StorageScope.PROFILE */, 0 /* StorageTarget.USER */);
|
||||
}
|
||||
finally {
|
||||
this._ignoreChangeEvent = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
PersistedMenuHideState = PersistedMenuHideState_1 = __decorate([
|
||||
__param(0, IStorageService)
|
||||
], PersistedMenuHideState);
|
||||
class MenuInfoSnapshot {
|
||||
constructor(_id, _collectContextKeysForSubmenus) {
|
||||
this._id = _id;
|
||||
this._collectContextKeysForSubmenus = _collectContextKeysForSubmenus;
|
||||
this._menuGroups = [];
|
||||
this._allMenuIds = new Set();
|
||||
this._structureContextKeys = new Set();
|
||||
this._preconditionContextKeys = new Set();
|
||||
this._toggledContextKeys = new Set();
|
||||
this.refresh();
|
||||
}
|
||||
get allMenuIds() {
|
||||
return this._allMenuIds;
|
||||
}
|
||||
get structureContextKeys() {
|
||||
return this._structureContextKeys;
|
||||
}
|
||||
get preconditionContextKeys() {
|
||||
return this._preconditionContextKeys;
|
||||
}
|
||||
get toggledContextKeys() {
|
||||
return this._toggledContextKeys;
|
||||
}
|
||||
refresh() {
|
||||
// reset
|
||||
this._menuGroups.length = 0;
|
||||
this._allMenuIds.clear();
|
||||
this._structureContextKeys.clear();
|
||||
this._preconditionContextKeys.clear();
|
||||
this._toggledContextKeys.clear();
|
||||
const menuItems = this._sort(MenuRegistry.getMenuItems(this._id));
|
||||
let group;
|
||||
for (const item of menuItems) {
|
||||
// group by groupId
|
||||
const groupName = item.group || '';
|
||||
if (!group || group[0] !== groupName) {
|
||||
group = [groupName, []];
|
||||
this._menuGroups.push(group);
|
||||
}
|
||||
group[1].push(item);
|
||||
// keep keys and submenu ids for eventing
|
||||
this._collectContextKeysAndSubmenuIds(item);
|
||||
}
|
||||
this._allMenuIds.add(this._id);
|
||||
}
|
||||
_sort(menuItems) {
|
||||
// no sorting needed in snapshot
|
||||
return menuItems;
|
||||
}
|
||||
_collectContextKeysAndSubmenuIds(item) {
|
||||
MenuInfoSnapshot._fillInKbExprKeys(item.when, this._structureContextKeys);
|
||||
if (isIMenuItem(item)) {
|
||||
// keep precondition keys for event if applicable
|
||||
if (item.command.precondition) {
|
||||
MenuInfoSnapshot._fillInKbExprKeys(item.command.precondition, this._preconditionContextKeys);
|
||||
}
|
||||
// keep toggled keys for event if applicable
|
||||
if (item.command.toggled) {
|
||||
const toggledExpression = item.command.toggled.condition || item.command.toggled;
|
||||
MenuInfoSnapshot._fillInKbExprKeys(toggledExpression, this._toggledContextKeys);
|
||||
}
|
||||
}
|
||||
else if (this._collectContextKeysForSubmenus) {
|
||||
// recursively collect context keys from submenus so that this
|
||||
// menu fires events when context key changes affect submenus
|
||||
MenuRegistry.getMenuItems(item.submenu).forEach(this._collectContextKeysAndSubmenuIds, this);
|
||||
this._allMenuIds.add(item.submenu);
|
||||
}
|
||||
}
|
||||
static _fillInKbExprKeys(exp, set) {
|
||||
if (exp) {
|
||||
for (const key of exp.keys()) {
|
||||
set.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let MenuInfo = MenuInfo_1 = class MenuInfo extends MenuInfoSnapshot {
|
||||
constructor(_id, _hiddenStates, _collectContextKeysForSubmenus, _commandService, _keybindingService, _contextKeyService) {
|
||||
super(_id, _collectContextKeysForSubmenus);
|
||||
this._hiddenStates = _hiddenStates;
|
||||
this._commandService = _commandService;
|
||||
this._keybindingService = _keybindingService;
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this.refresh();
|
||||
}
|
||||
createActionGroups(options) {
|
||||
const result = [];
|
||||
for (const group of this._menuGroups) {
|
||||
const [id, items] = group;
|
||||
let activeActions;
|
||||
for (const item of items) {
|
||||
if (this._contextKeyService.contextMatchesRules(item.when)) {
|
||||
const isMenuItem = isIMenuItem(item);
|
||||
if (isMenuItem) {
|
||||
this._hiddenStates.setDefaultState(this._id, item.command.id, !!item.isHiddenByDefault);
|
||||
}
|
||||
const menuHide = createMenuHide(this._id, isMenuItem ? item.command : item, this._hiddenStates);
|
||||
if (isMenuItem) {
|
||||
// MenuItemAction
|
||||
const menuKeybinding = createConfigureKeybindingAction(this._commandService, this._keybindingService, item.command.id, item.when);
|
||||
(activeActions ??= []).push(new MenuItemAction(item.command, item.alt, options, menuHide, menuKeybinding, this._contextKeyService, this._commandService));
|
||||
}
|
||||
else {
|
||||
// SubmenuItemAction
|
||||
const groups = new MenuInfo_1(item.submenu, this._hiddenStates, this._collectContextKeysForSubmenus, this._commandService, this._keybindingService, this._contextKeyService).createActionGroups(options);
|
||||
const submenuActions = Separator.join(...groups.map(g => g[1]));
|
||||
if (submenuActions.length > 0) {
|
||||
(activeActions ??= []).push(new SubmenuItemAction(item, menuHide, submenuActions));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (activeActions && activeActions.length > 0) {
|
||||
result.push([id, activeActions]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
_sort(menuItems) {
|
||||
return menuItems.sort(MenuInfo_1._compareMenuItems);
|
||||
}
|
||||
static _compareMenuItems(a, b) {
|
||||
const aGroup = a.group;
|
||||
const bGroup = b.group;
|
||||
if (aGroup !== bGroup) {
|
||||
// Falsy groups come last
|
||||
if (!aGroup) {
|
||||
return 1;
|
||||
}
|
||||
else if (!bGroup) {
|
||||
return -1;
|
||||
}
|
||||
// 'navigation' group comes first
|
||||
if (aGroup === 'navigation') {
|
||||
return -1;
|
||||
}
|
||||
else if (bGroup === 'navigation') {
|
||||
return 1;
|
||||
}
|
||||
// lexical sort for groups
|
||||
const value = aGroup.localeCompare(bGroup);
|
||||
if (value !== 0) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
// sort on priority - default is 0
|
||||
const aPrio = a.order || 0;
|
||||
const bPrio = b.order || 0;
|
||||
if (aPrio < bPrio) {
|
||||
return -1;
|
||||
}
|
||||
else if (aPrio > bPrio) {
|
||||
return 1;
|
||||
}
|
||||
// sort on titles
|
||||
return MenuInfo_1._compareTitles(isIMenuItem(a) ? a.command.title : a.title, isIMenuItem(b) ? b.command.title : b.title);
|
||||
}
|
||||
static _compareTitles(a, b) {
|
||||
const aStr = typeof a === 'string' ? a : a.original;
|
||||
const bStr = typeof b === 'string' ? b : b.original;
|
||||
return aStr.localeCompare(bStr);
|
||||
}
|
||||
};
|
||||
MenuInfo = MenuInfo_1 = __decorate([
|
||||
__param(3, ICommandService),
|
||||
__param(4, IKeybindingService),
|
||||
__param(5, IContextKeyService)
|
||||
], MenuInfo);
|
||||
let MenuImpl = class MenuImpl {
|
||||
constructor(id, hiddenStates, options, commandService, keybindingService, contextKeyService) {
|
||||
this._disposables = new DisposableStore();
|
||||
this._menuInfo = new MenuInfo(id, hiddenStates, options.emitEventsForSubmenuChanges, commandService, keybindingService, contextKeyService);
|
||||
// Rebuild this menu whenever the menu registry reports an event for this MenuId.
|
||||
// This usually happen while code and extensions are loaded and affects the over
|
||||
// structure of the menu
|
||||
const rebuildMenuSoon = new RunOnceScheduler(() => {
|
||||
this._menuInfo.refresh();
|
||||
this._onDidChange.fire({ menu: this, isStructuralChange: true, isEnablementChange: true, isToggleChange: true });
|
||||
}, options.eventDebounceDelay);
|
||||
this._disposables.add(rebuildMenuSoon);
|
||||
this._disposables.add(MenuRegistry.onDidChangeMenu(e => {
|
||||
for (const id of this._menuInfo.allMenuIds) {
|
||||
if (e.has(id)) {
|
||||
rebuildMenuSoon.schedule();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}));
|
||||
// When context keys or storage state changes we need to check if the menu also has changed. However,
|
||||
// we only do that when someone listens on this menu because (1) these events are
|
||||
// firing often and (2) menu are often leaked
|
||||
const lazyListener = this._disposables.add(new DisposableStore());
|
||||
const merge = (events) => {
|
||||
let isStructuralChange = false;
|
||||
let isEnablementChange = false;
|
||||
let isToggleChange = false;
|
||||
for (const item of events) {
|
||||
isStructuralChange = isStructuralChange || item.isStructuralChange;
|
||||
isEnablementChange = isEnablementChange || item.isEnablementChange;
|
||||
isToggleChange = isToggleChange || item.isToggleChange;
|
||||
if (isStructuralChange && isEnablementChange && isToggleChange) {
|
||||
// everything is TRUE, no need to continue iterating
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { menu: this, isStructuralChange, isEnablementChange, isToggleChange };
|
||||
};
|
||||
const startLazyListener = () => {
|
||||
lazyListener.add(contextKeyService.onDidChangeContext(e => {
|
||||
const isStructuralChange = e.affectsSome(this._menuInfo.structureContextKeys);
|
||||
const isEnablementChange = e.affectsSome(this._menuInfo.preconditionContextKeys);
|
||||
const isToggleChange = e.affectsSome(this._menuInfo.toggledContextKeys);
|
||||
if (isStructuralChange || isEnablementChange || isToggleChange) {
|
||||
this._onDidChange.fire({ menu: this, isStructuralChange, isEnablementChange, isToggleChange });
|
||||
}
|
||||
}));
|
||||
lazyListener.add(hiddenStates.onDidChange(e => {
|
||||
this._onDidChange.fire({ menu: this, isStructuralChange: true, isEnablementChange: false, isToggleChange: false });
|
||||
}));
|
||||
};
|
||||
this._onDidChange = new DebounceEmitter({
|
||||
// start/stop context key listener
|
||||
onWillAddFirstListener: startLazyListener,
|
||||
onDidRemoveLastListener: lazyListener.clear.bind(lazyListener),
|
||||
delay: options.eventDebounceDelay,
|
||||
merge
|
||||
});
|
||||
this.onDidChange = this._onDidChange.event;
|
||||
}
|
||||
getActions(options) {
|
||||
return this._menuInfo.createActionGroups(options);
|
||||
}
|
||||
dispose() {
|
||||
this._disposables.dispose();
|
||||
this._onDidChange.dispose();
|
||||
}
|
||||
};
|
||||
MenuImpl = __decorate([
|
||||
__param(3, ICommandService),
|
||||
__param(4, IKeybindingService),
|
||||
__param(5, IContextKeyService)
|
||||
], MenuImpl);
|
||||
function createMenuHide(menu, command, states) {
|
||||
const id = isISubmenuItem(command) ? command.submenu.id : command.id;
|
||||
const title = typeof command.title === 'string' ? command.title : command.title.value;
|
||||
const hide = toAction({
|
||||
id: `hide/${menu.id}/${id}`,
|
||||
label: localize(1636, 'Hide \'{0}\'', title),
|
||||
run() { states.updateHidden(menu, id, true); }
|
||||
});
|
||||
const toggle = toAction({
|
||||
id: `toggle/${menu.id}/${id}`,
|
||||
label: title,
|
||||
get checked() { return !states.isHidden(menu, id); },
|
||||
run() { states.updateHidden(menu, id, !!this.checked); }
|
||||
});
|
||||
return {
|
||||
hide,
|
||||
toggle,
|
||||
get isHidden() { return !toggle.checked; },
|
||||
};
|
||||
}
|
||||
export function createConfigureKeybindingAction(commandService, keybindingService, commandId, when = undefined, enabled = true) {
|
||||
return toAction({
|
||||
id: `configureKeybinding/${commandId}`,
|
||||
label: localize(1637, "Configure Keybinding"),
|
||||
enabled,
|
||||
run() {
|
||||
// Only set the when clause when there is no keybinding
|
||||
// It is possible that the action and the keybinding have different when clauses
|
||||
const hasKeybinding = !!keybindingService.lookupKeybinding(commandId); // This may only be called inside the `run()` method as it can be expensive on startup. #210529
|
||||
const whenValue = !hasKeybinding && when ? when.serialize() : undefined;
|
||||
commandService.executeCommand('workbench.action.openGlobalKeybindings', `@command:${commandId}` + (whenValue ? ` +when:${whenValue}` : ''));
|
||||
}
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=menuService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,214 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 BrowserClipboardService_1;
|
||||
import { isSafari, isWebkitWebView } from '../../../base/browser/browser.js';
|
||||
import { $, addDisposableListener, getActiveDocument, getActiveWindow, isHTMLElement, onDidRegisterWindow } from '../../../base/browser/dom.js';
|
||||
import { mainWindow } from '../../../base/browser/window.js';
|
||||
import { DeferredPromise } from '../../../base/common/async.js';
|
||||
import { Event } from '../../../base/common/event.js';
|
||||
import { hash } from '../../../base/common/hash.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { ILayoutService } from '../../layout/browser/layoutService.js';
|
||||
import { ILogService } from '../../log/common/log.js';
|
||||
/**
|
||||
* Custom mime type used for storing a list of uris in the clipboard.
|
||||
*
|
||||
* Requires support for custom web clipboards https://github.com/w3c/clipboard-apis/pull/175
|
||||
*/
|
||||
const vscodeResourcesMime = 'application/vnd.code.resources';
|
||||
let BrowserClipboardService = class BrowserClipboardService extends Disposable {
|
||||
static { BrowserClipboardService_1 = this; }
|
||||
constructor(layoutService, logService) {
|
||||
super();
|
||||
this.layoutService = layoutService;
|
||||
this.logService = logService;
|
||||
this.mapTextToType = new Map(); // unsupported in web (only in-memory)
|
||||
this.findText = ''; // unsupported in web (only in-memory)
|
||||
this.resources = []; // unsupported in web (only in-memory)
|
||||
this.resourcesStateHash = undefined;
|
||||
if (isSafari || isWebkitWebView) {
|
||||
this.installWebKitWriteTextWorkaround();
|
||||
}
|
||||
// Keep track of copy operations to reset our set of
|
||||
// copied resources: since we keep resources in memory
|
||||
// and not in the clipboard, we have to invalidate
|
||||
// that state when the user copies other data.
|
||||
this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => {
|
||||
disposables.add(addDisposableListener(window.document, 'copy', () => this.clearResourcesState()));
|
||||
}, { window: mainWindow, disposables: this._store }));
|
||||
}
|
||||
triggerPaste() {
|
||||
this.logService.trace('BrowserClipboardService#triggerPaste');
|
||||
return undefined;
|
||||
}
|
||||
// In Safari, it has the following note:
|
||||
//
|
||||
// "The request to write to the clipboard must be triggered during a user gesture.
|
||||
// A call to clipboard.write or clipboard.writeText outside the scope of a user
|
||||
// gesture(such as "click" or "touch" event handlers) will result in the immediate
|
||||
// rejection of the promise returned by the API call."
|
||||
// From: https://webkit.org/blog/10855/async-clipboard-api/
|
||||
//
|
||||
// Since extensions run in a web worker, and handle gestures in an asynchronous way,
|
||||
// they are not classified by Safari as "in response to a user gesture" and will reject.
|
||||
//
|
||||
// This function sets up some handlers to work around that behavior.
|
||||
installWebKitWriteTextWorkaround() {
|
||||
const handler = () => {
|
||||
const currentWritePromise = new DeferredPromise();
|
||||
// Cancel the previous promise since we just created a new one in response to this new event
|
||||
if (this.webKitPendingClipboardWritePromise && !this.webKitPendingClipboardWritePromise.isSettled) {
|
||||
this.webKitPendingClipboardWritePromise.cancel();
|
||||
}
|
||||
this.webKitPendingClipboardWritePromise = currentWritePromise;
|
||||
// The ctor of ClipboardItem allows you to pass in a promise that will resolve to a string.
|
||||
// This allows us to pass in a Promise that will either be cancelled by another event or
|
||||
// resolved with the contents of the first call to this.writeText.
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#parameters
|
||||
getActiveWindow().navigator.clipboard.write([new ClipboardItem({
|
||||
'text/plain': currentWritePromise.p,
|
||||
})]).catch(async (err) => {
|
||||
if (!(err instanceof Error) || err.name !== 'NotAllowedError' || !currentWritePromise.isRejected) {
|
||||
this.logService.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
this._register(Event.runAndSubscribe(this.layoutService.onDidAddContainer, ({ container, disposables }) => {
|
||||
disposables.add(addDisposableListener(container, 'click', handler));
|
||||
disposables.add(addDisposableListener(container, 'keydown', handler));
|
||||
}, { container: this.layoutService.mainContainer, disposables: this._store }));
|
||||
}
|
||||
async writeText(text, type) {
|
||||
this.logService.trace('BrowserClipboardService#writeText called with type:', type, ' text.length:', text.length);
|
||||
// Clear resources given we are writing text
|
||||
this.clearResourcesState();
|
||||
// With type: only in-memory is supported
|
||||
if (type) {
|
||||
this.mapTextToType.set(type, text);
|
||||
this.logService.trace('BrowserClipboardService#writeText');
|
||||
return;
|
||||
}
|
||||
if (this.webKitPendingClipboardWritePromise) {
|
||||
// For Safari, we complete this Promise which allows the call to `navigator.clipboard.write()`
|
||||
// above to resolve and successfully copy to the clipboard. If we let this continue, Safari
|
||||
// would throw an error because this call stack doesn't appear to originate from a user gesture.
|
||||
return this.webKitPendingClipboardWritePromise.complete(text);
|
||||
}
|
||||
// Guard access to navigator.clipboard with try/catch
|
||||
// as we have seen DOMExceptions in certain browsers
|
||||
// due to security policies.
|
||||
try {
|
||||
this.logService.trace('before navigator.clipboard.writeText');
|
||||
return await getActiveWindow().navigator.clipboard.writeText(text);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
// Fallback to textarea and execCommand solution
|
||||
this.fallbackWriteText(text);
|
||||
}
|
||||
fallbackWriteText(text) {
|
||||
this.logService.trace('BrowserClipboardService#fallbackWriteText');
|
||||
const activeDocument = getActiveDocument();
|
||||
const activeElement = activeDocument.activeElement;
|
||||
const textArea = activeDocument.body.appendChild($('textarea', { 'aria-hidden': true }));
|
||||
textArea.style.height = '1px';
|
||||
textArea.style.width = '1px';
|
||||
textArea.style.position = 'absolute';
|
||||
textArea.value = text;
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
activeDocument.execCommand('copy');
|
||||
if (isHTMLElement(activeElement)) {
|
||||
activeElement.focus();
|
||||
}
|
||||
textArea.remove();
|
||||
}
|
||||
async readText(type) {
|
||||
this.logService.trace('BrowserClipboardService#readText called with type:', type);
|
||||
// With type: only in-memory is supported
|
||||
if (type) {
|
||||
const readText = this.mapTextToType.get(type) || '';
|
||||
this.logService.trace('BrowserClipboardService#readText text.length:', readText.length);
|
||||
return readText;
|
||||
}
|
||||
// Guard access to navigator.clipboard with try/catch
|
||||
// as we have seen DOMExceptions in certain browsers
|
||||
// due to security policies.
|
||||
try {
|
||||
const readText = await getActiveWindow().navigator.clipboard.readText();
|
||||
this.logService.trace('BrowserClipboardService#readText text.length:', readText.length);
|
||||
return readText;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
async readFindText() {
|
||||
return this.findText;
|
||||
}
|
||||
async writeFindText(text) {
|
||||
this.findText = text;
|
||||
}
|
||||
static { this.MAX_RESOURCE_STATE_SOURCE_LENGTH = 1000; }
|
||||
async readResources() {
|
||||
// Guard access to navigator.clipboard with try/catch
|
||||
// as we have seen DOMExceptions in certain browsers
|
||||
// due to security policies.
|
||||
try {
|
||||
const items = await getActiveWindow().navigator.clipboard.read();
|
||||
for (const item of items) {
|
||||
if (item.types.includes(`web ${vscodeResourcesMime}`)) {
|
||||
const blob = await item.getType(`web ${vscodeResourcesMime}`);
|
||||
const resources = JSON.parse(await blob.text()).map(x => URI.from(x));
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// Noop
|
||||
}
|
||||
const resourcesStateHash = await this.computeResourcesStateHash();
|
||||
if (this.resourcesStateHash !== resourcesStateHash) {
|
||||
this.clearResourcesState(); // state mismatch, resources no longer valid
|
||||
}
|
||||
return this.resources;
|
||||
}
|
||||
async computeResourcesStateHash() {
|
||||
if (this.resources.length === 0) {
|
||||
return undefined; // no resources, no hash needed
|
||||
}
|
||||
// Resources clipboard is managed in-memory only and thus
|
||||
// fails to invalidate when clipboard data is changing.
|
||||
// As such, we compute the hash of the current clipboard
|
||||
// and use that to later validate the resources clipboard.
|
||||
const clipboardText = await this.readText();
|
||||
return hash(clipboardText.substring(0, BrowserClipboardService_1.MAX_RESOURCE_STATE_SOURCE_LENGTH));
|
||||
}
|
||||
clearInternalState() {
|
||||
this.clearResourcesState();
|
||||
}
|
||||
clearResourcesState() {
|
||||
this.resources = [];
|
||||
this.resourcesStateHash = undefined;
|
||||
}
|
||||
};
|
||||
BrowserClipboardService = BrowserClipboardService_1 = __decorate([
|
||||
__param(0, ILayoutService),
|
||||
__param(1, ILogService)
|
||||
], BrowserClipboardService);
|
||||
export { BrowserClipboardService };
|
||||
//# sourceMappingURL=clipboardService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IClipboardService = createDecorator('clipboardService');
|
||||
//# sourceMappingURL=clipboardService.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/clipboard/common/clipboardService.ts","vs/platform/clipboard/common/clipboardService.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAGhG,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAE9E,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAoB,kBAAkB,CAAC,CAAC","file":"clipboardService.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IClipboardService = createDecorator<IClipboardService>('clipboardService');\n\nexport interface IClipboardService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Trigger the paste. Returns undefined if the paste was not triggered or a promise that resolves on paste end.\n\t */\n\ttriggerPaste(targetWindowId: number): Promise<void> | undefined;\n\n\t/**\n\t * Writes text to the system clipboard.\n\t */\n\twriteText(text: string, type?: string): Promise<void>;\n\n\t/**\n\t * Reads the content of the clipboard in plain text\n\t */\n\treadText(type?: string): Promise<string>;\n\n\t/**\n\t * Reads text from the system find pasteboard.\n\t */\n\treadFindText(): Promise<string>;\n\n\t/**\n\t * Writes text to the system find pasteboard.\n\t */\n\twriteFindText(text: string): Promise<void>;\n\n\t/**\n\t * Reads resources from the system clipboard.\n\t */\n\treadResources(): Promise<URI[]>;\n\n\t/**\n\t * Resets the internal state of the clipboard (if any) without touching the real clipboard.\n\t *\n\t * Used for implementations such as web which do not always support using the real clipboard.\n\t */\n\tclearInternalState?(): void;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IClipboardService = createDecorator<IClipboardService>('clipboardService');\n\nexport interface IClipboardService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Trigger the paste. Returns undefined if the paste was not triggered or a promise that resolves on paste end.\n\t */\n\ttriggerPaste(targetWindowId: number): Promise<void> | undefined;\n\n\t/**\n\t * Writes text to the system clipboard.\n\t */\n\twriteText(text: string, type?: string): Promise<void>;\n\n\t/**\n\t * Reads the content of the clipboard in plain text\n\t */\n\treadText(type?: string): Promise<string>;\n\n\t/**\n\t * Reads text from the system find pasteboard.\n\t */\n\treadFindText(): Promise<string>;\n\n\t/**\n\t * Writes text to the system find pasteboard.\n\t */\n\twriteFindText(text: string): Promise<void>;\n\n\t/**\n\t * Reads resources from the system clipboard.\n\t */\n\treadResources(): Promise<URI[]>;\n\n\t/**\n\t * Resets the internal state of the clipboard (if any) without touching the real clipboard.\n\t *\n\t * Used for implementations such as web which do not always support using the real clipboard.\n\t */\n\tclearInternalState?(): void;\n}\n"]}
|
||||
81
_internal/editor/esm/vs/platform/commands/common/commands.js
Normal file
81
_internal/editor/esm/vs/platform/commands/common/commands.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Iterable } from '../../../base/common/iterator.js';
|
||||
import { markAsSingleton, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { LinkedList } from '../../../base/common/linkedList.js';
|
||||
import { validateConstraints } from '../../../base/common/types.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const ICommandService = createDecorator('commandService');
|
||||
export const CommandsRegistry = new class {
|
||||
constructor() {
|
||||
this._commands = new Map();
|
||||
this._onDidRegisterCommand = new Emitter();
|
||||
this.onDidRegisterCommand = this._onDidRegisterCommand.event;
|
||||
}
|
||||
registerCommand(idOrCommand, handler) {
|
||||
if (!idOrCommand) {
|
||||
throw new Error(`invalid command`);
|
||||
}
|
||||
if (typeof idOrCommand === 'string') {
|
||||
if (!handler) {
|
||||
throw new Error(`invalid command`);
|
||||
}
|
||||
return this.registerCommand({ id: idOrCommand, handler });
|
||||
}
|
||||
// add argument validation if rich command metadata is provided
|
||||
if (idOrCommand.metadata && Array.isArray(idOrCommand.metadata.args)) {
|
||||
const constraints = [];
|
||||
for (const arg of idOrCommand.metadata.args) {
|
||||
constraints.push(arg.constraint);
|
||||
}
|
||||
const actualHandler = idOrCommand.handler;
|
||||
idOrCommand.handler = function (accessor, ...args) {
|
||||
validateConstraints(args, constraints);
|
||||
return actualHandler(accessor, ...args);
|
||||
};
|
||||
}
|
||||
// find a place to store the command
|
||||
const { id } = idOrCommand;
|
||||
let commands = this._commands.get(id);
|
||||
if (!commands) {
|
||||
commands = new LinkedList();
|
||||
this._commands.set(id, commands);
|
||||
}
|
||||
const removeFn = commands.unshift(idOrCommand);
|
||||
const ret = toDisposable(() => {
|
||||
removeFn();
|
||||
const command = this._commands.get(id);
|
||||
if (command?.isEmpty()) {
|
||||
this._commands.delete(id);
|
||||
}
|
||||
});
|
||||
// tell the world about this command
|
||||
this._onDidRegisterCommand.fire(id);
|
||||
return markAsSingleton(ret);
|
||||
}
|
||||
registerCommandAlias(oldId, newId) {
|
||||
return CommandsRegistry.registerCommand(oldId, (accessor, ...args) => accessor.get(ICommandService).executeCommand(newId, ...args));
|
||||
}
|
||||
getCommand(id) {
|
||||
const list = this._commands.get(id);
|
||||
if (!list || list.isEmpty()) {
|
||||
return undefined;
|
||||
}
|
||||
return Iterable.first(list);
|
||||
}
|
||||
getCommands() {
|
||||
const result = new Map();
|
||||
for (const key of this._commands.keys()) {
|
||||
const command = this.getCommand(key);
|
||||
if (command) {
|
||||
result.set(key, command);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
CommandsRegistry.registerCommand('noop', () => { });
|
||||
//# sourceMappingURL=commands.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,90 @@
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IConfigurationService = createDecorator('configurationService');
|
||||
export function toValuesTree(properties, conflictReporter) {
|
||||
const root = Object.create(null);
|
||||
for (const key in properties) {
|
||||
addToValueTree(root, key, properties[key], conflictReporter);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
export function addToValueTree(settingsTreeRoot, key, value, conflictReporter) {
|
||||
const segments = key.split('.');
|
||||
const last = segments.pop();
|
||||
let curr = settingsTreeRoot;
|
||||
for (let i = 0; i < segments.length; i++) {
|
||||
const s = segments[i];
|
||||
let obj = curr[s];
|
||||
switch (typeof obj) {
|
||||
case 'undefined':
|
||||
obj = curr[s] = Object.create(null);
|
||||
break;
|
||||
case 'object':
|
||||
if (obj === null) {
|
||||
conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is null`);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`);
|
||||
return;
|
||||
}
|
||||
curr = obj;
|
||||
}
|
||||
if (typeof curr === 'object' && curr !== null) {
|
||||
try {
|
||||
curr[last] = value; // workaround https://github.com/microsoft/vscode/issues/13606
|
||||
}
|
||||
catch (e) {
|
||||
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
|
||||
}
|
||||
}
|
||||
export function removeFromValueTree(valueTree, key) {
|
||||
const segments = key.split('.');
|
||||
doRemoveFromValueTree(valueTree, segments);
|
||||
}
|
||||
function doRemoveFromValueTree(valueTree, segments) {
|
||||
if (!valueTree) {
|
||||
return;
|
||||
}
|
||||
const first = segments.shift();
|
||||
if (segments.length === 0) {
|
||||
// Reached last segment
|
||||
delete valueTree[first];
|
||||
return;
|
||||
}
|
||||
if (Object.keys(valueTree).indexOf(first) !== -1) {
|
||||
const value = valueTree[first];
|
||||
if (typeof value === 'object' && !Array.isArray(value)) {
|
||||
doRemoveFromValueTree(value, segments);
|
||||
if (Object.keys(value).length === 0) {
|
||||
delete valueTree[first];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export function getConfigurationValue(config, settingPath, defaultValue) {
|
||||
function accessSetting(config, path) {
|
||||
let current = config;
|
||||
for (const component of path) {
|
||||
if (typeof current !== 'object' || current === null) {
|
||||
return undefined;
|
||||
}
|
||||
current = current[component];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
const path = settingPath.split('.');
|
||||
const result = accessSetting(config, path);
|
||||
return typeof result === 'undefined' ? defaultValue : result;
|
||||
}
|
||||
export function getLanguageTagSettingPlainKey(settingKey) {
|
||||
return settingKey
|
||||
.replace(/^\[/, '')
|
||||
.replace(/]$/g, '')
|
||||
.replace(/\]\[/g, ', ');
|
||||
}
|
||||
//# sourceMappingURL=configuration.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,612 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as arrays from '../../../base/common/arrays.js';
|
||||
import { ResourceMap } from '../../../base/common/map.js';
|
||||
import * as objects from '../../../base/common/objects.js';
|
||||
import * as types from '../../../base/common/types.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { addToValueTree, getConfigurationValue, removeFromValueTree, toValuesTree } from './configuration.js';
|
||||
import { Extensions, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX } from './configurationRegistry.js';
|
||||
import { Registry } from '../../registry/common/platform.js';
|
||||
function freeze(data) {
|
||||
return Object.isFrozen(data) ? data : objects.deepFreeze(data);
|
||||
}
|
||||
export class ConfigurationModel {
|
||||
static createEmptyModel(logService) {
|
||||
return new ConfigurationModel({}, [], [], undefined, logService);
|
||||
}
|
||||
constructor(_contents, _keys, _overrides, raw, logService) {
|
||||
this._contents = _contents;
|
||||
this._keys = _keys;
|
||||
this._overrides = _overrides;
|
||||
this.raw = raw;
|
||||
this.logService = logService;
|
||||
this.overrideConfigurations = new Map();
|
||||
}
|
||||
get rawConfiguration() {
|
||||
if (!this._rawConfiguration) {
|
||||
if (this.raw) {
|
||||
const rawConfigurationModels = (Array.isArray(this.raw) ? this.raw : [this.raw]).map(raw => {
|
||||
if (raw instanceof ConfigurationModel) {
|
||||
return raw;
|
||||
}
|
||||
const parser = new ConfigurationModelParser('', this.logService);
|
||||
parser.parseRaw(raw);
|
||||
return parser.configurationModel;
|
||||
});
|
||||
this._rawConfiguration = rawConfigurationModels.reduce((previous, current) => current === previous ? current : previous.merge(current), rawConfigurationModels[0]);
|
||||
}
|
||||
else {
|
||||
// raw is same as current
|
||||
this._rawConfiguration = this;
|
||||
}
|
||||
}
|
||||
return this._rawConfiguration;
|
||||
}
|
||||
get contents() {
|
||||
return this._contents;
|
||||
}
|
||||
get overrides() {
|
||||
return this._overrides;
|
||||
}
|
||||
get keys() {
|
||||
return this._keys;
|
||||
}
|
||||
isEmpty() {
|
||||
return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;
|
||||
}
|
||||
getValue(section) {
|
||||
return section ? getConfigurationValue(this.contents, section) : this.contents;
|
||||
}
|
||||
inspect(section, overrideIdentifier) {
|
||||
const that = this;
|
||||
return {
|
||||
get value() {
|
||||
return freeze(that.rawConfiguration.getValue(section));
|
||||
},
|
||||
get override() {
|
||||
return overrideIdentifier ? freeze(that.rawConfiguration.getOverrideValue(section, overrideIdentifier)) : undefined;
|
||||
},
|
||||
get merged() {
|
||||
return freeze(overrideIdentifier ? that.rawConfiguration.override(overrideIdentifier).getValue(section) : that.rawConfiguration.getValue(section));
|
||||
},
|
||||
get overrides() {
|
||||
const overrides = [];
|
||||
for (const { contents, identifiers, keys } of that.rawConfiguration.overrides) {
|
||||
const value = new ConfigurationModel(contents, keys, [], undefined, that.logService).getValue(section);
|
||||
if (value !== undefined) {
|
||||
overrides.push({ identifiers, value });
|
||||
}
|
||||
}
|
||||
return overrides.length ? freeze(overrides) : undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
getOverrideValue(section, overrideIdentifier) {
|
||||
const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);
|
||||
return overrideContents
|
||||
? section ? getConfigurationValue(overrideContents, section) : overrideContents
|
||||
: undefined;
|
||||
}
|
||||
override(identifier) {
|
||||
let overrideConfigurationModel = this.overrideConfigurations.get(identifier);
|
||||
if (!overrideConfigurationModel) {
|
||||
overrideConfigurationModel = this.createOverrideConfigurationModel(identifier);
|
||||
this.overrideConfigurations.set(identifier, overrideConfigurationModel);
|
||||
}
|
||||
return overrideConfigurationModel;
|
||||
}
|
||||
merge(...others) {
|
||||
const contents = objects.deepClone(this.contents);
|
||||
const overrides = objects.deepClone(this.overrides);
|
||||
const keys = [...this.keys];
|
||||
const raws = this.raw ? Array.isArray(this.raw) ? [...this.raw] : [this.raw] : [this];
|
||||
for (const other of others) {
|
||||
raws.push(...(other.raw ? Array.isArray(other.raw) ? other.raw : [other.raw] : [other]));
|
||||
if (other.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
this.mergeContents(contents, other.contents);
|
||||
for (const otherOverride of other.overrides) {
|
||||
const [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers));
|
||||
if (override) {
|
||||
this.mergeContents(override.contents, otherOverride.contents);
|
||||
override.keys.push(...otherOverride.keys);
|
||||
override.keys = arrays.distinct(override.keys);
|
||||
}
|
||||
else {
|
||||
overrides.push(objects.deepClone(otherOverride));
|
||||
}
|
||||
}
|
||||
for (const key of other.keys) {
|
||||
if (keys.indexOf(key) === -1) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ConfigurationModel(contents, keys, overrides, !raws.length || raws.every(raw => raw instanceof ConfigurationModel) ? undefined : raws, this.logService);
|
||||
}
|
||||
createOverrideConfigurationModel(identifier) {
|
||||
const overrideContents = this.getContentsForOverrideIdentifer(identifier);
|
||||
if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) {
|
||||
// If there are no valid overrides, return self
|
||||
return this;
|
||||
}
|
||||
const contents = {};
|
||||
for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) {
|
||||
let contentsForKey = this.contents[key];
|
||||
const overrideContentsForKey = overrideContents[key];
|
||||
// If there are override contents for the key, clone and merge otherwise use base contents
|
||||
if (overrideContentsForKey) {
|
||||
// Clone and merge only if base contents and override contents are of type object otherwise just override
|
||||
if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') {
|
||||
contentsForKey = objects.deepClone(contentsForKey);
|
||||
this.mergeContents(contentsForKey, overrideContentsForKey);
|
||||
}
|
||||
else {
|
||||
contentsForKey = overrideContentsForKey;
|
||||
}
|
||||
}
|
||||
contents[key] = contentsForKey;
|
||||
}
|
||||
return new ConfigurationModel(contents, this.keys, this.overrides, undefined, this.logService);
|
||||
}
|
||||
mergeContents(source, target) {
|
||||
for (const key of Object.keys(target)) {
|
||||
if (key in source) {
|
||||
if (types.isObject(source[key]) && types.isObject(target[key])) {
|
||||
this.mergeContents(source[key], target[key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
source[key] = objects.deepClone(target[key]);
|
||||
}
|
||||
}
|
||||
getContentsForOverrideIdentifer(identifier) {
|
||||
let contentsForIdentifierOnly = null;
|
||||
let contents = null;
|
||||
const mergeContents = (contentsToMerge) => {
|
||||
if (contentsToMerge) {
|
||||
if (contents) {
|
||||
this.mergeContents(contents, contentsToMerge);
|
||||
}
|
||||
else {
|
||||
contents = objects.deepClone(contentsToMerge);
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const override of this.overrides) {
|
||||
if (override.identifiers.length === 1 && override.identifiers[0] === identifier) {
|
||||
contentsForIdentifierOnly = override.contents;
|
||||
}
|
||||
else if (override.identifiers.includes(identifier)) {
|
||||
mergeContents(override.contents);
|
||||
}
|
||||
}
|
||||
// Merge contents of the identifier only at the end to take precedence.
|
||||
mergeContents(contentsForIdentifierOnly);
|
||||
return contents;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
contents: this.contents,
|
||||
overrides: this.overrides,
|
||||
keys: this.keys
|
||||
};
|
||||
}
|
||||
setValue(key, value) {
|
||||
this.updateValue(key, value, false);
|
||||
}
|
||||
removeValue(key) {
|
||||
const index = this.keys.indexOf(key);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
this.keys.splice(index, 1);
|
||||
removeFromValueTree(this.contents, key);
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
this.overrides.splice(this.overrides.findIndex(o => arrays.equals(o.identifiers, overrideIdentifiersFromKey(key))), 1);
|
||||
}
|
||||
}
|
||||
updateValue(key, value, add) {
|
||||
addToValueTree(this.contents, key, value, e => this.logService.error(e));
|
||||
add = add || this.keys.indexOf(key) === -1;
|
||||
if (add) {
|
||||
this.keys.push(key);
|
||||
}
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
const identifiers = overrideIdentifiersFromKey(key);
|
||||
const override = {
|
||||
identifiers,
|
||||
keys: Object.keys(this.contents[key]),
|
||||
contents: toValuesTree(this.contents[key], message => this.logService.error(message)),
|
||||
};
|
||||
const index = this.overrides.findIndex(o => arrays.equals(o.identifiers, identifiers));
|
||||
if (index !== -1) {
|
||||
this.overrides[index] = override;
|
||||
}
|
||||
else {
|
||||
this.overrides.push(override);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export class ConfigurationModelParser {
|
||||
constructor(_name, logService) {
|
||||
this._name = _name;
|
||||
this.logService = logService;
|
||||
this._raw = null;
|
||||
this._configurationModel = null;
|
||||
this._restrictedConfigurations = [];
|
||||
}
|
||||
get configurationModel() {
|
||||
return this._configurationModel || ConfigurationModel.createEmptyModel(this.logService);
|
||||
}
|
||||
parseRaw(raw, options) {
|
||||
this._raw = raw;
|
||||
const { contents, keys, overrides, restricted, hasExcludedProperties } = this.doParseRaw(raw, options);
|
||||
this._configurationModel = new ConfigurationModel(contents, keys, overrides, hasExcludedProperties ? [raw] : undefined /* raw has not changed */, this.logService);
|
||||
this._restrictedConfigurations = restricted || [];
|
||||
}
|
||||
doParseRaw(raw, options) {
|
||||
const registry = Registry.as(Extensions.Configuration);
|
||||
const configurationProperties = registry.getConfigurationProperties();
|
||||
const excludedConfigurationProperties = registry.getExcludedConfigurationProperties();
|
||||
const filtered = this.filter(raw, configurationProperties, excludedConfigurationProperties, true, options);
|
||||
raw = filtered.raw;
|
||||
const contents = toValuesTree(raw, message => this.logService.error(`Conflict in settings file ${this._name}: ${message}`));
|
||||
const keys = Object.keys(raw);
|
||||
const overrides = this.toOverrides(raw, message => this.logService.error(`Conflict in settings file ${this._name}: ${message}`));
|
||||
return { contents, keys, overrides, restricted: filtered.restricted, hasExcludedProperties: filtered.hasExcludedProperties };
|
||||
}
|
||||
filter(properties, configurationProperties, excludedConfigurationProperties, filterOverriddenProperties, options) {
|
||||
let hasExcludedProperties = false;
|
||||
if (!options?.scopes && !options?.skipRestricted && !options?.skipUnregistered && !options?.exclude?.length) {
|
||||
return { raw: properties, restricted: [], hasExcludedProperties };
|
||||
}
|
||||
const raw = {};
|
||||
const restricted = [];
|
||||
for (const key in properties) {
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key) && filterOverriddenProperties) {
|
||||
const result = this.filter(properties[key], configurationProperties, excludedConfigurationProperties, false, options);
|
||||
raw[key] = result.raw;
|
||||
hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties;
|
||||
restricted.push(...result.restricted);
|
||||
}
|
||||
else {
|
||||
const propertySchema = configurationProperties[key];
|
||||
if (propertySchema?.restricted) {
|
||||
restricted.push(key);
|
||||
}
|
||||
if (this.shouldInclude(key, propertySchema, excludedConfigurationProperties, options)) {
|
||||
raw[key] = properties[key];
|
||||
}
|
||||
else {
|
||||
hasExcludedProperties = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { raw, restricted, hasExcludedProperties };
|
||||
}
|
||||
shouldInclude(key, propertySchema, excludedConfigurationProperties, options) {
|
||||
if (options.exclude?.includes(key)) {
|
||||
return false;
|
||||
}
|
||||
if (options.include?.includes(key)) {
|
||||
return true;
|
||||
}
|
||||
if (options.skipRestricted && propertySchema?.restricted) {
|
||||
return false;
|
||||
}
|
||||
if (options.skipUnregistered && !propertySchema) {
|
||||
return false;
|
||||
}
|
||||
const schema = propertySchema ?? excludedConfigurationProperties[key];
|
||||
const scope = schema ? typeof schema.scope !== 'undefined' ? schema.scope : 4 /* ConfigurationScope.WINDOW */ : undefined;
|
||||
if (scope === undefined || options.scopes === undefined) {
|
||||
return true;
|
||||
}
|
||||
return options.scopes.includes(scope);
|
||||
}
|
||||
toOverrides(raw, conflictReporter) {
|
||||
const overrides = [];
|
||||
for (const key of Object.keys(raw)) {
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
const overrideRaw = {};
|
||||
for (const keyInOverrideRaw in raw[key]) {
|
||||
overrideRaw[keyInOverrideRaw] = raw[key][keyInOverrideRaw];
|
||||
}
|
||||
overrides.push({
|
||||
identifiers: overrideIdentifiersFromKey(key),
|
||||
keys: Object.keys(overrideRaw),
|
||||
contents: toValuesTree(overrideRaw, conflictReporter)
|
||||
});
|
||||
}
|
||||
}
|
||||
return overrides;
|
||||
}
|
||||
}
|
||||
class ConfigurationInspectValue {
|
||||
constructor(key, overrides, _value, overrideIdentifiers, defaultConfiguration, policyConfiguration, applicationConfiguration, userConfiguration, localUserConfiguration, remoteUserConfiguration, workspaceConfiguration, folderConfigurationModel, memoryConfigurationModel) {
|
||||
this.key = key;
|
||||
this.overrides = overrides;
|
||||
this._value = _value;
|
||||
this.overrideIdentifiers = overrideIdentifiers;
|
||||
this.defaultConfiguration = defaultConfiguration;
|
||||
this.policyConfiguration = policyConfiguration;
|
||||
this.applicationConfiguration = applicationConfiguration;
|
||||
this.userConfiguration = userConfiguration;
|
||||
this.localUserConfiguration = localUserConfiguration;
|
||||
this.remoteUserConfiguration = remoteUserConfiguration;
|
||||
this.workspaceConfiguration = workspaceConfiguration;
|
||||
this.folderConfigurationModel = folderConfigurationModel;
|
||||
this.memoryConfigurationModel = memoryConfigurationModel;
|
||||
}
|
||||
toInspectValue(inspectValue) {
|
||||
return inspectValue?.value !== undefined || inspectValue?.override !== undefined || inspectValue?.overrides !== undefined ? inspectValue : undefined;
|
||||
}
|
||||
get userInspectValue() {
|
||||
if (!this._userInspectValue) {
|
||||
this._userInspectValue = this.userConfiguration.inspect(this.key, this.overrides.overrideIdentifier);
|
||||
}
|
||||
return this._userInspectValue;
|
||||
}
|
||||
get user() {
|
||||
return this.toInspectValue(this.userInspectValue);
|
||||
}
|
||||
}
|
||||
export class Configuration {
|
||||
constructor(_defaultConfiguration, _policyConfiguration, _applicationConfiguration, _localUserConfiguration, _remoteUserConfiguration, _workspaceConfiguration, _folderConfigurations, _memoryConfiguration, _memoryConfigurationByResource, logService) {
|
||||
this._defaultConfiguration = _defaultConfiguration;
|
||||
this._policyConfiguration = _policyConfiguration;
|
||||
this._applicationConfiguration = _applicationConfiguration;
|
||||
this._localUserConfiguration = _localUserConfiguration;
|
||||
this._remoteUserConfiguration = _remoteUserConfiguration;
|
||||
this._workspaceConfiguration = _workspaceConfiguration;
|
||||
this._folderConfigurations = _folderConfigurations;
|
||||
this._memoryConfiguration = _memoryConfiguration;
|
||||
this._memoryConfigurationByResource = _memoryConfigurationByResource;
|
||||
this.logService = logService;
|
||||
this._workspaceConsolidatedConfiguration = null;
|
||||
this._foldersConsolidatedConfigurations = new ResourceMap();
|
||||
this._userConfiguration = null;
|
||||
}
|
||||
getValue(section, overrides, workspace) {
|
||||
const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(section, overrides, workspace);
|
||||
return consolidateConfigurationModel.getValue(section);
|
||||
}
|
||||
updateValue(key, value, overrides = {}) {
|
||||
let memoryConfiguration;
|
||||
if (overrides.resource) {
|
||||
memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);
|
||||
if (!memoryConfiguration) {
|
||||
memoryConfiguration = ConfigurationModel.createEmptyModel(this.logService);
|
||||
this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
memoryConfiguration = this._memoryConfiguration;
|
||||
}
|
||||
if (value === undefined) {
|
||||
memoryConfiguration.removeValue(key);
|
||||
}
|
||||
else {
|
||||
memoryConfiguration.setValue(key, value);
|
||||
}
|
||||
if (!overrides.resource) {
|
||||
this._workspaceConsolidatedConfiguration = null;
|
||||
}
|
||||
}
|
||||
inspect(key, overrides, workspace) {
|
||||
const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(key, overrides, workspace);
|
||||
const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);
|
||||
const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;
|
||||
const overrideIdentifiers = new Set();
|
||||
for (const override of consolidateConfigurationModel.overrides) {
|
||||
for (const overrideIdentifier of override.identifiers) {
|
||||
if (consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined) {
|
||||
overrideIdentifiers.add(overrideIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ConfigurationInspectValue(key, overrides, consolidateConfigurationModel.getValue(key), overrideIdentifiers.size ? [...overrideIdentifiers] : undefined, this._defaultConfiguration, this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration, this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration, this.userConfiguration, this.localUserConfiguration, this.remoteUserConfiguration, workspace ? this._workspaceConfiguration : undefined, folderConfigurationModel ? folderConfigurationModel : undefined, memoryConfigurationModel);
|
||||
}
|
||||
get applicationConfiguration() {
|
||||
return this._applicationConfiguration;
|
||||
}
|
||||
get userConfiguration() {
|
||||
if (!this._userConfiguration) {
|
||||
if (this._remoteUserConfiguration.isEmpty()) {
|
||||
this._userConfiguration = this._localUserConfiguration;
|
||||
}
|
||||
else {
|
||||
const merged = this._localUserConfiguration.merge(this._remoteUserConfiguration);
|
||||
this._userConfiguration = new ConfigurationModel(merged.contents, merged.keys, merged.overrides, undefined, this.logService);
|
||||
}
|
||||
}
|
||||
return this._userConfiguration;
|
||||
}
|
||||
get localUserConfiguration() {
|
||||
return this._localUserConfiguration;
|
||||
}
|
||||
get remoteUserConfiguration() {
|
||||
return this._remoteUserConfiguration;
|
||||
}
|
||||
getConsolidatedConfigurationModel(section, overrides, workspace) {
|
||||
let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace);
|
||||
if (overrides.overrideIdentifier) {
|
||||
configurationModel = configurationModel.override(overrides.overrideIdentifier);
|
||||
}
|
||||
if (!this._policyConfiguration.isEmpty() && this._policyConfiguration.getValue(section) !== undefined) {
|
||||
// clone by merging
|
||||
configurationModel = configurationModel.merge();
|
||||
for (const key of this._policyConfiguration.keys) {
|
||||
configurationModel.setValue(key, this._policyConfiguration.getValue(key));
|
||||
}
|
||||
}
|
||||
return configurationModel;
|
||||
}
|
||||
getConsolidatedConfigurationModelForResource({ resource }, workspace) {
|
||||
let consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
|
||||
if (workspace && resource) {
|
||||
const root = workspace.getFolder(resource);
|
||||
if (root) {
|
||||
consolidateConfiguration = this.getFolderConsolidatedConfiguration(root.uri) || consolidateConfiguration;
|
||||
}
|
||||
const memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource);
|
||||
if (memoryConfigurationForResource) {
|
||||
consolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource);
|
||||
}
|
||||
}
|
||||
return consolidateConfiguration;
|
||||
}
|
||||
getWorkspaceConsolidatedConfiguration() {
|
||||
if (!this._workspaceConsolidatedConfiguration) {
|
||||
this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.applicationConfiguration, this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
|
||||
}
|
||||
return this._workspaceConsolidatedConfiguration;
|
||||
}
|
||||
getFolderConsolidatedConfiguration(folder) {
|
||||
let folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder);
|
||||
if (!folderConsolidatedConfiguration) {
|
||||
const workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
|
||||
const folderConfiguration = this._folderConfigurations.get(folder);
|
||||
if (folderConfiguration) {
|
||||
folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration);
|
||||
this._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration);
|
||||
}
|
||||
else {
|
||||
folderConsolidatedConfiguration = workspaceConsolidateConfiguration;
|
||||
}
|
||||
}
|
||||
return folderConsolidatedConfiguration;
|
||||
}
|
||||
getFolderConfigurationModelForResource(resource, workspace) {
|
||||
if (workspace && resource) {
|
||||
const root = workspace.getFolder(resource);
|
||||
if (root) {
|
||||
return this._folderConfigurations.get(root.uri);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
toData() {
|
||||
return {
|
||||
defaults: {
|
||||
contents: this._defaultConfiguration.contents,
|
||||
overrides: this._defaultConfiguration.overrides,
|
||||
keys: this._defaultConfiguration.keys,
|
||||
},
|
||||
policy: {
|
||||
contents: this._policyConfiguration.contents,
|
||||
overrides: this._policyConfiguration.overrides,
|
||||
keys: this._policyConfiguration.keys
|
||||
},
|
||||
application: {
|
||||
contents: this.applicationConfiguration.contents,
|
||||
overrides: this.applicationConfiguration.overrides,
|
||||
keys: this.applicationConfiguration.keys,
|
||||
raw: Array.isArray(this.applicationConfiguration.raw) ? undefined : this.applicationConfiguration.raw
|
||||
},
|
||||
userLocal: {
|
||||
contents: this.localUserConfiguration.contents,
|
||||
overrides: this.localUserConfiguration.overrides,
|
||||
keys: this.localUserConfiguration.keys,
|
||||
raw: Array.isArray(this.localUserConfiguration.raw) ? undefined : this.localUserConfiguration.raw
|
||||
},
|
||||
userRemote: {
|
||||
contents: this.remoteUserConfiguration.contents,
|
||||
overrides: this.remoteUserConfiguration.overrides,
|
||||
keys: this.remoteUserConfiguration.keys,
|
||||
raw: Array.isArray(this.remoteUserConfiguration.raw) ? undefined : this.remoteUserConfiguration.raw
|
||||
},
|
||||
workspace: {
|
||||
contents: this._workspaceConfiguration.contents,
|
||||
overrides: this._workspaceConfiguration.overrides,
|
||||
keys: this._workspaceConfiguration.keys
|
||||
},
|
||||
folders: [...this._folderConfigurations.keys()].reduce((result, folder) => {
|
||||
const { contents, overrides, keys } = this._folderConfigurations.get(folder);
|
||||
result.push([folder, { contents, overrides, keys }]);
|
||||
return result;
|
||||
}, [])
|
||||
};
|
||||
}
|
||||
static parse(data, logService) {
|
||||
const defaultConfiguration = this.parseConfigurationModel(data.defaults, logService);
|
||||
const policyConfiguration = this.parseConfigurationModel(data.policy, logService);
|
||||
const applicationConfiguration = this.parseConfigurationModel(data.application, logService);
|
||||
const userLocalConfiguration = this.parseConfigurationModel(data.userLocal, logService);
|
||||
const userRemoteConfiguration = this.parseConfigurationModel(data.userRemote, logService);
|
||||
const workspaceConfiguration = this.parseConfigurationModel(data.workspace, logService);
|
||||
const folders = data.folders.reduce((result, value) => {
|
||||
result.set(URI.revive(value[0]), this.parseConfigurationModel(value[1], logService));
|
||||
return result;
|
||||
}, new ResourceMap());
|
||||
return new Configuration(defaultConfiguration, policyConfiguration, applicationConfiguration, userLocalConfiguration, userRemoteConfiguration, workspaceConfiguration, folders, ConfigurationModel.createEmptyModel(logService), new ResourceMap(), logService);
|
||||
}
|
||||
static parseConfigurationModel(model, logService) {
|
||||
return new ConfigurationModel(model.contents, model.keys, model.overrides, model.raw, logService);
|
||||
}
|
||||
}
|
||||
export class ConfigurationChangeEvent {
|
||||
constructor(change, previous, currentConfiguraiton, currentWorkspace, logService) {
|
||||
this.change = change;
|
||||
this.previous = previous;
|
||||
this.currentConfiguraiton = currentConfiguraiton;
|
||||
this.currentWorkspace = currentWorkspace;
|
||||
this.logService = logService;
|
||||
this._marker = '\n';
|
||||
this._markerCode1 = this._marker.charCodeAt(0);
|
||||
this._markerCode2 = '.'.charCodeAt(0);
|
||||
this.affectedKeys = new Set();
|
||||
this._previousConfiguration = undefined;
|
||||
for (const key of change.keys) {
|
||||
this.affectedKeys.add(key);
|
||||
}
|
||||
for (const [, keys] of change.overrides) {
|
||||
for (const key of keys) {
|
||||
this.affectedKeys.add(key);
|
||||
}
|
||||
}
|
||||
// Example: '\nfoo.bar\nabc.def\n'
|
||||
this._affectsConfigStr = this._marker;
|
||||
for (const key of this.affectedKeys) {
|
||||
this._affectsConfigStr += key + this._marker;
|
||||
}
|
||||
}
|
||||
get previousConfiguration() {
|
||||
if (!this._previousConfiguration && this.previous) {
|
||||
this._previousConfiguration = Configuration.parse(this.previous.data, this.logService);
|
||||
}
|
||||
return this._previousConfiguration;
|
||||
}
|
||||
affectsConfiguration(section, overrides) {
|
||||
// we have one large string with all keys that have changed. we pad (marker) the section
|
||||
// and check that either find it padded or before a segment character
|
||||
const needle = this._marker + section;
|
||||
const idx = this._affectsConfigStr.indexOf(needle);
|
||||
if (idx < 0) {
|
||||
// NOT: (marker + section)
|
||||
return false;
|
||||
}
|
||||
const pos = idx + needle.length;
|
||||
if (pos >= this._affectsConfigStr.length) {
|
||||
return false;
|
||||
}
|
||||
const code = this._affectsConfigStr.charCodeAt(pos);
|
||||
if (code !== this._markerCode1 && code !== this._markerCode2) {
|
||||
// NOT: section + (marker | segment)
|
||||
return false;
|
||||
}
|
||||
if (overrides) {
|
||||
const value1 = this.previousConfiguration ? this.previousConfiguration.getValue(section, overrides, this.previous?.workspace) : undefined;
|
||||
const value2 = this.currentConfiguraiton.getValue(section, overrides, this.currentWorkspace);
|
||||
return !objects.equals(value1, value2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=configurationModels.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,415 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { distinct } from '../../../base/common/arrays.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import * as types from '../../../base/common/types.js';
|
||||
import * as nls from '../../../nls.js';
|
||||
import { getLanguageTagSettingPlainKey } from './configuration.js';
|
||||
import { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';
|
||||
import { Registry } from '../../registry/common/platform.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
export const Extensions = {
|
||||
Configuration: 'base.contributions.configuration'
|
||||
};
|
||||
export const allSettings = { properties: {}, patternProperties: {} };
|
||||
export const applicationSettings = { properties: {}, patternProperties: {} };
|
||||
export const applicationMachineSettings = { properties: {}, patternProperties: {} };
|
||||
export const machineSettings = { properties: {}, patternProperties: {} };
|
||||
export const machineOverridableSettings = { properties: {}, patternProperties: {} };
|
||||
export const windowSettings = { properties: {}, patternProperties: {} };
|
||||
export const resourceSettings = { properties: {}, patternProperties: {} };
|
||||
export const resourceLanguageSettingsSchemaId = 'vscode://schemas/settings/resourceLanguage';
|
||||
const contributionRegistry = Registry.as(JSONExtensions.JSONContribution);
|
||||
class ConfigurationRegistry extends Disposable {
|
||||
constructor() {
|
||||
super();
|
||||
this.registeredConfigurationDefaults = [];
|
||||
this.overrideIdentifiers = new Set();
|
||||
this._onDidSchemaChange = this._register(new Emitter());
|
||||
this._onDidUpdateConfiguration = this._register(new Emitter());
|
||||
this.configurationDefaultsOverrides = new Map();
|
||||
this.defaultLanguageConfigurationOverridesNode = {
|
||||
id: 'defaultOverrides',
|
||||
title: nls.localize(1649, "Default Language Configuration Overrides"),
|
||||
properties: {}
|
||||
};
|
||||
this.configurationContributors = [this.defaultLanguageConfigurationOverridesNode];
|
||||
this.resourceLanguageSettingsSchema = {
|
||||
properties: {},
|
||||
patternProperties: {},
|
||||
additionalProperties: true,
|
||||
allowTrailingCommas: true,
|
||||
allowComments: true
|
||||
};
|
||||
this.configurationProperties = {};
|
||||
this.policyConfigurations = new Map();
|
||||
this.excludedConfigurationProperties = {};
|
||||
contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);
|
||||
this.registerOverridePropertyPatternKey();
|
||||
}
|
||||
registerConfiguration(configuration, validate = true) {
|
||||
this.registerConfigurations([configuration], validate);
|
||||
return configuration;
|
||||
}
|
||||
registerConfigurations(configurations, validate = true) {
|
||||
const properties = new Set();
|
||||
this.doRegisterConfigurations(configurations, validate, properties);
|
||||
contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);
|
||||
this._onDidSchemaChange.fire();
|
||||
this._onDidUpdateConfiguration.fire({ properties });
|
||||
}
|
||||
registerDefaultConfigurations(configurationDefaults) {
|
||||
const properties = new Set();
|
||||
this.doRegisterDefaultConfigurations(configurationDefaults, properties);
|
||||
this._onDidSchemaChange.fire();
|
||||
this._onDidUpdateConfiguration.fire({ properties, defaultsOverrides: true });
|
||||
}
|
||||
doRegisterDefaultConfigurations(configurationDefaults, bucket) {
|
||||
this.registeredConfigurationDefaults.push(...configurationDefaults);
|
||||
const overrideIdentifiers = [];
|
||||
for (const { overrides, source } of configurationDefaults) {
|
||||
for (const key in overrides) {
|
||||
bucket.add(key);
|
||||
const configurationDefaultOverridesForKey = this.configurationDefaultsOverrides.get(key)
|
||||
?? this.configurationDefaultsOverrides.set(key, { configurationDefaultOverrides: [] }).get(key);
|
||||
const value = overrides[key];
|
||||
configurationDefaultOverridesForKey.configurationDefaultOverrides.push({ value, source });
|
||||
// Configuration defaults for Override Identifiers
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
const newDefaultOverride = this.mergeDefaultConfigurationsForOverrideIdentifier(key, value, source, configurationDefaultOverridesForKey.configurationDefaultOverrideValue);
|
||||
if (!newDefaultOverride) {
|
||||
continue;
|
||||
}
|
||||
configurationDefaultOverridesForKey.configurationDefaultOverrideValue = newDefaultOverride;
|
||||
this.updateDefaultOverrideProperty(key, newDefaultOverride, source);
|
||||
overrideIdentifiers.push(...overrideIdentifiersFromKey(key));
|
||||
}
|
||||
// Configuration defaults for Configuration Properties
|
||||
else {
|
||||
const newDefaultOverride = this.mergeDefaultConfigurationsForConfigurationProperty(key, value, source, configurationDefaultOverridesForKey.configurationDefaultOverrideValue);
|
||||
if (!newDefaultOverride) {
|
||||
continue;
|
||||
}
|
||||
configurationDefaultOverridesForKey.configurationDefaultOverrideValue = newDefaultOverride;
|
||||
const property = this.configurationProperties[key];
|
||||
if (property) {
|
||||
this.updatePropertyDefaultValue(key, property);
|
||||
this.updateSchema(key, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.doRegisterOverrideIdentifiers(overrideIdentifiers);
|
||||
}
|
||||
updateDefaultOverrideProperty(key, newDefaultOverride, source) {
|
||||
const property = {
|
||||
type: 'object',
|
||||
default: newDefaultOverride.value,
|
||||
description: nls.localize(1650, "Configure settings to be overridden for {0}.", getLanguageTagSettingPlainKey(key)),
|
||||
$ref: resourceLanguageSettingsSchemaId,
|
||||
defaultDefaultValue: newDefaultOverride.value,
|
||||
source,
|
||||
defaultValueSource: source
|
||||
};
|
||||
this.configurationProperties[key] = property;
|
||||
this.defaultLanguageConfigurationOverridesNode.properties[key] = property;
|
||||
}
|
||||
mergeDefaultConfigurationsForOverrideIdentifier(overrideIdentifier, configurationValueObject, valueSource, existingDefaultOverride) {
|
||||
const defaultValue = existingDefaultOverride?.value || {};
|
||||
const source = existingDefaultOverride?.source ?? new Map();
|
||||
// This should not happen
|
||||
if (!(source instanceof Map)) {
|
||||
console.error('objectConfigurationSources is not a Map');
|
||||
return undefined;
|
||||
}
|
||||
for (const propertyKey of Object.keys(configurationValueObject)) {
|
||||
const propertyDefaultValue = configurationValueObject[propertyKey];
|
||||
const isObjectSetting = types.isObject(propertyDefaultValue) &&
|
||||
(types.isUndefined(defaultValue[propertyKey]) || types.isObject(defaultValue[propertyKey]));
|
||||
// If the default value is an object, merge the objects and store the source of each keys
|
||||
if (isObjectSetting) {
|
||||
defaultValue[propertyKey] = { ...(defaultValue[propertyKey] ?? {}), ...propertyDefaultValue };
|
||||
// Track the source of each value in the object
|
||||
if (valueSource) {
|
||||
for (const objectKey in propertyDefaultValue) {
|
||||
source.set(`${propertyKey}.${objectKey}`, valueSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Primitive values are overridden
|
||||
else {
|
||||
defaultValue[propertyKey] = propertyDefaultValue;
|
||||
if (valueSource) {
|
||||
source.set(propertyKey, valueSource);
|
||||
}
|
||||
else {
|
||||
source.delete(propertyKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { value: defaultValue, source };
|
||||
}
|
||||
mergeDefaultConfigurationsForConfigurationProperty(propertyKey, value, valuesSource, existingDefaultOverride) {
|
||||
const property = this.configurationProperties[propertyKey];
|
||||
const existingDefaultValue = existingDefaultOverride?.value ?? property?.defaultDefaultValue;
|
||||
let source = valuesSource;
|
||||
const isObjectSetting = types.isObject(value) &&
|
||||
(property !== undefined && property.type === 'object' ||
|
||||
property === undefined && (types.isUndefined(existingDefaultValue) || types.isObject(existingDefaultValue)));
|
||||
// If the default value is an object, merge the objects and store the source of each keys
|
||||
if (isObjectSetting) {
|
||||
source = existingDefaultOverride?.source ?? new Map();
|
||||
// This should not happen
|
||||
if (!(source instanceof Map)) {
|
||||
console.error('defaultValueSource is not a Map');
|
||||
return undefined;
|
||||
}
|
||||
for (const objectKey in value) {
|
||||
if (valuesSource) {
|
||||
source.set(`${propertyKey}.${objectKey}`, valuesSource);
|
||||
}
|
||||
}
|
||||
value = { ...(types.isObject(existingDefaultValue) ? existingDefaultValue : {}), ...value };
|
||||
}
|
||||
return { value, source };
|
||||
}
|
||||
registerOverrideIdentifiers(overrideIdentifiers) {
|
||||
this.doRegisterOverrideIdentifiers(overrideIdentifiers);
|
||||
this._onDidSchemaChange.fire();
|
||||
}
|
||||
doRegisterOverrideIdentifiers(overrideIdentifiers) {
|
||||
for (const overrideIdentifier of overrideIdentifiers) {
|
||||
this.overrideIdentifiers.add(overrideIdentifier);
|
||||
}
|
||||
this.updateOverridePropertyPatternKey();
|
||||
}
|
||||
doRegisterConfigurations(configurations, validate, bucket) {
|
||||
configurations.forEach(configuration => {
|
||||
this.validateAndRegisterProperties(configuration, validate, configuration.extensionInfo, configuration.restrictedProperties, undefined, bucket);
|
||||
this.configurationContributors.push(configuration);
|
||||
this.registerJSONConfiguration(configuration);
|
||||
});
|
||||
}
|
||||
validateAndRegisterProperties(configuration, validate = true, extensionInfo, restrictedProperties, scope = 4 /* ConfigurationScope.WINDOW */, bucket) {
|
||||
scope = types.isUndefinedOrNull(configuration.scope) ? scope : configuration.scope;
|
||||
const properties = configuration.properties;
|
||||
if (properties) {
|
||||
for (const key in properties) {
|
||||
const property = properties[key];
|
||||
if (validate && validateProperty(key, property)) {
|
||||
delete properties[key];
|
||||
continue;
|
||||
}
|
||||
property.source = extensionInfo;
|
||||
// update default value
|
||||
property.defaultDefaultValue = properties[key].default;
|
||||
this.updatePropertyDefaultValue(key, property);
|
||||
// update scope
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
property.scope = undefined; // No scope for overridable properties `[${identifier}]`
|
||||
}
|
||||
else {
|
||||
property.scope = types.isUndefinedOrNull(property.scope) ? scope : property.scope;
|
||||
property.restricted = types.isUndefinedOrNull(property.restricted) ? !!restrictedProperties?.includes(key) : property.restricted;
|
||||
}
|
||||
if (property.experiment) {
|
||||
if (!property.tags?.some(tag => tag.toLowerCase() === 'onexp')) {
|
||||
property.tags = property.tags ?? [];
|
||||
property.tags.push('onExP');
|
||||
}
|
||||
}
|
||||
else if (property.tags?.some(tag => tag.toLowerCase() === 'onexp')) {
|
||||
console.error(`Invalid tag 'onExP' found for property '${key}'. Please use 'experiment' property instead.`);
|
||||
property.experiment = { mode: 'startup' };
|
||||
}
|
||||
const excluded = properties[key].hasOwnProperty('included') && !properties[key].included;
|
||||
const policyName = properties[key].policy?.name;
|
||||
if (excluded) {
|
||||
this.excludedConfigurationProperties[key] = properties[key];
|
||||
if (policyName) {
|
||||
this.policyConfigurations.set(policyName, key);
|
||||
bucket.add(key);
|
||||
}
|
||||
delete properties[key];
|
||||
}
|
||||
else {
|
||||
bucket.add(key);
|
||||
if (policyName) {
|
||||
this.policyConfigurations.set(policyName, key);
|
||||
}
|
||||
this.configurationProperties[key] = properties[key];
|
||||
if (!properties[key].deprecationMessage && properties[key].markdownDeprecationMessage) {
|
||||
// If not set, default deprecationMessage to the markdown source
|
||||
properties[key].deprecationMessage = properties[key].markdownDeprecationMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const subNodes = configuration.allOf;
|
||||
if (subNodes) {
|
||||
for (const node of subNodes) {
|
||||
this.validateAndRegisterProperties(node, validate, extensionInfo, restrictedProperties, scope, bucket);
|
||||
}
|
||||
}
|
||||
}
|
||||
getConfigurationProperties() {
|
||||
return this.configurationProperties;
|
||||
}
|
||||
getPolicyConfigurations() {
|
||||
return this.policyConfigurations;
|
||||
}
|
||||
getExcludedConfigurationProperties() {
|
||||
return this.excludedConfigurationProperties;
|
||||
}
|
||||
registerJSONConfiguration(configuration) {
|
||||
const register = (configuration) => {
|
||||
const properties = configuration.properties;
|
||||
if (properties) {
|
||||
for (const key in properties) {
|
||||
this.updateSchema(key, properties[key]);
|
||||
}
|
||||
}
|
||||
const subNodes = configuration.allOf;
|
||||
subNodes?.forEach(register);
|
||||
};
|
||||
register(configuration);
|
||||
}
|
||||
updateSchema(key, property) {
|
||||
allSettings.properties[key] = property;
|
||||
switch (property.scope) {
|
||||
case 1 /* ConfigurationScope.APPLICATION */:
|
||||
applicationSettings.properties[key] = property;
|
||||
break;
|
||||
case 2 /* ConfigurationScope.MACHINE */:
|
||||
machineSettings.properties[key] = property;
|
||||
break;
|
||||
case 3 /* ConfigurationScope.APPLICATION_MACHINE */:
|
||||
applicationMachineSettings.properties[key] = property;
|
||||
break;
|
||||
case 7 /* ConfigurationScope.MACHINE_OVERRIDABLE */:
|
||||
machineOverridableSettings.properties[key] = property;
|
||||
break;
|
||||
case 4 /* ConfigurationScope.WINDOW */:
|
||||
windowSettings.properties[key] = property;
|
||||
break;
|
||||
case 5 /* ConfigurationScope.RESOURCE */:
|
||||
resourceSettings.properties[key] = property;
|
||||
break;
|
||||
case 6 /* ConfigurationScope.LANGUAGE_OVERRIDABLE */:
|
||||
resourceSettings.properties[key] = property;
|
||||
this.resourceLanguageSettingsSchema.properties[key] = property;
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateOverridePropertyPatternKey() {
|
||||
for (const overrideIdentifier of this.overrideIdentifiers.values()) {
|
||||
const overrideIdentifierProperty = `[${overrideIdentifier}]`;
|
||||
const resourceLanguagePropertiesSchema = {
|
||||
type: 'object',
|
||||
description: nls.localize(1651, "Configure editor settings to be overridden for a language."),
|
||||
errorMessage: nls.localize(1652, "This setting does not support per-language configuration."),
|
||||
$ref: resourceLanguageSettingsSchemaId,
|
||||
};
|
||||
this.updatePropertyDefaultValue(overrideIdentifierProperty, resourceLanguagePropertiesSchema);
|
||||
allSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
applicationSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
applicationMachineSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
machineSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
machineOverridableSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
windowSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
resourceSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
|
||||
}
|
||||
}
|
||||
registerOverridePropertyPatternKey() {
|
||||
const resourceLanguagePropertiesSchema = {
|
||||
type: 'object',
|
||||
description: nls.localize(1653, "Configure editor settings to be overridden for a language."),
|
||||
errorMessage: nls.localize(1654, "This setting does not support per-language configuration."),
|
||||
$ref: resourceLanguageSettingsSchemaId,
|
||||
};
|
||||
allSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
applicationSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
applicationMachineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
machineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
machineOverridableSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
windowSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
resourceSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
|
||||
this._onDidSchemaChange.fire();
|
||||
}
|
||||
updatePropertyDefaultValue(key, property) {
|
||||
const configurationdefaultOverride = this.configurationDefaultsOverrides.get(key)?.configurationDefaultOverrideValue;
|
||||
let defaultValue = undefined;
|
||||
let defaultSource = undefined;
|
||||
if (configurationdefaultOverride
|
||||
&& (!property.disallowConfigurationDefault || !configurationdefaultOverride.source) // Prevent overriding the default value if the property is disallowed to be overridden by configuration defaults from extensions
|
||||
) {
|
||||
defaultValue = configurationdefaultOverride.value;
|
||||
defaultSource = configurationdefaultOverride.source;
|
||||
}
|
||||
if (types.isUndefined(defaultValue)) {
|
||||
defaultValue = property.defaultDefaultValue;
|
||||
defaultSource = undefined;
|
||||
}
|
||||
if (types.isUndefined(defaultValue)) {
|
||||
defaultValue = getDefaultValue(property.type);
|
||||
}
|
||||
property.default = defaultValue;
|
||||
property.defaultValueSource = defaultSource;
|
||||
}
|
||||
}
|
||||
const OVERRIDE_IDENTIFIER_PATTERN = `\\[([^\\]]+)\\]`;
|
||||
const OVERRIDE_IDENTIFIER_REGEX = new RegExp(OVERRIDE_IDENTIFIER_PATTERN, 'g');
|
||||
export const OVERRIDE_PROPERTY_PATTERN = `^(${OVERRIDE_IDENTIFIER_PATTERN})+$`;
|
||||
export const OVERRIDE_PROPERTY_REGEX = new RegExp(OVERRIDE_PROPERTY_PATTERN);
|
||||
export function overrideIdentifiersFromKey(key) {
|
||||
const identifiers = [];
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
|
||||
let matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
|
||||
while (matches?.length) {
|
||||
const identifier = matches[1].trim();
|
||||
if (identifier) {
|
||||
identifiers.push(identifier);
|
||||
}
|
||||
matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
|
||||
}
|
||||
}
|
||||
return distinct(identifiers);
|
||||
}
|
||||
export function getDefaultValue(type) {
|
||||
const t = Array.isArray(type) ? type[0] : type;
|
||||
switch (t) {
|
||||
case 'boolean':
|
||||
return false;
|
||||
case 'integer':
|
||||
case 'number':
|
||||
return 0;
|
||||
case 'string':
|
||||
return '';
|
||||
case 'array':
|
||||
return [];
|
||||
case 'object':
|
||||
return {};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const configurationRegistry = new ConfigurationRegistry();
|
||||
Registry.add(Extensions.Configuration, configurationRegistry);
|
||||
export function validateProperty(property, schema) {
|
||||
if (!property.trim()) {
|
||||
return nls.localize(1655, "Cannot register an empty property");
|
||||
}
|
||||
if (OVERRIDE_PROPERTY_REGEX.test(property)) {
|
||||
return nls.localize(1656, "Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", property);
|
||||
}
|
||||
if (configurationRegistry.getConfigurationProperties()[property] !== undefined) {
|
||||
return nls.localize(1657, "Cannot register '{0}'. This property is already registered.", property);
|
||||
}
|
||||
if (schema.policy?.name && configurationRegistry.getPolicyConfigurations().get(schema.policy?.name) !== undefined) {
|
||||
return nls.localize(1658, "Cannot register '{0}'. The associated policy {1} is already registered with {2}.", property, schema.policy?.name, configurationRegistry.getPolicyConfigurations().get(schema.policy?.name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//# sourceMappingURL=configurationRegistry.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,44 @@
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { deepClone } from '../../../base/common/objects.js';
|
||||
import { ConfigurationModel } from './configurationModels.js';
|
||||
import { Extensions } from './configurationRegistry.js';
|
||||
import { Registry } from '../../registry/common/platform.js';
|
||||
export class DefaultConfiguration extends Disposable {
|
||||
get configurationModel() {
|
||||
return this._configurationModel;
|
||||
}
|
||||
constructor(logService) {
|
||||
super();
|
||||
this.logService = logService;
|
||||
this._configurationModel = ConfigurationModel.createEmptyModel(logService);
|
||||
}
|
||||
reload() {
|
||||
this.resetConfigurationModel();
|
||||
return this.configurationModel;
|
||||
}
|
||||
getConfigurationDefaultOverrides() {
|
||||
return {};
|
||||
}
|
||||
resetConfigurationModel() {
|
||||
this._configurationModel = ConfigurationModel.createEmptyModel(this.logService);
|
||||
const properties = Registry.as(Extensions.Configuration).getConfigurationProperties();
|
||||
this.updateConfigurationModel(Object.keys(properties), properties);
|
||||
}
|
||||
updateConfigurationModel(properties, configurationProperties) {
|
||||
const configurationDefaultsOverrides = this.getConfigurationDefaultOverrides();
|
||||
for (const key of properties) {
|
||||
const defaultOverrideValue = configurationDefaultsOverrides[key];
|
||||
const propertySchema = configurationProperties[key];
|
||||
if (defaultOverrideValue !== undefined) {
|
||||
this._configurationModel.setValue(key, defaultOverrideValue);
|
||||
}
|
||||
else if (propertySchema) {
|
||||
this._configurationModel.setValue(key, deepClone(propertySchema.default));
|
||||
}
|
||||
else {
|
||||
this._configurationModel.removeValue(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=configurations.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,467 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { Event, PauseableEmitter } from '../../../base/common/event.js';
|
||||
import { Iterable } from '../../../base/common/iterator.js';
|
||||
import { Disposable, DisposableStore, MutableDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { cloneAndChange } from '../../../base/common/objects.js';
|
||||
import { TernarySearchTree } from '../../../base/common/ternarySearchTree.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { CommandsRegistry } from '../../commands/common/commands.js';
|
||||
import { IConfigurationService } from '../../configuration/common/configuration.js';
|
||||
import { IContextKeyService, RawContextKey } from '../common/contextkey.js';
|
||||
import { InputFocusedContext } from '../common/contextkeys.js';
|
||||
import { mainWindow } from '../../../base/browser/window.js';
|
||||
import { addDisposableListener, EventType, getActiveWindow, isEditableElement, onDidRegisterWindow, trackFocus } from '../../../base/browser/dom.js';
|
||||
const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
|
||||
export class Context {
|
||||
constructor(id, parent) {
|
||||
this._id = id;
|
||||
this._parent = parent;
|
||||
this._value = Object.create(null);
|
||||
this._value['_contextId'] = id;
|
||||
}
|
||||
get value() {
|
||||
return { ...this._value };
|
||||
}
|
||||
setValue(key, value) {
|
||||
// console.log('SET ' + key + ' = ' + value + ' ON ' + this._id);
|
||||
if (this._value[key] !== value) {
|
||||
this._value[key] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
removeValue(key) {
|
||||
// console.log('REMOVE ' + key + ' FROM ' + this._id);
|
||||
if (key in this._value) {
|
||||
delete this._value[key];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
getValue(key) {
|
||||
const ret = this._value[key];
|
||||
if (typeof ret === 'undefined' && this._parent) {
|
||||
return this._parent.getValue(key);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
class NullContext extends Context {
|
||||
static { this.INSTANCE = new NullContext(); }
|
||||
constructor() {
|
||||
super(-1, null);
|
||||
}
|
||||
setValue(key, value) {
|
||||
return false;
|
||||
}
|
||||
removeValue(key) {
|
||||
return false;
|
||||
}
|
||||
getValue(key) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
class ConfigAwareContextValuesContainer extends Context {
|
||||
static { this._keyPrefix = 'config.'; }
|
||||
constructor(id, _configurationService, emitter) {
|
||||
super(id, null);
|
||||
this._configurationService = _configurationService;
|
||||
this._values = TernarySearchTree.forConfigKeys();
|
||||
this._listener = this._configurationService.onDidChangeConfiguration(event => {
|
||||
if (event.source === 7 /* ConfigurationTarget.DEFAULT */) {
|
||||
// new setting, reset everything
|
||||
const allKeys = Array.from(this._values, ([k]) => k);
|
||||
this._values.clear();
|
||||
emitter.fire(new ArrayContextKeyChangeEvent(allKeys));
|
||||
}
|
||||
else {
|
||||
const changedKeys = [];
|
||||
for (const configKey of event.affectedKeys) {
|
||||
const contextKey = `config.${configKey}`;
|
||||
const cachedItems = this._values.findSuperstr(contextKey);
|
||||
if (cachedItems !== undefined) {
|
||||
changedKeys.push(...Iterable.map(cachedItems, ([key]) => key));
|
||||
this._values.deleteSuperstr(contextKey);
|
||||
}
|
||||
if (this._values.has(contextKey)) {
|
||||
changedKeys.push(contextKey);
|
||||
this._values.delete(contextKey);
|
||||
}
|
||||
}
|
||||
emitter.fire(new ArrayContextKeyChangeEvent(changedKeys));
|
||||
}
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
this._listener.dispose();
|
||||
}
|
||||
getValue(key) {
|
||||
if (key.indexOf(ConfigAwareContextValuesContainer._keyPrefix) !== 0) {
|
||||
return super.getValue(key);
|
||||
}
|
||||
if (this._values.has(key)) {
|
||||
return this._values.get(key);
|
||||
}
|
||||
const configKey = key.substr(ConfigAwareContextValuesContainer._keyPrefix.length);
|
||||
const configValue = this._configurationService.getValue(configKey);
|
||||
let value = undefined;
|
||||
switch (typeof configValue) {
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
case 'string':
|
||||
value = configValue;
|
||||
break;
|
||||
default:
|
||||
if (Array.isArray(configValue)) {
|
||||
value = JSON.stringify(configValue);
|
||||
}
|
||||
else {
|
||||
value = configValue;
|
||||
}
|
||||
}
|
||||
this._values.set(key, value);
|
||||
return value;
|
||||
}
|
||||
setValue(key, value) {
|
||||
return super.setValue(key, value);
|
||||
}
|
||||
removeValue(key) {
|
||||
return super.removeValue(key);
|
||||
}
|
||||
}
|
||||
class ContextKey {
|
||||
constructor(service, key, defaultValue) {
|
||||
this._service = service;
|
||||
this._key = key;
|
||||
this._defaultValue = defaultValue;
|
||||
this.reset();
|
||||
}
|
||||
set(value) {
|
||||
this._service.setContext(this._key, value);
|
||||
}
|
||||
reset() {
|
||||
if (typeof this._defaultValue === 'undefined') {
|
||||
this._service.removeContext(this._key);
|
||||
}
|
||||
else {
|
||||
this._service.setContext(this._key, this._defaultValue);
|
||||
}
|
||||
}
|
||||
get() {
|
||||
return this._service.getContextKeyValue(this._key);
|
||||
}
|
||||
}
|
||||
class SimpleContextKeyChangeEvent {
|
||||
constructor(key) {
|
||||
this.key = key;
|
||||
}
|
||||
affectsSome(keys) {
|
||||
return keys.has(this.key);
|
||||
}
|
||||
allKeysContainedIn(keys) {
|
||||
return this.affectsSome(keys);
|
||||
}
|
||||
}
|
||||
class ArrayContextKeyChangeEvent {
|
||||
constructor(keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
affectsSome(keys) {
|
||||
for (const key of this.keys) {
|
||||
if (keys.has(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
allKeysContainedIn(keys) {
|
||||
return this.keys.every(key => keys.has(key));
|
||||
}
|
||||
}
|
||||
class CompositeContextKeyChangeEvent {
|
||||
constructor(events) {
|
||||
this.events = events;
|
||||
}
|
||||
affectsSome(keys) {
|
||||
for (const e of this.events) {
|
||||
if (e.affectsSome(keys)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
allKeysContainedIn(keys) {
|
||||
return this.events.every(evt => evt.allKeysContainedIn(keys));
|
||||
}
|
||||
}
|
||||
function allEventKeysInContext(event, context) {
|
||||
return event.allKeysContainedIn(new Set(Object.keys(context)));
|
||||
}
|
||||
export class AbstractContextKeyService extends Disposable {
|
||||
get onDidChangeContext() { return this._onDidChangeContext.event; }
|
||||
constructor(myContextId) {
|
||||
super();
|
||||
this._onDidChangeContext = this._register(new PauseableEmitter({ merge: input => new CompositeContextKeyChangeEvent(input) }));
|
||||
this._isDisposed = false;
|
||||
this._myContextId = myContextId;
|
||||
}
|
||||
createKey(key, defaultValue) {
|
||||
if (this._isDisposed) {
|
||||
throw new Error(`AbstractContextKeyService has been disposed`);
|
||||
}
|
||||
return new ContextKey(this, key, defaultValue);
|
||||
}
|
||||
bufferChangeEvents(callback) {
|
||||
this._onDidChangeContext.pause();
|
||||
try {
|
||||
callback();
|
||||
}
|
||||
finally {
|
||||
this._onDidChangeContext.resume();
|
||||
}
|
||||
}
|
||||
createScoped(domNode) {
|
||||
if (this._isDisposed) {
|
||||
throw new Error(`AbstractContextKeyService has been disposed`);
|
||||
}
|
||||
return new ScopedContextKeyService(this, domNode);
|
||||
}
|
||||
contextMatchesRules(rules) {
|
||||
if (this._isDisposed) {
|
||||
throw new Error(`AbstractContextKeyService has been disposed`);
|
||||
}
|
||||
const context = this.getContextValuesContainer(this._myContextId);
|
||||
const result = (rules ? rules.evaluate(context) : true);
|
||||
// console.group(rules.serialize() + ' -> ' + result);
|
||||
// rules.keys().forEach(key => { console.log(key, ctx[key]); });
|
||||
// console.groupEnd();
|
||||
return result;
|
||||
}
|
||||
getContextKeyValue(key) {
|
||||
if (this._isDisposed) {
|
||||
return undefined;
|
||||
}
|
||||
return this.getContextValuesContainer(this._myContextId).getValue(key);
|
||||
}
|
||||
setContext(key, value) {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
const myContext = this.getContextValuesContainer(this._myContextId);
|
||||
if (!myContext) {
|
||||
return;
|
||||
}
|
||||
if (myContext.setValue(key, value)) {
|
||||
this._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));
|
||||
}
|
||||
}
|
||||
removeContext(key) {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
if (this.getContextValuesContainer(this._myContextId).removeValue(key)) {
|
||||
this._onDidChangeContext.fire(new SimpleContextKeyChangeEvent(key));
|
||||
}
|
||||
}
|
||||
getContext(target) {
|
||||
if (this._isDisposed) {
|
||||
return NullContext.INSTANCE;
|
||||
}
|
||||
return this.getContextValuesContainer(findContextAttr(target));
|
||||
}
|
||||
dispose() {
|
||||
super.dispose();
|
||||
this._isDisposed = true;
|
||||
}
|
||||
}
|
||||
let ContextKeyService = class ContextKeyService extends AbstractContextKeyService {
|
||||
constructor(configurationService) {
|
||||
super(0);
|
||||
this._contexts = new Map();
|
||||
this._lastContextId = 0;
|
||||
this.inputFocusedContext = InputFocusedContext.bindTo(this);
|
||||
const myContext = this._register(new ConfigAwareContextValuesContainer(this._myContextId, configurationService, this._onDidChangeContext));
|
||||
this._contexts.set(this._myContextId, myContext);
|
||||
// Uncomment this to see the contexts continuously logged
|
||||
// let lastLoggedValue: string | null = null;
|
||||
// setInterval(() => {
|
||||
// let values = Object.keys(this._contexts).map((key) => this._contexts[key]);
|
||||
// let logValue = values.map(v => JSON.stringify(v._value, null, '\t')).join('\n');
|
||||
// if (lastLoggedValue !== logValue) {
|
||||
// lastLoggedValue = logValue;
|
||||
// console.log(lastLoggedValue);
|
||||
// }
|
||||
// }, 2000);
|
||||
this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => {
|
||||
const onFocusDisposables = disposables.add(new MutableDisposable());
|
||||
disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => {
|
||||
onFocusDisposables.value = new DisposableStore();
|
||||
this.updateInputContextKeys(window.document, onFocusDisposables.value);
|
||||
}, true));
|
||||
}, { window: mainWindow, disposables: this._store }));
|
||||
}
|
||||
updateInputContextKeys(ownerDocument, disposables) {
|
||||
function activeElementIsInput() {
|
||||
return !!ownerDocument.activeElement && isEditableElement(ownerDocument.activeElement);
|
||||
}
|
||||
const isInputFocused = activeElementIsInput();
|
||||
this.inputFocusedContext.set(isInputFocused);
|
||||
if (isInputFocused) {
|
||||
const tracker = disposables.add(trackFocus(ownerDocument.activeElement));
|
||||
Event.once(tracker.onDidBlur)(() => {
|
||||
// Ensure we are only updating the context key if we are
|
||||
// still in the same document that we are tracking. This
|
||||
// fixes a race condition in multi-window setups where
|
||||
// the blur event arrives in the inactive window overwriting
|
||||
// the context key of the active window. This is because
|
||||
// blur events from the focus tracker are emitted with a
|
||||
// timeout of 0.
|
||||
if (getActiveWindow().document === ownerDocument) {
|
||||
this.inputFocusedContext.set(activeElementIsInput());
|
||||
}
|
||||
tracker.dispose();
|
||||
}, undefined, disposables);
|
||||
}
|
||||
}
|
||||
getContextValuesContainer(contextId) {
|
||||
if (this._isDisposed) {
|
||||
return NullContext.INSTANCE;
|
||||
}
|
||||
return this._contexts.get(contextId) || NullContext.INSTANCE;
|
||||
}
|
||||
createChildContext(parentContextId = this._myContextId) {
|
||||
if (this._isDisposed) {
|
||||
throw new Error(`ContextKeyService has been disposed`);
|
||||
}
|
||||
const id = (++this._lastContextId);
|
||||
this._contexts.set(id, new Context(id, this.getContextValuesContainer(parentContextId)));
|
||||
return id;
|
||||
}
|
||||
disposeContext(contextId) {
|
||||
if (!this._isDisposed) {
|
||||
this._contexts.delete(contextId);
|
||||
}
|
||||
}
|
||||
};
|
||||
ContextKeyService = __decorate([
|
||||
__param(0, IConfigurationService)
|
||||
], ContextKeyService);
|
||||
export { ContextKeyService };
|
||||
class ScopedContextKeyService extends AbstractContextKeyService {
|
||||
constructor(parent, domNode) {
|
||||
super(parent.createChildContext());
|
||||
this._parentChangeListener = this._register(new MutableDisposable());
|
||||
this._parent = parent;
|
||||
this._updateParentChangeListener();
|
||||
this._domNode = domNode;
|
||||
if (this._domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {
|
||||
let extraInfo = '';
|
||||
if (this._domNode.classList) {
|
||||
extraInfo = Array.from(this._domNode.classList.values()).join(', ');
|
||||
}
|
||||
console.error(`Element already has context attribute${extraInfo ? ': ' + extraInfo : ''}`);
|
||||
}
|
||||
this._domNode.setAttribute(KEYBINDING_CONTEXT_ATTR, String(this._myContextId));
|
||||
}
|
||||
_updateParentChangeListener() {
|
||||
// Forward parent events to this listener. Parent will change.
|
||||
this._parentChangeListener.value = this._parent.onDidChangeContext(e => {
|
||||
const thisContainer = this._parent.getContextValuesContainer(this._myContextId);
|
||||
const thisContextValues = thisContainer.value;
|
||||
if (!allEventKeysInContext(e, thisContextValues)) {
|
||||
this._onDidChangeContext.fire(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this._parent.disposeContext(this._myContextId);
|
||||
this._domNode.removeAttribute(KEYBINDING_CONTEXT_ATTR);
|
||||
super.dispose();
|
||||
}
|
||||
getContextValuesContainer(contextId) {
|
||||
if (this._isDisposed) {
|
||||
return NullContext.INSTANCE;
|
||||
}
|
||||
return this._parent.getContextValuesContainer(contextId);
|
||||
}
|
||||
createChildContext(parentContextId = this._myContextId) {
|
||||
if (this._isDisposed) {
|
||||
throw new Error(`ScopedContextKeyService has been disposed`);
|
||||
}
|
||||
return this._parent.createChildContext(parentContextId);
|
||||
}
|
||||
disposeContext(contextId) {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this._parent.disposeContext(contextId);
|
||||
}
|
||||
}
|
||||
function findContextAttr(domNode) {
|
||||
while (domNode) {
|
||||
if (domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {
|
||||
const attr = domNode.getAttribute(KEYBINDING_CONTEXT_ATTR);
|
||||
if (attr) {
|
||||
return parseInt(attr, 10);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
domNode = domNode.parentElement;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
export function setContext(accessor, contextKey, contextValue) {
|
||||
const contextKeyService = accessor.get(IContextKeyService);
|
||||
contextKeyService.createKey(String(contextKey), stringifyURIs(contextValue));
|
||||
}
|
||||
function stringifyURIs(contextValue) {
|
||||
return cloneAndChange(contextValue, (obj) => {
|
||||
if (typeof obj === 'object' && obj.$mid === 1 /* MarshalledId.Uri */) {
|
||||
return URI.revive(obj).toString();
|
||||
}
|
||||
if (obj instanceof URI) {
|
||||
return obj.toString();
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
CommandsRegistry.registerCommand('_setContext', setContext);
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'getContextKeyInfo',
|
||||
handler() {
|
||||
return [...RawContextKey.all()].sort((a, b) => a.key.localeCompare(b.key));
|
||||
},
|
||||
metadata: {
|
||||
description: localize(1659, "A command that returns information about context keys"),
|
||||
args: []
|
||||
}
|
||||
});
|
||||
CommandsRegistry.registerCommand('_generateContextKeyInfo', function () {
|
||||
const result = [];
|
||||
const seen = new Set();
|
||||
for (const info of RawContextKey.all()) {
|
||||
if (!seen.has(info.key)) {
|
||||
seen.add(info.key);
|
||||
result.push(info);
|
||||
}
|
||||
}
|
||||
result.sort((a, b) => a.key.localeCompare(b.key));
|
||||
console.log(JSON.stringify(result, undefined, 2));
|
||||
});
|
||||
//# sourceMappingURL=contextKeyService.js.map
|
||||
File diff suppressed because one or more lines are too long
1548
_internal/editor/esm/vs/platform/contextkey/common/contextkey.js
Normal file
1548
_internal/editor/esm/vs/platform/contextkey/common/contextkey.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { isIOS, isLinux, isMacintosh, isMobile, isWeb, isWindows } from '../../../base/common/platform.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { RawContextKey } from './contextkey.js';
|
||||
export const IsMacContext = new RawContextKey('isMac', isMacintosh, localize(1669, "Whether the operating system is macOS"));
|
||||
export const IsLinuxContext = new RawContextKey('isLinux', isLinux, localize(1670, "Whether the operating system is Linux"));
|
||||
export const IsWindowsContext = new RawContextKey('isWindows', isWindows, localize(1671, "Whether the operating system is Windows"));
|
||||
export const IsWebContext = new RawContextKey('isWeb', isWeb, localize(1672, "Whether the platform is a web browser"));
|
||||
export const IsMacNativeContext = new RawContextKey('isMacNative', isMacintosh && !isWeb, localize(1673, "Whether the operating system is macOS on a non-browser platform"));
|
||||
export const IsIOSContext = new RawContextKey('isIOS', isIOS, localize(1674, "Whether the operating system is iOS"));
|
||||
export const IsMobileContext = new RawContextKey('isMobile', isMobile, localize(1675, "Whether the platform is a mobile web browser"));
|
||||
export const IsDevelopmentContext = new RawContextKey('isDevelopment', false, true);
|
||||
export const ProductQualityContext = new RawContextKey('productQualityType', '', localize(1676, "Quality type of VS Code"));
|
||||
export const InputFocusedContextKey = 'inputFocus';
|
||||
export const InputFocusedContext = new RawContextKey(InputFocusedContextKey, false, localize(1677, "Whether keyboard focus is inside an input box"));
|
||||
//# sourceMappingURL=contextkeys.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["vs/platform/contextkey/common/contextkeys.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC3G,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,aAAa,CAAU,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,IAAO,EAAE,uCAAuC,CAAC,CAAC,CAAC;AACzI,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,aAAa,CAAU,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAS,EAAE,uCAAuC,CAAC,CAAC,CAAC;AAC3I,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,aAAa,CAAU,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAW,EAAE,yCAAyC,CAAC,CAAC,CAAC;AAErJ,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,aAAa,CAAU,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAO,EAAE,uCAAuC,CAAC,CAAC,CAAC;AACnI,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,aAAa,CAAU,aAAa,EAAE,WAAW,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAa,EAAE,iEAAiE,CAAC,CAAC,CAAC;AAC/L,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,aAAa,CAAU,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAO,EAAE,qCAAqC,CAAC,CAAC,CAAC;AACjI,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,aAAa,CAAU,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAU,EAAE,8CAA8C,CAAC,CAAC,CAAC;AAEtJ,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,aAAa,CAAU,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,aAAa,CAAS,oBAAoB,EAAE,EAAE,EAAE,QAAQ,CAAC,IAAoB,EAAE,yBAAyB,CAAC,CAAC,CAAC;AAEpJ,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AACnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,aAAa,CAAU,sBAAsB,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAY,EAAE,+CAA+C,CAAC,CAAC,CAAC","file":"contextkeys.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { isIOS, isLinux, isMacintosh, isMobile, isWeb, isWindows } from '../../../base/common/platform.js';\nimport { localize } from '../../../nls.js';\nimport { RawContextKey } from './contextkey.js';\n\nexport const IsMacContext = new RawContextKey<boolean>('isMac', isMacintosh, localize('isMac', \"Whether the operating system is macOS\"));\nexport const IsLinuxContext = new RawContextKey<boolean>('isLinux', isLinux, localize('isLinux', \"Whether the operating system is Linux\"));\nexport const IsWindowsContext = new RawContextKey<boolean>('isWindows', isWindows, localize('isWindows', \"Whether the operating system is Windows\"));\n\nexport const IsWebContext = new RawContextKey<boolean>('isWeb', isWeb, localize('isWeb', \"Whether the platform is a web browser\"));\nexport const IsMacNativeContext = new RawContextKey<boolean>('isMacNative', isMacintosh && !isWeb, localize('isMacNative', \"Whether the operating system is macOS on a non-browser platform\"));\nexport const IsIOSContext = new RawContextKey<boolean>('isIOS', isIOS, localize('isIOS', \"Whether the operating system is iOS\"));\nexport const IsMobileContext = new RawContextKey<boolean>('isMobile', isMobile, localize('isMobile', \"Whether the platform is a mobile web browser\"));\n\nexport const IsDevelopmentContext = new RawContextKey<boolean>('isDevelopment', false, true);\nexport const ProductQualityContext = new RawContextKey<string>('productQualityType', '', localize('productQualityType', \"Quality type of VS Code\"));\n\nexport const InputFocusedContextKey = 'inputFocus';\nexport const InputFocusedContext = new RawContextKey<boolean>(InputFocusedContextKey, false, localize('inputFocus', \"Whether keyboard focus is inside an input box\"));\n"]}
|
||||
285
_internal/editor/esm/vs/platform/contextkey/common/scanner.js
Normal file
285
_internal/editor/esm/vs/platform/contextkey/common/scanner.js
Normal file
@@ -0,0 +1,285 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { illegalState } from '../../../base/common/errors.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
function hintDidYouMean(...meant) {
|
||||
switch (meant.length) {
|
||||
case 1:
|
||||
return localize(1678, "Did you mean {0}?", meant[0]);
|
||||
case 2:
|
||||
return localize(1679, "Did you mean {0} or {1}?", meant[0], meant[1]);
|
||||
case 3:
|
||||
return localize(1680, "Did you mean {0}, {1} or {2}?", meant[0], meant[1], meant[2]);
|
||||
default: // we just don't expect that many
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
const hintDidYouForgetToOpenOrCloseQuote = localize(1681, "Did you forget to open or close the quote?");
|
||||
const hintDidYouForgetToEscapeSlash = localize(1682, "Did you forget to escape the '/' (slash) character? Put two backslashes before it to escape, e.g., '\\\\/\'.");
|
||||
/**
|
||||
* A simple scanner for context keys.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```ts
|
||||
* const scanner = new Scanner().reset('resourceFileName =~ /docker/ && !config.docker.enabled');
|
||||
* const tokens = [...scanner];
|
||||
* if (scanner.errorTokens.length > 0) {
|
||||
* scanner.errorTokens.forEach(err => console.error(`Unexpected token at ${err.offset}: ${err.lexeme}\nHint: ${err.additional}`));
|
||||
* } else {
|
||||
* // process tokens
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export class Scanner {
|
||||
constructor() {
|
||||
this._input = '';
|
||||
this._start = 0;
|
||||
this._current = 0;
|
||||
this._tokens = [];
|
||||
this._errors = [];
|
||||
// u - unicode, y - sticky // TODO@ulugbekna: we accept double quotes as part of the string rather than as a delimiter (to preserve old parser's behavior)
|
||||
this.stringRe = /[a-zA-Z0-9_<>\-\./\\:\*\?\+\[\]\^,#@;"%\$\p{L}-]+/uy;
|
||||
}
|
||||
static getLexeme(token) {
|
||||
switch (token.type) {
|
||||
case 0 /* TokenType.LParen */:
|
||||
return '(';
|
||||
case 1 /* TokenType.RParen */:
|
||||
return ')';
|
||||
case 2 /* TokenType.Neg */:
|
||||
return '!';
|
||||
case 3 /* TokenType.Eq */:
|
||||
return token.isTripleEq ? '===' : '==';
|
||||
case 4 /* TokenType.NotEq */:
|
||||
return token.isTripleEq ? '!==' : '!=';
|
||||
case 5 /* TokenType.Lt */:
|
||||
return '<';
|
||||
case 6 /* TokenType.LtEq */:
|
||||
return '<=';
|
||||
case 7 /* TokenType.Gt */:
|
||||
return '>=';
|
||||
case 8 /* TokenType.GtEq */:
|
||||
return '>=';
|
||||
case 9 /* TokenType.RegexOp */:
|
||||
return '=~';
|
||||
case 10 /* TokenType.RegexStr */:
|
||||
return token.lexeme;
|
||||
case 11 /* TokenType.True */:
|
||||
return 'true';
|
||||
case 12 /* TokenType.False */:
|
||||
return 'false';
|
||||
case 13 /* TokenType.In */:
|
||||
return 'in';
|
||||
case 14 /* TokenType.Not */:
|
||||
return 'not';
|
||||
case 15 /* TokenType.And */:
|
||||
return '&&';
|
||||
case 16 /* TokenType.Or */:
|
||||
return '||';
|
||||
case 17 /* TokenType.Str */:
|
||||
return token.lexeme;
|
||||
case 18 /* TokenType.QuotedStr */:
|
||||
return token.lexeme;
|
||||
case 19 /* TokenType.Error */:
|
||||
return token.lexeme;
|
||||
case 20 /* TokenType.EOF */:
|
||||
return 'EOF';
|
||||
default:
|
||||
throw illegalState(`unhandled token type: ${JSON.stringify(token)}; have you forgotten to add a case?`);
|
||||
}
|
||||
}
|
||||
static { this._regexFlags = new Set(['i', 'g', 's', 'm', 'y', 'u'].map(ch => ch.charCodeAt(0))); }
|
||||
static { this._keywords = new Map([
|
||||
['not', 14 /* TokenType.Not */],
|
||||
['in', 13 /* TokenType.In */],
|
||||
['false', 12 /* TokenType.False */],
|
||||
['true', 11 /* TokenType.True */],
|
||||
]); }
|
||||
reset(value) {
|
||||
this._input = value;
|
||||
this._start = 0;
|
||||
this._current = 0;
|
||||
this._tokens = [];
|
||||
this._errors = [];
|
||||
return this;
|
||||
}
|
||||
scan() {
|
||||
while (!this._isAtEnd()) {
|
||||
this._start = this._current;
|
||||
const ch = this._advance();
|
||||
switch (ch) {
|
||||
case 40 /* CharCode.OpenParen */:
|
||||
this._addToken(0 /* TokenType.LParen */);
|
||||
break;
|
||||
case 41 /* CharCode.CloseParen */:
|
||||
this._addToken(1 /* TokenType.RParen */);
|
||||
break;
|
||||
case 33 /* CharCode.ExclamationMark */:
|
||||
if (this._match(61 /* CharCode.Equals */)) {
|
||||
const isTripleEq = this._match(61 /* CharCode.Equals */); // eat last `=` if `!==`
|
||||
this._tokens.push({ type: 4 /* TokenType.NotEq */, offset: this._start, isTripleEq });
|
||||
}
|
||||
else {
|
||||
this._addToken(2 /* TokenType.Neg */);
|
||||
}
|
||||
break;
|
||||
case 39 /* CharCode.SingleQuote */:
|
||||
this._quotedString();
|
||||
break;
|
||||
case 47 /* CharCode.Slash */:
|
||||
this._regex();
|
||||
break;
|
||||
case 61 /* CharCode.Equals */:
|
||||
if (this._match(61 /* CharCode.Equals */)) { // support `==`
|
||||
const isTripleEq = this._match(61 /* CharCode.Equals */); // eat last `=` if `===`
|
||||
this._tokens.push({ type: 3 /* TokenType.Eq */, offset: this._start, isTripleEq });
|
||||
}
|
||||
else if (this._match(126 /* CharCode.Tilde */)) {
|
||||
this._addToken(9 /* TokenType.RegexOp */);
|
||||
}
|
||||
else {
|
||||
this._error(hintDidYouMean('==', '=~'));
|
||||
}
|
||||
break;
|
||||
case 60 /* CharCode.LessThan */:
|
||||
this._addToken(this._match(61 /* CharCode.Equals */) ? 6 /* TokenType.LtEq */ : 5 /* TokenType.Lt */);
|
||||
break;
|
||||
case 62 /* CharCode.GreaterThan */:
|
||||
this._addToken(this._match(61 /* CharCode.Equals */) ? 8 /* TokenType.GtEq */ : 7 /* TokenType.Gt */);
|
||||
break;
|
||||
case 38 /* CharCode.Ampersand */:
|
||||
if (this._match(38 /* CharCode.Ampersand */)) {
|
||||
this._addToken(15 /* TokenType.And */);
|
||||
}
|
||||
else {
|
||||
this._error(hintDidYouMean('&&'));
|
||||
}
|
||||
break;
|
||||
case 124 /* CharCode.Pipe */:
|
||||
if (this._match(124 /* CharCode.Pipe */)) {
|
||||
this._addToken(16 /* TokenType.Or */);
|
||||
}
|
||||
else {
|
||||
this._error(hintDidYouMean('||'));
|
||||
}
|
||||
break;
|
||||
// TODO@ulugbekna: 1) rewrite using a regex 2) reconsider what characters are considered whitespace, including unicode, nbsp, etc.
|
||||
case 32 /* CharCode.Space */:
|
||||
case 13 /* CharCode.CarriageReturn */:
|
||||
case 9 /* CharCode.Tab */:
|
||||
case 10 /* CharCode.LineFeed */:
|
||||
case 160 /* CharCode.NoBreakSpace */: //  
|
||||
break;
|
||||
default:
|
||||
this._string();
|
||||
}
|
||||
}
|
||||
this._start = this._current;
|
||||
this._addToken(20 /* TokenType.EOF */);
|
||||
return Array.from(this._tokens);
|
||||
}
|
||||
_match(expected) {
|
||||
if (this._isAtEnd()) {
|
||||
return false;
|
||||
}
|
||||
if (this._input.charCodeAt(this._current) !== expected) {
|
||||
return false;
|
||||
}
|
||||
this._current++;
|
||||
return true;
|
||||
}
|
||||
_advance() {
|
||||
return this._input.charCodeAt(this._current++);
|
||||
}
|
||||
_peek() {
|
||||
return this._isAtEnd() ? 0 /* CharCode.Null */ : this._input.charCodeAt(this._current);
|
||||
}
|
||||
_addToken(type) {
|
||||
this._tokens.push({ type, offset: this._start });
|
||||
}
|
||||
_error(additional) {
|
||||
const offset = this._start;
|
||||
const lexeme = this._input.substring(this._start, this._current);
|
||||
const errToken = { type: 19 /* TokenType.Error */, offset: this._start, lexeme };
|
||||
this._errors.push({ offset, lexeme, additionalInfo: additional });
|
||||
this._tokens.push(errToken);
|
||||
}
|
||||
_string() {
|
||||
this.stringRe.lastIndex = this._start;
|
||||
const match = this.stringRe.exec(this._input);
|
||||
if (match) {
|
||||
this._current = this._start + match[0].length;
|
||||
const lexeme = this._input.substring(this._start, this._current);
|
||||
const keyword = Scanner._keywords.get(lexeme);
|
||||
if (keyword) {
|
||||
this._addToken(keyword);
|
||||
}
|
||||
else {
|
||||
this._tokens.push({ type: 17 /* TokenType.Str */, lexeme, offset: this._start });
|
||||
}
|
||||
}
|
||||
}
|
||||
// captures the lexeme without the leading and trailing '
|
||||
_quotedString() {
|
||||
while (this._peek() !== 39 /* CharCode.SingleQuote */ && !this._isAtEnd()) { // TODO@ulugbekna: add support for escaping ' ?
|
||||
this._advance();
|
||||
}
|
||||
if (this._isAtEnd()) {
|
||||
this._error(hintDidYouForgetToOpenOrCloseQuote);
|
||||
return;
|
||||
}
|
||||
// consume the closing '
|
||||
this._advance();
|
||||
this._tokens.push({ type: 18 /* TokenType.QuotedStr */, lexeme: this._input.substring(this._start + 1, this._current - 1), offset: this._start + 1 });
|
||||
}
|
||||
/*
|
||||
* Lexing a regex expression: /.../[igsmyu]*
|
||||
* Based on https://github.com/microsoft/TypeScript/blob/9247ef115e617805983740ba795d7a8164babf89/src/compiler/scanner.ts#L2129-L2181
|
||||
*
|
||||
* Note that we want slashes within a regex to be escaped, e.g., /file:\\/\\/\\// should match `file:///`
|
||||
*/
|
||||
_regex() {
|
||||
let p = this._current;
|
||||
let inEscape = false;
|
||||
let inCharacterClass = false;
|
||||
while (true) {
|
||||
if (p >= this._input.length) {
|
||||
this._current = p;
|
||||
this._error(hintDidYouForgetToEscapeSlash);
|
||||
return;
|
||||
}
|
||||
const ch = this._input.charCodeAt(p);
|
||||
if (inEscape) { // parsing an escape character
|
||||
inEscape = false;
|
||||
}
|
||||
else if (ch === 47 /* CharCode.Slash */ && !inCharacterClass) { // end of regex
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
else if (ch === 91 /* CharCode.OpenSquareBracket */) {
|
||||
inCharacterClass = true;
|
||||
}
|
||||
else if (ch === 92 /* CharCode.Backslash */) {
|
||||
inEscape = true;
|
||||
}
|
||||
else if (ch === 93 /* CharCode.CloseSquareBracket */) {
|
||||
inCharacterClass = false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
// Consume flags // TODO@ulugbekna: use regex instead
|
||||
while (p < this._input.length && Scanner._regexFlags.has(this._input.charCodeAt(p))) {
|
||||
p++;
|
||||
}
|
||||
this._current = p;
|
||||
const lexeme = this._input.substring(this._start, this._current);
|
||||
this._tokens.push({ type: 10 /* TokenType.RegexStr */, lexeme, offset: this._start });
|
||||
}
|
||||
_isAtEnd() {
|
||||
return this._current >= this._input.length;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=scanner.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,124 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { $, addDisposableListener, EventType, getActiveElement, getWindow, isAncestor, isHTMLElement } from '../../../base/browser/dom.js';
|
||||
import { StandardMouseEvent } from '../../../base/browser/mouseEvent.js';
|
||||
import { Menu } from '../../../base/browser/ui/menu/menu.js';
|
||||
import { ActionRunner } from '../../../base/common/actions.js';
|
||||
import { isCancellationError } from '../../../base/common/errors.js';
|
||||
import { combinedDisposable, DisposableStore } from '../../../base/common/lifecycle.js';
|
||||
import { defaultMenuStyles } from '../../theme/browser/defaultStyles.js';
|
||||
export class ContextMenuHandler {
|
||||
constructor(contextViewService, telemetryService, notificationService, keybindingService) {
|
||||
this.contextViewService = contextViewService;
|
||||
this.telemetryService = telemetryService;
|
||||
this.notificationService = notificationService;
|
||||
this.keybindingService = keybindingService;
|
||||
this.focusToReturn = null;
|
||||
this.lastContainer = null;
|
||||
this.block = null;
|
||||
this.blockDisposable = null;
|
||||
this.options = { blockMouse: true };
|
||||
}
|
||||
configure(options) {
|
||||
this.options = options;
|
||||
}
|
||||
showContextMenu(delegate) {
|
||||
const actions = delegate.getActions();
|
||||
if (!actions.length) {
|
||||
return; // Don't render an empty context menu
|
||||
}
|
||||
this.focusToReturn = getActiveElement();
|
||||
let menu;
|
||||
const shadowRootElement = isHTMLElement(delegate.domForShadowRoot) ? delegate.domForShadowRoot : undefined;
|
||||
this.contextViewService.showContextView({
|
||||
getAnchor: () => delegate.getAnchor(),
|
||||
canRelayout: false,
|
||||
anchorAlignment: delegate.anchorAlignment,
|
||||
anchorAxisAlignment: delegate.anchorAxisAlignment,
|
||||
layer: delegate.layer,
|
||||
render: (container) => {
|
||||
this.lastContainer = container;
|
||||
const className = delegate.getMenuClassName ? delegate.getMenuClassName() : '';
|
||||
if (className) {
|
||||
container.className += ' ' + className;
|
||||
}
|
||||
// Render invisible div to block mouse interaction in the rest of the UI
|
||||
if (this.options.blockMouse) {
|
||||
this.block = container.appendChild($('.context-view-block'));
|
||||
this.block.style.position = 'fixed';
|
||||
this.block.style.cursor = 'initial';
|
||||
this.block.style.left = '0';
|
||||
this.block.style.top = '0';
|
||||
this.block.style.width = '100%';
|
||||
this.block.style.height = '100%';
|
||||
this.block.style.zIndex = '-1';
|
||||
this.blockDisposable?.dispose();
|
||||
this.blockDisposable = addDisposableListener(this.block, EventType.MOUSE_DOWN, e => e.stopPropagation());
|
||||
}
|
||||
const menuDisposables = new DisposableStore();
|
||||
const actionRunner = delegate.actionRunner || menuDisposables.add(new ActionRunner());
|
||||
actionRunner.onWillRun(evt => this.onActionRun(evt, !delegate.skipTelemetry), this, menuDisposables);
|
||||
actionRunner.onDidRun(this.onDidActionRun, this, menuDisposables);
|
||||
menu = new Menu(container, actions, {
|
||||
actionViewItemProvider: delegate.getActionViewItem,
|
||||
context: delegate.getActionsContext ? delegate.getActionsContext() : null,
|
||||
actionRunner,
|
||||
getKeyBinding: delegate.getKeyBinding ? delegate.getKeyBinding : action => this.keybindingService.lookupKeybinding(action.id)
|
||||
}, defaultMenuStyles);
|
||||
menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);
|
||||
menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);
|
||||
const targetWindow = getWindow(container);
|
||||
menuDisposables.add(addDisposableListener(targetWindow, EventType.BLUR, () => this.contextViewService.hideContextView(true)));
|
||||
menuDisposables.add(addDisposableListener(targetWindow, EventType.MOUSE_DOWN, (e) => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
const event = new StandardMouseEvent(targetWindow, e);
|
||||
let element = event.target;
|
||||
// Don't do anything as we are likely creating a context menu
|
||||
if (event.rightButton) {
|
||||
return;
|
||||
}
|
||||
while (element) {
|
||||
if (element === container) {
|
||||
return;
|
||||
}
|
||||
element = element.parentElement;
|
||||
}
|
||||
this.contextViewService.hideContextView(true);
|
||||
}));
|
||||
return combinedDisposable(menuDisposables, menu);
|
||||
},
|
||||
focus: () => {
|
||||
menu?.focus(!!delegate.autoSelectFirstItem);
|
||||
},
|
||||
onHide: (didCancel) => {
|
||||
delegate.onHide?.(!!didCancel);
|
||||
if (this.block) {
|
||||
this.block.remove();
|
||||
this.block = null;
|
||||
}
|
||||
this.blockDisposable?.dispose();
|
||||
this.blockDisposable = null;
|
||||
if (!!this.lastContainer && (getActiveElement() === this.lastContainer || isAncestor(getActiveElement(), this.lastContainer))) {
|
||||
this.focusToReturn?.focus();
|
||||
}
|
||||
this.lastContainer = null;
|
||||
}
|
||||
}, shadowRootElement, !!shadowRootElement);
|
||||
}
|
||||
onActionRun(e, logTelemetry) {
|
||||
if (logTelemetry) {
|
||||
this.telemetryService.publicLog2('workbenchActionExecuted', { id: e.action.id, from: 'contextMenu' });
|
||||
}
|
||||
this.contextViewService.hideContextView(false);
|
||||
}
|
||||
onDidActionRun(e) {
|
||||
if (e.error && !isCancellationError(e.error)) {
|
||||
this.notificationService.error(e.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=contextMenuHandler.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,102 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { ModifierKeyEmitter } from '../../../base/browser/dom.js';
|
||||
import { Separator } from '../../../base/common/actions.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { getFlatContextMenuActions } from '../../actions/browser/menuEntryActionViewItem.js';
|
||||
import { IMenuService, MenuId } from '../../actions/common/actions.js';
|
||||
import { IContextKeyService } from '../../contextkey/common/contextkey.js';
|
||||
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
|
||||
import { INotificationService } from '../../notification/common/notification.js';
|
||||
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
|
||||
import { ContextMenuHandler } from './contextMenuHandler.js';
|
||||
import { IContextViewService } from './contextView.js';
|
||||
let ContextMenuService = class ContextMenuService extends Disposable {
|
||||
get contextMenuHandler() {
|
||||
if (!this._contextMenuHandler) {
|
||||
this._contextMenuHandler = new ContextMenuHandler(this.contextViewService, this.telemetryService, this.notificationService, this.keybindingService);
|
||||
}
|
||||
return this._contextMenuHandler;
|
||||
}
|
||||
constructor(telemetryService, notificationService, contextViewService, keybindingService, menuService, contextKeyService) {
|
||||
super();
|
||||
this.telemetryService = telemetryService;
|
||||
this.notificationService = notificationService;
|
||||
this.contextViewService = contextViewService;
|
||||
this.keybindingService = keybindingService;
|
||||
this.menuService = menuService;
|
||||
this.contextKeyService = contextKeyService;
|
||||
this._contextMenuHandler = undefined;
|
||||
this._onDidShowContextMenu = this._store.add(new Emitter());
|
||||
this.onDidShowContextMenu = this._onDidShowContextMenu.event;
|
||||
this._onDidHideContextMenu = this._store.add(new Emitter());
|
||||
this.onDidHideContextMenu = this._onDidHideContextMenu.event;
|
||||
}
|
||||
configure(options) {
|
||||
this.contextMenuHandler.configure(options);
|
||||
}
|
||||
// ContextMenu
|
||||
showContextMenu(delegate) {
|
||||
delegate = ContextMenuMenuDelegate.transform(delegate, this.menuService, this.contextKeyService);
|
||||
this.contextMenuHandler.showContextMenu({
|
||||
...delegate,
|
||||
onHide: (didCancel) => {
|
||||
delegate.onHide?.(didCancel);
|
||||
this._onDidHideContextMenu.fire();
|
||||
}
|
||||
});
|
||||
ModifierKeyEmitter.getInstance().resetKeyStatus();
|
||||
this._onDidShowContextMenu.fire();
|
||||
}
|
||||
};
|
||||
ContextMenuService = __decorate([
|
||||
__param(0, ITelemetryService),
|
||||
__param(1, INotificationService),
|
||||
__param(2, IContextViewService),
|
||||
__param(3, IKeybindingService),
|
||||
__param(4, IMenuService),
|
||||
__param(5, IContextKeyService)
|
||||
], ContextMenuService);
|
||||
export { ContextMenuService };
|
||||
export var ContextMenuMenuDelegate;
|
||||
(function (ContextMenuMenuDelegate) {
|
||||
function is(thing) {
|
||||
return thing && thing.menuId instanceof MenuId;
|
||||
}
|
||||
function transform(delegate, menuService, globalContextKeyService) {
|
||||
if (!is(delegate)) {
|
||||
return delegate;
|
||||
}
|
||||
const { menuId, menuActionOptions, contextKeyService } = delegate;
|
||||
return {
|
||||
...delegate,
|
||||
getActions: () => {
|
||||
let target = [];
|
||||
if (menuId) {
|
||||
const menu = menuService.getMenuActions(menuId, contextKeyService ?? globalContextKeyService, menuActionOptions);
|
||||
target = getFlatContextMenuActions(menu);
|
||||
}
|
||||
if (!delegate.getActions) {
|
||||
return target;
|
||||
}
|
||||
else {
|
||||
return Separator.join(delegate.getActions(), target);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
ContextMenuMenuDelegate.transform = transform;
|
||||
})(ContextMenuMenuDelegate || (ContextMenuMenuDelegate = {}));
|
||||
//# sourceMappingURL=contextMenuService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IContextViewService = createDecorator('contextViewService');
|
||||
export const IContextMenuService = createDecorator('contextMenuService');
|
||||
//# sourceMappingURL=contextView.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { ContextView } from '../../../base/browser/ui/contextview/contextview.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import { ILayoutService } from '../../layout/browser/layoutService.js';
|
||||
import { getWindow } from '../../../base/browser/dom.js';
|
||||
let ContextViewHandler = class ContextViewHandler extends Disposable {
|
||||
constructor(layoutService) {
|
||||
super();
|
||||
this.layoutService = layoutService;
|
||||
this.contextView = this._register(new ContextView(this.layoutService.mainContainer, 1 /* ContextViewDOMPosition.ABSOLUTE */));
|
||||
this.layout();
|
||||
this._register(layoutService.onDidLayoutContainer(() => this.layout()));
|
||||
}
|
||||
// ContextView
|
||||
showContextView(delegate, container, shadowRoot) {
|
||||
let domPosition;
|
||||
if (container) {
|
||||
if (container === this.layoutService.getContainer(getWindow(container))) {
|
||||
domPosition = 1 /* ContextViewDOMPosition.ABSOLUTE */;
|
||||
}
|
||||
else if (shadowRoot) {
|
||||
domPosition = 3 /* ContextViewDOMPosition.FIXED_SHADOW */;
|
||||
}
|
||||
else {
|
||||
domPosition = 2 /* ContextViewDOMPosition.FIXED */;
|
||||
}
|
||||
}
|
||||
else {
|
||||
domPosition = 1 /* ContextViewDOMPosition.ABSOLUTE */;
|
||||
}
|
||||
this.contextView.setContainer(container ?? this.layoutService.activeContainer, domPosition);
|
||||
this.contextView.show(delegate);
|
||||
const openContextView = {
|
||||
close: () => {
|
||||
if (this.openContextView === openContextView) {
|
||||
this.hideContextView();
|
||||
}
|
||||
}
|
||||
};
|
||||
this.openContextView = openContextView;
|
||||
return openContextView;
|
||||
}
|
||||
layout() {
|
||||
this.contextView.layout();
|
||||
}
|
||||
hideContextView(data) {
|
||||
this.contextView.hide(data);
|
||||
this.openContextView = undefined;
|
||||
}
|
||||
};
|
||||
ContextViewHandler = __decorate([
|
||||
__param(0, ILayoutService)
|
||||
], ContextViewHandler);
|
||||
export { ContextViewHandler };
|
||||
export class ContextViewService extends ContextViewHandler {
|
||||
getContextViewElement() {
|
||||
return this.contextView.getViewElement();
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=contextViewService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,59 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
|
||||
import { IDataChannelService } from '../common/dataChannel.js';
|
||||
export class InterceptingTelemetryService {
|
||||
constructor(_baseService, _intercept) {
|
||||
this._baseService = _baseService;
|
||||
this._intercept = _intercept;
|
||||
}
|
||||
publicLog2(eventName, data) {
|
||||
this._intercept(eventName, data);
|
||||
this._baseService.publicLog2(eventName, data);
|
||||
}
|
||||
}
|
||||
let DataChannelForwardingTelemetryService = class DataChannelForwardingTelemetryService extends InterceptingTelemetryService {
|
||||
constructor(telemetryService, dataChannelService) {
|
||||
super(telemetryService, (eventName, data) => {
|
||||
// filter for extension
|
||||
let forward = true;
|
||||
if (data && shouldForwardToChannel in data) {
|
||||
forward = Boolean(data[shouldForwardToChannel]);
|
||||
}
|
||||
if (forward) {
|
||||
dataChannelService.getDataChannel('editTelemetry').sendData({ eventName, data: data });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
DataChannelForwardingTelemetryService = __decorate([
|
||||
__param(0, ITelemetryService),
|
||||
__param(1, IDataChannelService)
|
||||
], DataChannelForwardingTelemetryService);
|
||||
export { DataChannelForwardingTelemetryService };
|
||||
const shouldForwardToChannel = Symbol('shouldForwardToChannel');
|
||||
export function forwardToChannelIf(value) {
|
||||
return {
|
||||
// This will not be sent via telemetry, it is just a marker
|
||||
[shouldForwardToChannel]: value
|
||||
};
|
||||
}
|
||||
export function isCopilotLikeExtension(extensionId) {
|
||||
if (!extensionId) {
|
||||
return false;
|
||||
}
|
||||
const extIdLowerCase = extensionId.toLowerCase();
|
||||
return extIdLowerCase === 'github.copilot' || extIdLowerCase === 'github.copilot-chat';
|
||||
}
|
||||
//# sourceMappingURL=forwardingTelemetryService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IDataChannelService = createDecorator('dataChannelService');
|
||||
export class NullDataChannelService {
|
||||
getDataChannel(_channelId) {
|
||||
return {
|
||||
sendData: () => { },
|
||||
};
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=dataChannel.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/dataChannel/common/dataChannel.ts","vs/platform/dataChannel/common/dataChannel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAE9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAsB,oBAAoB,CAAC,CAAC;AAY9F,MAAM,OAAO,sBAAsB;IAElC,cAAc,CAAI,UAAkB;QACnC,OAAO;YACN,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC;SACnB,CAAC;IACH,CAAC;CACD","file":"dataChannel.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IDataChannelService = createDecorator<IDataChannelService>('dataChannelService');\n\nexport interface IDataChannelService {\n\treadonly _serviceBrand: undefined;\n\n\tgetDataChannel<T>(channelId: string): CoreDataChannel<T>;\n}\n\nexport interface CoreDataChannel<T = unknown> {\n\tsendData(data: T): void;\n}\n\nexport class NullDataChannelService implements IDataChannelService {\n\t_serviceBrand: undefined;\n\tgetDataChannel<T>(_channelId: string): CoreDataChannel<T> {\n\t\treturn {\n\t\t\tsendData: () => { },\n\t\t};\n\t}\n}\n","\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IDataChannelService = createDecorator<IDataChannelService>('dataChannelService');\n\nexport interface IDataChannelService {\n\treadonly _serviceBrand: undefined;\n\n\tgetDataChannel<T>(channelId: string): CoreDataChannel<T>;\n}\n\nexport interface CoreDataChannel<T = unknown> {\n\tsendData(data: T): void;\n}\n\nexport class NullDataChannelService implements IDataChannelService {\n\t_serviceBrand: undefined;\n\tgetDataChannel<T>(_channelId: string): CoreDataChannel<T> {\n\t\treturn {\n\t\t\tsendData: () => { },\n\t\t};\n\t}\n}\n"]}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IDialogService = createDecorator('dialogService');
|
||||
//# sourceMappingURL=dialogs.js.map
|
||||
File diff suppressed because one or more lines are too long
52
_internal/editor/esm/vs/platform/dnd/browser/dnd.js
Normal file
52
_internal/editor/esm/vs/platform/dnd/browser/dnd.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { isNative } from '../../../base/common/platform.js';
|
||||
import { Registry } from '../../registry/common/platform.js';
|
||||
//#region Editor / Resources DND
|
||||
export const CodeDataTransfers = {
|
||||
EDITORS: 'CodeEditors',
|
||||
FILES: 'CodeFiles',
|
||||
SYMBOLS: 'application/vnd.code.symbols',
|
||||
MARKERS: 'application/vnd.code.diagnostics',
|
||||
NOTEBOOK_CELL_OUTPUT: 'notebook-cell-output',
|
||||
SCM_HISTORY_ITEM: 'scm-history-item',
|
||||
};
|
||||
class DragAndDropContributionRegistry {
|
||||
}
|
||||
export const Extensions = {
|
||||
DragAndDropContribution: 'workbench.contributions.dragAndDrop'
|
||||
};
|
||||
Registry.add(Extensions.DragAndDropContribution, new DragAndDropContributionRegistry());
|
||||
//#endregion
|
||||
//#region DND Utilities
|
||||
/**
|
||||
* A singleton to store transfer data during drag & drop operations that are only valid within the application.
|
||||
*/
|
||||
export class LocalSelectionTransfer {
|
||||
static { this.INSTANCE = new LocalSelectionTransfer(); }
|
||||
constructor() {
|
||||
// protect against external instantiation
|
||||
}
|
||||
static getInstance() {
|
||||
return LocalSelectionTransfer.INSTANCE;
|
||||
}
|
||||
hasData(proto) {
|
||||
return proto && proto === this.proto;
|
||||
}
|
||||
getData(proto) {
|
||||
if (this.hasData(proto)) {
|
||||
return this.data;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A helper to get access to Electrons `webUtils.getPathForFile` function
|
||||
* in a safe way without crashing the application when running in the web.
|
||||
*/
|
||||
export function getPathForFile(file) {
|
||||
if (isNative && typeof globalThis.vscode?.webUtils?.getPathForFile === 'function') {
|
||||
return globalThis.vscode.webUtils.getPathForFile(file);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
//#endregion
|
||||
//# sourceMappingURL=dnd.js.map
|
||||
1
_internal/editor/esm/vs/platform/dnd/browser/dnd.js.map
Normal file
1
_internal/editor/esm/vs/platform/dnd/browser/dnd.js.map
Normal file
File diff suppressed because one or more lines are too long
14
_internal/editor/esm/vs/platform/editor/common/editor.js
Normal file
14
_internal/editor/esm/vs/platform/editor/common/editor.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export var EditorOpenSource;
|
||||
(function (EditorOpenSource) {
|
||||
/**
|
||||
* Default: the editor is opening via a programmatic call
|
||||
* to the editor service API.
|
||||
*/
|
||||
EditorOpenSource[EditorOpenSource["API"] = 0] = "API";
|
||||
/**
|
||||
* Indicates that a user action triggered the opening, e.g.
|
||||
* via mouse or keyboard use.
|
||||
*/
|
||||
EditorOpenSource[EditorOpenSource["USER"] = 1] = "USER";
|
||||
})(EditorOpenSource || (EditorOpenSource = {}));
|
||||
//# sourceMappingURL=editor.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
export const IEnvironmentService = createDecorator('environmentService');
|
||||
//# sourceMappingURL=environment.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/environment/common/environment.ts","vs/platform/environment/common/environment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAE9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAsB,oBAAoB,CAAC,CAAC","file":"environment.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');\n\n/**\n * A basic environment service that can be used in various processes,\n * such as main, renderer and shared process. Use subclasses of this\n * service for specific environment.\n */\nexport interface IEnvironmentService {\n\n\treadonly _serviceBrand: undefined;\n\tisExtensionDevelopment: boolean;\n\tisBuilt: boolean;\n\n\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t//\n\t// NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE.\n\t//\n\t// AS SUCH:\n\t// - PUT NON-WEB PROPERTIES INTO NATIVE ENVIRONMENT SERVICE\n\t// - PUT WORKBENCH ONLY PROPERTIES INTO WORKBENCH ENVIRONMENT SERVICE\n\t// - PUT ELECTRON-MAIN ONLY PROPERTIES INTO MAIN ENVIRONMENT SERVICE\n\t//\n\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n}\n","\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\nexport const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');\n\n/**\n * A basic environment service that can be used in various processes,\n * such as main, renderer and shared process. Use subclasses of this\n * service for specific environment.\n */\nexport interface IEnvironmentService {\n\n\treadonly _serviceBrand: undefined;\n\tisExtensionDevelopment: boolean;\n\tisBuilt: boolean;\n\n\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t//\n\t// NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE.\n\t//\n\t// AS SUCH:\n\t// - PUT NON-WEB PROPERTIES INTO NATIVE ENVIRONMENT SERVICE\n\t// - PUT WORKBENCH ONLY PROPERTIES INTO WORKBENCH ENVIRONMENT SERVICE\n\t// - PUT ELECTRON-MAIN ONLY PROPERTIES INTO MAIN ENVIRONMENT SERVICE\n\t//\n\t// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n}\n"]}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* **!Do not construct directly!**
|
||||
*
|
||||
* **!Only static methods because it gets serialized!**
|
||||
*
|
||||
* This represents the "canonical" version for an extension identifier. Extension ids
|
||||
* have to be case-insensitive (due to the marketplace), but we must ensure case
|
||||
* preservation because the extension API is already public at this time.
|
||||
*
|
||||
* For example, given an extension with the publisher `"Hello"` and the name `"World"`,
|
||||
* its canonical extension identifier is `"Hello.World"`. This extension could be
|
||||
* referenced in some other extension's dependencies using the string `"hello.world"`.
|
||||
*
|
||||
* To make matters more complicated, an extension can optionally have an UUID. When two
|
||||
* extensions have the same UUID, they are considered equal even if their identifier is different.
|
||||
*/
|
||||
export class ExtensionIdentifier {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
this._lower = value.toLowerCase();
|
||||
}
|
||||
/**
|
||||
* Gives the value by which to index (for equality).
|
||||
*/
|
||||
static toKey(id) {
|
||||
if (typeof id === 'string') {
|
||||
return id.toLowerCase();
|
||||
}
|
||||
return id._lower;
|
||||
}
|
||||
}
|
||||
export class ExtensionIdentifierSet {
|
||||
constructor(iterable) {
|
||||
this._set = new Set();
|
||||
if (iterable) {
|
||||
for (const value of iterable) {
|
||||
this.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
add(id) {
|
||||
this._set.add(ExtensionIdentifier.toKey(id));
|
||||
}
|
||||
has(id) {
|
||||
return this._set.has(ExtensionIdentifier.toKey(id));
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=extensions.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/extensions/common/extensions.ts","vs/platform/extensions/common/extensions.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,mBAAmB;IAS/B,YAAY,KAAa;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,EAAgC;QACnD,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC,WAAW,EAAE,CAAC;QACzB,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,CAAC;IAClB,CAAC;CACD;AAED,MAAM,OAAO,sBAAsB;IAIlC,YAAY,QAAiD;QAF5C,SAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAGzC,IAAI,QAAQ,EAAE,CAAC;YACd,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACF,CAAC;IACF,CAAC;IAEM,GAAG,CAAC,EAAgC;QAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAEM,GAAG,CAAC,EAAgC;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;CACD","file":"extensions.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["\n\n/**\n * **!Do not construct directly!**\n *\n * **!Only static methods because it gets serialized!**\n *\n * This represents the \"canonical\" version for an extension identifier. Extension ids\n * have to be case-insensitive (due to the marketplace), but we must ensure case\n * preservation because the extension API is already public at this time.\n *\n * For example, given an extension with the publisher `\"Hello\"` and the name `\"World\"`,\n * its canonical extension identifier is `\"Hello.World\"`. This extension could be\n * referenced in some other extension's dependencies using the string `\"hello.world\"`.\n *\n * To make matters more complicated, an extension can optionally have an UUID. When two\n * extensions have the same UUID, they are considered equal even if their identifier is different.\n */\nexport class ExtensionIdentifier {\n\tpublic readonly value: string;\n\n\t/**\n\t * Do not use directly. This is public to avoid mangling and thus\n\t * allow compatibility between running from source and a built version.\n\t */\n\treadonly _lower: string;\n\n\tconstructor(value: string) {\n\t\tthis.value = value;\n\t\tthis._lower = value.toLowerCase();\n\t}\n\n\t/**\n\t * Gives the value by which to index (for equality).\n\t */\n\tpublic static toKey(id: ExtensionIdentifier | string): string {\n\t\tif (typeof id === 'string') {\n\t\t\treturn id.toLowerCase();\n\t\t}\n\t\treturn id._lower;\n\t}\n}\n\nexport class ExtensionIdentifierSet {\n\n\tprivate readonly _set = new Set<string>();\n\n\tconstructor(iterable?: Iterable<ExtensionIdentifier | string>) {\n\t\tif (iterable) {\n\t\t\tfor (const value of iterable) {\n\t\t\t\tthis.add(value);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic add(id: ExtensionIdentifier | string): void {\n\t\tthis._set.add(ExtensionIdentifier.toKey(id));\n\t}\n\n\tpublic has(id: ExtensionIdentifier | string): boolean {\n\t\treturn this._set.has(ExtensionIdentifier.toKey(id));\n\t}\n}\n","\n\n/**\n * **!Do not construct directly!**\n *\n * **!Only static methods because it gets serialized!**\n *\n * This represents the \"canonical\" version for an extension identifier. Extension ids\n * have to be case-insensitive (due to the marketplace), but we must ensure case\n * preservation because the extension API is already public at this time.\n *\n * For example, given an extension with the publisher `\"Hello\"` and the name `\"World\"`,\n * its canonical extension identifier is `\"Hello.World\"`. This extension could be\n * referenced in some other extension's dependencies using the string `\"hello.world\"`.\n *\n * To make matters more complicated, an extension can optionally have an UUID. When two\n * extensions have the same UUID, they are considered equal even if their identifier is different.\n */\nexport class ExtensionIdentifier {\n\tpublic readonly value: string;\n\n\t/**\n\t * Do not use directly. This is public to avoid mangling and thus\n\t * allow compatibility between running from source and a built version.\n\t */\n\treadonly _lower: string;\n\n\tconstructor(value: string) {\n\t\tthis.value = value;\n\t\tthis._lower = value.toLowerCase();\n\t}\n\n\t/**\n\t * Gives the value by which to index (for equality).\n\t */\n\tpublic static toKey(id: ExtensionIdentifier | string): string {\n\t\tif (typeof id === 'string') {\n\t\t\treturn id.toLowerCase();\n\t\t}\n\t\treturn id._lower;\n\t}\n}\n\nexport class ExtensionIdentifierSet {\n\n\tprivate readonly _set = new Set<string>();\n\n\tconstructor(iterable?: Iterable<ExtensionIdentifier | string>) {\n\t\tif (iterable) {\n\t\t\tfor (const value of iterable) {\n\t\t\t\tthis.add(value);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic add(id: ExtensionIdentifier | string): void {\n\t\tthis._set.add(ExtensionIdentifier.toKey(id));\n\t}\n\n\tpublic has(id: ExtensionIdentifier | string): boolean {\n\t\treturn this._set.has(ExtensionIdentifier.toKey(id));\n\t}\n}\n"]}
|
||||
17
_internal/editor/esm/vs/platform/files/common/files.js
Normal file
17
_internal/editor/esm/vs/platform/files/common/files.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
//#region file service & providers
|
||||
export const IFileService = createDecorator('fileService');
|
||||
//#endregion
|
||||
//#region Utilities
|
||||
export var FileKind;
|
||||
(function (FileKind) {
|
||||
FileKind[FileKind["FILE"] = 0] = "FILE";
|
||||
FileKind[FileKind["FOLDER"] = 1] = "FOLDER";
|
||||
FileKind[FileKind["ROOT_FOLDER"] = 2] = "ROOT_FOLDER";
|
||||
})(FileKind || (FileKind = {}));
|
||||
//#endregion
|
||||
//# sourceMappingURL=files.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/files/common/files.ts","vs/platform/files/common/files.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAIhG,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAE9E,kCAAkC;AAElC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAe,aAAa,CAAC,CAAC;AAoCzE,YAAY;AAEZ,mBAAmB;AAEnB,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IACnB,uCAAI,CAAA;IACJ,2CAAM,CAAA;IACN,qDAAW,CAAA;AACZ,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB;AAED,YAAY","file":"files.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { VSBuffer, VSBufferReadable, VSBufferReadableStream } from '../../../base/common/buffer.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\n//#region file service & providers\n\nexport const IFileService = createDecorator<IFileService>('fileService');\n\nexport interface IFileService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Updates the content replacing its previous value.\n\t *\n\t * Emits a `FileOperation.WRITE` file operation event when successful.\n\t */\n\twriteFile(resource: URI, bufferOrReadableOrStream: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: IWriteFileOptions): Promise<IFileStatWithMetadata>;\n\n\t/**\n\t * Frees up any resources occupied by this service.\n\t */\n\tdispose(): void;\n}\n\nexport interface IBaseFileStat {\n}\n\nexport interface IBaseFileStatWithMetadata extends Required<IBaseFileStat> { }\n\n/**\n * A file resource with meta information and resolved children if any.\n */\nexport interface IFileStat extends IBaseFileStat {\n}\n\nexport interface IFileStatWithMetadata extends IFileStat, IBaseFileStatWithMetadata {\n}\n\nexport interface IWriteFileOptions {\n}\n\n//#endregion\n\n//#region Utilities\n\nexport enum FileKind {\n\tFILE,\n\tFOLDER,\n\tROOT_FOLDER\n}\n\n//#endregion\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { VSBuffer, VSBufferReadable, VSBufferReadableStream } from '../../../base/common/buffer.js';\nimport { URI } from '../../../base/common/uri.js';\nimport { createDecorator } from '../../instantiation/common/instantiation.js';\n\n//#region file service & providers\n\nexport const IFileService = createDecorator<IFileService>('fileService');\n\nexport interface IFileService {\n\n\treadonly _serviceBrand: undefined;\n\n\t/**\n\t * Updates the content replacing its previous value.\n\t *\n\t * Emits a `FileOperation.WRITE` file operation event when successful.\n\t */\n\twriteFile(resource: URI, bufferOrReadableOrStream: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: IWriteFileOptions): Promise<IFileStatWithMetadata>;\n\n\t/**\n\t * Frees up any resources occupied by this service.\n\t */\n\tdispose(): void;\n}\n\nexport interface IBaseFileStat {\n}\n\nexport interface IBaseFileStatWithMetadata extends Required<IBaseFileStat> { }\n\n/**\n * A file resource with meta information and resolved children if any.\n */\nexport interface IFileStat extends IBaseFileStat {\n}\n\nexport interface IFileStatWithMetadata extends IFileStat, IBaseFileStatWithMetadata {\n}\n\nexport interface IWriteFileOptions {\n}\n\n//#endregion\n\n//#region Utilities\n\nexport enum FileKind {\n\tFILE,\n\tFOLDER,\n\tROOT_FOLDER\n}\n\n//#endregion\n"]}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { FindInput } from '../../../base/browser/ui/findinput/findInput.js';
|
||||
import { ReplaceInput } from '../../../base/browser/ui/findinput/replaceInput.js';
|
||||
import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';
|
||||
import { KeybindingsRegistry } from '../../keybinding/common/keybindingsRegistry.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { DisposableStore, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { isActiveElement } from '../../../base/browser/dom.js';
|
||||
export const historyNavigationVisible = new RawContextKey('suggestWidgetVisible', false, localize(1683, "Whether suggestion are visible"));
|
||||
const HistoryNavigationWidgetFocusContext = 'historyNavigationWidgetFocus';
|
||||
const HistoryNavigationForwardsEnablementContext = 'historyNavigationForwardsEnabled';
|
||||
const HistoryNavigationBackwardsEnablementContext = 'historyNavigationBackwardsEnabled';
|
||||
let lastFocusedWidget = undefined;
|
||||
const widgets = [];
|
||||
export function registerAndCreateHistoryNavigationContext(scopedContextKeyService, widget) {
|
||||
if (widgets.includes(widget)) {
|
||||
throw new Error('Cannot register the same widget multiple times');
|
||||
}
|
||||
widgets.push(widget);
|
||||
const disposableStore = new DisposableStore();
|
||||
const historyNavigationWidgetFocus = new RawContextKey(HistoryNavigationWidgetFocusContext, false).bindTo(scopedContextKeyService);
|
||||
const historyNavigationForwardsEnablement = new RawContextKey(HistoryNavigationForwardsEnablementContext, true).bindTo(scopedContextKeyService);
|
||||
const historyNavigationBackwardsEnablement = new RawContextKey(HistoryNavigationBackwardsEnablementContext, true).bindTo(scopedContextKeyService);
|
||||
const onDidFocus = () => {
|
||||
historyNavigationWidgetFocus.set(true);
|
||||
lastFocusedWidget = widget;
|
||||
};
|
||||
const onDidBlur = () => {
|
||||
historyNavigationWidgetFocus.set(false);
|
||||
if (lastFocusedWidget === widget) {
|
||||
lastFocusedWidget = undefined;
|
||||
}
|
||||
};
|
||||
// Check for currently being focused
|
||||
if (isActiveElement(widget.element)) {
|
||||
onDidFocus();
|
||||
}
|
||||
disposableStore.add(widget.onDidFocus(() => onDidFocus()));
|
||||
disposableStore.add(widget.onDidBlur(() => onDidBlur()));
|
||||
disposableStore.add(toDisposable(() => {
|
||||
widgets.splice(widgets.indexOf(widget), 1);
|
||||
onDidBlur();
|
||||
}));
|
||||
return {
|
||||
historyNavigationForwardsEnablement,
|
||||
historyNavigationBackwardsEnablement,
|
||||
dispose() {
|
||||
disposableStore.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
let ContextScopedFindInput = class ContextScopedFindInput extends FindInput {
|
||||
constructor(container, contextViewProvider, options, contextKeyService) {
|
||||
super(container, contextViewProvider, options);
|
||||
const scopedContextKeyService = this._register(contextKeyService.createScoped(this.inputBox.element));
|
||||
this._register(registerAndCreateHistoryNavigationContext(scopedContextKeyService, this.inputBox));
|
||||
}
|
||||
};
|
||||
ContextScopedFindInput = __decorate([
|
||||
__param(3, IContextKeyService)
|
||||
], ContextScopedFindInput);
|
||||
export { ContextScopedFindInput };
|
||||
let ContextScopedReplaceInput = class ContextScopedReplaceInput extends ReplaceInput {
|
||||
constructor(container, contextViewProvider, options, contextKeyService, showReplaceOptions = false) {
|
||||
super(container, contextViewProvider, showReplaceOptions, options);
|
||||
const scopedContextKeyService = this._register(contextKeyService.createScoped(this.inputBox.element));
|
||||
this._register(registerAndCreateHistoryNavigationContext(scopedContextKeyService, this.inputBox));
|
||||
}
|
||||
};
|
||||
ContextScopedReplaceInput = __decorate([
|
||||
__param(3, IContextKeyService)
|
||||
], ContextScopedReplaceInput);
|
||||
export { ContextScopedReplaceInput };
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'history.showPrevious',
|
||||
weight: 200 /* KeybindingWeight.WorkbenchContrib */,
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has(HistoryNavigationWidgetFocusContext), ContextKeyExpr.equals(HistoryNavigationBackwardsEnablementContext, true), ContextKeyExpr.not('isComposing'), historyNavigationVisible.isEqualTo(false)),
|
||||
primary: 16 /* KeyCode.UpArrow */,
|
||||
secondary: [512 /* KeyMod.Alt */ | 16 /* KeyCode.UpArrow */],
|
||||
handler: (accessor) => {
|
||||
lastFocusedWidget?.showPreviousValue();
|
||||
}
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'history.showNext',
|
||||
weight: 200 /* KeybindingWeight.WorkbenchContrib */,
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has(HistoryNavigationWidgetFocusContext), ContextKeyExpr.equals(HistoryNavigationForwardsEnablementContext, true), ContextKeyExpr.not('isComposing'), historyNavigationVisible.isEqualTo(false)),
|
||||
primary: 18 /* KeyCode.DownArrow */,
|
||||
secondary: [512 /* KeyMod.Alt */ | 18 /* KeyCode.DownArrow */],
|
||||
handler: (accessor) => {
|
||||
lastFocusedWidget?.showNextValue();
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=contextScopedHistoryWidget.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export function showHistoryKeybindingHint(keybindingService) {
|
||||
return keybindingService.lookupKeybinding('history.showPrevious')?.getElectronAccelerator() === 'Up' && keybindingService.lookupKeybinding('history.showNext')?.getElectronAccelerator() === 'Down';
|
||||
}
|
||||
//# sourceMappingURL=historyWidgetKeybindingHint.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/history/browser/historyWidgetKeybindingHint.ts","vs/platform/history/browser/historyWidgetKeybindingHint.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAIhG,MAAM,UAAU,yBAAyB,CAAC,iBAAqC;IAC9E,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,EAAE,KAAK,IAAI,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,KAAK,MAAM,CAAC;AACrM,CAAC","file":"historyWidgetKeybindingHint.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeybindingService } from '../../keybinding/common/keybinding.js';\n\nexport function showHistoryKeybindingHint(keybindingService: IKeybindingService): boolean {\n\treturn keybindingService.lookupKeybinding('history.showPrevious')?.getElectronAccelerator() === 'Up' && keybindingService.lookupKeybinding('history.showNext')?.getElectronAccelerator() === 'Down';\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IKeybindingService } from '../../keybinding/common/keybinding.js';\n\nexport function showHistoryKeybindingHint(keybindingService: IKeybindingService): boolean {\n\treturn keybindingService.lookupKeybinding('history.showPrevious')?.getElectronAccelerator() === 'Up' && keybindingService.lookupKeybinding('history.showNext')?.getElectronAccelerator() === 'Down';\n}\n"]}
|
||||
102
_internal/editor/esm/vs/platform/hover/browser/hover.js
Normal file
102
_internal/editor/esm/vs/platform/hover/browser/hover.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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); }
|
||||
};
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { Disposable, DisposableStore } from '../../../base/common/lifecycle.js';
|
||||
import { IConfigurationService } from '../../configuration/common/configuration.js';
|
||||
import { addStandardDisposableListener, isHTMLElement } from '../../../base/browser/dom.js';
|
||||
export const IHoverService = createDecorator('hoverService');
|
||||
let WorkbenchHoverDelegate = class WorkbenchHoverDelegate extends Disposable {
|
||||
get delay() {
|
||||
if (this.isInstantlyHovering()) {
|
||||
return 0; // show instantly when a hover was recently shown
|
||||
}
|
||||
if (this.hoverOptions?.dynamicDelay) {
|
||||
return content => this.hoverOptions?.dynamicDelay?.(content) ?? this._delay;
|
||||
}
|
||||
return this._delay;
|
||||
}
|
||||
constructor(placement, hoverOptions, overrideOptions = {}, configurationService, hoverService) {
|
||||
super();
|
||||
this.placement = placement;
|
||||
this.hoverOptions = hoverOptions;
|
||||
this.overrideOptions = overrideOptions;
|
||||
this.configurationService = configurationService;
|
||||
this.hoverService = hoverService;
|
||||
this.lastHoverHideTime = 0;
|
||||
this.timeLimit = 200;
|
||||
this.hoverDisposables = this._register(new DisposableStore());
|
||||
this._delay = this.configurationService.getValue('workbench.hover.delay');
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('workbench.hover.delay')) {
|
||||
this._delay = this.configurationService.getValue('workbench.hover.delay');
|
||||
}
|
||||
}));
|
||||
}
|
||||
showHover(options, focus) {
|
||||
const overrideOptions = typeof this.overrideOptions === 'function' ? this.overrideOptions(options, focus) : this.overrideOptions;
|
||||
// close hover on escape
|
||||
this.hoverDisposables.clear();
|
||||
const targets = isHTMLElement(options.target) ? [options.target] : options.target.targetElements;
|
||||
for (const target of targets) {
|
||||
this.hoverDisposables.add(addStandardDisposableListener(target, 'keydown', (e) => {
|
||||
if (e.equals(9 /* KeyCode.Escape */)) {
|
||||
this.hoverService.hideHover();
|
||||
}
|
||||
}));
|
||||
}
|
||||
const id = isHTMLElement(options.content)
|
||||
? undefined
|
||||
: typeof options.content === 'string'
|
||||
? options.content.toString()
|
||||
: options.content.value;
|
||||
return this.hoverService.showInstantHover({
|
||||
...options,
|
||||
...overrideOptions,
|
||||
persistence: {
|
||||
hideOnKeyDown: true,
|
||||
...overrideOptions.persistence
|
||||
},
|
||||
id,
|
||||
appearance: {
|
||||
...options.appearance,
|
||||
compact: true,
|
||||
skipFadeInAnimation: this.isInstantlyHovering(),
|
||||
...overrideOptions.appearance
|
||||
}
|
||||
}, focus);
|
||||
}
|
||||
isInstantlyHovering() {
|
||||
return !!this.hoverOptions?.instantHover && Date.now() - this.lastHoverHideTime < this.timeLimit;
|
||||
}
|
||||
onDidHideHover() {
|
||||
this.hoverDisposables.clear();
|
||||
if (this.hoverOptions?.instantHover) {
|
||||
this.lastHoverHideTime = Date.now();
|
||||
}
|
||||
}
|
||||
};
|
||||
WorkbenchHoverDelegate = __decorate([
|
||||
__param(3, IConfigurationService),
|
||||
__param(4, IHoverService)
|
||||
], WorkbenchHoverDelegate);
|
||||
export { WorkbenchHoverDelegate };
|
||||
// TODO@benibenj remove this, only temp fix for contextviews
|
||||
export const nativeHoverDelegate = {
|
||||
showHover: function () {
|
||||
throw new Error('Native hover function not implemented.');
|
||||
},
|
||||
delay: 0,
|
||||
showNativeHover: true
|
||||
};
|
||||
//# sourceMappingURL=hover.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export class SyncDescriptor {
|
||||
constructor(ctor, staticArguments = [], supportsDelayedInstantiation = false) {
|
||||
this.ctor = ctor;
|
||||
this.staticArguments = staticArguments;
|
||||
this.supportsDelayedInstantiation = supportsDelayedInstantiation;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=descriptors.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/instantiation/common/descriptors.ts","vs/platform/instantiation/common/descriptors.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,MAAM,OAAO,cAAc;IAM1B,YAAY,IAA+B,EAAE,kBAAyB,EAAE,EAAE,+BAAwC,KAAK;QACtH,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,4BAA4B,GAAG,4BAA4B,CAAC;IAClE,CAAC;CACD","file":"descriptors.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport class SyncDescriptor<T> {\n\n\treadonly ctor: any;\n\treadonly staticArguments: any[];\n\treadonly supportsDelayedInstantiation: boolean;\n\n\tconstructor(ctor: new (...args: any[]) => T, staticArguments: any[] = [], supportsDelayedInstantiation: boolean = false) {\n\t\tthis.ctor = ctor;\n\t\tthis.staticArguments = staticArguments;\n\t\tthis.supportsDelayedInstantiation = supportsDelayedInstantiation;\n\t}\n}\n\nexport interface SyncDescriptor0<T> {\n\treadonly ctor: new () => T;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nexport class SyncDescriptor<T> {\n\n\treadonly ctor: any;\n\treadonly staticArguments: any[];\n\treadonly supportsDelayedInstantiation: boolean;\n\n\tconstructor(ctor: new (...args: any[]) => T, staticArguments: any[] = [], supportsDelayedInstantiation: boolean = false) {\n\t\tthis.ctor = ctor;\n\t\tthis.staticArguments = staticArguments;\n\t\tthis.supportsDelayedInstantiation = supportsDelayedInstantiation;\n\t}\n}\n\nexport interface SyncDescriptor0<T> {\n\treadonly ctor: new () => T;\n}\n"]}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { SyncDescriptor } from './descriptors.js';
|
||||
const _registry = [];
|
||||
export function registerSingleton(id, ctorOrDescriptor, supportsDelayedInstantiation) {
|
||||
if (!(ctorOrDescriptor instanceof SyncDescriptor)) {
|
||||
ctorOrDescriptor = new SyncDescriptor(ctorOrDescriptor, [], Boolean(supportsDelayedInstantiation));
|
||||
}
|
||||
_registry.push([id, ctorOrDescriptor]);
|
||||
}
|
||||
export function getSingletonServiceDescriptors() {
|
||||
return _registry;
|
||||
}
|
||||
//# sourceMappingURL=extensions.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/instantiation/common/extensions.ts","vs/platform/instantiation/common/extensions.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,MAAM,SAAS,GAAoD,EAAE,CAAC;AAkBtE,MAAM,UAAU,iBAAiB,CAAuC,EAAwB,EAAE,gBAAyE,EAAE,4BAA0D;IACtO,IAAI,CAAC,CAAC,gBAAgB,YAAY,cAAc,CAAC,EAAE,CAAC;QACnD,gBAAgB,GAAG,IAAI,cAAc,CAAI,gBAA6C,EAAE,EAAE,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACpI,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC7C,OAAO,SAAS,CAAC;AAClB,CAAC","file":"extensions.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { SyncDescriptor } from './descriptors.js';\nimport { BrandedService, ServiceIdentifier } from './instantiation.js';\n\nconst _registry: [ServiceIdentifier<any>, SyncDescriptor<any>][] = [];\n\nexport const enum InstantiationType {\n\t/**\n\t * Instantiate this service as soon as a consumer depends on it. _Note_ that this\n\t * is more costly as some upfront work is done that is likely not needed\n\t */\n\tEager = 0,\n\n\t/**\n\t * Instantiate this service as soon as a consumer uses it. This is the _better_\n\t * way of registering a service.\n\t */\n\tDelayed = 1\n}\n\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, ctor: new (...services: Services) => T, supportsDelayedInstantiation: InstantiationType): void;\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, descriptor: SyncDescriptor<any>): void;\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, ctorOrDescriptor: { new(...services: Services): T } | SyncDescriptor<any>, supportsDelayedInstantiation?: boolean | InstantiationType): void {\n\tif (!(ctorOrDescriptor instanceof SyncDescriptor)) {\n\t\tctorOrDescriptor = new SyncDescriptor<T>(ctorOrDescriptor as new (...args: any[]) => T, [], Boolean(supportsDelayedInstantiation));\n\t}\n\n\t_registry.push([id, ctorOrDescriptor]);\n}\n\nexport function getSingletonServiceDescriptors(): [ServiceIdentifier<any>, SyncDescriptor<any>][] {\n\treturn _registry;\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { SyncDescriptor } from './descriptors.js';\nimport { BrandedService, ServiceIdentifier } from './instantiation.js';\n\nconst _registry: [ServiceIdentifier<any>, SyncDescriptor<any>][] = [];\n\nexport const enum InstantiationType {\n\t/**\n\t * Instantiate this service as soon as a consumer depends on it. _Note_ that this\n\t * is more costly as some upfront work is done that is likely not needed\n\t */\n\tEager = 0,\n\n\t/**\n\t * Instantiate this service as soon as a consumer uses it. This is the _better_\n\t * way of registering a service.\n\t */\n\tDelayed = 1\n}\n\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, ctor: new (...services: Services) => T, supportsDelayedInstantiation: InstantiationType): void;\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, descriptor: SyncDescriptor<any>): void;\nexport function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, ctorOrDescriptor: { new(...services: Services): T } | SyncDescriptor<any>, supportsDelayedInstantiation?: boolean | InstantiationType): void {\n\tif (!(ctorOrDescriptor instanceof SyncDescriptor)) {\n\t\tctorOrDescriptor = new SyncDescriptor<T>(ctorOrDescriptor as new (...args: any[]) => T, [], Boolean(supportsDelayedInstantiation));\n\t}\n\n\t_registry.push([id, ctorOrDescriptor]);\n}\n\nexport function getSingletonServiceDescriptors(): [ServiceIdentifier<any>, SyncDescriptor<any>][] {\n\treturn _registry;\n}\n"]}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export class Node {
|
||||
constructor(key, data) {
|
||||
this.key = key;
|
||||
this.data = data;
|
||||
this.incoming = new Map();
|
||||
this.outgoing = new Map();
|
||||
}
|
||||
}
|
||||
export class Graph {
|
||||
constructor(_hashFn) {
|
||||
this._hashFn = _hashFn;
|
||||
this._nodes = new Map();
|
||||
// empty
|
||||
}
|
||||
roots() {
|
||||
const ret = [];
|
||||
for (const node of this._nodes.values()) {
|
||||
if (node.outgoing.size === 0) {
|
||||
ret.push(node);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
insertEdge(from, to) {
|
||||
const fromNode = this.lookupOrInsertNode(from);
|
||||
const toNode = this.lookupOrInsertNode(to);
|
||||
fromNode.outgoing.set(toNode.key, toNode);
|
||||
toNode.incoming.set(fromNode.key, fromNode);
|
||||
}
|
||||
removeNode(data) {
|
||||
const key = this._hashFn(data);
|
||||
this._nodes.delete(key);
|
||||
for (const node of this._nodes.values()) {
|
||||
node.outgoing.delete(key);
|
||||
node.incoming.delete(key);
|
||||
}
|
||||
}
|
||||
lookupOrInsertNode(data) {
|
||||
const key = this._hashFn(data);
|
||||
let node = this._nodes.get(key);
|
||||
if (!node) {
|
||||
node = new Node(key, data);
|
||||
this._nodes.set(key, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
isEmpty() {
|
||||
return this._nodes.size === 0;
|
||||
}
|
||||
toString() {
|
||||
const data = [];
|
||||
for (const [key, value] of this._nodes) {
|
||||
data.push(`${key}\n\t(-> incoming)[${[...value.incoming.keys()].join(', ')}]\n\t(outgoing ->)[${[...value.outgoing.keys()].join(',')}]\n`);
|
||||
}
|
||||
return data.join('\n');
|
||||
}
|
||||
/**
|
||||
* This is brute force and slow and **only** be used
|
||||
* to trouble shoot.
|
||||
*/
|
||||
findCycleSlow() {
|
||||
for (const [id, node] of this._nodes) {
|
||||
const seen = new Set([id]);
|
||||
const res = this._findCycle(node, seen);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
_findCycle(node, seen) {
|
||||
for (const [id, outgoing] of node.outgoing) {
|
||||
if (seen.has(id)) {
|
||||
return [...seen, id].join(' -> ');
|
||||
}
|
||||
seen.add(id);
|
||||
const value = this._findCycle(outgoing, seen);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
seen.delete(id);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=graph.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
// ------ internal util
|
||||
export var _util;
|
||||
(function (_util) {
|
||||
_util.serviceIds = new Map();
|
||||
_util.DI_TARGET = '$di$target';
|
||||
_util.DI_DEPENDENCIES = '$di$dependencies';
|
||||
function getServiceDependencies(ctor) {
|
||||
return ctor[_util.DI_DEPENDENCIES] || [];
|
||||
}
|
||||
_util.getServiceDependencies = getServiceDependencies;
|
||||
})(_util || (_util = {}));
|
||||
export const IInstantiationService = createDecorator('instantiationService');
|
||||
function storeServiceDependency(id, target, index) {
|
||||
if (target[_util.DI_TARGET] === target) {
|
||||
target[_util.DI_DEPENDENCIES].push({ id, index });
|
||||
}
|
||||
else {
|
||||
target[_util.DI_DEPENDENCIES] = [{ id, index }];
|
||||
target[_util.DI_TARGET] = target;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The *only* valid way to create a {{ServiceIdentifier}}.
|
||||
*/
|
||||
export function createDecorator(serviceId) {
|
||||
if (_util.serviceIds.has(serviceId)) {
|
||||
return _util.serviceIds.get(serviceId);
|
||||
}
|
||||
const id = function (target, key, index) {
|
||||
if (arguments.length !== 3) {
|
||||
throw new Error('@IServiceName-decorator can only be used to decorate a parameter');
|
||||
}
|
||||
storeServiceDependency(id, target, index);
|
||||
};
|
||||
id.toString = () => serviceId;
|
||||
_util.serviceIds.set(serviceId, id);
|
||||
return id;
|
||||
}
|
||||
//# sourceMappingURL=instantiation.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,400 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { GlobalIdleValue } from '../../../base/common/async.js';
|
||||
import { illegalState } from '../../../base/common/errors.js';
|
||||
import { dispose, isDisposable, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { SyncDescriptor } from './descriptors.js';
|
||||
import { Graph } from './graph.js';
|
||||
import { IInstantiationService, _util } from './instantiation.js';
|
||||
import { ServiceCollection } from './serviceCollection.js';
|
||||
import { LinkedList } from '../../../base/common/linkedList.js';
|
||||
// TRACING
|
||||
const _enableAllTracing = false;
|
||||
class CyclicDependencyError extends Error {
|
||||
constructor(graph) {
|
||||
super('cyclic dependency between services');
|
||||
this.message = graph.findCycleSlow() ?? `UNABLE to detect cycle, dumping graph: \n${graph.toString()}`;
|
||||
}
|
||||
}
|
||||
export class InstantiationService {
|
||||
constructor(_services = new ServiceCollection(), _strict = false, _parent, _enableTracing = _enableAllTracing) {
|
||||
this._services = _services;
|
||||
this._strict = _strict;
|
||||
this._parent = _parent;
|
||||
this._enableTracing = _enableTracing;
|
||||
this._isDisposed = false;
|
||||
this._servicesToMaybeDispose = new Set();
|
||||
this._children = new Set();
|
||||
this._activeInstantiations = new Set();
|
||||
this._services.set(IInstantiationService, this);
|
||||
this._globalGraph = _enableTracing ? _parent?._globalGraph ?? new Graph(e => e) : undefined;
|
||||
}
|
||||
dispose() {
|
||||
if (!this._isDisposed) {
|
||||
this._isDisposed = true;
|
||||
// dispose all child services
|
||||
dispose(this._children);
|
||||
this._children.clear();
|
||||
// dispose all services created by this service
|
||||
for (const candidate of this._servicesToMaybeDispose) {
|
||||
if (isDisposable(candidate)) {
|
||||
candidate.dispose();
|
||||
}
|
||||
}
|
||||
this._servicesToMaybeDispose.clear();
|
||||
}
|
||||
}
|
||||
_throwIfDisposed() {
|
||||
if (this._isDisposed) {
|
||||
throw new Error('InstantiationService has been disposed');
|
||||
}
|
||||
}
|
||||
createChild(services, store) {
|
||||
this._throwIfDisposed();
|
||||
const that = this;
|
||||
const result = new class extends InstantiationService {
|
||||
dispose() {
|
||||
that._children.delete(result);
|
||||
super.dispose();
|
||||
}
|
||||
}(services, this._strict, this, this._enableTracing);
|
||||
this._children.add(result);
|
||||
store?.add(result);
|
||||
return result;
|
||||
}
|
||||
invokeFunction(fn, ...args) {
|
||||
this._throwIfDisposed();
|
||||
const _trace = Trace.traceInvocation(this._enableTracing, fn);
|
||||
let _done = false;
|
||||
try {
|
||||
const accessor = {
|
||||
get: (id) => {
|
||||
if (_done) {
|
||||
throw illegalState('service accessor is only valid during the invocation of its target method');
|
||||
}
|
||||
const result = this._getOrCreateServiceInstance(id, _trace);
|
||||
if (!result) {
|
||||
throw new Error(`[invokeFunction] unknown service '${id}'`);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getIfExists: (id) => {
|
||||
if (_done) {
|
||||
throw illegalState('service accessor is only valid during the invocation of its target method');
|
||||
}
|
||||
const result = this._getOrCreateServiceInstance(id, _trace);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
return fn(accessor, ...args);
|
||||
}
|
||||
finally {
|
||||
_done = true;
|
||||
_trace.stop();
|
||||
}
|
||||
}
|
||||
createInstance(ctorOrDescriptor, ...rest) {
|
||||
this._throwIfDisposed();
|
||||
let _trace;
|
||||
let result;
|
||||
if (ctorOrDescriptor instanceof SyncDescriptor) {
|
||||
_trace = Trace.traceCreation(this._enableTracing, ctorOrDescriptor.ctor);
|
||||
result = this._createInstance(ctorOrDescriptor.ctor, ctorOrDescriptor.staticArguments.concat(rest), _trace);
|
||||
}
|
||||
else {
|
||||
_trace = Trace.traceCreation(this._enableTracing, ctorOrDescriptor);
|
||||
result = this._createInstance(ctorOrDescriptor, rest, _trace);
|
||||
}
|
||||
_trace.stop();
|
||||
return result;
|
||||
}
|
||||
_createInstance(ctor, args = [], _trace) {
|
||||
// arguments defined by service decorators
|
||||
const serviceDependencies = _util.getServiceDependencies(ctor).sort((a, b) => a.index - b.index);
|
||||
const serviceArgs = [];
|
||||
for (const dependency of serviceDependencies) {
|
||||
const service = this._getOrCreateServiceInstance(dependency.id, _trace);
|
||||
if (!service) {
|
||||
this._throwIfStrict(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`, false);
|
||||
}
|
||||
serviceArgs.push(service);
|
||||
}
|
||||
const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;
|
||||
// check for argument mismatches, adjust static args if needed
|
||||
if (args.length !== firstServiceArgPos) {
|
||||
console.trace(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);
|
||||
const delta = firstServiceArgPos - args.length;
|
||||
if (delta > 0) {
|
||||
args = args.concat(new Array(delta));
|
||||
}
|
||||
else {
|
||||
args = args.slice(0, firstServiceArgPos);
|
||||
}
|
||||
}
|
||||
// now create the instance
|
||||
return Reflect.construct(ctor, args.concat(serviceArgs));
|
||||
}
|
||||
_setCreatedServiceInstance(id, instance) {
|
||||
if (this._services.get(id) instanceof SyncDescriptor) {
|
||||
this._services.set(id, instance);
|
||||
}
|
||||
else if (this._parent) {
|
||||
this._parent._setCreatedServiceInstance(id, instance);
|
||||
}
|
||||
else {
|
||||
throw new Error('illegalState - setting UNKNOWN service instance');
|
||||
}
|
||||
}
|
||||
_getServiceInstanceOrDescriptor(id) {
|
||||
const instanceOrDesc = this._services.get(id);
|
||||
if (!instanceOrDesc && this._parent) {
|
||||
return this._parent._getServiceInstanceOrDescriptor(id);
|
||||
}
|
||||
else {
|
||||
return instanceOrDesc;
|
||||
}
|
||||
}
|
||||
_getOrCreateServiceInstance(id, _trace) {
|
||||
if (this._globalGraph && this._globalGraphImplicitDependency) {
|
||||
this._globalGraph.insertEdge(this._globalGraphImplicitDependency, String(id));
|
||||
}
|
||||
const thing = this._getServiceInstanceOrDescriptor(id);
|
||||
if (thing instanceof SyncDescriptor) {
|
||||
return this._safeCreateAndCacheServiceInstance(id, thing, _trace.branch(id, true));
|
||||
}
|
||||
else {
|
||||
_trace.branch(id, false);
|
||||
return thing;
|
||||
}
|
||||
}
|
||||
_safeCreateAndCacheServiceInstance(id, desc, _trace) {
|
||||
if (this._activeInstantiations.has(id)) {
|
||||
throw new Error(`illegal state - RECURSIVELY instantiating service '${id}'`);
|
||||
}
|
||||
this._activeInstantiations.add(id);
|
||||
try {
|
||||
return this._createAndCacheServiceInstance(id, desc, _trace);
|
||||
}
|
||||
finally {
|
||||
this._activeInstantiations.delete(id);
|
||||
}
|
||||
}
|
||||
_createAndCacheServiceInstance(id, desc, _trace) {
|
||||
const graph = new Graph(data => data.id.toString());
|
||||
let cycleCount = 0;
|
||||
const stack = [{ id, desc, _trace }];
|
||||
const seen = new Set();
|
||||
while (stack.length) {
|
||||
const item = stack.pop();
|
||||
if (seen.has(String(item.id))) {
|
||||
continue;
|
||||
}
|
||||
seen.add(String(item.id));
|
||||
graph.lookupOrInsertNode(item);
|
||||
// a weak but working heuristic for cycle checks
|
||||
if (cycleCount++ > 1000) {
|
||||
throw new CyclicDependencyError(graph);
|
||||
}
|
||||
// check all dependencies for existence and if they need to be created first
|
||||
for (const dependency of _util.getServiceDependencies(item.desc.ctor)) {
|
||||
const instanceOrDesc = this._getServiceInstanceOrDescriptor(dependency.id);
|
||||
if (!instanceOrDesc) {
|
||||
this._throwIfStrict(`[createInstance] ${id} depends on ${dependency.id} which is NOT registered.`, true);
|
||||
}
|
||||
// take note of all service dependencies
|
||||
this._globalGraph?.insertEdge(String(item.id), String(dependency.id));
|
||||
if (instanceOrDesc instanceof SyncDescriptor) {
|
||||
const d = { id: dependency.id, desc: instanceOrDesc, _trace: item._trace.branch(dependency.id, true) };
|
||||
graph.insertEdge(item, d);
|
||||
stack.push(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
const roots = graph.roots();
|
||||
// if there is no more roots but still
|
||||
// nodes in the graph we have a cycle
|
||||
if (roots.length === 0) {
|
||||
if (!graph.isEmpty()) {
|
||||
throw new CyclicDependencyError(graph);
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (const { data } of roots) {
|
||||
// Repeat the check for this still being a service sync descriptor. That's because
|
||||
// instantiating a dependency might have side-effect and recursively trigger instantiation
|
||||
// so that some dependencies are now fullfilled already.
|
||||
const instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);
|
||||
if (instanceOrDesc instanceof SyncDescriptor) {
|
||||
// create instance and overwrite the service collections
|
||||
const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);
|
||||
this._setCreatedServiceInstance(data.id, instance);
|
||||
}
|
||||
graph.removeNode(data);
|
||||
}
|
||||
}
|
||||
return this._getServiceInstanceOrDescriptor(id);
|
||||
}
|
||||
_createServiceInstanceWithOwner(id, ctor, args = [], supportsDelayedInstantiation, _trace) {
|
||||
if (this._services.get(id) instanceof SyncDescriptor) {
|
||||
return this._createServiceInstance(id, ctor, args, supportsDelayedInstantiation, _trace, this._servicesToMaybeDispose);
|
||||
}
|
||||
else if (this._parent) {
|
||||
return this._parent._createServiceInstanceWithOwner(id, ctor, args, supportsDelayedInstantiation, _trace);
|
||||
}
|
||||
else {
|
||||
throw new Error(`illegalState - creating UNKNOWN service instance ${ctor.name}`);
|
||||
}
|
||||
}
|
||||
_createServiceInstance(id, ctor, args = [], supportsDelayedInstantiation, _trace, disposeBucket) {
|
||||
if (!supportsDelayedInstantiation) {
|
||||
// eager instantiation
|
||||
const result = this._createInstance(ctor, args, _trace);
|
||||
disposeBucket.add(result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
const child = new InstantiationService(undefined, this._strict, this, this._enableTracing);
|
||||
child._globalGraphImplicitDependency = String(id);
|
||||
// Return a proxy object that's backed by an idle value. That
|
||||
// strategy is to instantiate services in our idle time or when actually
|
||||
// needed but not when injected into a consumer
|
||||
// return "empty events" when the service isn't instantiated yet
|
||||
const earlyListeners = new Map();
|
||||
const idle = new GlobalIdleValue(() => {
|
||||
const result = child._createInstance(ctor, args, _trace);
|
||||
// early listeners that we kept are now being subscribed to
|
||||
// the real service
|
||||
for (const [key, values] of earlyListeners) {
|
||||
const candidate = result[key];
|
||||
if (typeof candidate === 'function') {
|
||||
for (const value of values) {
|
||||
value.disposable = candidate.apply(result, value.listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
earlyListeners.clear();
|
||||
disposeBucket.add(result);
|
||||
return result;
|
||||
});
|
||||
return new Proxy(Object.create(null), {
|
||||
get(target, key) {
|
||||
if (!idle.isInitialized) {
|
||||
// looks like an event
|
||||
if (typeof key === 'string' && (key.startsWith('onDid') || key.startsWith('onWill'))) {
|
||||
let list = earlyListeners.get(key);
|
||||
if (!list) {
|
||||
list = new LinkedList();
|
||||
earlyListeners.set(key, list);
|
||||
}
|
||||
const event = (callback, thisArg, disposables) => {
|
||||
if (idle.isInitialized) {
|
||||
return idle.value[key](callback, thisArg, disposables);
|
||||
}
|
||||
else {
|
||||
const entry = { listener: [callback, thisArg, disposables], disposable: undefined };
|
||||
const rm = list.push(entry);
|
||||
const result = toDisposable(() => {
|
||||
rm();
|
||||
entry.disposable?.dispose();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
return event;
|
||||
}
|
||||
}
|
||||
// value already exists
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
// create value
|
||||
const obj = idle.value;
|
||||
let prop = obj[key];
|
||||
if (typeof prop !== 'function') {
|
||||
return prop;
|
||||
}
|
||||
prop = prop.bind(obj);
|
||||
target[key] = prop;
|
||||
return prop;
|
||||
},
|
||||
set(_target, p, value) {
|
||||
idle.value[p] = value;
|
||||
return true;
|
||||
},
|
||||
getPrototypeOf(_target) {
|
||||
return ctor.prototype;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
_throwIfStrict(msg, printWarning) {
|
||||
if (printWarning) {
|
||||
console.warn(msg);
|
||||
}
|
||||
if (this._strict) {
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
export class Trace {
|
||||
static { this.all = new Set(); }
|
||||
static { this._None = new class extends Trace {
|
||||
constructor() { super(0 /* TraceType.None */, null); }
|
||||
stop() { }
|
||||
branch() { return this; }
|
||||
}; }
|
||||
static traceInvocation(_enableTracing, ctor) {
|
||||
return !_enableTracing ? Trace._None : new Trace(2 /* TraceType.Invocation */, ctor.name || new Error().stack.split('\n').slice(3, 4).join('\n'));
|
||||
}
|
||||
static traceCreation(_enableTracing, ctor) {
|
||||
return !_enableTracing ? Trace._None : new Trace(1 /* TraceType.Creation */, ctor.name);
|
||||
}
|
||||
static { this._totals = 0; }
|
||||
constructor(type, name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this._start = Date.now();
|
||||
this._dep = [];
|
||||
}
|
||||
branch(id, first) {
|
||||
const child = new Trace(3 /* TraceType.Branch */, id.toString());
|
||||
this._dep.push([id, first, child]);
|
||||
return child;
|
||||
}
|
||||
stop() {
|
||||
const dur = Date.now() - this._start;
|
||||
Trace._totals += dur;
|
||||
let causedCreation = false;
|
||||
function printChild(n, trace) {
|
||||
const res = [];
|
||||
const prefix = new Array(n + 1).join('\t');
|
||||
for (const [id, first, child] of trace._dep) {
|
||||
if (first && child) {
|
||||
causedCreation = true;
|
||||
res.push(`${prefix}CREATES -> ${id}`);
|
||||
const nested = printChild(n + 1, child);
|
||||
if (nested) {
|
||||
res.push(nested);
|
||||
}
|
||||
}
|
||||
else {
|
||||
res.push(`${prefix}uses -> ${id}`);
|
||||
}
|
||||
}
|
||||
return res.join('\n');
|
||||
}
|
||||
const lines = [
|
||||
`${this.type === 1 /* TraceType.Creation */ ? 'CREATE' : 'CALL'} ${this.name}`,
|
||||
`${printChild(1, this)}`,
|
||||
`DONE, took ${dur.toFixed(2)}ms (grand total ${Trace._totals.toFixed(2)}ms)`
|
||||
];
|
||||
if (dur > 2 || causedCreation) {
|
||||
Trace.all.add(lines.join('\n'));
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
//# sourceMappingURL=instantiationService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,21 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export class ServiceCollection {
|
||||
constructor(...entries) {
|
||||
this._entries = new Map();
|
||||
for (const [id, service] of entries) {
|
||||
this.set(id, service);
|
||||
}
|
||||
}
|
||||
set(id, instanceOrDescriptor) {
|
||||
const result = this._entries.get(id);
|
||||
this._entries.set(id, instanceOrDescriptor);
|
||||
return result;
|
||||
}
|
||||
get(id) {
|
||||
return this._entries.get(id);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=serviceCollection.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/platform/instantiation/common/serviceCollection.ts","vs/platform/instantiation/common/serviceCollection.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAKhG,MAAM,OAAO,iBAAiB;IAI7B,YAAY,GAAG,OAAwC;QAF/C,aAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;QAGzD,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;IAED,GAAG,CAAI,EAAwB,EAAE,oBAA2C;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC;IACf,CAAC;IAED,GAAG,CAAI,EAAwB;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;CACD","file":"serviceCollection.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ServiceIdentifier } from './instantiation.js';\nimport { SyncDescriptor } from './descriptors.js';\n\nexport class ServiceCollection {\n\n\tprivate _entries = new Map<ServiceIdentifier<any>, any>();\n\n\tconstructor(...entries: [ServiceIdentifier<any>, any][]) {\n\t\tfor (const [id, service] of entries) {\n\t\t\tthis.set(id, service);\n\t\t}\n\t}\n\n\tset<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | SyncDescriptor<T>): T | SyncDescriptor<T> {\n\t\tconst result = this._entries.get(id);\n\t\tthis._entries.set(id, instanceOrDescriptor);\n\t\treturn result;\n\t}\n\n\tget<T>(id: ServiceIdentifier<T>): T | SyncDescriptor<T> {\n\t\treturn this._entries.get(id);\n\t}\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ServiceIdentifier } from './instantiation.js';\nimport { SyncDescriptor } from './descriptors.js';\n\nexport class ServiceCollection {\n\n\tprivate _entries = new Map<ServiceIdentifier<any>, any>();\n\n\tconstructor(...entries: [ServiceIdentifier<any>, any][]) {\n\t\tfor (const [id, service] of entries) {\n\t\t\tthis.set(id, service);\n\t\t}\n\t}\n\n\tset<T>(id: ServiceIdentifier<T>, instanceOrDescriptor: T | SyncDescriptor<T>): T | SyncDescriptor<T> {\n\t\tconst result = this._entries.get(id);\n\t\tthis._entries.set(id, instanceOrDescriptor);\n\t\treturn result;\n\t}\n\n\tget<T>(id: ServiceIdentifier<T>): T | SyncDescriptor<T> {\n\t\treturn this._entries.get(id);\n\t}\n}\n"]}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Disposable, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import * as platform from '../../registry/common/platform.js';
|
||||
export const Extensions = {
|
||||
JSONContribution: 'base.contributions.json'
|
||||
};
|
||||
function normalizeId(id) {
|
||||
if (id.length > 0 && id.charAt(id.length - 1) === '#') {
|
||||
return id.substring(0, id.length - 1);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
class JSONContributionRegistry extends Disposable {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.schemasById = {};
|
||||
this._onDidChangeSchema = this._register(new Emitter());
|
||||
}
|
||||
registerSchema(uri, unresolvedSchemaContent, store) {
|
||||
const normalizedUri = normalizeId(uri);
|
||||
this.schemasById[normalizedUri] = unresolvedSchemaContent;
|
||||
this._onDidChangeSchema.fire(uri);
|
||||
if (store) {
|
||||
store.add(toDisposable(() => {
|
||||
delete this.schemasById[normalizedUri];
|
||||
this._onDidChangeSchema.fire(uri);
|
||||
}));
|
||||
}
|
||||
}
|
||||
notifySchemaChanged(uri) {
|
||||
this._onDidChangeSchema.fire(uri);
|
||||
}
|
||||
}
|
||||
const jsonContributionRegistry = new JSONContributionRegistry();
|
||||
platform.Registry.add(Extensions.JSONContribution, jsonContributionRegistry);
|
||||
//# sourceMappingURL=jsonContributionRegistry.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,284 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { IntervalTimer, TimeoutTimer } from '../../../base/common/async.js';
|
||||
import { illegalState } from '../../../base/common/errors.js';
|
||||
import { Emitter, Event } from '../../../base/common/event.js';
|
||||
import { IME } from '../../../base/common/ime.js';
|
||||
import { Disposable } from '../../../base/common/lifecycle.js';
|
||||
import * as nls from '../../../nls.js';
|
||||
import { NoMatchingKb } from './keybindingResolver.js';
|
||||
const HIGH_FREQ_COMMANDS = /^(cursor|delete|undo|redo|tab|editor\.action\.clipboard)/;
|
||||
export class AbstractKeybindingService extends Disposable {
|
||||
get onDidUpdateKeybindings() {
|
||||
return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype
|
||||
}
|
||||
get inChordMode() {
|
||||
return this._currentChords.length > 0;
|
||||
}
|
||||
constructor(_contextKeyService, _commandService, _telemetryService, _notificationService, _logService) {
|
||||
super();
|
||||
this._contextKeyService = _contextKeyService;
|
||||
this._commandService = _commandService;
|
||||
this._telemetryService = _telemetryService;
|
||||
this._notificationService = _notificationService;
|
||||
this._logService = _logService;
|
||||
this._onDidUpdateKeybindings = this._register(new Emitter());
|
||||
this._currentChords = [];
|
||||
this._currentChordChecker = new IntervalTimer();
|
||||
this._currentChordStatusMessage = null;
|
||||
this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;
|
||||
this._currentSingleModifier = null;
|
||||
this._currentSingleModifierClearTimeout = new TimeoutTimer();
|
||||
this._currentlyDispatchingCommandId = null;
|
||||
this._logging = false;
|
||||
}
|
||||
dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
_log(str) {
|
||||
if (this._logging) {
|
||||
this._logService.info(`[KeybindingService]: ${str}`);
|
||||
}
|
||||
}
|
||||
getKeybindings() {
|
||||
return this._getResolver().getKeybindings();
|
||||
}
|
||||
lookupKeybinding(commandId, context, enforceContextCheck = false) {
|
||||
const result = this._getResolver().lookupPrimaryKeybinding(commandId, context || this._contextKeyService, enforceContextCheck);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
return result.resolvedKeybinding;
|
||||
}
|
||||
dispatchEvent(e, target) {
|
||||
return this._dispatch(e, target);
|
||||
}
|
||||
// TODO@ulugbekna: update namings to align with `_doDispatch`
|
||||
// TODO@ulugbekna: this fn doesn't seem to take into account single-modifier keybindings, eg `shift shift`
|
||||
softDispatch(e, target) {
|
||||
this._log(`/ Soft dispatching keyboard event`);
|
||||
const keybinding = this.resolveKeyboardEvent(e);
|
||||
if (keybinding.hasMultipleChords()) {
|
||||
console.warn('keyboard event should not be mapped to multiple chords');
|
||||
return NoMatchingKb;
|
||||
}
|
||||
const [firstChord,] = keybinding.getDispatchChords();
|
||||
if (firstChord === null) {
|
||||
// cannot be dispatched, probably only modifier keys
|
||||
this._log(`\\ Keyboard event cannot be dispatched`);
|
||||
return NoMatchingKb;
|
||||
}
|
||||
const contextValue = this._contextKeyService.getContext(target);
|
||||
const currentChords = this._currentChords.map((({ keypress }) => keypress));
|
||||
return this._getResolver().resolve(contextValue, currentChords, firstChord);
|
||||
}
|
||||
_scheduleLeaveChordMode() {
|
||||
const chordLastInteractedTime = Date.now();
|
||||
this._currentChordChecker.cancelAndSet(() => {
|
||||
if (!this._documentHasFocus()) {
|
||||
// Focus has been lost => leave chord mode
|
||||
this._leaveChordMode();
|
||||
return;
|
||||
}
|
||||
if (Date.now() - chordLastInteractedTime > 5000) {
|
||||
// 5 seconds elapsed => leave chord mode
|
||||
this._leaveChordMode();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
_expectAnotherChord(firstChord, keypressLabel) {
|
||||
this._currentChords.push({ keypress: firstChord, label: keypressLabel });
|
||||
switch (this._currentChords.length) {
|
||||
case 0:
|
||||
throw illegalState('impossible');
|
||||
case 1:
|
||||
// TODO@ulugbekna: revise this message and the one below (at least, fix terminology)
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize(1684, "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
|
||||
break;
|
||||
default: {
|
||||
const fullKeypressLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize(1685, "({0}) was pressed. Waiting for next key of chord...", fullKeypressLabel));
|
||||
}
|
||||
}
|
||||
this._scheduleLeaveChordMode();
|
||||
if (IME.enabled) {
|
||||
IME.disable();
|
||||
}
|
||||
}
|
||||
_leaveChordMode() {
|
||||
if (this._currentChordStatusMessage) {
|
||||
this._currentChordStatusMessage.close();
|
||||
this._currentChordStatusMessage = null;
|
||||
}
|
||||
this._currentChordChecker.cancel();
|
||||
this._currentChords = [];
|
||||
IME.enable();
|
||||
}
|
||||
_dispatch(e, target) {
|
||||
return this._doDispatch(this.resolveKeyboardEvent(e), target, /*isSingleModiferChord*/ false);
|
||||
}
|
||||
_singleModifierDispatch(e, target) {
|
||||
const keybinding = this.resolveKeyboardEvent(e);
|
||||
const [singleModifier,] = keybinding.getSingleModifierDispatchChords();
|
||||
if (singleModifier) {
|
||||
if (this._ignoreSingleModifiers.has(singleModifier)) {
|
||||
this._log(`+ Ignoring single modifier ${singleModifier} due to it being pressed together with other keys.`);
|
||||
this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;
|
||||
this._currentSingleModifierClearTimeout.cancel();
|
||||
this._currentSingleModifier = null;
|
||||
return false;
|
||||
}
|
||||
this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;
|
||||
if (this._currentSingleModifier === null) {
|
||||
// we have a valid `singleModifier`, store it for the next keyup, but clear it in 300ms
|
||||
this._log(`+ Storing single modifier for possible chord ${singleModifier}.`);
|
||||
this._currentSingleModifier = singleModifier;
|
||||
this._currentSingleModifierClearTimeout.cancelAndSet(() => {
|
||||
this._log(`+ Clearing single modifier due to 300ms elapsed.`);
|
||||
this._currentSingleModifier = null;
|
||||
}, 300);
|
||||
return false;
|
||||
}
|
||||
if (singleModifier === this._currentSingleModifier) {
|
||||
// bingo!
|
||||
this._log(`/ Dispatching single modifier chord ${singleModifier} ${singleModifier}`);
|
||||
this._currentSingleModifierClearTimeout.cancel();
|
||||
this._currentSingleModifier = null;
|
||||
return this._doDispatch(keybinding, target, /*isSingleModiferChord*/ true);
|
||||
}
|
||||
this._log(`+ Clearing single modifier due to modifier mismatch: ${this._currentSingleModifier} ${singleModifier}`);
|
||||
this._currentSingleModifierClearTimeout.cancel();
|
||||
this._currentSingleModifier = null;
|
||||
return false;
|
||||
}
|
||||
// When pressing a modifier and holding it pressed with any other modifier or key combination,
|
||||
// the pressed modifiers should no longer be considered for single modifier dispatch.
|
||||
const [firstChord,] = keybinding.getChords();
|
||||
this._ignoreSingleModifiers = new KeybindingModifierSet(firstChord);
|
||||
if (this._currentSingleModifier !== null) {
|
||||
this._log(`+ Clearing single modifier due to other key up.`);
|
||||
}
|
||||
this._currentSingleModifierClearTimeout.cancel();
|
||||
this._currentSingleModifier = null;
|
||||
return false;
|
||||
}
|
||||
_doDispatch(userKeypress, target, isSingleModiferChord = false) {
|
||||
let shouldPreventDefault = false;
|
||||
if (userKeypress.hasMultipleChords()) { // warn - because user can press a single chord at a time
|
||||
console.warn('Unexpected keyboard event mapped to multiple chords');
|
||||
return false;
|
||||
}
|
||||
let userPressedChord = null;
|
||||
let currentChords = null;
|
||||
if (isSingleModiferChord) {
|
||||
// The keybinding is the second keypress of a single modifier chord, e.g. "shift shift".
|
||||
// A single modifier can only occur when the same modifier is pressed in short sequence,
|
||||
// hence we disregard `_currentChord` and use the same modifier instead.
|
||||
const [dispatchKeyname,] = userKeypress.getSingleModifierDispatchChords();
|
||||
userPressedChord = dispatchKeyname;
|
||||
currentChords = dispatchKeyname ? [dispatchKeyname] : []; // TODO@ulugbekna: in the `else` case we assign an empty array - make sure `resolve` can handle an empty array well
|
||||
}
|
||||
else {
|
||||
[userPressedChord,] = userKeypress.getDispatchChords();
|
||||
currentChords = this._currentChords.map(({ keypress }) => keypress);
|
||||
}
|
||||
if (userPressedChord === null) {
|
||||
this._log(`\\ Keyboard event cannot be dispatched in keydown phase.`);
|
||||
// cannot be dispatched, probably only modifier keys
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
const contextValue = this._contextKeyService.getContext(target);
|
||||
const keypressLabel = userKeypress.getLabel();
|
||||
const resolveResult = this._getResolver().resolve(contextValue, currentChords, userPressedChord);
|
||||
switch (resolveResult.kind) {
|
||||
case 0 /* ResultKind.NoMatchingKb */: {
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ No matching keybinding ]`);
|
||||
if (this.inChordMode) {
|
||||
const currentChordsLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._log(`+ Leaving multi-chord mode: Nothing bound to "${currentChordsLabel}, ${keypressLabel}".`);
|
||||
this._notificationService.status(nls.localize(1686, "The key combination ({0}, {1}) is not a command.", currentChordsLabel, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
this._leaveChordMode();
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
case 1 /* ResultKind.MoreChordsNeeded */: {
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ Several keybindings match - more chords needed ]`);
|
||||
shouldPreventDefault = true;
|
||||
this._expectAnotherChord(userPressedChord, keypressLabel);
|
||||
this._log(this._currentChords.length === 1 ? `+ Entering multi-chord mode...` : `+ Continuing multi-chord mode...`);
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
case 2 /* ResultKind.KbFound */: {
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ Will dispatch command ${resolveResult.commandId} ]`);
|
||||
if (resolveResult.commandId === null || resolveResult.commandId === '') {
|
||||
if (this.inChordMode) {
|
||||
const currentChordsLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._log(`+ Leaving chord mode: Nothing bound to "${currentChordsLabel}, ${keypressLabel}".`);
|
||||
this._notificationService.status(nls.localize(1687, "The key combination ({0}, {1}) is not a command.", currentChordsLabel, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
this._leaveChordMode();
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.inChordMode) {
|
||||
this._leaveChordMode();
|
||||
}
|
||||
if (!resolveResult.isBubble) {
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
this._log(`+ Invoking command ${resolveResult.commandId}.`);
|
||||
this._currentlyDispatchingCommandId = resolveResult.commandId;
|
||||
try {
|
||||
if (typeof resolveResult.commandArgs === 'undefined') {
|
||||
this._commandService.executeCommand(resolveResult.commandId).then(undefined, err => this._notificationService.warn(err));
|
||||
}
|
||||
else {
|
||||
this._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this._currentlyDispatchingCommandId = null;
|
||||
}
|
||||
if (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {
|
||||
this._telemetryService.publicLog2('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding', detail: userKeypress.getUserSettingsLabel() ?? undefined });
|
||||
}
|
||||
}
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
mightProducePrintableCharacter(event) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
// ignore ctrl/cmd-combination but not shift/alt-combinatios
|
||||
return false;
|
||||
}
|
||||
// weak check for certain ranges. this is properly implemented in a subclass
|
||||
// with access to the KeyboardMapperFactory.
|
||||
if ((event.keyCode >= 31 /* KeyCode.KeyA */ && event.keyCode <= 56 /* KeyCode.KeyZ */)
|
||||
|| (event.keyCode >= 21 /* KeyCode.Digit0 */ && event.keyCode <= 30 /* KeyCode.Digit9 */)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
class KeybindingModifierSet {
|
||||
static { this.EMPTY = new KeybindingModifierSet(null); }
|
||||
constructor(source) {
|
||||
this._ctrlKey = source ? source.ctrlKey : false;
|
||||
this._shiftKey = source ? source.shiftKey : false;
|
||||
this._altKey = source ? source.altKey : false;
|
||||
this._metaKey = source ? source.metaKey : false;
|
||||
}
|
||||
has(modifier) {
|
||||
switch (modifier) {
|
||||
case 'ctrl': return this._ctrlKey;
|
||||
case 'shift': return this._shiftKey;
|
||||
case 'alt': return this._altKey;
|
||||
case 'meta': return this._metaKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=abstractKeybindingService.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,54 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { illegalArgument } from '../../../base/common/errors.js';
|
||||
import { AriaLabelProvider, ElectronAcceleratorLabelProvider, UILabelProvider, UserSettingsLabelProvider } from '../../../base/common/keybindingLabels.js';
|
||||
import { ResolvedKeybinding, ResolvedChord } from '../../../base/common/keybindings.js';
|
||||
export class BaseResolvedKeybinding extends ResolvedKeybinding {
|
||||
constructor(os, chords) {
|
||||
super();
|
||||
if (chords.length === 0) {
|
||||
throw illegalArgument(`chords`);
|
||||
}
|
||||
this._os = os;
|
||||
this._chords = chords;
|
||||
}
|
||||
getLabel() {
|
||||
return UILabelProvider.toLabel(this._os, this._chords, (keybinding) => this._getLabel(keybinding));
|
||||
}
|
||||
getAriaLabel() {
|
||||
return AriaLabelProvider.toLabel(this._os, this._chords, (keybinding) => this._getAriaLabel(keybinding));
|
||||
}
|
||||
getElectronAccelerator() {
|
||||
if (this._chords.length > 1) {
|
||||
// [Electron Accelerators] Electron cannot handle chords
|
||||
return null;
|
||||
}
|
||||
if (this._chords[0].isDuplicateModifierCase()) {
|
||||
// [Electron Accelerators] Electron cannot handle modifier only keybindings
|
||||
// e.g. "shift shift"
|
||||
return null;
|
||||
}
|
||||
return ElectronAcceleratorLabelProvider.toLabel(this._os, this._chords, (keybinding) => this._getElectronAccelerator(keybinding));
|
||||
}
|
||||
getUserSettingsLabel() {
|
||||
return UserSettingsLabelProvider.toLabel(this._os, this._chords, (keybinding) => this._getUserSettingsLabel(keybinding));
|
||||
}
|
||||
hasMultipleChords() {
|
||||
return (this._chords.length > 1);
|
||||
}
|
||||
getChords() {
|
||||
return this._chords.map((keybinding) => this._getChord(keybinding));
|
||||
}
|
||||
_getChord(keybinding) {
|
||||
return new ResolvedChord(keybinding.ctrlKey, keybinding.shiftKey, keybinding.altKey, keybinding.metaKey, this._getLabel(keybinding), this._getAriaLabel(keybinding));
|
||||
}
|
||||
getDispatchChords() {
|
||||
return this._chords.map((keybinding) => this._getChordDispatch(keybinding));
|
||||
}
|
||||
getSingleModifierDispatchChords() {
|
||||
return this._chords.map((keybinding) => this._getSingleModifierChordDispatch(keybinding));
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=baseResolvedKeybinding.js.map
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user