177 lines
5.6 KiB
Rust
177 lines
5.6 KiB
Rust
//! Paint-only syntax colors, ported from bezel
|
|
//! (`crates/theme/src/theme/syntax.rs`, MIT License, Copyright (c) 2026 bezel
|
|
//! contributors). The hues follow the Git history graph's lane palette
|
|
//! (indigo, pink, emerald, amber, red, neutral), while light-mode variants are
|
|
//! darkened enough to remain readable as text on white.
|
|
|
|
use gpui::Hsla;
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::color;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
|
pub struct SyntaxPalette {
|
|
pub comment: Hsla,
|
|
pub keyword: Hsla,
|
|
pub string: Hsla,
|
|
pub string_special: Hsla,
|
|
pub escape: Hsla,
|
|
pub number: Hsla,
|
|
pub boolean: Hsla,
|
|
pub type_name: Hsla,
|
|
pub type_builtin: Hsla,
|
|
pub constructor: Hsla,
|
|
pub function: Hsla,
|
|
pub function_builtin: Hsla,
|
|
pub macro_name: Hsla,
|
|
pub property: Hsla,
|
|
pub constant: Hsla,
|
|
pub variable: Hsla,
|
|
pub variable_special: Hsla,
|
|
pub parameter: Hsla,
|
|
pub operator: Hsla,
|
|
pub punctuation: Hsla,
|
|
pub tag: Hsla,
|
|
pub attribute: Hsla,
|
|
pub label: Hsla,
|
|
pub invalid: Hsla,
|
|
}
|
|
|
|
/// The token category a highlighter paints with, mirroring [`SyntaxPalette`]
|
|
/// field-for-field so classification can name a kind without knowing its color.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum HighlightKind {
|
|
Comment,
|
|
Keyword,
|
|
String,
|
|
StringSpecial,
|
|
Escape,
|
|
Number,
|
|
Boolean,
|
|
TypeName,
|
|
TypeBuiltin,
|
|
Constructor,
|
|
Function,
|
|
FunctionBuiltin,
|
|
MacroName,
|
|
Property,
|
|
Constant,
|
|
Variable,
|
|
VariableSpecial,
|
|
Parameter,
|
|
Operator,
|
|
Punctuation,
|
|
Tag,
|
|
Attribute,
|
|
Label,
|
|
Invalid,
|
|
}
|
|
|
|
impl SyntaxPalette {
|
|
/// The palette color for a token kind.
|
|
pub fn color(&self, kind: HighlightKind) -> Hsla {
|
|
match kind {
|
|
HighlightKind::Comment => self.comment,
|
|
HighlightKind::Keyword => self.keyword,
|
|
HighlightKind::String => self.string,
|
|
HighlightKind::StringSpecial => self.string_special,
|
|
HighlightKind::Escape => self.escape,
|
|
HighlightKind::Number => self.number,
|
|
HighlightKind::Boolean => self.boolean,
|
|
HighlightKind::TypeName => self.type_name,
|
|
HighlightKind::TypeBuiltin => self.type_builtin,
|
|
HighlightKind::Constructor => self.constructor,
|
|
HighlightKind::Function => self.function,
|
|
HighlightKind::FunctionBuiltin => self.function_builtin,
|
|
HighlightKind::MacroName => self.macro_name,
|
|
HighlightKind::Property => self.property,
|
|
HighlightKind::Constant => self.constant,
|
|
HighlightKind::Variable => self.variable,
|
|
HighlightKind::VariableSpecial => self.variable_special,
|
|
HighlightKind::Parameter => self.parameter,
|
|
HighlightKind::Operator => self.operator,
|
|
HighlightKind::Punctuation => self.punctuation,
|
|
HighlightKind::Tag => self.tag,
|
|
HighlightKind::Attribute => self.attribute,
|
|
HighlightKind::Label => self.label,
|
|
HighlightKind::Invalid => self.invalid,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn dark(text: Hsla, comment: Hsla, danger: Hsla) -> Self {
|
|
let indigo = git_graph_tone(color::oklch(0.673, 0.182, 276.935));
|
|
let pink = git_graph_tone(color::oklch(0.718, 0.202, 349.761));
|
|
let emerald = git_graph_tone(color::oklch(0.765, 0.177, 163.223));
|
|
let amber = git_graph_tone(color::oklch(0.828, 0.189, 84.429));
|
|
let red = git_graph_tone(danger);
|
|
Self {
|
|
comment,
|
|
keyword: indigo,
|
|
string: emerald,
|
|
string_special: pink,
|
|
escape: pink,
|
|
number: amber,
|
|
boolean: amber,
|
|
type_name: amber,
|
|
type_builtin: emerald,
|
|
constructor: amber,
|
|
function: indigo,
|
|
function_builtin: pink,
|
|
macro_name: pink,
|
|
property: amber,
|
|
constant: emerald,
|
|
variable: text,
|
|
variable_special: pink,
|
|
parameter: text,
|
|
operator: text,
|
|
punctuation: text,
|
|
tag: pink,
|
|
attribute: amber,
|
|
label: amber,
|
|
invalid: red,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn light(text: Hsla, comment: Hsla, danger: Hsla) -> Self {
|
|
let indigo = git_graph_tone(color::oklch(0.47, 0.20, 276.966));
|
|
let pink = git_graph_tone(color::oklch(0.47, 0.17, 0.584));
|
|
let emerald = git_graph_tone(color::oklch(0.46, 0.11, 163.225));
|
|
let amber = git_graph_tone(color::oklch(0.47, 0.12, 48.998));
|
|
let red = git_graph_tone(danger);
|
|
Self {
|
|
comment,
|
|
keyword: indigo,
|
|
string: emerald,
|
|
string_special: pink,
|
|
escape: pink,
|
|
number: amber,
|
|
boolean: amber,
|
|
type_name: amber,
|
|
type_builtin: emerald,
|
|
constructor: amber,
|
|
function: indigo,
|
|
function_builtin: pink,
|
|
macro_name: pink,
|
|
property: amber,
|
|
constant: emerald,
|
|
variable: text,
|
|
variable_special: pink,
|
|
parameter: text,
|
|
operator: text,
|
|
punctuation: text,
|
|
tag: pink,
|
|
attribute: amber,
|
|
label: amber,
|
|
invalid: red,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Git history intentionally softens lane saturation so the graph remains
|
|
/// colorful without competing with content. Syntax uses the same treatment.
|
|
fn git_graph_tone(mut color: Hsla) -> Hsla {
|
|
color.s *= 0.72;
|
|
color
|
|
}
|