Compare commits

...
Author SHA1 Message Date
arookieofc c49cd874af test(themes): palette themes inherit selection foreground from base
Solarized/One keep the base default (preserve syntax colours on
selection); record that intent in INHERITED_FROM_BASE.
2026-11-10 18:03:05 +08:00
arookieofc c82e5da0d3 feat(scheme): support a selection foreground colour (#2446)
Settings › Editor › Color Scheme › General › Editor gains a
Selection foreground attribute next to Selection background, wired
to a new --fg-editor-selection token. The editor paints selected
text with it (.cm-openidea-selected, including the diff viewer);
unset it keeps the previous rendering, with syntax colours showing
through (token default: inherit). .icls import/export round trips
it via SELECTION_FOREGROUND.
2026-11-10 18:03:05 +08:00
12 changed files with 71 additions and 5 deletions

No files matched your search

@@ -79,6 +79,7 @@
"--border-right-margin": "#2a313b",
"--bg-editor-selection": "#2d7772",
"--bg-editor-selection-inactive": "#255854",
"--fg-editor-selection": "inherit",
"--bg-text-search-result": "#114957",
"--bg-text-search-result-current": "#165e70",
"--bg-matched-brace": "#38424f",
+4 -3
View File
@@ -214,7 +214,7 @@ The full table is `UI_KEYS` in [`src/features/plugins/intellijTheme.ts`](../src/
|---|---|
| `--fg-editor`, `--bg-editor` | attribute `TEXT` (foreground, background) |
| `--caret`, `--bg-current-line` | colour `CARET_COLOR`, `CARET_ROW_COLOR` |
| `--bg-editor-selection` | colour `SELECTION_BACKGROUND` |
| `--bg-editor-selection`, `--fg-editor-selection` | colour `SELECTION_BACKGROUND`, `SELECTION_FOREGROUND` |
| `--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` |
@@ -268,7 +268,7 @@ from `type`, then map:
| `--fg-editor` | `editor.foreground` |
| `--caret` | `editorCursor.foreground` |
| `--bg-current-line` | `editor.lineHighlightBackground` |
| `--bg-editor-selection`, `--bg-editor-selection-inactive` | `editor.selectionBackground`, `editor.inactiveSelectionBackground` |
| `--bg-editor-selection`, `--bg-editor-selection-inactive`, `--fg-editor-selection` | `editor.selectionBackground`, `editor.inactiveSelectionBackground`, `editor.selectionForeground` |
| `--fg-line-number`, `--fg-line-number-current` | `editorLineNumber.foreground`, `editorLineNumber.activeForeground` |
| `--border-indent-guide`, `--border-indent-guide-active` | `editorIndentGuide.background1`, `editorIndentGuide.activeBackground1` |
| `--fg-whitespace` | `editorWhitespace.foreground` |
@@ -329,7 +329,7 @@ a token.
<!-- BEGIN GENERATED TOKEN REFERENCE: pnpm gen:theme-docs -->
255 themeable tokens: 125 in the UI theme file, 130 in the editor colour scheme file.
256 themeable tokens: 125 in the UI theme file, 131 in the editor colour scheme file.
### Surfaces (UI theme)
@@ -499,6 +499,7 @@ a token.
| `--border-right-margin` | `#323438` | `#ebecf0` |
| `--bg-editor-selection` | `#214283` | `#a6d2ff` |
| `--bg-editor-selection-inactive` | `#1d3460` | `#c9e3ff` |
| `--fg-editor-selection` | `inherit` | `inherit` |
| `--bg-text-search-result` | `#114957` | `#fcd47e` |
| `--bg-text-search-result-current` | `#165e70` | `#f2bf57` |
| `--bg-matched-brace` | `#43454a` | `#93d9d9` |
+11
View File
@@ -159,6 +159,17 @@ describe("IntelliJ theme import", () => {
expect(s).toBeNull();
});
it("maps the selection foreground colour (#2446)", () => {
const s = convertIcls(`<scheme name="Sel" version="142" parent_scheme="Default"><colors>
<option name="SELECTION_BACKGROUND" value="214283" />
<option name="SELECTION_FOREGROUND" value="112233" />
</colors></scheme>`);
expect(s.tokens).toMatchObject({
"--bg-editor-selection": "#214283",
"--fg-editor-selection": "#112233",
});
});
it("only targets tokens that exist in tokens.css", () => {
const declared = new Set([...css.matchAll(/(--[a-z0-9-]+)\s*:/g)].map((m) => m[1]!));
// Read with a fallback by the editor (no tokens.css default), still themeable.
+2
View File
@@ -38,6 +38,8 @@ const plugin = ViewPlugin.fromClass(
const theme = EditorView.baseTheme({
".cm-openidea-selected": {
backgroundColor: "var(--editor-selection-inactive, var(--bg-editor-selection-inactive))",
// Unset (the default `inherit`): the declaration drops and the syntax colours show through.
color: "var(--fg-editor-selection)",
},
"&.cm-focused .cm-openidea-selected": {
backgroundColor: "var(--editor-selection, var(--bg-editor-selection))",
+1
View File
@@ -89,6 +89,7 @@ export const ICLS_COLORS: Record<string, string[]> = {
CARET_COLOR: ["--caret"],
CARET_ROW_COLOR: ["--bg-current-line"],
SELECTION_BACKGROUND: ["--bg-editor-selection"],
SELECTION_FOREGROUND: ["--fg-editor-selection"],
LINE_NUMBERS_COLOR: ["--fg-line-number"],
LINE_NUMBER_ON_CARET_ROW_COLOR: ["--fg-line-number-current"],
// The new UI paints the gutter with this, else with the editor's background; `GUTTER_BACKGROUND` is the classic UI's.
@@ -121,9 +121,11 @@ describe("theme tokens", () => {
/**
* Tokens the palette themes (Solarized, One) take from their light / dark base
* on purpose: colours the user assigns (project and data source colours), the
* platform's caption close and macOS window buttons, and the tint strength.
* platform's caption close and macOS window buttons, the tint strength, and
* the selection foreground, whose base default preserves syntax colours.
*/
const INHERITED_FROM_BASE = /^--(project-color-|db-color-|caption-close-|fg-caption-close-|tint-strength$)/;
const INHERITED_FROM_BASE =
/^--(project-color-|db-color-|caption-close-|fg-caption-close-|tint-strength$|fg-editor-selection$)/;
describe("palette themes", () => {
const ISLANDS = ["light", "dark", "dark-hc"];
+2
View File
@@ -339,6 +339,8 @@ export const viewerTheme = EditorView.theme(
"&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, ::selection, .cm-openidea-selected, &.cm-focused .cm-openidea-selected":
{
backgroundColor: "var(--bg-selected-strong)",
// Unset (the default `inherit`): the declaration drops and the syntax colours show through.
color: "var(--fg-editor-selection)",
},
".cm-activeLine": { backgroundColor: "var(--bg-current-line)" },
".cm-gutters": {
+24
View File
@@ -116,6 +116,30 @@ describe("color schemes", () => {
expect(pythonItalic).toContain("--syn-python-static-italic: italic !important");
});
it("leaves selected text in syntax colours until a selection foreground is set (#2446)", () => {
expect(ATTRIBUTES.find((a) => a.id === "selectionForeground")).toMatchObject({
name: "Selection foreground",
path: ["General", "Editor"],
fg: "--fg-editor-selection",
});
// The `inherit` default is not a colour: the settings page shows no foreground.
expect(resolvedAttribute("light", "selectionForeground")).toEqual({});
expect(resolvedAttribute("dark", "selectionForeground")).toEqual({});
const customs = {
"custom-sel": {
name: "Sel",
parent: "dark" as const,
attributes: { selectionForeground: { foreground: "#112233" } },
},
};
expect(resolvedAttribute("custom-sel", "selectionForeground", customs)).toMatchObject({
foreground: "#112233",
});
expect(schemeCss("dark", { dark: { selectionForeground: { foreground: "#112233" } } })).toContain(
"--fg-editor-selection: #112233 !important",
);
});
it("applies an explicit scheme over a plugin theme of the same base", () => {
const root = document.documentElement;
root.dataset.theme = "dark";
+6
View File
@@ -61,6 +61,12 @@ const BASE_ATTRIBUTES: readonly AttributeDef[] = [
{ id: "caret", name: "Caret", path: ["General", "Editor"], fg: "--caret" },
{ id: "caretRow", name: "Caret row", path: ["General", "Editor"], bg: "--bg-current-line" },
{ id: "selection", name: "Selection background", path: ["General", "Editor"], bg: "--bg-editor-selection" },
{
id: "selectionForeground",
name: "Selection foreground",
path: ["General", "Editor"],
fg: "--fg-editor-selection",
},
{
id: "selectionInactive",
name: "Selection background (inactive)",
+13
View File
@@ -34,6 +34,19 @@ describe(".icls schemes", () => {
expect(parseIcls(xml).scheme.attributes).toMatchObject(scheme.attributes);
});
it("round trips the selection foreground through SELECTION_FOREGROUND (#2446)", () => {
const { scheme } = parseIcls(`<scheme name="Sel" parent_scheme="Default"><colors>
<option name="SELECTION_BACKGROUND" value="214283"/>
<option name="SELECTION_FOREGROUND" value="ffffff"/>
</colors></scheme>`);
expect(scheme.attributes.selection).toEqual({ background: "#214283" });
expect(scheme.attributes.selectionForeground).toEqual({ foreground: "#ffffff" });
const { id, customs } = importScheme({}, scheme);
const xml = exportIcls(id, customs);
expect(xml).toContain('<option name="SELECTION_FOREGROUND" value="ffffff" />');
expect(parseIcls(xml).scheme.attributes.selectionForeground).toEqual({ foreground: "#ffffff" });
});
it("resolves explicit attribute inheritance independent of XML order and stops cycles", () => {
const { scheme } = parseIcls(`<scheme name="Inherited"><attributes>
<option name="PHP_PARAMETER" baseAttributes="PHP_VAR"/>
+1
View File
@@ -179,6 +179,7 @@ const COLOR_NAMES: Record<string, [string, "foreground" | "background"]> = {
CARET_COLOR: ["caret", "foreground"],
CARET_ROW_COLOR: ["caretRow", "background"],
SELECTION_BACKGROUND: ["selection", "background"],
SELECTION_FOREGROUND: ["selectionForeground", "foreground"],
INACTIVE_SELECTION_BACKGROUND: ["selectionInactive", "background"],
GUTTER_BACKGROUND: ["gutter", "background"],
LINE_NUMBERS_COLOR: ["lineNumber", "foreground"],
+2
View File
@@ -184,6 +184,7 @@ html {
--border-right-margin: #323438;
--bg-editor-selection: #214283;
--bg-editor-selection-inactive: #1d3460;
--fg-editor-selection: inherit;
--bg-text-search-result: #114957;
--bg-text-search-result-current: #165e70;
--bg-matched-brace: #43454a;
@@ -599,6 +600,7 @@ html {
--border-right-margin: #ebecf0;
--bg-editor-selection: #a6d2ff;
--bg-editor-selection-inactive: #c9e3ff;
--fg-editor-selection: inherit;
--bg-text-search-result: #fcd47e;
--bg-text-search-result-current: #f2bf57;
--bg-matched-brace: #93d9d9;