From 2bf6e915098ed0cb48a138503a9edec406e1f3ed Mon Sep 17 00:00:00 2001 From: j4rviscmd Date: Fri, 5 Jun 2026 16:14:06 +0900 Subject: [PATCH] feat: add eager extension activation for vim/neovim extensions Add coderm.extensions.eagerActivation setting to force immediate startup activation of specified extensions (default: vscode-neovim and vscodevim). Injects '*' activation event into listed extensions via ImplicitActivationEvents, bypassing normal lazy activation triggers like onCommand:type or onStartupFinished. --- README.ja.md | 33 +++++----- README.md | 33 +++++----- .../common/implicitActivationEvents.ts | 61 +++++++++++++++++++ .../coderm/browser/coderm.contribution.ts | 1 + .../contrib/coderm/browser/eagerExtensions.ts | 34 +++++++++++ .../common/abstractExtensionService.ts | 6 ++ 6 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 src/vs/workbench/contrib/coderm/browser/eagerExtensions.ts diff --git a/README.ja.md b/README.ja.md index 8b110e43f69..442092d204a 100644 --- a/README.ja.md +++ b/README.ja.md @@ -52,22 +52,23 @@ VS Codeのフォーク。本家にはないUI/UX改善を追加した(してい 本家VS Codeにはない、Coderm固有の設定項目です。 -| 設定キー | 型 | デフォルト | 説明 | -| :----------------------------------------------- | :-------- | :--------- | :----------------------------------------------- | -| `coderm.activePaneBorder.enabled` | `boolean` | `true` | アクティブペインの境界線ハイライトを有効化 | -| `coderm.activePaneBorder.color` | `string` | `""` | 境界線の色(空文字 = テーマの`focusBorder`) | -| `coderm.activePaneBorder.width` | `number` | `1` | 境界線の太さ(px, 1–5) | -| `coderm.cursorAutoHide.enabled` | `boolean` | `true` | 無操作時にマウスカーソルを自動的に非表示にする | -| `coderm.cursorAutoHide.delay` | `number` | `3000` | カーソル非表示までの遅延(ms) | -| `coderm.cursorAutoHide.suppressHover` | `boolean` | `true` | カーソル非表示時にエディタhoverを抑制する | -| `coderm.workbench.editor.editorGroupIndexInTab` | `boolean` | `false` | タブにエディタグループ番号`[N]`を表示 | -| `coderm.workbench.editor.autoMaximizeOnFocus` | `boolean` | `true` | 最小ペインにフォーカス時の自動最大化を制御 | -| `coderm.workbench.editor.preventNewGroupOnFocus` | `boolean` | `false` | フォーカス時に新しいエディタグループの作成を抑制 | -| `coderm.workbench.editor.resizeIncrement` | `number` | `60` | ペインリサイズの増分(px) | -| `coderm.terminal.horizontalPadding` | `number` | `20` | ターミナルの水平パディング(px, 0–100) | -| `coderm.quickOpen.includeTerminals` | `boolean` | `true` | Quick Openにターミナルエディタを含める | -| `coderm.updateDownloadProgress.enabled` | `boolean` | `true` | アップデートダウンロード時に進捗通知を表示 | -| `coderm.terminal.closeEmptyPaneOnKill` | `boolean` | `true` | ターミナルkill時に空ペインを閉じてフォーカス復帰 | +| 設定キー | 型 | デフォルト | 説明 | +| :----------------------------------------------- | :--------- | :----------------------------------------------- | :------------------------------------------------- | +| `coderm.activePaneBorder.enabled` | `boolean` | `true` | アクティブペインの境界線ハイライトを有効化 | +| `coderm.activePaneBorder.color` | `string` | `""` | 境界線の色(空文字 = テーマの`focusBorder`) | +| `coderm.activePaneBorder.width` | `number` | `1` | 境界線の太さ(px, 1–5) | +| `coderm.cursorAutoHide.enabled` | `boolean` | `true` | 無操作時にマウスカーソルを自動的に非表示にする | +| `coderm.cursorAutoHide.delay` | `number` | `3000` | カーソル非表示までの遅延(ms) | +| `coderm.cursorAutoHide.suppressHover` | `boolean` | `true` | カーソル非表示時にエディタhoverを抑制する | +| `coderm.workbench.editor.editorGroupIndexInTab` | `boolean` | `false` | タブにエディタグループ番号`[N]`を表示 | +| `coderm.workbench.editor.autoMaximizeOnFocus` | `boolean` | `true` | 最小ペインにフォーカス時の自動最大化を制御 | +| `coderm.workbench.editor.preventNewGroupOnFocus` | `boolean` | `false` | フォーカス時に新しいエディタグループの作成を抑制 | +| `coderm.extensions.eagerActivation` | `string[]` | `["asvetliakov.vscode-neovim", "vscodevim.vim"]` | 起動時に即座にアクティベートする拡張機能IDのリスト | +| `coderm.workbench.editor.resizeIncrement` | `number` | `60` | ペインリサイズの増分(px) | +| `coderm.terminal.horizontalPadding` | `number` | `20` | ターミナルの水平パディング(px, 0–100) | +| `coderm.quickOpen.includeTerminals` | `boolean` | `true` | Quick Openにターミナルエディタを含める | +| `coderm.updateDownloadProgress.enabled` | `boolean` | `true` | アップデートダウンロード時に進捗通知を表示 | +| `coderm.terminal.closeEmptyPaneOnKill` | `boolean` | `true` | ターミナルkill時に空ペインを閉じてフォーカス復帰 | --- diff --git a/README.md b/README.md index 60d4a1605d3..3c847daaebd 100644 --- a/README.md +++ b/README.md @@ -52,22 +52,23 @@ A customized fork of VS Code with UI/UX improvements not found in upstream. Settings unique to Coderm that are not available in upstream VS Code. -| Setting | Type | Default | Description | -| :----------------------------------------------- | :-------- | :------ | :-------------------------------------------------- | -| `coderm.activePaneBorder.enabled` | `boolean` | `true` | Enable active pane border highlight | -| `coderm.activePaneBorder.color` | `string` | `""` | Border color (empty = theme's `focusBorder`) | -| `coderm.activePaneBorder.width` | `number` | `1` | Border thickness (px, 1–5) | -| `coderm.cursorAutoHide.enabled` | `boolean` | `true` | Auto-hide mouse cursor after inactivity | -| `coderm.cursorAutoHide.delay` | `number` | `3000` | Delay before hiding cursor (ms) | -| `coderm.cursorAutoHide.suppressHover` | `boolean` | `true` | Suppress editor hover when cursor is auto-hidden | -| `coderm.workbench.editor.editorGroupIndexInTab` | `boolean` | `false` | Show editor group index `[N]` in tab | -| `coderm.workbench.editor.autoMaximizeOnFocus` | `boolean` | `true` | Control auto-maximize when focusing smallest pane | -| `coderm.workbench.editor.preventNewGroupOnFocus` | `boolean` | `false` | Prevent creating new editor group on focus | -| `coderm.workbench.editor.resizeIncrement` | `number` | `60` | Pane resize increment (px) | -| `coderm.terminal.horizontalPadding` | `number` | `20` | Terminal horizontal padding (px, 0–100) | -| `coderm.quickOpen.includeTerminals` | `boolean` | `true` | Include terminal editors in Quick Open | -| `coderm.updateDownloadProgress.enabled` | `boolean` | `true` | Show progress notification during update download | -| `coderm.terminal.closeEmptyPaneOnKill` | `boolean` | `true` | Close empty pane and restore focus on terminal kill | +| Setting | Type | Default | Description | +| :----------------------------------------------- | :--------- | :----------------------------------------------- | :-------------------------------------------------- | +| `coderm.activePaneBorder.enabled` | `boolean` | `true` | Enable active pane border highlight | +| `coderm.activePaneBorder.color` | `string` | `""` | Border color (empty = theme's `focusBorder`) | +| `coderm.activePaneBorder.width` | `number` | `1` | Border thickness (px, 1–5) | +| `coderm.cursorAutoHide.enabled` | `boolean` | `true` | Auto-hide mouse cursor after inactivity | +| `coderm.cursorAutoHide.delay` | `number` | `3000` | Delay before hiding cursor (ms) | +| `coderm.cursorAutoHide.suppressHover` | `boolean` | `true` | Suppress editor hover when cursor is auto-hidden | +| `coderm.workbench.editor.editorGroupIndexInTab` | `boolean` | `false` | Show editor group index `[N]` in tab | +| `coderm.workbench.editor.autoMaximizeOnFocus` | `boolean` | `true` | Control auto-maximize when focusing smallest pane | +| `coderm.workbench.editor.preventNewGroupOnFocus` | `boolean` | `false` | Prevent creating new editor group on focus | +| `coderm.extensions.eagerActivation` | `string[]` | `["asvetliakov.vscode-neovim", "vscodevim.vim"]` | Extensions to activate eagerly on startup | +| `coderm.workbench.editor.resizeIncrement` | `number` | `60` | Pane resize increment (px) | +| `coderm.terminal.horizontalPadding` | `number` | `20` | Terminal horizontal padding (px, 0–100) | +| `coderm.quickOpen.includeTerminals` | `boolean` | `true` | Include terminal editors in Quick Open | +| `coderm.updateDownloadProgress.enabled` | `boolean` | `true` | Show progress notification during update download | +| `coderm.terminal.closeEmptyPaneOnKill` | `boolean` | `true` | Close empty pane and restore focus on terminal kill | --- diff --git a/src/vs/platform/extensionManagement/common/implicitActivationEvents.ts b/src/vs/platform/extensionManagement/common/implicitActivationEvents.ts index f9f417adb8a..7fbbfd00a37 100644 --- a/src/vs/platform/extensionManagement/common/implicitActivationEvents.ts +++ b/src/vs/platform/extensionManagement/common/implicitActivationEvents.ts @@ -7,15 +7,57 @@ import { IStringDictionary } from '../../../base/common/collections.js'; import { onUnexpectedError } from '../../../base/common/errors.js'; import { ExtensionIdentifier, IExtensionDescription } from '../../extensions/common/extensions.js'; +/** + * A function that maps extension contribution values to their corresponding + * implicit activation event strings (e.g. `onCommand:...`, `onLanguage:...`). + * + * @typeParam T - The concrete contribution type for a given extension point. + */ export interface IActivationEventsGenerator { (contributions: readonly T[]): Iterable; } +/** + * Manages implicit activation events for extensions. + * + * VS Code extensions declare activation events in `package.json`, but certain + * extension contributions (e.g. commands, languages, views) implicitly trigger + * activation. This class collects those implicit events by iterating registered + * generators for each extension point found in an extension's `contributes` field. + * + * Must be used on the **renderer process** where all extension points and their + * generators are known. + */ export class ImplicitActivationEventsImpl { + /** Maps extension point names to their implicit activation event generators. */ private readonly _generators = new Map>(); + + /** Per-extension cache of resolved activation event arrays. */ private readonly _cache = new WeakMap(); + /** + * Coderm: extension IDs that should activate eagerly (treated as `*`). + * Populated from the `coderm.extensions.eagerActivation` setting. + */ + private _eagerExtensions = new Set(); + + /** + * Coderm: Register extension IDs whose activation events should include `*`, + * forcing eager (startup) activation regardless of their package.json declaration. + */ + public setEagerExtensions(ids: ReadonlySet): void { + this._eagerExtensions = new Set(ids); + } + + /** + * Register a generator that produces implicit activation events for a given + * extension point. + * + * @param extensionPointName - The `contributes` key (e.g. `"commands"`, `"languages"`). + * @param generator - Function that receives the contribution values and returns + * the corresponding activation event strings. + */ public register(extensionPointName: string, generator: IActivationEventsGenerator): void { this._generators.set(extensionPointName, generator as IActivationEventsGenerator); } @@ -46,6 +88,16 @@ export class ImplicitActivationEventsImpl { return result; } + /** + * Build the full activation event list for a single extension. + * + * Combines events from: + * 1. `activationEvents` in `package.json` (with `onUri` expansion) + * 2. Implicit events from registered generators for each contribution key + * 3. Coderm: `*` injected for extensions listed in {@link _eagerExtensions} + * + * Non-host extensions (no `main`/`browser`) get an empty array. + */ private _readActivationEvents(desc: IExtensionDescription): string[] { if (typeof desc.main === 'undefined' && typeof desc.browser === 'undefined') { return []; @@ -80,8 +132,17 @@ export class ImplicitActivationEventsImpl { } } + // Coderm: inject `*` for eager extensions to force startup activation + if (this._eagerExtensions.has(ExtensionIdentifier.toKey(desc.identifier)) && !activationEvents.includes('*')) { + activationEvents.push('*'); + } + return activationEvents; } } +/** + * Singleton instance shared across the renderer process. + * Extension points register their generators here during startup. + */ export const ImplicitActivationEvents: ImplicitActivationEventsImpl = new ImplicitActivationEventsImpl(); diff --git a/src/vs/workbench/contrib/coderm/browser/coderm.contribution.ts b/src/vs/workbench/contrib/coderm/browser/coderm.contribution.ts index d0e52cd209d..c586414af37 100644 --- a/src/vs/workbench/contrib/coderm/browser/coderm.contribution.ts +++ b/src/vs/workbench/contrib/coderm/browser/coderm.contribution.ts @@ -13,6 +13,7 @@ import './autoMaximizeActions.js'; import './cursorAutoHide.js'; import './defaultThemeInstaller.js'; import './devTitlePrefix.js'; +import './eagerExtensions.js'; import './editorGroupIndex.js'; import './gitWorktreeDefaults.js'; import './preventNewGroupOnFocus.js'; diff --git a/src/vs/workbench/contrib/coderm/browser/eagerExtensions.ts b/src/vs/workbench/contrib/coderm/browser/eagerExtensions.ts new file mode 100644 index 00000000000..54c3b16bb10 --- /dev/null +++ b/src/vs/workbench/contrib/coderm/browser/eagerExtensions.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from '../../../../nls.js'; +import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js'; +import { Registry } from '../../../../platform/registry/common/platform.js'; + +/** + * Configuration key for eager extension activation. + * + * Extensions listed here will have `*` injected into their activation events, + * causing them to activate during the eager (startup) phase instead of waiting + * for their normal activation triggers (e.g. key press, onStartupFinished). + */ +export const CodermEagerExtensionsSetting = 'coderm.extensions.eagerActivation'; + +Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({ + id: 'coderm.eagerExtensions', + order: 105, + title: localize('codermConfigurationTitle', 'Coderm'), + type: 'object', + properties: { + [CodermEagerExtensionsSetting]: { + type: 'array', + items: { type: 'string' }, + default: ['asvetliakov.vscode-neovim', 'vscodevim.vim'], + scope: ConfigurationScope.APPLICATION, + description: localize('coderm.extensions.eagerActivation', + 'List of extension IDs to activate eagerly on startup. Extensions listed here will be activated immediately instead of waiting for their normal activation triggers (e.g. first key press). This is useful for vim/neovim extensions where every millisecond of activation latency matters.'), + }, + }, +}); diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 6a83d64d718..4d0584fcb40 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -126,6 +126,12 @@ export abstract class AbstractExtensionService extends Disposable implements IEx this._hasLocalProcess = options.hasLocalProcess; this._allowRemoteExtensionsInLocalWebWorker = options.allowRemoteExtensionsInLocalWebWorker; + // Coderm: Force eager (startup) activation for configured extensions + const codermEagerExts = this._configurationService.getValue('coderm.extensions.eagerActivation'); + if (Array.isArray(codermEagerExts) && codermEagerExts.length > 0) { + ImplicitActivationEvents.setEagerExtensions(new Set(codermEagerExts)); + } + // help the file service to activate providers by activating extensions by file system event this._register(this._fileService.onWillActivateFileSystemProvider(e => { if (e.scheme !== Schemas.vscodeRemote) {