From 001381459ec8aa75e4beedbc329facc5390b401c Mon Sep 17 00:00:00 2001 From: Lee Dong Geon <100822592+ldg030201@users.noreply.github.com> Date: Thu, 5 Nov 2026 11:48:21 +0900 Subject: [PATCH] fix(themes): match IntelliJ's gutter, selected tab border and completion colours on import (#1424) Themes imported from IntelliJ drew a lighter gutter strip and kept the built-in blue for the selected tab's border and completion matches. The converter read the classic UI's GUTTER_BACKGROUND, where the new UI paints EDITOR_GUTTER_BACKGROUND or else the editor's background; it read EditorTabs.underlineColor, where Islands borders the selected tab with underlinedBorderColor; and it didn't map CompletionPopup.matchForeground. Scheme attributes written as `` (no colours, not inherited) now show as plain text instead of keeping the built-in colours. Co-authored-by: ldg030201 <100822592+ldg030201@users.noreply.github.com> --- docs/plugins/themes.md | 9 ++++++-- scripts/theme/theme.test.ts | 12 ++++++++++ src/features/plugins/intellijTheme.ts | 33 ++++++++++++++++++++------- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/docs/plugins/themes.md b/docs/plugins/themes.md index f1bff5350..e28db7a85 100644 --- a/docs/plugins/themes.md +++ b/docs/plugins/themes.md @@ -192,7 +192,9 @@ ship no `.icls` at all keep the built-in syntax colours. | `--danger`, `--warning` | `Component.errorFocusColor`, `Component.warningFocusColor` | | `--bg-tooltip`, `--fg-tooltip`, `--border-tooltip` | `ToolTip.background`, `.foreground`, `.borderColor` | | `--bg-button`, `--border-button` | `Button.startBackground`, `Button.startBorderColor` | -| `--bg-tab-selected`, `--border-tab-selected` | `EditorTabs.underlinedTabBackground`, `EditorTabs.underlineColor` | +| `--bg-tab-selected` | `EditorTabs.underlinedTabBackground` | +| `--border-tab-selected` | `EditorTabs.underlinedBorderColor` (Islands), `EditorTabs.underlineColor` | +| `--fg-completion-match` | `CompletionPopup.matchForeground` | | `--bg-toolbar-hover`, `--bg-toolbar-pressed` | `ActionButton.hoverBackground`, `ActionButton.pressedBackground` | | `--bg-stripe-hover`, `--bg-stripe-selected` | `ToolWindow.Button.hoverBackground`, `.selectedBackground` | | `--scrollbar-thumb`, `--scrollbar-thumb-hover` | `ScrollBar.Mac.thumbColor`, `ScrollBar.Mac.hoverThumbColor` | @@ -209,6 +211,7 @@ The full table is `UI_KEYS` in [`src/features/plugins/intellijTheme.ts`](../../s | `--caret`, `--bg-current-line` | colour `CARET_COLOR`, `CARET_ROW_COLOR` | | `--bg-editor-selection` | colour `SELECTION_BACKGROUND` | | `--fg-line-number`, `--fg-line-number-current` | colour `LINE_NUMBERS_COLOR`, `LINE_NUMBER_ON_CARET_ROW_COLOR` | +| `--bg-editor-gutter` | colour `EDITOR_GUTTER_BACKGROUND`, else the editor background (as the new UI paints it; `GUTTER_BACKGROUND` is the classic UI's) | | `--border-indent-guide`, `--border-right-margin`, `--fg-whitespace` | colour `INDENT_GUIDE`, `RIGHT_MARGIN_COLOR`, `WHITESPACES` | | `--vcs-*`, `--gutter-*` | colour `FILESTATUS_*`, `MODIFIED_LINES_COLOR`, `ADDED_LINES_COLOR`, `DELETED_LINES_COLOR` | | `--syn-keyword`, `--syn-string`, `--syn-number` | `DEFAULT_KEYWORD`, `DEFAULT_STRING`, `DEFAULT_NUMBER` | @@ -226,7 +229,9 @@ The full table is `UI_KEYS` in [`src/features/plugins/intellijTheme.ts`](../../s | `--syn-self`, `--syn-keyword-arg`, `--syn-docstring`, `--syn-predefined` | `PY.SELF_PARAMETER`, `PY.KEYWORD_ARGUMENT`, `PY.DOC_COMMENT`, `PY.BUILTIN_NAME` | | `--ansi-*` | `CONSOLE_*_OUTPUT` (`CONSOLE_DARKGRAY_OUTPUT` is bright black, `CONSOLE_GRAY_OUTPUT` white) | -The full tables are `ICLS_COLORS` and `ICLS_ATTRIBUTES` in the same file. +The full tables are `ICLS_COLORS` and `ICLS_ATTRIBUTES` in the same file. An +attribute written as `` has no colours of its own and shows as plain +text (`TEXT`'s foreground), as in IntelliJ, not with the parent scheme's colour. ### From VS Code (by hand) diff --git a/scripts/theme/theme.test.ts b/scripts/theme/theme.test.ts index 4e340c609..404d99096 100644 --- a/scripts/theme/theme.test.ts +++ b/scripts/theme/theme.test.ts @@ -91,6 +91,8 @@ describe("IntelliJ theme import", () => { "Button": { "default": { "startBackground": "accent" } }, "Popup.background": "#181f28", "Label.infoForeground": "#80888F80", + "EditorTabs": { "underlineColor": "#405060", "underlinedBorderColor": "#bd93f9" }, + "CompletionPopup.matchForeground": "#ff79c6", "Tree": { "rowHeight": 24 } } }`; @@ -99,6 +101,7 @@ describe("IntelliJ theme import", () => { `; @@ -138,6 +144,9 @@ describe("IntelliJ theme import", () => { expect(t.tokens["--bg-selected"]).toBe("#203040"); expect(t.tokens["--fg-muted"]).toBe("#80888f80"); expect(t.tokens["--fg"]).toBe("#c0c8d0"); + // Islands borders the selected tab with underlinedBorderColor. + expect(t.tokens["--border-tab-selected"]).toBe("#bd93f9"); + expect(t.tokens["--fg-completion-match"]).toBe("#ff79c6"); expect(s).toBeNull(); }); @@ -165,9 +174,12 @@ describe("IntelliJ theme import", () => { "--syn-comment-style": "italic", "--fg-editor": "#a9b7c6", "--bg-editor": "#2b2b2b", + // GUTTER_BACKGROUND is the classic UI's: the gutter keeps the editor's background. "--bg-editor-gutter": "#2b2b2b", "--wave-error": "#ff0000", "--editor-error-decoration": "underline wavy #ff0000", + // : plain text, not the parent scheme's colour. + "--syn-property": "#a9b7c6", }); expect(s.tokens["--syn-constant"]).toBeUndefined(); }); diff --git a/src/features/plugins/intellijTheme.ts b/src/features/plugins/intellijTheme.ts index 0d345f3fe..963b80efe 100644 --- a/src/features/plugins/intellijTheme.ts +++ b/src/features/plugins/intellijTheme.ts @@ -53,7 +53,8 @@ export const UI_KEYS: Record = { "--bg-checkbox": ["Checkbox.Background.Default"], "--border-checkbox": ["Checkbox.Border.Default"], "--bg-tab-selected": ["EditorTabs.underlinedTabBackground", "EditorTabs.selectedBackground"], - "--border-tab-selected": ["EditorTabs.underlineColor"], + // Islands paints the selected tab's border with `underlinedBorderColor`; the classic tabs underline with `underlineColor`. + "--border-tab-selected": ["EditorTabs.underlinedBorderColor", "EditorTabs.underlineColor"], "--bg-tab-hover": ["EditorTabs.hoverBackground"], "--border-editor-tabs": ["EditorTabs.borderColor"], "--bg-toolbar-hover": ["ActionButton.hoverBackground"], @@ -66,6 +67,7 @@ export const UI_KEYS: Record = { "--bg-counter": ["Counter.background"], "--fg-counter": ["Counter.foreground"], "--bg-search-match": ["SearchMatch.startBackground", "SearchMatch.endBackground"], + "--fg-completion-match": ["CompletionPopup.matchForeground"], "--bg-toggle-on": ["ToggleButton.onBackground"], "--fg-toggle-on": ["ToggleButton.onForeground"], "--bg-toggle-off": ["ToggleButton.offBackground"], @@ -89,7 +91,8 @@ export const ICLS_COLORS: Record = { SELECTION_BACKGROUND: ["--bg-editor-selection"], LINE_NUMBERS_COLOR: ["--fg-line-number"], LINE_NUMBER_ON_CARET_ROW_COLOR: ["--fg-line-number-current"], - GUTTER_BACKGROUND: ["--bg-editor-gutter"], + // The new UI paints the gutter with this, else with the editor's background; `GUTTER_BACKGROUND` is the classic UI's. + EDITOR_GUTTER_BACKGROUND: ["--bg-editor-gutter"], INDENT_GUIDE: ["--border-indent-guide"], SELECTED_INDENT_GUIDE: ["--border-indent-guide-active"], RIGHT_MARGIN_COLOR: ["--border-right-margin"], @@ -244,19 +247,33 @@ export function convertIcls(xml: string): { name: string; dark: boolean | null; if (key && value !== undefined && ICLS_COLORS[key]) set(ICLS_COLORS[key], iclsColor(value)); } - const attributes = /([\s\S]*?)<\/attributes>/.exec(xml)?.[1] ?? ""; - for (const m of attributes.matchAll(/