@theia/core 1.77.0-next.49 → 1.77.0-next.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/breadcrumbs/breadcrumbs-renderer.js +1 -1
- package/lib/browser/breadcrumbs/breadcrumbs-renderer.js.map +1 -1
- package/lib/browser/catalog.json +81 -0
- package/lib/browser/color-application-contribution.d.ts +1 -1
- package/lib/browser/color-application-contribution.d.ts.map +1 -1
- package/lib/browser/color-registry.d.ts +1 -1
- package/lib/browser/color-registry.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.d.ts +6 -1
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +20 -3
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/common-frontend-contribution.spec.js +2 -1
- package/lib/browser/common-frontend-contribution.spec.js.map +1 -1
- package/lib/browser/components/card.d.ts +1 -1
- package/lib/browser/components/card.d.ts.map +1 -1
- package/lib/browser/components/card.js +3 -2
- package/lib/browser/components/card.js.map +1 -1
- package/lib/browser/connection-status-service.spec.js +2 -1
- package/lib/browser/connection-status-service.spec.js.map +1 -1
- package/lib/browser/context-key-service.d.ts +11 -0
- package/lib/browser/context-key-service.d.ts.map +1 -1
- package/lib/browser/context-key-service.js +7 -0
- package/lib/browser/context-key-service.js.map +1 -1
- package/lib/browser/decorations-service.spec.js +2 -1
- package/lib/browser/decorations-service.spec.js.map +1 -1
- package/lib/browser/dialogs/react-dialog.spec.js +2 -1
- package/lib/browser/dialogs/react-dialog.spec.js.map +1 -1
- package/lib/browser/diff-uris.js +1 -1
- package/lib/browser/diff-uris.js.map +1 -1
- package/lib/browser/endpoint.js +2 -1
- package/lib/browser/endpoint.js.map +1 -1
- package/lib/browser/endpoint.spec.js +2 -1
- package/lib/browser/endpoint.spec.js.map +1 -1
- package/lib/browser/keybinding.d.ts +95 -17
- package/lib/browser/keybinding.d.ts.map +1 -1
- package/lib/browser/keybinding.js +406 -76
- package/lib/browser/keybinding.js.map +1 -1
- package/lib/browser/keybinding.spec.js +789 -33
- package/lib/browser/keybinding.spec.js.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js +1 -1
- package/lib/browser/keyboard/browser-keyboard-frontend-contribution.js.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-layout-provider.d.ts +3 -4
- package/lib/browser/keyboard/browser-keyboard-layout-provider.d.ts.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-layout-provider.js +3 -3
- package/lib/browser/keyboard/browser-keyboard-layout-provider.js.map +1 -1
- package/lib/browser/keyboard/browser-keyboard-layout-provider.spec.js +42 -3
- package/lib/browser/keyboard/browser-keyboard-layout-provider.spec.js.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.d.ts +67 -15
- package/lib/browser/keyboard/keyboard-layout-service.d.ts.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.js +309 -98
- package/lib/browser/keyboard/keyboard-layout-service.js.map +1 -1
- package/lib/browser/keyboard/keyboard-layout-service.spec.js +541 -15
- package/lib/browser/keyboard/keyboard-layout-service.spec.js.map +1 -1
- package/lib/browser/keyboard/keys.spec.js +187 -3
- package/lib/browser/keyboard/keys.spec.js.map +1 -1
- package/lib/browser/label-provider.d.ts.map +1 -1
- package/lib/browser/label-provider.js +5 -3
- package/lib/browser/label-provider.js.map +1 -1
- package/lib/browser/label-provider.spec.js +2 -1
- package/lib/browser/label-provider.spec.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown-link-handler.js +2 -1
- package/lib/browser/markdown-rendering/markdown-link-handler.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.d.ts +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.d.ts.map +1 -1
- package/lib/browser/markdown-rendering/markdown-renderer.js +4 -4
- package/lib/browser/markdown-rendering/markdown-renderer.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown.js +2 -1
- package/lib/browser/markdown-rendering/markdown.js.map +1 -1
- package/lib/browser/markdown-rendering/markdown.spec.js +2 -1
- package/lib/browser/markdown-rendering/markdown.spec.js.map +1 -1
- package/lib/browser/menu/action-menu-node.d.ts +5 -3
- package/lib/browser/menu/action-menu-node.d.ts.map +1 -1
- package/lib/browser/menu/action-menu-node.js +2 -11
- package/lib/browser/menu/action-menu-node.js.map +1 -1
- package/lib/browser/menu/action-menu-node.spec.d.ts +2 -0
- package/lib/browser/menu/action-menu-node.spec.d.ts.map +1 -0
- package/lib/browser/menu/action-menu-node.spec.js +54 -0
- package/lib/browser/menu/action-menu-node.spec.js.map +1 -0
- package/lib/browser/menu/browser-menu-plugin.js +1 -1
- package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
- package/lib/browser/menu/menu.spec.js +2 -1
- package/lib/browser/menu/menu.spec.js.map +1 -1
- package/lib/browser/opener-service.spec.js +3 -2
- package/lib/browser/opener-service.spec.js.map +1 -1
- package/lib/browser/perspective-service.spec.js +2 -1
- package/lib/browser/perspective-service.spec.js.map +1 -1
- package/lib/browser/preferences/preference-proxy.spec.js +2 -1
- package/lib/browser/preferences/preference-proxy.spec.js.map +1 -1
- package/lib/browser/preferences/preference-schema-provider.spec.js +2 -1
- package/lib/browser/preferences/preference-schema-provider.spec.js.map +1 -1
- package/lib/browser/preferences/preference-service.spec.js +2 -1
- package/lib/browser/preferences/preference-service.spec.js.map +1 -1
- package/lib/browser/preferences/preference-validation-service.spec.js +78 -77
- package/lib/browser/preferences/preference-validation-service.spec.js.map +1 -1
- package/lib/browser/quick-input/quick-command-service.d.ts +10 -1
- package/lib/browser/quick-input/quick-command-service.d.ts.map +1 -1
- package/lib/browser/quick-input/quick-command-service.js +31 -6
- package/lib/browser/quick-input/quick-command-service.js.map +1 -1
- package/lib/browser/quick-input/quick-command-service.spec.d.ts +2 -0
- package/lib/browser/quick-input/quick-command-service.spec.d.ts.map +1 -0
- package/lib/browser/quick-input/quick-command-service.spec.js +130 -0
- package/lib/browser/quick-input/quick-command-service.spec.js.map +1 -0
- package/lib/browser/quick-input/quick-help-service.js +1 -1
- package/lib/browser/quick-input/quick-help-service.js.map +1 -1
- package/lib/browser/quick-input/quick-input-service.spec.js +2 -1
- package/lib/browser/quick-input/quick-input-service.spec.js.map +1 -1
- package/lib/browser/quick-input/quick-pick-service-impl.d.ts +6 -6
- package/lib/browser/quick-input/quick-pick-service-impl.d.ts.map +1 -1
- package/lib/browser/quick-input/quick-view-service.spec.js +2 -1
- package/lib/browser/quick-input/quick-view-service.spec.js.map +1 -1
- package/lib/browser/secondary-window-handler.d.ts +4 -4
- package/lib/browser/secondary-window-handler.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +1 -1
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/application-shell.spec.js +2 -1
- package/lib/browser/shell/application-shell.spec.js.map +1 -1
- package/lib/browser/shell/shell-layout-restorer.spec.js +2 -1
- package/lib/browser/shell/shell-layout-restorer.spec.js.map +1 -1
- package/lib/browser/shell/side-panel-toolbar.d.ts +1 -1
- package/lib/browser/shell/side-panel-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/sidebar-menu-widget.js +1 -1
- package/lib/browser/shell/sidebar-menu-widget.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +2 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
- package/lib/browser/shell/tab-bars.js +2 -1
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/status-bar/status-bar.js +1 -1
- package/lib/browser/status-bar/status-bar.js.map +1 -1
- package/lib/browser/storage-service.spec.js +2 -1
- package/lib/browser/storage-service.spec.js.map +1 -1
- package/lib/browser/test/jsdom.d.ts.map +1 -1
- package/lib/browser/test/jsdom.js +11 -0
- package/lib/browser/test/jsdom.js.map +1 -1
- package/lib/browser/tooltip-service.js +1 -1
- package/lib/browser/tooltip-service.js.map +1 -1
- package/lib/browser/tree/tree-consistency.spec.js +1 -1
- package/lib/browser/tree/tree-consistency.spec.js.map +1 -1
- package/lib/browser/tree/tree-container.spec.js +6 -5
- package/lib/browser/tree/tree-container.spec.js.map +1 -1
- package/lib/browser/tree/tree-iterator.js +1 -1
- package/lib/browser/tree/tree-iterator.js.map +1 -1
- package/lib/browser/tree/tree-model.js +2 -2
- package/lib/browser/tree/tree-model.js.map +1 -1
- package/lib/browser/tree/tree-view-welcome-widget.js +1 -1
- package/lib/browser/tree/tree-view-welcome-widget.js.map +1 -1
- package/lib/browser/tree/tree-widget.d.ts +2 -2
- package/lib/browser/tree/tree-widget.d.ts.map +1 -1
- package/lib/browser/tree/tree-widget.js +1 -1
- package/lib/browser/tree/tree-widget.js.map +1 -1
- package/lib/browser/tree/tree.spec.js +2 -1
- package/lib/browser/tree/tree.spec.js.map +1 -1
- package/lib/browser/user-working-directory-provider.js +1 -1
- package/lib/browser/user-working-directory-provider.js.map +1 -1
- package/lib/browser/widgets/react-renderer.js +1 -1
- package/lib/browser/widgets/react-renderer.js.map +1 -1
- package/lib/browser/widgets/react-widget.js +1 -1
- package/lib/browser/widgets/react-widget.js.map +1 -1
- package/lib/browser/widgets/select-component.js +4 -3
- package/lib/browser/widgets/select-component.js.map +1 -1
- package/lib/browser/widgets/select-component.spec.js +3 -2
- package/lib/browser/widgets/select-component.spec.js.map +1 -1
- package/lib/browser/widgets/widget.js +1 -1
- package/lib/browser/widgets/widget.js.map +1 -1
- package/lib/common/buffer.js +3 -2
- package/lib/common/buffer.js.map +1 -1
- package/lib/common/cancellation.js.map +1 -1
- package/lib/common/command.spec.js +2 -1
- package/lib/common/command.spec.js.map +1 -1
- package/lib/common/disposable.spec.js +3 -2
- package/lib/common/disposable.spec.js.map +1 -1
- package/lib/common/encoding-service.js +2 -2
- package/lib/common/encoding-service.js.map +1 -1
- package/lib/common/event.d.ts +1 -1
- package/lib/common/event.d.ts.map +1 -1
- package/lib/common/event.js +0 -1
- package/lib/common/event.js.map +1 -1
- package/lib/common/file-uri.js +2 -1
- package/lib/common/file-uri.js.map +1 -1
- package/lib/common/fuzzy-search.js +1 -1
- package/lib/common/fuzzy-search.js.map +1 -1
- package/lib/common/glob.d.ts.map +1 -1
- package/lib/common/glob.js +9 -15
- package/lib/common/glob.js.map +1 -1
- package/lib/common/index.js +1 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/keyboard/keyboard-layout-provider.d.ts +7 -0
- package/lib/common/keyboard/keyboard-layout-provider.d.ts.map +1 -1
- package/lib/common/keyboard/keyboard-layout-provider.js.map +1 -1
- package/lib/common/keys.d.ts +86 -3
- package/lib/common/keys.d.ts.map +1 -1
- package/lib/common/keys.js +263 -24
- package/lib/common/keys.js.map +1 -1
- package/lib/common/message-rpc/channel.spec.js +3 -2
- package/lib/common/message-rpc/channel.spec.js.map +1 -1
- package/lib/common/messaging/proxy-factory.js +2 -2
- package/lib/common/messaging/proxy-factory.js.map +1 -1
- package/lib/common/messaging/proxy-factory.spec.js +2 -1
- package/lib/common/messaging/proxy-factory.spec.js.map +1 -1
- package/lib/common/messaging/web-socket-channel.d.ts +1 -1
- package/lib/common/messaging/web-socket-channel.d.ts.map +1 -1
- package/lib/common/path.spec.js +2 -1
- package/lib/common/path.spec.js.map +1 -1
- package/lib/common/performance/stopwatch.spec.js +2 -1
- package/lib/common/performance/stopwatch.spec.js.map +1 -1
- package/lib/common/preferences/preference-schema-service.d.ts +2 -2
- package/lib/common/preferences/preference-schema-service.d.ts.map +1 -1
- package/lib/common/preferences/preference-service.js +1 -1
- package/lib/common/preferences/preference-service.js.map +1 -1
- package/lib/common/promise-util.spec.js +2 -1
- package/lib/common/promise-util.spec.js.map +1 -1
- package/lib/common/quick-pick-service.d.ts +5 -0
- package/lib/common/quick-pick-service.d.ts.map +1 -1
- package/lib/common/quick-pick-service.js +2 -1
- package/lib/common/quick-pick-service.js.map +1 -1
- package/lib/common/reference.spec.js +2 -1
- package/lib/common/reference.spec.js.map +1 -1
- package/lib/common/resource.js +1 -1
- package/lib/common/resource.js.map +1 -1
- package/lib/common/selection-service.spec.js +2 -1
- package/lib/common/selection-service.spec.js.map +1 -1
- package/lib/common/selection.js +2 -1
- package/lib/common/selection.js.map +1 -1
- package/lib/common/stream.d.ts.map +1 -1
- package/lib/common/stream.js +2 -1
- package/lib/common/stream.js.map +1 -1
- package/lib/common/strings.d.ts.map +1 -1
- package/lib/common/strings.js +1 -2
- package/lib/common/strings.js.map +1 -1
- package/lib/common/ternary-search-tree.js +2 -2
- package/lib/common/ternary-search-tree.js.map +1 -1
- package/lib/common/ternary-search-tree.spec.js +12 -0
- package/lib/common/ternary-search-tree.spec.js.map +1 -1
- package/lib/common/test/mock-resource-provider.js +1 -1
- package/lib/common/test/mock-resource-provider.js.map +1 -1
- package/lib/common/types.spec.js +2 -1
- package/lib/common/types.spec.js.map +1 -1
- package/lib/common/uri-command-handler.js +4 -3
- package/lib/common/uri-command-handler.js.map +1 -1
- package/lib/common/uri-command-handler.spec.js +3 -2
- package/lib/common/uri-command-handler.spec.js.map +1 -1
- package/lib/common/uri.spec.js +3 -2
- package/lib/common/uri.spec.js.map +1 -1
- package/lib/electron-browser/keyboard/electron-keyboard-module.d.ts +2 -0
- package/lib/electron-browser/keyboard/electron-keyboard-module.d.ts.map +1 -1
- package/lib/electron-browser/keyboard/electron-keyboard-module.js +8 -1
- package/lib/electron-browser/keyboard/electron-keyboard-module.js.map +1 -1
- package/lib/electron-browser/keyboard/electron-keyboard-module.spec.d.ts +2 -0
- package/lib/electron-browser/keyboard/electron-keyboard-module.spec.d.ts.map +1 -0
- package/lib/electron-browser/keyboard/electron-keyboard-module.spec.js +28 -0
- package/lib/electron-browser/keyboard/electron-keyboard-module.spec.js.map +1 -0
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +3 -2
- package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.js +3 -0
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/window/window-zoom-action-bar.js +2 -1
- package/lib/electron-browser/window/window-zoom-action-bar.js.map +1 -1
- package/lib/electron-common/electron-api.d.ts +5 -0
- package/lib/electron-common/electron-api.d.ts.map +1 -1
- package/lib/electron-common/electron-api.js +21 -0
- package/lib/electron-common/electron-api.js.map +1 -1
- package/lib/electron-common/electron-api.spec.d.ts +2 -0
- package/lib/electron-common/electron-api.spec.d.ts.map +1 -0
- package/lib/electron-common/electron-api.spec.js +40 -0
- package/lib/electron-common/electron-api.spec.js.map +1 -0
- package/lib/electron-main/electron-api-main.d.ts +0 -1
- package/lib/electron-main/electron-api-main.d.ts.map +1 -1
- package/lib/electron-main/electron-api-main.js +3 -14
- package/lib/electron-main/electron-api-main.js.map +1 -1
- package/lib/electron-main/electron-main-application.js +2 -2
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/lib/electron-node/hosting/electron-backend-hosting-module.spec.js +2 -1
- package/lib/electron-node/hosting/electron-backend-hosting-module.spec.js.map +1 -1
- package/lib/electron-node/keyboard/electron-keyboard-layout-provider.js +1 -1
- package/lib/electron-node/keyboard/electron-keyboard-layout-provider.js.map +1 -1
- package/lib/electron-node/token/electron-token-validator.js +2 -2
- package/lib/electron-node/token/electron-token-validator.js.map +1 -1
- package/lib/node/backend-application.d.ts +1 -1
- package/lib/node/backend-application.d.ts.map +1 -1
- package/lib/node/backend-application.js +7 -7
- package/lib/node/backend-application.js.map +1 -1
- package/lib/node/backend-application.spec.js +1 -1
- package/lib/node/backend-application.spec.js.map +1 -1
- package/lib/node/bundled-resource-provider.js +4 -4
- package/lib/node/bundled-resource-provider.js.map +1 -1
- package/lib/node/bundled-resource-provider.spec.js +5 -4
- package/lib/node/bundled-resource-provider.spec.js.map +1 -1
- package/lib/node/cli.d.ts +1 -1
- package/lib/node/cli.d.ts.map +1 -1
- package/lib/node/cli.js +2 -2
- package/lib/node/cli.js.map +1 -1
- package/lib/node/cli.spec.js +3 -2
- package/lib/node/cli.spec.js.map +1 -1
- package/lib/node/console-logger-server.js +1 -1
- package/lib/node/console-logger-server.js.map +1 -1
- package/lib/node/env-variables/env-variables-server.js +1 -1
- package/lib/node/env-variables/env-variables-server.js.map +1 -1
- package/lib/node/environment-utils.spec.js +2 -1
- package/lib/node/environment-utils.spec.js.map +1 -1
- package/lib/node/file-uri.spec.js +4 -3
- package/lib/node/file-uri.spec.js.map +1 -1
- package/lib/node/filesystem-locking.js +1 -1
- package/lib/node/filesystem-locking.js.map +1 -1
- package/lib/node/hosting/browser-connection-token.js +2 -2
- package/lib/node/hosting/browser-connection-token.js.map +1 -1
- package/lib/node/i18n/localization-contribution.js +1 -1
- package/lib/node/i18n/localization-contribution.js.map +1 -1
- package/lib/node/key-store-server.js +1 -1
- package/lib/node/key-store-server.js.map +1 -1
- package/lib/node/logger-cli-contribution.js +2 -2
- package/lib/node/logger-cli-contribution.js.map +1 -1
- package/lib/node/logger-cli-contribution.spec.js +17 -16
- package/lib/node/logger-cli-contribution.spec.js.map +1 -1
- package/lib/node/messaging/ipc-connection-provider.js +2 -2
- package/lib/node/messaging/ipc-connection-provider.js.map +1 -1
- package/lib/node/process-utils.js +1 -1
- package/lib/node/process-utils.js.map +1 -1
- package/lib/node/process-utils.spec.js +2 -1
- package/lib/node/process-utils.spec.js.map +1 -1
- package/lib/node/request/backend-request-facade.spec.js +2 -1
- package/lib/node/request/backend-request-facade.spec.js.map +1 -1
- package/lib/node/setting-service.spec.js +2 -1
- package/lib/node/setting-service.spec.js.map +1 -1
- package/package.json +4 -4
- package/src/browser/common-frontend-contribution.ts +17 -1
- package/src/browser/components/card.tsx +1 -1
- package/src/browser/context-key-service.ts +15 -0
- package/src/browser/keybinding.spec.ts +878 -34
- package/src/browser/keybinding.ts +470 -85
- package/src/browser/keyboard/browser-keyboard-frontend-contribution.ts +1 -1
- package/src/browser/keyboard/browser-keyboard-layout-provider.spec.ts +52 -1
- package/src/browser/keyboard/browser-keyboard-layout-provider.ts +5 -5
- package/src/browser/keyboard/keyboard-layout-service.spec.ts +640 -15
- package/src/browser/keyboard/keyboard-layout-service.ts +358 -106
- package/src/browser/keyboard/keys.spec.ts +206 -1
- package/src/browser/label-provider.ts +3 -1
- package/src/browser/markdown-rendering/markdown-renderer.ts +1 -1
- package/src/browser/menu/action-menu-node.spec.ts +60 -0
- package/src/browser/menu/action-menu-node.ts +8 -14
- package/src/browser/menu/browser-menu-plugin.ts +1 -1
- package/src/browser/preferences/preference-validation-service.spec.ts +1 -1
- package/src/browser/quick-input/quick-command-service.spec.ts +159 -0
- package/src/browser/quick-input/quick-command-service.ts +36 -9
- package/src/browser/quick-input/quick-help-service.ts +1 -1
- package/src/browser/test/jsdom.ts +11 -0
- package/src/browser/tree/tree-container.spec.ts +1 -1
- package/src/browser/tree/tree-iterator.ts +1 -1
- package/src/browser/tree/tree-model.ts +2 -2
- package/src/browser/tree/tree-widget.tsx +2 -2
- package/src/common/cancellation.ts +1 -1
- package/src/common/disposable.spec.ts +1 -1
- package/src/common/event.ts +1 -2
- package/src/common/glob.ts +13 -30
- package/src/common/json-schema.ts +1 -1
- package/src/common/keyboard/keyboard-layout-provider.ts +8 -0
- package/src/common/keys.ts +312 -27
- package/src/common/message-rpc/channel.spec.ts +1 -1
- package/src/common/messaging/proxy-factory.ts +2 -2
- package/src/common/quick-pick-service.ts +5 -0
- package/src/common/stream.ts +4 -3
- package/src/common/strings.ts +2 -5
- package/src/common/ternary-search-tree.spec.ts +14 -0
- package/src/common/ternary-search-tree.ts +3 -3
- package/src/common/uri-command-handler.ts +2 -2
- package/src/electron-browser/keyboard/electron-keyboard-module.spec.ts +29 -0
- package/src/electron-browser/keyboard/electron-keyboard-module.ts +9 -2
- package/src/electron-browser/menu/electron-main-menu-factory.ts +3 -3
- package/src/electron-browser/menu/electron-menu-contribution.ts +4 -0
- package/src/electron-common/electron-api.spec.ts +42 -0
- package/src/electron-common/electron-api.ts +23 -0
- package/src/electron-main/electron-api-main.ts +2 -13
- package/src/node/backend-application.ts +1 -1
- package/src/node/cli.ts +1 -1
- package/src/node/logger-cli-contribution.spec.ts +1 -1
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { enableJSDOM } from '../../browser/test/jsdom';
|
|
18
18
|
let disableJSDOM = enableJSDOM();
|
|
19
19
|
|
|
20
|
-
import { KeyCode, Key, KeyModifier, KeySequence } from './keys';
|
|
20
|
+
import { KeyCode, Key, KeyModifier, KeySequence, NormalizedKeyboardInput, normalizeKeyboardInput, readAltGraph } from './keys';
|
|
21
21
|
import * as os from '../../common/os';
|
|
22
22
|
import * as chai from 'chai';
|
|
23
23
|
import * as sinon from 'sinon';
|
|
@@ -117,6 +117,139 @@ describe('keys api', () => {
|
|
|
117
117
|
expect(equalKeyCode(parsedKeyCode, keyCode)).to.be.true;
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
+
it('should keep dispatch strings equivalent to serialized strings', () => {
|
|
121
|
+
const keyCodes = [
|
|
122
|
+
...Array.from({ length: 16 }, (_, modifiers) => new KeyCode({
|
|
123
|
+
key: Key.KEY_A,
|
|
124
|
+
ctrl: !!(modifiers & 1),
|
|
125
|
+
shift: !!(modifiers & 2),
|
|
126
|
+
alt: !!(modifiers & 4),
|
|
127
|
+
meta: !!(modifiers & 8)
|
|
128
|
+
})),
|
|
129
|
+
new KeyCode({}),
|
|
130
|
+
KeyCode.parse('ctrl+['),
|
|
131
|
+
KeyCode.parse('shift+/'),
|
|
132
|
+
...KeySequence.parse('ctrlcmd+k ctrlcmd+c')
|
|
133
|
+
];
|
|
134
|
+
for (const keyCode of keyCodes) {
|
|
135
|
+
expect(keyCode.dispatchString()).to.equal(keyCode.toString());
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should distinguish layout modifiers in dispatch identity without changing serialization', () => {
|
|
140
|
+
const command = new KeyCode({ key: Key.DIGIT8, ctrl: true, alt: true });
|
|
141
|
+
const layout = new KeyCode({ key: Key.DIGIT8, ctrl: true, layoutModifiers: 'altGraph', character: '[' });
|
|
142
|
+
const shiftedLayout = new KeyCode({ key: Key.SLASH, layoutModifiers: 'shift', character: '/' });
|
|
143
|
+
|
|
144
|
+
expect(command.toString()).to.equal('alt+ctrl+8');
|
|
145
|
+
expect(layout.toString()).to.equal('ctrl+8');
|
|
146
|
+
expect(layout.dispatchString()).to.equal('ctrl+8@altgraph');
|
|
147
|
+
expect(shiftedLayout.toString()).to.equal('/');
|
|
148
|
+
expect(shiftedLayout.dispatchString()).to.equal('/@shift');
|
|
149
|
+
expect(command.equals(layout)).to.be.false;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should keep equality and dispatch identity equivalent for layout modifiers', () => {
|
|
153
|
+
const layers = ['none', 'shift', 'altGraph', 'shiftAltGraph'] as const;
|
|
154
|
+
const keyCodes = Array.from({ length: 64 }, (_, modifiers) => new KeyCode({
|
|
155
|
+
key: Key.KEY_A,
|
|
156
|
+
ctrl: !!(modifiers & 1),
|
|
157
|
+
shift: !!(modifiers & 2),
|
|
158
|
+
alt: !!(modifiers & 4),
|
|
159
|
+
meta: !!(modifiers & 8),
|
|
160
|
+
layoutModifiers: layers[modifiers >> 4]
|
|
161
|
+
}));
|
|
162
|
+
for (const left of keyCodes) {
|
|
163
|
+
for (const right of keyCodes) {
|
|
164
|
+
expect(left.equals(right)).to.equal(left.dispatchString() === right.dispatchString());
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should keep interpretation provenance outside dispatch identity', () => {
|
|
170
|
+
const command = new KeyCode({ key: Key.DIGIT8, ctrl: true, interpretation: 'commandModifiers' });
|
|
171
|
+
const layout = new KeyCode({ key: Key.DIGIT8, ctrl: true, interpretation: 'layoutModifiers' });
|
|
172
|
+
|
|
173
|
+
expect(command.dispatchString()).to.equal(layout.dispatchString());
|
|
174
|
+
expect(command.equals(layout)).to.be.true;
|
|
175
|
+
expect(command.interpretation).to.equal('commandModifiers');
|
|
176
|
+
expect(layout.interpretation).to.equal('layoutModifiers');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should normalize explicit and native AltGraph state', () => {
|
|
180
|
+
expect(readAltGraph({ altGraph: false, getModifierState: () => true })).to.be.false;
|
|
181
|
+
expect(readAltGraph({ getModifierState: modifier => modifier === 'AltGraph' })).to.be.true;
|
|
182
|
+
expect(readAltGraph({ code: 'Digit8' })).to.be.false;
|
|
183
|
+
|
|
184
|
+
expect(normalizeKeyboardInput({
|
|
185
|
+
key: '[',
|
|
186
|
+
code: 'Digit8',
|
|
187
|
+
keyCode: 56,
|
|
188
|
+
ctrlKey: true,
|
|
189
|
+
altGraph: true,
|
|
190
|
+
location: 0
|
|
191
|
+
})).to.deep.equal({
|
|
192
|
+
key: '[',
|
|
193
|
+
code: 'Digit8',
|
|
194
|
+
keyCode: 56,
|
|
195
|
+
charCode: undefined,
|
|
196
|
+
ctrlKey: true,
|
|
197
|
+
shiftKey: undefined,
|
|
198
|
+
altKey: undefined,
|
|
199
|
+
metaKey: undefined,
|
|
200
|
+
altGraph: true,
|
|
201
|
+
repeat: undefined,
|
|
202
|
+
isComposing: undefined,
|
|
203
|
+
location: 0,
|
|
204
|
+
timeStamp: undefined,
|
|
205
|
+
keyIdentifier: undefined,
|
|
206
|
+
getModifierState: undefined
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should preserve every normalized keyboard input field', () => {
|
|
211
|
+
const getModifierState = (modifier: string) => modifier === 'AltGraph';
|
|
212
|
+
const input: Required<NormalizedKeyboardInput> = {
|
|
213
|
+
key: '[',
|
|
214
|
+
code: 'Digit8',
|
|
215
|
+
keyCode: 56,
|
|
216
|
+
charCode: 91,
|
|
217
|
+
ctrlKey: true,
|
|
218
|
+
shiftKey: true,
|
|
219
|
+
altKey: false,
|
|
220
|
+
metaKey: true,
|
|
221
|
+
altGraph: true,
|
|
222
|
+
repeat: true,
|
|
223
|
+
isComposing: false,
|
|
224
|
+
location: 2,
|
|
225
|
+
timeStamp: 42,
|
|
226
|
+
keyIdentifier: 'U+005B',
|
|
227
|
+
getModifierState
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const normalized = normalizeKeyboardInput(input);
|
|
231
|
+
|
|
232
|
+
expect({ ...normalized, getModifierState: undefined }).to.deep.equal({ ...input, getModifierState: undefined });
|
|
233
|
+
expect(normalized.getModifierState?.('AltGraph')).to.be.true;
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should create key codes from normalized plain data', () => {
|
|
237
|
+
const keyCode = KeyCode.createKeyCode({
|
|
238
|
+
key: '[',
|
|
239
|
+
code: 'Digit8',
|
|
240
|
+
keyCode: 56,
|
|
241
|
+
ctrlKey: true
|
|
242
|
+
});
|
|
243
|
+
expect(keyCode.key).to.equal(Key.DIGIT8);
|
|
244
|
+
expect(keyCode.ctrl).to.be.true;
|
|
245
|
+
expect(keyCode.character).to.equal('[');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('should preserve legacy key identifier fallback in normalized data', () => {
|
|
249
|
+
const input = normalizeKeyboardInput({ keyIdentifier: Key.F1.code });
|
|
250
|
+
expect(KeyCode.createKeyCode(input).key).to.equal(Key.F1);
|
|
251
|
+
});
|
|
252
|
+
|
|
120
253
|
it('the order of the modifiers should not matter when parsing the key code', () => {
|
|
121
254
|
const left = KeySequence.parse('shift+alt+a');
|
|
122
255
|
const right = KeySequence.parse('alt+shift+a');
|
|
@@ -231,6 +364,78 @@ describe('keys api', () => {
|
|
|
231
364
|
expect(second.key).is.equal(Key.KEY_B);
|
|
232
365
|
});
|
|
233
366
|
|
|
367
|
+
it('should parse physical scan codes and preserve them when serializing', () => {
|
|
368
|
+
const keycode = KeyCode.parse('ctrl+[BracketLeft]');
|
|
369
|
+
expect(keycode.ctrl).to.be.true;
|
|
370
|
+
expect(keycode.key).to.equal(Key.BRACKET_LEFT);
|
|
371
|
+
expect(keycode.physical).to.be.true;
|
|
372
|
+
expect(keycode.toString()).to.equal('ctrl+[BracketLeft]');
|
|
373
|
+
expect(() => KeyCode.parse('[UnknownPhysicalKey]')).to.throw(/Unknown scan code/);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('should parse bare and escaped logical characters', () => {
|
|
377
|
+
for (const character of ['^', '§', '²', 'ä']) {
|
|
378
|
+
const keycode = KeyCode.parse(`ctrl+${character}`);
|
|
379
|
+
expect(keycode.character).to.equal(character);
|
|
380
|
+
expect(keycode.toString()).to.equal(`ctrl+${character}`);
|
|
381
|
+
}
|
|
382
|
+
expect(KeyCode.parse('ctrl+[char:0x2B]').character).to.equal('+');
|
|
383
|
+
expect(KeyCode.parse('ctrl+[char:0x20]').character).to.equal(' ');
|
|
384
|
+
expect(KeyCode.parse('ctrl+[char:0x5D]').character).to.equal(']');
|
|
385
|
+
expect(KeyCode.parse('ctrl+[char:§]').character).to.equal('§');
|
|
386
|
+
expect(KeyCode.parse('ctrl+[char:0x2B]').toString()).to.equal('ctrl+[char:0x2B]');
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('should keep bracketed separators and whitespace within one key token', () => {
|
|
390
|
+
expect(KeySequence.parse('ctrl+[char:0x20] ctrl+[BracketLeft]')).to.have.length(2);
|
|
391
|
+
expect(KeySequence.parse('ctrl+[ ctrl+]')).to.have.length(2);
|
|
392
|
+
expect(KeySequence.parse('ctrl+] ctrl+[')).to.have.length(2);
|
|
393
|
+
expect(KeyCode.parse('ctrl+[char:0x2B]').character).to.equal('+');
|
|
394
|
+
expect(KeyCode.parse('ctrl+[char:0x2D]').character).to.equal('-');
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('should reject invalid and multi-code-point logical characters', () => {
|
|
398
|
+
expect(() => KeyCode.parse('[char:0x110000]')).to.throw(/Invalid Unicode/);
|
|
399
|
+
expect(() => KeyCode.parse('[char:0xD800]')).to.throw(/Invalid Unicode/);
|
|
400
|
+
expect(() => KeyCode.parse('[char:ab]')).to.throw(/Invalid Unicode/);
|
|
401
|
+
expect(() => KeyCode.parse('👨👩👧👦')).to.throw(/Unrecognized key/);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should serialize recorder strokes as logical characters, named keys, or physical scan codes', () => {
|
|
405
|
+
expect(new KeyCode({ key: Key.DIGIT8, ctrl: true, character: '[' }).toAuthoredKeybindingString()).to.equal('ctrl+[');
|
|
406
|
+
expect(new KeyCode({ key: Key.EQUAL, ctrl: true, character: '+' }).toAuthoredKeybindingString()).to.equal('ctrl+[char:0x2B]');
|
|
407
|
+
|
|
408
|
+
const namedKeys: Array<[Key, string]> = [
|
|
409
|
+
[Key.F1, 'f1'],
|
|
410
|
+
[Key.DELETE, 'delete'],
|
|
411
|
+
[Key.BACKSPACE, 'backspace'],
|
|
412
|
+
[Key.ENTER, 'enter'],
|
|
413
|
+
[Key.ARROW_LEFT, 'left'],
|
|
414
|
+
[Key.SPACE, 'space'],
|
|
415
|
+
[Key.ESCAPE, 'escape']
|
|
416
|
+
];
|
|
417
|
+
for (const [key, name] of namedKeys) {
|
|
418
|
+
const serialized = new KeyCode({ key, ctrl: true }).toAuthoredKeybindingString();
|
|
419
|
+
expect(serialized).to.equal(`ctrl+${name}`);
|
|
420
|
+
expect(KeyCode.parse(serialized).key).to.equal(key);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const physicalPrintable = new KeyCode({ key: Key.DIGIT8, ctrl: true }).toAuthoredKeybindingString();
|
|
424
|
+
expect(physicalPrintable).to.equal('ctrl+[Digit8]');
|
|
425
|
+
expect(KeyCode.parse(physicalPrintable).key).to.equal(Key.DIGIT8);
|
|
426
|
+
|
|
427
|
+
const shiftedLetter = new KeyCode({ key: Key.KEY_P, ctrl: true, shift: true, character: 'P' });
|
|
428
|
+
expect(shiftedLetter.toAuthoredKeybindingString()).to.equal('shift+ctrl+p');
|
|
429
|
+
expect(KeyCode.parse(shiftedLetter.toAuthoredKeybindingString()).dispatchString()).to.equal('shift+ctrl+p');
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
it('should serialize recorder strokes for Space and numpad keys by name', () => {
|
|
433
|
+
expect(new KeyCode({ key: Key.SPACE, meta: true, shift: true, character: ' ' }).toAuthoredKeybindingString()).to.equal('meta+shift+space');
|
|
434
|
+
expect(new KeyCode({ key: Key.ADD, ctrl: true, character: '+' }).toAuthoredKeybindingString()).to.equal('ctrl+add');
|
|
435
|
+
expect(new KeyCode({ key: Key.DECIMAL, ctrl: true, character: '.' }).toAuthoredKeybindingString()).to.equal('ctrl+decimal');
|
|
436
|
+
expect(new KeyCode({ key: Key.DIGIT1, ctrl: true, character: '1' }).toAuthoredKeybindingString()).to.equal('ctrl+1');
|
|
437
|
+
});
|
|
438
|
+
|
|
234
439
|
it('should parse minus as key', () => {
|
|
235
440
|
const keycode = KeyCode.parse('ctrl+-');
|
|
236
441
|
expect(keycode.ctrl).to.be.true;
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { inject, injectable, named, postConstruct } from 'inversify';
|
|
18
|
-
import
|
|
18
|
+
// The default import returns the exported FileIcons instance itself; a namespace import would be an interop copy of its own
|
|
19
|
+
// properties only, and getClass/getClassWithColor live on the prototype.
|
|
20
|
+
import fileIcons from 'file-icons-js';
|
|
19
21
|
import URI from '../common/uri';
|
|
20
22
|
import { ContributionProvider } from '../common/contribution-provider';
|
|
21
23
|
import { Event, Emitter, Disposable, isObject, Path, Prioritizeable } from '../common';
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import * as DOMPurify from 'dompurify';
|
|
18
18
|
import { injectable, inject, postConstruct } from 'inversify';
|
|
19
|
-
import
|
|
19
|
+
import markdownit from 'markdown-it';
|
|
20
20
|
import * as markdownitemoji from 'markdown-it-emoji';
|
|
21
21
|
import { MarkdownString } from '../../common/markdown-rendering/markdown-string';
|
|
22
22
|
import { Disposable, DisposableGroup } from '../../common';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { expect } from 'chai';
|
|
18
|
+
import { Key, KeyCode } from '../keyboard/keys';
|
|
19
|
+
import { KeybindingRegistry } from '../keybinding';
|
|
20
|
+
import { ActionMenuNode } from './action-menu-node';
|
|
21
|
+
|
|
22
|
+
describe('ActionMenuNode accelerators', () => {
|
|
23
|
+
it('selects logical and physical accelerator forms explicitly', () => {
|
|
24
|
+
const binding = { command: 'test.command', keybinding: 'ctrl+[' };
|
|
25
|
+
const state = { inactive: false };
|
|
26
|
+
const keybindingRegistry = Object.create(KeybindingRegistry.prototype) as KeybindingRegistry;
|
|
27
|
+
keybindingRegistry.getKeybindingsForCommand = () => [{ ...binding, scope: 0 }];
|
|
28
|
+
keybindingRegistry.isEnabledInScope = () => true;
|
|
29
|
+
keybindingRegistry.isKeybindingInactive = () => state.inactive;
|
|
30
|
+
keybindingRegistry.resolveKeybinding = () => [new KeyCode({
|
|
31
|
+
key: Key.DIGIT8,
|
|
32
|
+
ctrl: true,
|
|
33
|
+
character: '[',
|
|
34
|
+
layoutModifiers: 'altGraph'
|
|
35
|
+
})];
|
|
36
|
+
Object.defineProperty(keybindingRegistry, 'keyboardLayoutService', {
|
|
37
|
+
value: { getKeyboardCharacter: (key: Key) => key.easyString }
|
|
38
|
+
});
|
|
39
|
+
const commands = {
|
|
40
|
+
getAllHandlers: () => [],
|
|
41
|
+
getCommand: () => ({ id: 'test.command' })
|
|
42
|
+
};
|
|
43
|
+
const contextKeyService = {
|
|
44
|
+
parseKeys: () => undefined
|
|
45
|
+
};
|
|
46
|
+
const node = new ActionMenuNode(
|
|
47
|
+
{ commandId: 'test.command' },
|
|
48
|
+
commands as never,
|
|
49
|
+
keybindingRegistry,
|
|
50
|
+
contextKeyService as never
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(node.getAccelerator(undefined, 'logical')).to.deep.equal(['Ctrl+[']);
|
|
54
|
+
expect(node.getAccelerator(undefined, 'physical')).to.deep.equal(['Ctrl+AltGr+8']);
|
|
55
|
+
|
|
56
|
+
state.inactive = true;
|
|
57
|
+
expect(node.getAccelerator(undefined, 'logical')).to.deep.equal(['Ctrl+[']);
|
|
58
|
+
expect(node.getAccelerator(undefined, 'physical')).to.deep.equal([]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -14,13 +14,16 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { KeybindingRegistry } from '../keybinding';
|
|
17
|
+
import { AcceleratorForm, KeybindingRegistry } from '../keybinding';
|
|
18
18
|
import { ContextKeyService } from '../context-key-service';
|
|
19
|
-
import { DisposableCollection, isObject, CommandRegistry, Emitter
|
|
19
|
+
import { DisposableCollection, isObject, CommandRegistry, Emitter } from '../../common';
|
|
20
20
|
import { CommandMenu, ContextExpressionMatcher, MenuAction, MenuPath } from '../../common/menu/menu-types';
|
|
21
21
|
|
|
22
|
+
export { AcceleratorForm } from '../keybinding';
|
|
23
|
+
|
|
22
24
|
export interface AcceleratorSource {
|
|
23
|
-
|
|
25
|
+
/** Return the accelerator rendered in the explicitly requested logical or physical form. */
|
|
26
|
+
getAccelerator(context: HTMLElement | undefined, form: AcceleratorForm): string[];
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export namespace AcceleratorSource {
|
|
@@ -80,17 +83,8 @@ export class ActionMenuNode implements CommandMenu {
|
|
|
80
83
|
return true;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
getAccelerator(context: HTMLElement | undefined): string[] {
|
|
84
|
-
|
|
85
|
-
// Only consider the first active keybinding.
|
|
86
|
-
if (bindings.length) {
|
|
87
|
-
const binding = bindings.find(b => this.keybindingRegistry.isEnabledInScope(b, context));
|
|
88
|
-
if (binding) {
|
|
89
|
-
const asciiOnly = environment.electron.is();
|
|
90
|
-
return this.keybindingRegistry.acceleratorFor(binding, '+', asciiOnly);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return [];
|
|
86
|
+
getAccelerator(context: HTMLElement | undefined, form: AcceleratorForm): string[] {
|
|
87
|
+
return this.keybindingRegistry.acceleratorForCommand(this.action.commandId, context, form);
|
|
94
88
|
}
|
|
95
89
|
|
|
96
90
|
isEnabled(effeciveMenuPath: MenuPath, ...args: unknown[]): boolean {
|
|
@@ -368,7 +368,7 @@ export class DynamicMenuWidget extends MenuWidget {
|
|
|
368
368
|
iconClass: node.icon,
|
|
369
369
|
});
|
|
370
370
|
|
|
371
|
-
const accelerator = (AcceleratorSource.is(node) ? node.getAccelerator(this.options.context) : []);
|
|
371
|
+
const accelerator = (AcceleratorSource.is(node) ? node.getAccelerator(this.options.context, 'logical') : []);
|
|
372
372
|
if (accelerator.length > 0) {
|
|
373
373
|
phCommandRegistry.addKeyBinding({
|
|
374
374
|
command: id,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { Container } from 'inversify';
|
|
18
18
|
import { PreferenceValidationService } from './preference-validation-service';
|
|
19
|
-
import
|
|
19
|
+
import assert from 'assert';
|
|
20
20
|
import { JSONValue } from '@lumino/coreutils';
|
|
21
21
|
import { IJSONSchema, JsonType } from '../../common/json-schema';
|
|
22
22
|
import {
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { enableJSDOM } from '../test/jsdom';
|
|
18
|
+
let disableJSDOM = enableJSDOM();
|
|
19
|
+
|
|
20
|
+
import { FrontendApplicationConfigProvider } from '../frontend-application-config-provider';
|
|
21
|
+
FrontendApplicationConfigProvider.set({});
|
|
22
|
+
|
|
23
|
+
import * as chai from 'chai';
|
|
24
|
+
import { Container } from 'inversify';
|
|
25
|
+
import { CancellationToken, CommandRegistry, Emitter } from '../../common';
|
|
26
|
+
import { CorePreferences } from '../../common/core-preferences';
|
|
27
|
+
import { ContextKeyService, ContextKeyServiceDummyImpl } from '../context-key-service';
|
|
28
|
+
import { KeybindingRegistry } from '../keybinding';
|
|
29
|
+
import { QuickAccessRegistry } from './quick-access';
|
|
30
|
+
import { QuickCommandService } from './quick-command-service';
|
|
31
|
+
import { QuickInputService, QuickPickItem } from './quick-input-service';
|
|
32
|
+
|
|
33
|
+
disableJSDOM();
|
|
34
|
+
|
|
35
|
+
const expect = chai.expect;
|
|
36
|
+
|
|
37
|
+
class RecordingContextKeyService extends ContextKeyServiceDummyImpl {
|
|
38
|
+
activeContext: unknown;
|
|
39
|
+
|
|
40
|
+
override withContext<T>(context: unknown, callback: () => T): T {
|
|
41
|
+
const previous = this.activeContext;
|
|
42
|
+
this.activeContext = context;
|
|
43
|
+
try {
|
|
44
|
+
return callback();
|
|
45
|
+
} finally {
|
|
46
|
+
this.activeContext = previous;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describe('quick-command-service', () => {
|
|
52
|
+
|
|
53
|
+
let editor: HTMLElement;
|
|
54
|
+
let quickInput: HTMLInputElement;
|
|
55
|
+
let contextKeyService: RecordingContextKeyService;
|
|
56
|
+
let commandRegistry: CommandRegistry;
|
|
57
|
+
let onHideEmitter: Emitter<void>;
|
|
58
|
+
let quickInputService: { previousFocusElement?: HTMLElement, onHide: Emitter<void>['event'] };
|
|
59
|
+
let service: QuickCommandService;
|
|
60
|
+
|
|
61
|
+
before(() => {
|
|
62
|
+
disableJSDOM = enableJSDOM();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
after(() => {
|
|
66
|
+
disableJSDOM();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
beforeEach(() => {
|
|
70
|
+
editor = document.createElement('div');
|
|
71
|
+
editor.tabIndex = 0;
|
|
72
|
+
quickInput = document.createElement('input');
|
|
73
|
+
document.body.append(editor, quickInput);
|
|
74
|
+
// Focus has moved to the quick input, as it does while the palette is open.
|
|
75
|
+
quickInput.focus();
|
|
76
|
+
|
|
77
|
+
contextKeyService = new RecordingContextKeyService();
|
|
78
|
+
commandRegistry = new CommandRegistry({ getContributions: () => [] });
|
|
79
|
+
onHideEmitter = new Emitter<void>();
|
|
80
|
+
quickInputService = { previousFocusElement: editor, onHide: onHideEmitter.event };
|
|
81
|
+
|
|
82
|
+
const container = new Container();
|
|
83
|
+
container.bind(ContextKeyService).toConstantValue(contextKeyService);
|
|
84
|
+
container.bind(CommandRegistry).toConstantValue(commandRegistry);
|
|
85
|
+
container.bind(CorePreferences).toConstantValue(<CorePreferences>{ 'workbench.commandPalette.history': 50 });
|
|
86
|
+
container.bind(QuickAccessRegistry).toConstantValue(<QuickAccessRegistry>{});
|
|
87
|
+
container.bind(KeybindingRegistry).toConstantValue(<KeybindingRegistry><unknown>{ getKeybindingsForCommand: () => [] });
|
|
88
|
+
container.bind(QuickInputService).toConstantValue(<QuickInputService><unknown>quickInputService);
|
|
89
|
+
container.bind(QuickCommandService).toSelf();
|
|
90
|
+
service = container.get(QuickCommandService);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
editor.remove();
|
|
95
|
+
quickInput.remove();
|
|
96
|
+
onHideEmitter.dispose();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
function inEditorContext(): boolean {
|
|
100
|
+
return contextKeyService.activeContext === editor;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function picks(): QuickPickItem[] {
|
|
104
|
+
return service.getPicks('', CancellationToken.None).filter((pick): pick is QuickPickItem => pick.type !== 'separator');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
it('evaluates command enablement against the element focused before the quick input opened', () => {
|
|
108
|
+
commandRegistry.registerCommand({ id: 'test.editorOnly', label: 'Editor Only' }, { execute: () => { }, isEnabled: inEditorContext });
|
|
109
|
+
|
|
110
|
+
expect(picks().map(pick => pick.label)).to.deep.equal(['Editor Only']);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('evaluates item state against the element focused before the quick input opened', () => {
|
|
114
|
+
commandRegistry.registerCommand({ id: 'test.toggle', label: 'Toggle' }, { execute: () => { }, isEnabled: inEditorContext, isToggled: inEditorContext });
|
|
115
|
+
|
|
116
|
+
const [item] = picks();
|
|
117
|
+
expect(item.alwaysShow).to.be.true;
|
|
118
|
+
expect(item.iconClasses).to.not.be.undefined;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('evaluates pushed command contexts against the element focused before the quick input opened', () => {
|
|
122
|
+
contextKeyService.match = () => inEditorContext();
|
|
123
|
+
commandRegistry.registerCommand({ id: 'test.when', label: 'When' }, { execute: () => { } });
|
|
124
|
+
service.pushCommandContext('test.when', 'editorFocus');
|
|
125
|
+
|
|
126
|
+
expect(picks().map(pick => pick.label)).to.deep.equal(['When']);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('restores focus to the element focused before the quick input opened on execute', () => {
|
|
130
|
+
commandRegistry.registerCommand({ id: 'test.command', label: 'Command' }, { execute: () => { } });
|
|
131
|
+
|
|
132
|
+
picks()[0].execute!();
|
|
133
|
+
|
|
134
|
+
expect(document.activeElement).to.equal(editor);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('falls back to the active element when items are created without a reset', () => {
|
|
138
|
+
commandRegistry.registerCommand({ id: 'test.command', label: 'Command' }, { execute: () => { } });
|
|
139
|
+
const item = service.toItem({ id: 'test.command', label: 'Command' });
|
|
140
|
+
editor.focus();
|
|
141
|
+
|
|
142
|
+
item.execute!();
|
|
143
|
+
|
|
144
|
+
expect(document.activeElement).to.equal(quickInput);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('forgets the context element when the quick input is hidden', () => {
|
|
148
|
+
commandRegistry.registerCommand({ id: 'test.command', label: 'Command' }, { execute: () => { } });
|
|
149
|
+
service.reset();
|
|
150
|
+
onHideEmitter.fire();
|
|
151
|
+
|
|
152
|
+
const item = service.toItem({ id: 'test.command', label: 'Command' });
|
|
153
|
+
editor.focus();
|
|
154
|
+
item.execute!();
|
|
155
|
+
|
|
156
|
+
expect(document.activeElement).to.equal(quickInput);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
});
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { inject, injectable } from 'inversify';
|
|
17
|
+
import { inject, injectable, optional, postConstruct } from 'inversify';
|
|
18
18
|
import { KeybindingRegistry } from '../keybinding';
|
|
19
19
|
import { Disposable, Command, CommandRegistry, CancellationToken, nls } from '../../common';
|
|
20
20
|
import { ContextKeyService } from '../context-key-service';
|
|
21
21
|
import { CorePreferences } from '../../common/core-preferences';
|
|
22
22
|
import { QuickAccessContribution, QuickAccessProvider, QuickAccessRegistry } from './quick-access';
|
|
23
|
-
import { filterItems, QuickPickItem, QuickPicks } from './quick-input-service';
|
|
23
|
+
import { filterItems, QuickInputService, QuickPickItem, QuickPicks } from './quick-input-service';
|
|
24
24
|
import { KeySequence } from '../keys';
|
|
25
25
|
import { codiconArray } from '../widgets';
|
|
26
26
|
|
|
@@ -56,6 +56,9 @@ export class QuickCommandService implements QuickAccessContribution, QuickAccess
|
|
|
56
56
|
@inject(KeybindingRegistry)
|
|
57
57
|
protected readonly keybindingRegistry: KeybindingRegistry;
|
|
58
58
|
|
|
59
|
+
@inject(QuickInputService) @optional()
|
|
60
|
+
protected readonly quickInputService: QuickInputService | undefined;
|
|
61
|
+
|
|
59
62
|
// The list of exempted commands not to be displayed in the recently used list.
|
|
60
63
|
readonly exemptedCommands: Command[] = [
|
|
61
64
|
CLEAR_COMMAND_HISTORY,
|
|
@@ -64,6 +67,17 @@ export class QuickCommandService implements QuickAccessContribution, QuickAccess
|
|
|
64
67
|
private recentItems: QuickPickItem[] = [];
|
|
65
68
|
private otherItems: QuickPickItem[] = [];
|
|
66
69
|
|
|
70
|
+
/**
|
|
71
|
+
* The element that was focused when the quick input was opened.
|
|
72
|
+
* Commands are evaluated against its context, since focus moves to the quick input while the palette is open.
|
|
73
|
+
*/
|
|
74
|
+
protected commandContextElement: HTMLElement | undefined;
|
|
75
|
+
|
|
76
|
+
@postConstruct()
|
|
77
|
+
protected init(): void {
|
|
78
|
+
this.quickInputService?.onHide(() => this.commandContextElement = undefined);
|
|
79
|
+
}
|
|
80
|
+
|
|
67
81
|
registerQuickAccessProvider(): void {
|
|
68
82
|
this.quickAccessRegistry.registerQuickAccessProvider({
|
|
69
83
|
getInstance: () => this,
|
|
@@ -74,11 +88,12 @@ export class QuickCommandService implements QuickAccessContribution, QuickAccess
|
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
reset(): void {
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
this.updateCommandContextElement();
|
|
92
|
+
this.withCommandContext(() => {
|
|
93
|
+
const { recent, other } = this.getCommands();
|
|
94
|
+
this.recentItems = recent.map(command => this.toItem(command));
|
|
95
|
+
this.otherItems = other.map(command => this.toItem(command));
|
|
96
|
+
});
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
getPicks(filter: string, token: CancellationToken): QuickPicks {
|
|
@@ -105,7 +120,8 @@ export class QuickCommandService implements QuickAccessContribution, QuickAccess
|
|
|
105
120
|
toItem(command: Command): QuickPickItem {
|
|
106
121
|
const label = (command.category) ? `${command.category}: ` + command.label! : command.label!;
|
|
107
122
|
const iconClasses = this.getItemIconClasses(command);
|
|
108
|
-
const activeElement = window.document.activeElement
|
|
123
|
+
const activeElement = window.document.activeElement;
|
|
124
|
+
const commandContextElement = this.commandContextElement ?? (activeElement instanceof HTMLElement ? activeElement : undefined);
|
|
109
125
|
|
|
110
126
|
const originalLabel = command.originalLabel || command.label!;
|
|
111
127
|
const originalCategory = command.originalCategory || command.category;
|
|
@@ -121,13 +137,24 @@ export class QuickCommandService implements QuickAccessContribution, QuickAccess
|
|
|
121
137
|
alwaysShow: !!this.commandRegistry.getActiveHandler(command.id),
|
|
122
138
|
keySequence: this.getKeybinding(command),
|
|
123
139
|
execute: () => {
|
|
124
|
-
|
|
140
|
+
commandContextElement?.focus({ preventScroll: true });
|
|
125
141
|
this.commandRegistry.executeCommand(command.id);
|
|
126
142
|
this.commandRegistry.addRecentCommand(command);
|
|
127
143
|
}
|
|
128
144
|
};
|
|
129
145
|
}
|
|
130
146
|
|
|
147
|
+
protected updateCommandContextElement(): void {
|
|
148
|
+
// When the palette is opened directly, the picks are computed before the quick input is shown and focused.
|
|
149
|
+
const element = this.quickInputService?.previousFocusElement ?? window.document.activeElement;
|
|
150
|
+
this.commandContextElement = element instanceof HTMLElement ? element : undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
protected withCommandContext<T>(callback: () => T): T {
|
|
154
|
+
const element = this.commandContextElement;
|
|
155
|
+
return element?.isConnected ? this.contextKeyService.withContext(element, callback) : callback();
|
|
156
|
+
}
|
|
157
|
+
|
|
131
158
|
private getKeybinding(command: Command): KeySequence | undefined {
|
|
132
159
|
const keybindings = this.keybindingRegistry.getKeybindingsForCommand(command.id);
|
|
133
160
|
if (!keybindings || keybindings.length === 0) {
|
|
@@ -60,7 +60,7 @@ export class QuickHelpService implements QuickAccessProvider, QuickAccessContrib
|
|
|
60
60
|
|
|
61
61
|
for (const helpEntry of provider.helpEntries) {
|
|
62
62
|
const prefix = helpEntry.prefix || provider.prefix;
|
|
63
|
-
const label = prefix || '\u2026'
|
|
63
|
+
const label = prefix || '\u2026'; // ...
|
|
64
64
|
|
|
65
65
|
(helpEntry.needsEditor ? editorProviders : globalProviders).push({
|
|
66
66
|
label,
|
|
@@ -58,6 +58,17 @@ export function enableJSDOM(): () => void {
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
(dom.window.document as any)['queryCommandSupported'] = function (): void { };
|
|
61
|
+
dom.window.matchMedia = () => ({
|
|
62
|
+
matches: false,
|
|
63
|
+
media: '',
|
|
64
|
+
// eslint-disable-next-line no-null/no-null
|
|
65
|
+
onchange: null,
|
|
66
|
+
addListener: () => undefined,
|
|
67
|
+
removeListener: () => undefined,
|
|
68
|
+
addEventListener: () => undefined,
|
|
69
|
+
removeEventListener: () => undefined,
|
|
70
|
+
dispatchEvent: () => false
|
|
71
|
+
});
|
|
61
72
|
|
|
62
73
|
const disableJSDOM = (global as any)['_disableJSDOM'] = () => {
|
|
63
74
|
let property: string | undefined;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import assert from 'assert';
|
|
18
18
|
import { Container } from 'inversify';
|
|
19
19
|
import { createTreeContainer, isTreeServices } from './tree-container';
|
|
20
20
|
import { TreeSearch } from './tree-search';
|