UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

475 lines (474 loc) 18.6 kB
/*--------------------------------------------------------------------------------------------- * 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 { SubmenuAction } from '@sussudio/base/common/actions.mjs'; import { CSSIcon } from '@sussudio/base/common/codicons.mjs'; import { MicrotaskEmitter } from '@sussudio/base/common/event.mjs'; import { DisposableStore, toDisposable } from '@sussudio/base/common/lifecycle.mjs'; import { LinkedList } from '@sussudio/base/common/linkedList.mjs'; import { CommandsRegistry, ICommandService } from '../../commands/common/commands.mjs'; import { ContextKeyExpr, IContextKeyService } from '../../contextkey/common/contextkey.mjs'; import { SyncDescriptor } from '../../instantiation/common/descriptors.mjs'; import { createDecorator } from '../../instantiation/common/instantiation.mjs'; import { KeybindingsRegistry } from '../../keybinding/common/keybindingsRegistry.mjs'; import { ThemeIcon } from '../../theme/common/themeService.mjs'; export function isIMenuItem(item) { return item.command !== undefined; } export function isISubmenuItem(item) { return item.submenu !== undefined; } export class MenuId { static _instances = new Map(); static CommandPalette = new MenuId('CommandPalette'); static DebugBreakpointsContext = new MenuId('DebugBreakpointsContext'); static DebugCallStackContext = new MenuId('DebugCallStackContext'); static DebugConsoleContext = new MenuId('DebugConsoleContext'); static DebugVariablesContext = new MenuId('DebugVariablesContext'); static DebugWatchContext = new MenuId('DebugWatchContext'); static DebugToolBar = new MenuId('DebugToolBar'); static DebugToolBarStop = new MenuId('DebugToolBarStop'); static EditorContext = new MenuId('EditorContext'); static SimpleEditorContext = new MenuId('SimpleEditorContext'); static EditorContent = new MenuId('EditorContent'); static EditorContextCopy = new MenuId('EditorContextCopy'); static EditorContextPeek = new MenuId('EditorContextPeek'); static EditorContextShare = new MenuId('EditorContextShare'); static EditorTitle = new MenuId('EditorTitle'); static EditorTitleRun = new MenuId('EditorTitleRun'); static EditorTitleContext = new MenuId('EditorTitleContext'); static EmptyEditorGroup = new MenuId('EmptyEditorGroup'); static EmptyEditorGroupContext = new MenuId('EmptyEditorGroupContext'); static ExplorerContext = new MenuId('ExplorerContext'); static ExtensionContext = new MenuId('ExtensionContext'); static GlobalActivity = new MenuId('GlobalActivity'); static CommandCenter = new MenuId('CommandCenter'); static LayoutControlMenuSubmenu = new MenuId('LayoutControlMenuSubmenu'); static LayoutControlMenu = new MenuId('LayoutControlMenu'); static MenubarMainMenu = new MenuId('MenubarMainMenu'); static MenubarAppearanceMenu = new MenuId('MenubarAppearanceMenu'); static MenubarDebugMenu = new MenuId('MenubarDebugMenu'); static MenubarEditMenu = new MenuId('MenubarEditMenu'); static MenubarCopy = new MenuId('MenubarCopy'); static MenubarFileMenu = new MenuId('MenubarFileMenu'); static MenubarGoMenu = new MenuId('MenubarGoMenu'); static MenubarHelpMenu = new MenuId('MenubarHelpMenu'); static MenubarLayoutMenu = new MenuId('MenubarLayoutMenu'); static MenubarNewBreakpointMenu = new MenuId('MenubarNewBreakpointMenu'); static MenubarPanelAlignmentMenu = new MenuId('MenubarPanelAlignmentMenu'); static MenubarPanelPositionMenu = new MenuId('MenubarPanelPositionMenu'); static MenubarPreferencesMenu = new MenuId('MenubarPreferencesMenu'); static MenubarRecentMenu = new MenuId('MenubarRecentMenu'); static MenubarSelectionMenu = new MenuId('MenubarSelectionMenu'); static MenubarShare = new MenuId('MenubarShare'); static MenubarSwitchEditorMenu = new MenuId('MenubarSwitchEditorMenu'); static MenubarSwitchGroupMenu = new MenuId('MenubarSwitchGroupMenu'); static MenubarTerminalMenu = new MenuId('MenubarTerminalMenu'); static MenubarViewMenu = new MenuId('MenubarViewMenu'); static MenubarHomeMenu = new MenuId('MenubarHomeMenu'); static OpenEditorsContext = new MenuId('OpenEditorsContext'); static ProblemsPanelContext = new MenuId('ProblemsPanelContext'); static SCMChangeContext = new MenuId('SCMChangeContext'); static SCMResourceContext = new MenuId('SCMResourceContext'); static SCMResourceFolderContext = new MenuId('SCMResourceFolderContext'); static SCMResourceGroupContext = new MenuId('SCMResourceGroupContext'); static SCMSourceControl = new MenuId('SCMSourceControl'); static SCMTitle = new MenuId('SCMTitle'); static SearchContext = new MenuId('SearchContext'); static SearchActionMenu = new MenuId('SearchActionContext'); static StatusBarWindowIndicatorMenu = new MenuId('StatusBarWindowIndicatorMenu'); static StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu'); static StickyScrollContext = new MenuId('StickyScrollContext'); static TestItem = new MenuId('TestItem'); static TestItemGutter = new MenuId('TestItemGutter'); static TestPeekElement = new MenuId('TestPeekElement'); static TestPeekTitle = new MenuId('TestPeekTitle'); static TouchBarContext = new MenuId('TouchBarContext'); static TitleBarContext = new MenuId('TitleBarContext'); static TitleBarTitleContext = new MenuId('TitleBarTitleContext'); static TunnelContext = new MenuId('TunnelContext'); static TunnelPrivacy = new MenuId('TunnelPrivacy'); static TunnelProtocol = new MenuId('TunnelProtocol'); static TunnelPortInline = new MenuId('TunnelInline'); static TunnelTitle = new MenuId('TunnelTitle'); static TunnelLocalAddressInline = new MenuId('TunnelLocalAddressInline'); static TunnelOriginInline = new MenuId('TunnelOriginInline'); static ViewItemContext = new MenuId('ViewItemContext'); static ViewContainerTitle = new MenuId('ViewContainerTitle'); static ViewContainerTitleContext = new MenuId('ViewContainerTitleContext'); static ViewTitle = new MenuId('ViewTitle'); static ViewTitleContext = new MenuId('ViewTitleContext'); static CommentEditorActions = new MenuId('CommentEditorActions'); static CommentThreadTitle = new MenuId('CommentThreadTitle'); static CommentThreadActions = new MenuId('CommentThreadActions'); static CommentThreadAdditionalActions = new MenuId('CommentThreadAdditionalActions'); static CommentThreadTitleContext = new MenuId('CommentThreadTitleContext'); static CommentThreadCommentContext = new MenuId('CommentThreadCommentContext'); static CommentTitle = new MenuId('CommentTitle'); static CommentActions = new MenuId('CommentActions'); static InteractiveToolbar = new MenuId('InteractiveToolbar'); static InteractiveCellTitle = new MenuId('InteractiveCellTitle'); static InteractiveCellDelete = new MenuId('InteractiveCellDelete'); static InteractiveCellExecute = new MenuId('InteractiveCellExecute'); static InteractiveInputExecute = new MenuId('InteractiveInputExecute'); static NotebookToolbar = new MenuId('NotebookToolbar'); static NotebookCellTitle = new MenuId('NotebookCellTitle'); static NotebookCellDelete = new MenuId('NotebookCellDelete'); static NotebookCellInsert = new MenuId('NotebookCellInsert'); static NotebookCellBetween = new MenuId('NotebookCellBetween'); static NotebookCellListTop = new MenuId('NotebookCellTop'); static NotebookCellExecute = new MenuId('NotebookCellExecute'); static NotebookCellExecutePrimary = new MenuId('NotebookCellExecutePrimary'); static NotebookDiffCellInputTitle = new MenuId('NotebookDiffCellInputTitle'); static NotebookDiffCellMetadataTitle = new MenuId('NotebookDiffCellMetadataTitle'); static NotebookDiffCellOutputsTitle = new MenuId('NotebookDiffCellOutputsTitle'); static NotebookOutputToolbar = new MenuId('NotebookOutputToolbar'); static NotebookEditorLayoutConfigure = new MenuId('NotebookEditorLayoutConfigure'); static NotebookKernelSource = new MenuId('NotebookKernelSource'); static BulkEditTitle = new MenuId('BulkEditTitle'); static BulkEditContext = new MenuId('BulkEditContext'); static TimelineItemContext = new MenuId('TimelineItemContext'); static TimelineTitle = new MenuId('TimelineTitle'); static TimelineTitleContext = new MenuId('TimelineTitleContext'); static TimelineFilterSubMenu = new MenuId('TimelineFilterSubMenu'); static AccountsContext = new MenuId('AccountsContext'); static PanelTitle = new MenuId('PanelTitle'); static AuxiliaryBarTitle = new MenuId('AuxiliaryBarTitle'); static TerminalInstanceContext = new MenuId('TerminalInstanceContext'); static TerminalEditorInstanceContext = new MenuId('TerminalEditorInstanceContext'); static TerminalNewDropdownContext = new MenuId('TerminalNewDropdownContext'); static TerminalTabContext = new MenuId('TerminalTabContext'); static TerminalTabEmptyAreaContext = new MenuId('TerminalTabEmptyAreaContext'); static TerminalInlineTabContext = new MenuId('TerminalInlineTabContext'); static WebviewContext = new MenuId('WebviewContext'); static InlineCompletionsActions = new MenuId('InlineCompletionsActions'); static NewFile = new MenuId('NewFile'); static MergeInput1Toolbar = new MenuId('MergeToolbar1Toolbar'); static MergeInput2Toolbar = new MenuId('MergeToolbar2Toolbar'); static MergeBaseToolbar = new MenuId('MergeBaseToolbar'); static MergeInputResultToolbar = new MenuId('MergeToolbarResultToolbar'); /** * Create or reuse a `MenuId` with the given identifier */ static for(identifier) { return MenuId._instances.get(identifier) ?? new MenuId(identifier); } id; /** * 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 { id; static _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; } has; constructor(id) { this.id = id; this.has = (candidate) => candidate === id; } } export const MenuRegistry = new (class { _commands = new Map(); _menuItems = new Map(); _onDidChangeMenu = new MicrotaskEmitter({ merge: MenuRegistryChangeEvent.merge, }); onDidChangeMenu = this._onDidChangeMenu.event; addCommand(command) { this._commands.set(command.id, command); this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(MenuId.CommandPalette)); return 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 toDisposable(rm); } 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 { item; hideActions; 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 = class MenuItemAction { hideActions; _commandService; 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; } item; alt; _options; id; label; tooltip; class; enabled; checked; constructor(item, alt, options, hideActions, contextKeyService, _commandService) { this.hideActions = hideActions; this._commandService = _commandService; this.id = item.id; this.label = MenuItemAction.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; 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 (toggled.title) { this.label = typeof toggled.title === 'string' ? toggled.title : toggled.title.value; } } this.item = item; this.alt = alt ? new MenuItemAction(alt, undefined, options, hideActions, contextKeyService, _commandService) : undefined; this._options = options; if (ThemeIcon.isThemeIcon(item.icon)) { this.class = CSSIcon.asClassName(item.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 = __decorate([__param(4, IContextKeyService), __param(5, ICommandService)], MenuItemAction); export { MenuItemAction }; /** * @deprecated Use {@link registerAction2} instead. */ export class SyncActionDescriptor { _descriptor; _id; _label; _keybindings; _keybindingContext; _keybindingWeight; static create(ctor, id, label, keybindings, keybindingContext, keybindingWeight) { return new SyncActionDescriptor(ctor, id, label, keybindings, keybindingContext, keybindingWeight); } static from(ctor, keybindings, keybindingContext, keybindingWeight) { return SyncActionDescriptor.create(ctor, ctor.ID, ctor.LABEL, keybindings, keybindingContext, keybindingWeight); } constructor(ctor, id, label, keybindings, keybindingContext, keybindingWeight) { this._id = id; this._label = label; this._keybindings = keybindings; this._keybindingContext = keybindingContext; this._keybindingWeight = keybindingWeight; this._descriptor = new SyncDescriptor(ctor, [this._id, this._label]); } get syncDescriptor() { return this._descriptor; } get id() { return this._id; } get label() { return this._label; } get keybindings() { return this._keybindings; } get keybindingContext() { return this._keybindingContext; } get keybindingWeight() { return this._keybindingWeight; } } export class Action2 { desc; constructor(desc) { this.desc = desc; } } export function registerAction2(ctor) { const disposables = new DisposableStore(); const action = new ctor(); const { f1, menu, keybinding, description, ...command } = action.desc; // command disposables.add( CommandsRegistry.registerCommand({ id: command.id, handler: (accessor, ...args) => action.run(accessor, ...args), description: description, }), ); // menu if (Array.isArray(menu)) { for (const item of menu) { disposables.add( MenuRegistry.appendMenuItem(item.id, { command: { ...command, precondition: item.precondition === null ? undefined : command.precondition }, ...item, }), ); } } else if (menu) { disposables.add( MenuRegistry.appendMenuItem(menu.id, { command: { ...command, precondition: menu.precondition === null ? undefined : command.precondition }, ...menu, }), ); } if (f1) { disposables.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command, when: command.precondition })); disposables.add(MenuRegistry.addCommand(command)); } // keybinding if (Array.isArray(keybinding)) { for (const item of keybinding) { disposables.add( KeybindingsRegistry.registerKeybindingRule({ ...item, id: command.id, when: command.precondition ? ContextKeyExpr.and(command.precondition, item.when) : item.when, }), ); } } else if (keybinding) { disposables.add( KeybindingsRegistry.registerKeybindingRule({ ...keybinding, id: command.id, when: command.precondition ? ContextKeyExpr.and(command.precondition, keybinding.when) : keybinding.when, }), ); } return disposables; } //#endregion