From 2b95e5fb14e3fd334ea30f543c0a293a13ecb0c7 Mon Sep 17 00:00:00 2001 From: Beyond <46542494+crypticpy@users.noreply.github.com> Date: Tue, 18 Aug 2026 01:30:32 -0500 Subject: [PATCH] feat(scopes): diff/log/preprocessor/constants/labels/strikethrough/support coverage New tokenColors rules and semantic selectors in base.yaml, all bound to existing role tokens (no new hexes, parity unchanged). Snapshot test now checks additions-only structural coverage. samples/demo.{diff,log} added (.gitignore negation for the .log sample). Co-Authored-By: Claude Fable 5 --- .gitignore | 3 + CHANGELOG.md | 14 ++ samples/demo.diff | 13 ++ samples/demo.log | 6 + themes/_src/base.yaml | 134 +++++++++++++++++ themes/alone-color-theme.json | 200 +++++++++++++++++++++++++- themes/alone-focused-color-theme.json | 200 +++++++++++++++++++++++++- themes/alone-soft-color-theme.json | 200 +++++++++++++++++++++++++- 8 files changed, 767 insertions(+), 3 deletions(-) create mode 100644 samples/demo.diff create mode 100644 samples/demo.log diff --git a/.gitignore b/.gitignore index ab306e5..dc10099 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ Thumbs.db *.log *.zip .claude/ + +# sample files for theme preview are tracked even though *.log is ignored +!samples/demo.log diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fe2170..330fb24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,20 @@ The first palette change since 1.0. Everything below was made in `themes/_src/va - **ANSI blue and cyan.** Blue is now a warm gray `#9C948E` (was `#8B8178`, Lc 36 → 45 — `ls`, `grep`, `man` output on black is readable again) and cyan is the terracotta already used for functions, `#C08868` (was `#9A8B7A`). The two former slots were near-identical warm grays (ΔE2000 5.2, indistinguishable under CVD); every pair among the eight normal slots is now ≥ ΔE2000 10 (min 13.6). Bright slots follow: `#A89A8C→#B2AAA3`, `#B8A898→#CEA284`. Black/red/green/yellow/magenta unchanged. Kitty, iTerm2, Alacritty (normal + dim) and Windows Terminal files updated to match. - **`themes/_snapshot/`** stays as the immutable v1.2.0 reference; the pipeline test now checks structural coverage — every snapshot colour key, tokenColors rule (name/scope/fontStyle) and semantic selector is still present and styled the same, additions allowed — rather than hex equality. +### Added — Scope coverage (all variants, no new hexes) + +New `tokenColors` rules and `semanticTokenColors` selectors in `themes/_src/base.yaml`, each bound to an existing role token so every variant inherits it and key parity holds: + +- **Diffs / patches**: `markup.inserted` / `markup.deleted` / `markup.changed` take the git-decoration added/deleted/modified colours; `meta.diff.header` (`---`/`+++`/`index`) in doc-comment gray; `meta.diff.range` (`@@ … @@`) in keyword gold, non-bold. `samples/demo.diff` added. +- **Log files**: `token.info-token` / `token.warn-token` / `token.error-token` / `token.debug-token` take the debug-console info/warning/error/source colours (error bold). `samples/demo.log` added. +- **Preprocessor**: `keyword.control.directive` + `punctuation.definition.directive` (so `#` is coloured with `include`/`define`) in keyword gold bold; `entity.name.function.preprocessor` / `entity.name.function.macro` in the macro colour, bold (matches Rust macros). +- **ALL_CAPS constants**: `variable.other.constant`, `constant.other.caps`, `variable.other.enummember` in the constants colour (previously fell through to plain variables). +- **Labels**: `entity.name.label`, `entity.name.goto-label` in the semantic `label` colour. +- **Markdown strikethrough**: `markup.strikethrough` gets `strikethrough` + the deprecated gray. +- **Support variables** (`document`, `window`, `process`, `console`…): `support.variable*` in the `defaultLibrary` colour, italic — same treatment as semantic `*.defaultLibrary`. +- **Semantic selectors**: `selfParameter` / `clsParameter` (= `this`/`self`/`super`), `magicFunction` (= Python magic methods), `builtinConstant` and `boolean` (= number/boolean colour), `builtinType` (= `type.defaultLibrary`, italic), `lifetime`, `attribute`, `derive` (= Rust lifetime/attribute colours, italic), `formatSpecifier` (= f-string braces), `escapeSequence` (= escapes, bold), `event` (= property). +- The pipeline test now checks that everything the v1.2.0 snapshot styled is still styled the same way (additions allowed, drops/restyles fail). + ### Changed — Internal: verifier v2, tests, CI - **Verifier v2** (`scripts/verify-palette.mjs`). New checks alongside the L\* ladder, wavelength band, and key parity: an **APCA Lc** column and per-role floors (body 60 / syntax 40 / special 37 / punctuation 28 / comments 22, overridable per variant via `verify.apcaFloors` — Alone Soft declares a scaled set); **ΔE2000** on every tight ladder gap; a **colour-vision-deficiency** table (Viénot protan/deutan/tritan simulation) over the ten most confusable role pairs, passing on ΔE2000 ≥ 5 or a font-style difference; **ANSI** pairwise ΔE2000 among the eight normal terminal slots (≥ 10); and a **whole-theme wavelength scan** — every chromatic hex in every variant, not just the ten headline roles, must have a dominant wavelength ≥ 575 nm. The perceptual checks were introduced as warnings against the 1.3.1 palette (which missed several — comments Lc 16, ANSI blue/cyan ΔE 5.2, Variables/Parameter under CVD) and are hard failures from 2.0.0. Each check's severity is a one-line `POLICY` entry. diff --git a/samples/demo.diff b/samples/demo.diff new file mode 100644 index 0000000..cf95f38 --- /dev/null +++ b/samples/demo.diff @@ -0,0 +1,13 @@ +diff --git a/src/palette.ts b/src/palette.ts +index 3f2a1c0..9b7e4d2 100644 +--- a/src/palette.ts ++++ b/src/palette.ts +@@ -12,7 +12,9 @@ export const COMMENTS = '#5C544A'; +-export const COMMENTS = '#5C544A'; ++export const COMMENTS = '#6E665B'; // APCA Lc 23 + export const KEYWORDS = '#C8A040'; +-export const ANSI_BLUE = '#8B8178'; +-export const ANSI_CYAN = '#9A8B7A'; ++export const ANSI_BLUE = '#9C948E'; ++export const ANSI_CYAN = '#C08868'; + export const FOREGROUND = '#C8B89A'; diff --git a/samples/demo.log b/samples/demo.log new file mode 100644 index 0000000..30d4ab8 --- /dev/null +++ b/samples/demo.log @@ -0,0 +1,6 @@ +2026-08-18T01:30:12.004Z [INFO] server listening on :3000 +2026-08-18T01:30:12.118Z [DEBUG] loaded 3 theme variants (alone, alone-soft, alone-focused) +2026-08-18T01:30:14.902Z [WARN] slow request GET /api/palette took 1843ms +2026-08-18T01:30:15.007Z [ERROR] verify-palette: README tables out of date + at check (scripts/verify-palette.mjs:412:9) +2026-08-18T01:30:15.010Z [INFO] rebuild complete diff --git a/themes/_src/base.yaml b/themes/_src/base.yaml index 7cd5f63..c638c0b 100644 --- a/themes/_src/base.yaml +++ b/themes/_src/base.yaml @@ -86,6 +86,36 @@ semanticTokenColors: foreground: ${semanticTokenColors.*.modification.foreground} "*.async": italic: true + # ── Coverage additions (2.0.0): every selector below is bound to an existing + # role token so all variants inherit it and key parity is unaffected. ── + selfParameter: + foreground: ${tokenColors.special_variables_this_self_super.settings.foreground} + italic: true + clsParameter: + foreground: ${tokenColors.special_variables_this_self_super.settings.foreground} + italic: true + magicFunction: + foreground: ${tokenColors.python_magic_methods.settings.foreground} + italic: true + builtinConstant: ${tokenColors.boolean_null_constants.settings.foreground} + boolean: ${tokenColors.boolean_null_constants.settings.foreground} + builtinType: + foreground: ${semanticTokenColors.type.defaultLibrary.foreground} + italic: true + lifetime: + foreground: ${tokenColors.rust_lifetime.settings.foreground} + italic: true + attribute: + foreground: ${tokenColors.rust_attributes.settings.foreground} + italic: true + derive: + foreground: ${tokenColors.rust_attributes.settings.foreground} + italic: true + formatSpecifier: ${tokenColors.python_f_string_braces.settings.foreground} + escapeSequence: + foreground: ${tokenColors.escape_characters.settings.foreground} + bold: true + event: ${semanticTokenColors.property} tokenColors: - name: Comments scope: @@ -599,6 +629,110 @@ tokenColors: settings: foreground: ${tokenColors.invalid_deprecated.settings.foreground} fontStyle: strikethrough + # ── Coverage additions (2.0.0): diffs, logs, preprocessor, constants, + # labels, strikethrough, support variables. All bound to existing tokens. ── + - name: Diff Inserted + scope: + - markup.inserted + - markup.inserted.diff + - punctuation.definition.inserted.diff + settings: + foreground: ${colors.gitDecoration.addedResourceForeground} + - name: Diff Deleted + scope: + - markup.deleted + - markup.deleted.diff + - punctuation.definition.deleted.diff + settings: + foreground: ${colors.gitDecoration.deletedResourceForeground} + - name: Diff Changed + scope: + - markup.changed + - markup.changed.diff + - punctuation.definition.changed.diff + settings: + foreground: ${colors.gitDecoration.modifiedResourceForeground} + - name: Diff Headers + scope: + - meta.diff.header + - meta.diff.header.from-file + - meta.diff.header.to-file + - meta.diff.index + - punctuation.definition.from-file.diff + - punctuation.definition.to-file.diff + settings: + foreground: ${tokenColors.documentation_comments.settings.foreground} + - name: Diff Ranges + scope: + - meta.diff.range + - punctuation.definition.range.diff + settings: + foreground: ${tokenColors.keywords.settings.foreground} + fontStyle: "" + - name: Log Info + scope: + - token.info-token + settings: + foreground: ${colors.debugConsole.infoForeground} + - name: Log Warning + scope: + - token.warn-token + settings: + foreground: ${colors.debugConsole.warningForeground} + - name: Log Error + scope: + - token.error-token + settings: + foreground: ${colors.debugConsole.errorForeground} + fontStyle: bold + - name: Log Debug + scope: + - token.debug-token + settings: + foreground: ${colors.debugConsole.sourceForeground} + - name: Preprocessor Directives + scope: + - keyword.control.directive + - punctuation.definition.directive + settings: + foreground: ${tokenColors.keywords.settings.foreground} + fontStyle: bold + - name: Preprocessor Macros + scope: + - entity.name.function.preprocessor + - entity.name.function.macro + settings: + foreground: ${tokenColors.rust_macros.settings.foreground} + fontStyle: bold + - name: Constants (ALL_CAPS) + scope: + - variable.other.constant + - constant.other.caps + - variable.other.enummember + settings: + foreground: ${tokenColors.other_constants.settings.foreground} + - name: Labels + scope: + - entity.name.label + - entity.name.goto-label + settings: + foreground: ${semanticTokenColors.label} + - name: Markdown Strikethrough + scope: + - markup.strikethrough + - punctuation.definition.strikethrough.markdown + settings: + foreground: ${tokenColors.invalid_deprecated.settings.foreground} + fontStyle: strikethrough + - name: Support Variables (globals, DOM) + scope: + - support.variable + - support.variable.property + - support.variable.dom + - support.variable.object.process + settings: + foreground: ${semanticTokenColors.variable.defaultLibrary.foreground} + fontStyle: italic colors: foreground: ${colors.foreground} disabledForeground: ${colors.disabledForeground} diff --git a/themes/alone-color-theme.json b/themes/alone-color-theme.json index 8f09f9a..475716e 100644 --- a/themes/alone-color-theme.json +++ b/themes/alone-color-theme.json @@ -96,7 +96,43 @@ }, "*.async": { "italic": true - } + }, + "selfParameter": { + "foreground": "#B08C50", + "italic": true + }, + "clsParameter": { + "foreground": "#B08C50", + "italic": true + }, + "magicFunction": { + "foreground": "#A87878", + "italic": true + }, + "builtinConstant": "#DEA64E", + "boolean": "#DEA64E", + "builtinType": { + "foreground": "#BC9858", + "italic": true + }, + "lifetime": { + "foreground": "#A87878", + "italic": true + }, + "attribute": { + "foreground": "#A87878", + "italic": true + }, + "derive": { + "foreground": "#A87878", + "italic": true + }, + "formatSpecifier": "#C4A078", + "escapeSequence": { + "foreground": "#D4B088", + "bold": true + }, + "event": "#C8B89A" }, "tokenColors": [ { @@ -902,6 +938,168 @@ "foreground": "#7C7262", "fontStyle": "strikethrough" } + }, + { + "name": "Diff Inserted", + "scope": [ + "markup.inserted", + "markup.inserted.diff", + "punctuation.definition.inserted.diff" + ], + "settings": { + "foreground": "#9A8B60" + } + }, + { + "name": "Diff Deleted", + "scope": [ + "markup.deleted", + "markup.deleted.diff", + "punctuation.definition.deleted.diff" + ], + "settings": { + "foreground": "#B85450" + } + }, + { + "name": "Diff Changed", + "scope": [ + "markup.changed", + "markup.changed.diff", + "punctuation.definition.changed.diff" + ], + "settings": { + "foreground": "#D4A048" + } + }, + { + "name": "Diff Headers", + "scope": [ + "meta.diff.header", + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "meta.diff.index", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#787062" + } + }, + { + "name": "Diff Ranges", + "scope": [ + "meta.diff.range", + "punctuation.definition.range.diff" + ], + "settings": { + "foreground": "#C8A040", + "fontStyle": "" + } + }, + { + "name": "Log Info", + "scope": [ + "token.info-token" + ], + "settings": { + "foreground": "#B89860" + } + }, + { + "name": "Log Warning", + "scope": [ + "token.warn-token" + ], + "settings": { + "foreground": "#D4A048" + } + }, + { + "name": "Log Error", + "scope": [ + "token.error-token" + ], + "settings": { + "foreground": "#D46A66", + "fontStyle": "bold" + } + }, + { + "name": "Log Debug", + "scope": [ + "token.debug-token" + ], + "settings": { + "foreground": "#9D9078" + } + }, + { + "name": "Preprocessor Directives", + "scope": [ + "keyword.control.directive", + "punctuation.definition.directive" + ], + "settings": { + "foreground": "#C8A040", + "fontStyle": "bold" + } + }, + { + "name": "Preprocessor Macros", + "scope": [ + "entity.name.function.preprocessor", + "entity.name.function.macro" + ], + "settings": { + "foreground": "#E8B850", + "fontStyle": "bold" + } + }, + { + "name": "Constants (ALL_CAPS)", + "scope": [ + "variable.other.constant", + "constant.other.caps", + "variable.other.enummember" + ], + "settings": { + "foreground": "#D4A878" + } + }, + { + "name": "Labels", + "scope": [ + "entity.name.label", + "entity.name.goto-label" + ], + "settings": { + "foreground": "#E8B850" + } + }, + { + "name": "Markdown Strikethrough", + "scope": [ + "markup.strikethrough", + "punctuation.definition.strikethrough.markdown" + ], + "settings": { + "foreground": "#7C7262", + "fontStyle": "strikethrough" + } + }, + { + "name": "Support Variables (globals, DOM)", + "scope": [ + "support.variable", + "support.variable.property", + "support.variable.dom", + "support.variable.object.process" + ], + "settings": { + "foreground": "#B08C50", + "fontStyle": "italic" + } } ], "colors": { diff --git a/themes/alone-focused-color-theme.json b/themes/alone-focused-color-theme.json index 0d2ea63..13694ba 100644 --- a/themes/alone-focused-color-theme.json +++ b/themes/alone-focused-color-theme.json @@ -96,7 +96,43 @@ }, "*.async": { "italic": true - } + }, + "selfParameter": { + "foreground": "#B08C50", + "italic": true + }, + "clsParameter": { + "foreground": "#B08C50", + "italic": true + }, + "magicFunction": { + "foreground": "#A87878", + "italic": true + }, + "builtinConstant": "#DEA64E", + "boolean": "#DEA64E", + "builtinType": { + "foreground": "#BC9858", + "italic": true + }, + "lifetime": { + "foreground": "#A87878", + "italic": true + }, + "attribute": { + "foreground": "#A87878", + "italic": true + }, + "derive": { + "foreground": "#A87878", + "italic": true + }, + "formatSpecifier": "#C4A078", + "escapeSequence": { + "foreground": "#D4B088", + "bold": true + }, + "event": "#C8B89A" }, "tokenColors": [ { @@ -902,6 +938,168 @@ "foreground": "#7C7262", "fontStyle": "strikethrough" } + }, + { + "name": "Diff Inserted", + "scope": [ + "markup.inserted", + "markup.inserted.diff", + "punctuation.definition.inserted.diff" + ], + "settings": { + "foreground": "#9A8B60" + } + }, + { + "name": "Diff Deleted", + "scope": [ + "markup.deleted", + "markup.deleted.diff", + "punctuation.definition.deleted.diff" + ], + "settings": { + "foreground": "#B85450" + } + }, + { + "name": "Diff Changed", + "scope": [ + "markup.changed", + "markup.changed.diff", + "punctuation.definition.changed.diff" + ], + "settings": { + "foreground": "#D4A048" + } + }, + { + "name": "Diff Headers", + "scope": [ + "meta.diff.header", + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "meta.diff.index", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#787062" + } + }, + { + "name": "Diff Ranges", + "scope": [ + "meta.diff.range", + "punctuation.definition.range.diff" + ], + "settings": { + "foreground": "#C8A040", + "fontStyle": "" + } + }, + { + "name": "Log Info", + "scope": [ + "token.info-token" + ], + "settings": { + "foreground": "#B89860" + } + }, + { + "name": "Log Warning", + "scope": [ + "token.warn-token" + ], + "settings": { + "foreground": "#D4A048" + } + }, + { + "name": "Log Error", + "scope": [ + "token.error-token" + ], + "settings": { + "foreground": "#D46A66", + "fontStyle": "bold" + } + }, + { + "name": "Log Debug", + "scope": [ + "token.debug-token" + ], + "settings": { + "foreground": "#7C7262" + } + }, + { + "name": "Preprocessor Directives", + "scope": [ + "keyword.control.directive", + "punctuation.definition.directive" + ], + "settings": { + "foreground": "#C8A040", + "fontStyle": "bold" + } + }, + { + "name": "Preprocessor Macros", + "scope": [ + "entity.name.function.preprocessor", + "entity.name.function.macro" + ], + "settings": { + "foreground": "#E8B850", + "fontStyle": "bold" + } + }, + { + "name": "Constants (ALL_CAPS)", + "scope": [ + "variable.other.constant", + "constant.other.caps", + "variable.other.enummember" + ], + "settings": { + "foreground": "#D4A878" + } + }, + { + "name": "Labels", + "scope": [ + "entity.name.label", + "entity.name.goto-label" + ], + "settings": { + "foreground": "#E8B850" + } + }, + { + "name": "Markdown Strikethrough", + "scope": [ + "markup.strikethrough", + "punctuation.definition.strikethrough.markdown" + ], + "settings": { + "foreground": "#7C7262", + "fontStyle": "strikethrough" + } + }, + { + "name": "Support Variables (globals, DOM)", + "scope": [ + "support.variable", + "support.variable.property", + "support.variable.dom", + "support.variable.object.process" + ], + "settings": { + "foreground": "#B08C50", + "fontStyle": "italic" + } } ], "colors": { diff --git a/themes/alone-soft-color-theme.json b/themes/alone-soft-color-theme.json index 8d41e2f..4ed405c 100644 --- a/themes/alone-soft-color-theme.json +++ b/themes/alone-soft-color-theme.json @@ -96,7 +96,43 @@ }, "*.async": { "italic": true - } + }, + "selfParameter": { + "foreground": "#8D7040", + "italic": true + }, + "clsParameter": { + "foreground": "#8D7040", + "italic": true + }, + "magicFunction": { + "foreground": "#866060", + "italic": true + }, + "builtinConstant": "#B38640", + "boolean": "#B38640", + "builtinType": { + "foreground": "#967946", + "italic": true + }, + "lifetime": { + "foreground": "#866060", + "italic": true + }, + "attribute": { + "foreground": "#866060", + "italic": true + }, + "derive": { + "foreground": "#866060", + "italic": true + }, + "formatSpecifier": "#9D8060", + "escapeSequence": { + "foreground": "#AA8D6D", + "bold": true + }, + "event": "#A0937B" }, "tokenColors": [ { @@ -902,6 +938,168 @@ "foreground": "#645B4E", "fontStyle": "strikethrough" } + }, + { + "name": "Diff Inserted", + "scope": [ + "markup.inserted", + "markup.inserted.diff", + "punctuation.definition.inserted.diff" + ], + "settings": { + "foreground": "#7B6F4D" + } + }, + { + "name": "Diff Deleted", + "scope": [ + "markup.deleted", + "markup.deleted.diff", + "punctuation.definition.deleted.diff" + ], + "settings": { + "foreground": "#934440" + } + }, + { + "name": "Diff Changed", + "scope": [ + "markup.changed", + "markup.changed.diff", + "punctuation.definition.changed.diff" + ], + "settings": { + "foreground": "#AA8039" + } + }, + { + "name": "Diff Headers", + "scope": [ + "meta.diff.header", + "meta.diff.header.from-file", + "meta.diff.header.to-file", + "meta.diff.index", + "punctuation.definition.from-file.diff", + "punctuation.definition.to-file.diff" + ], + "settings": { + "foreground": "#6B635A" + } + }, + { + "name": "Diff Ranges", + "scope": [ + "meta.diff.range", + "punctuation.definition.range.diff" + ], + "settings": { + "foreground": "#A08033", + "fontStyle": "" + } + }, + { + "name": "Log Info", + "scope": [ + "token.info-token" + ], + "settings": { + "foreground": "#937A4D" + } + }, + { + "name": "Log Warning", + "scope": [ + "token.warn-token" + ], + "settings": { + "foreground": "#AA8039" + } + }, + { + "name": "Log Error", + "scope": [ + "token.error-token" + ], + "settings": { + "foreground": "#AA5552", + "fontStyle": "bold" + } + }, + { + "name": "Log Debug", + "scope": [ + "token.debug-token" + ], + "settings": { + "foreground": "#7D7360" + } + }, + { + "name": "Preprocessor Directives", + "scope": [ + "keyword.control.directive", + "punctuation.definition.directive" + ], + "settings": { + "foreground": "#A08033", + "fontStyle": "bold" + } + }, + { + "name": "Preprocessor Macros", + "scope": [ + "entity.name.function.preprocessor", + "entity.name.function.macro" + ], + "settings": { + "foreground": "#BA9340", + "fontStyle": "bold" + } + }, + { + "name": "Constants (ALL_CAPS)", + "scope": [ + "variable.other.constant", + "constant.other.caps", + "variable.other.enummember" + ], + "settings": { + "foreground": "#AA8660" + } + }, + { + "name": "Labels", + "scope": [ + "entity.name.label", + "entity.name.goto-label" + ], + "settings": { + "foreground": "#BA9340" + } + }, + { + "name": "Markdown Strikethrough", + "scope": [ + "markup.strikethrough", + "punctuation.definition.strikethrough.markdown" + ], + "settings": { + "foreground": "#645B4E", + "fontStyle": "strikethrough" + } + }, + { + "name": "Support Variables (globals, DOM)", + "scope": [ + "support.variable", + "support.variable.property", + "support.variable.dom", + "support.variable.object.process" + ], + "settings": { + "foreground": "#8D7040", + "fontStyle": "italic" + } } ], "colors": {