feat: give column data types a dedicated syntax-highlight colour

Both Node::Ident and Word carried a highlight_override field, and
both were dead — the walker driver discarded the Ident's and
walk_word hardcoded Keyword. So column types (int, serial, …)
rendered identically to table/column names.

Wire both overrides through, and add a dedicated HighlightClass::Type
with its own theme colour (tok_type), distinct from keyword-purple
and identifier-teal. The three type Ident slots opt in, so canonical
types and the advanced-mode single-word SQL aliases (float, varchar,
…) render as types; the two-word `double precision` alias opts in via
a new Word::type_keyword constructor. ADR-0022 Amendment 4.
This commit is contained in:
claude@clouddev1
2026-05-29 22:07:18 +00:00
parent 46a31284c5
commit d20f765325
10 changed files with 195 additions and 13 deletions
+22
View File
@@ -51,6 +51,11 @@ pub struct Theme {
// ---- Per-token-class colours (ADR-0022 §3) -------------------
pub tok_keyword: Color,
pub tok_identifier: Color,
/// Column data-type keyword colour (ADR-0022 Amendment 4) —
/// a dedicated tone distinct from both `tok_keyword` and
/// `tok_identifier` so a learner can tell a type from a
/// clause keyword or an invented name at a glance.
pub tok_type: Color,
pub tok_number: Color,
pub tok_string: Color,
pub tok_punct: Color,
@@ -84,6 +89,7 @@ impl Theme {
// distinct from the mode-banner blue.
tok_keyword: Color::Rgb(0xC7, 0x92, 0xEA), // muted purple
tok_identifier: Color::Rgb(0x56, 0xB6, 0xC2), // cyan-teal — identifiers are the user's content, deserve a vivid distinct colour
tok_type: Color::Rgb(0xF0, 0x8F, 0xC0), // pink — types sit in the red-purple range, clearly apart from the lavender keyword and teal identifier
tok_number: Color::Rgb(0xF7, 0x8C, 0x6C), // warm orange
tok_string: Color::Rgb(0xC3, 0xE8, 0x8D), // soft green
tok_punct: Color::Rgb(0x8B, 0x90, 0x9A), // == muted
@@ -113,6 +119,7 @@ impl Theme {
// literals + flags; cool accent for keyword.
tok_keyword: Color::Rgb(0x6F, 0x42, 0xC1), // royal purple
tok_identifier: Color::Rgb(0x0F, 0x6B, 0x76), // deep teal — same role as dark variant: identifiers stand out
tok_type: Color::Rgb(0xA8, 0x2D, 0x73), // deep magenta — red-purple, distinct from royal-purple keyword + teal identifier
tok_number: Color::Rgb(0xBC, 0x4F, 0x1F), // burnt orange
tok_string: Color::Rgb(0x22, 0x86, 0x3A), // forest green
tok_punct: Color::Rgb(0x60, 0x66, 0x73), // == muted
@@ -132,6 +139,7 @@ impl Theme {
match class {
HighlightClass::Keyword => self.tok_keyword,
HighlightClass::Identifier => self.tok_identifier,
HighlightClass::Type => self.tok_type,
HighlightClass::Number => self.tok_number,
HighlightClass::String => self.tok_string,
HighlightClass::Punct => self.tok_punct,
@@ -156,6 +164,7 @@ mod tests {
let t = Theme::dark();
for (name, c) in [
("tok_keyword", t.tok_keyword),
("tok_type", t.tok_type),
("tok_number", t.tok_number),
("tok_string", t.tok_string),
("tok_flag", t.tok_flag),
@@ -174,6 +183,7 @@ mod tests {
let t = Theme::light();
for (name, c) in [
("tok_keyword", t.tok_keyword),
("tok_type", t.tok_type),
("tok_number", t.tok_number),
("tok_string", t.tok_string),
("tok_flag", t.tok_flag),
@@ -192,10 +202,22 @@ mod tests {
let t = Theme::dark();
assert_eq!(t.highlight_class_color(HighlightClass::Keyword), t.tok_keyword);
assert_eq!(t.highlight_class_color(HighlightClass::Identifier), t.tok_identifier);
assert_eq!(t.highlight_class_color(HighlightClass::Type), t.tok_type);
assert_eq!(t.highlight_class_color(HighlightClass::Number), t.tok_number);
assert_eq!(t.highlight_class_color(HighlightClass::String), t.tok_string);
assert_eq!(t.highlight_class_color(HighlightClass::Punct), t.tok_punct);
assert_eq!(t.highlight_class_color(HighlightClass::Flag), t.tok_flag);
assert_eq!(t.highlight_class_color(HighlightClass::Error), t.tok_error);
}
#[test]
fn type_colour_is_distinct_from_keyword_and_identifier() {
// ADR-0022 Amendment 4 / issue #8: the whole point of a
// dedicated type class is that types do NOT share a colour
// with clause keywords or invented identifiers.
for t in [Theme::dark(), Theme::light()] {
assert_ne!(t.tok_type, t.tok_keyword);
assert_ne!(t.tok_type, t.tok_identifier);
}
}
}