feat: syntax highlighting for diff view
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
use crate::colors::{hex, hex_alpha};
|
||||
|
||||
use super::{Theme, ThemeColors, ThemeMode};
|
||||
use super::{
|
||||
Theme, ThemeColors, ThemeMode, ThemeSyntaxHighlight,
|
||||
syntax::{build, key},
|
||||
};
|
||||
|
||||
pub(crate) const FAMILY_ID: &str = "catppuccin";
|
||||
pub(crate) const FAMILY_LABEL: &str = "Catppuccin";
|
||||
@@ -8,7 +11,31 @@ pub(crate) const FAMILY_LABEL: &str = "Catppuccin";
|
||||
pub(crate) const LATTE_LABEL: &str = "Catppuccin Latte";
|
||||
pub(crate) const MOCHA_LABEL: &str = "Catppuccin Mocha";
|
||||
|
||||
pub(crate) const fn latte() -> Theme {
|
||||
const fn highlight(color: u32) -> ThemeSyntaxHighlight {
|
||||
ThemeSyntaxHighlight {
|
||||
color: hex(color),
|
||||
font_style: gpui::FontStyle::Normal,
|
||||
font_weight: None,
|
||||
}
|
||||
}
|
||||
|
||||
const fn highlight_italic(color: u32) -> ThemeSyntaxHighlight {
|
||||
ThemeSyntaxHighlight {
|
||||
color: hex(color),
|
||||
font_style: gpui::FontStyle::Italic,
|
||||
font_weight: None,
|
||||
}
|
||||
}
|
||||
|
||||
const fn highlight_weight(color: u32, font_weight: gpui::FontWeight) -> ThemeSyntaxHighlight {
|
||||
ThemeSyntaxHighlight {
|
||||
color: hex(color),
|
||||
font_style: gpui::FontStyle::Normal,
|
||||
font_weight: Some(font_weight),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn latte() -> Theme {
|
||||
Theme {
|
||||
id: "catppuccin-latte",
|
||||
name: LATTE_LABEL,
|
||||
@@ -61,10 +88,63 @@ pub(crate) const fn latte() -> Theme {
|
||||
info_solid: hex(0x1e66f5),
|
||||
info_on_solid: hex(0xeff1f5),
|
||||
},
|
||||
syntax: build([
|
||||
(key::ATTRIBUTE, highlight(0x179299)),
|
||||
(key::BOOLEAN, highlight(0xfe640b)),
|
||||
(key::COMMENT, highlight(0x7c7f93)),
|
||||
(key::COMMENT_DOC, highlight(0x8c8fa1)),
|
||||
(key::CONSTANT, highlight(0xfe640b)),
|
||||
(key::CONSTRUCTOR, highlight(0x209fb5)),
|
||||
(key::EMBEDDED, highlight(0x4c4f69)),
|
||||
(key::EMPHASIS, highlight(0x1e66f5)),
|
||||
(
|
||||
key::EMPHASIS_STRONG,
|
||||
highlight_weight(0xdf8e1d, gpui::FontWeight::BOLD),
|
||||
),
|
||||
(key::ENUM, highlight(0x179299)),
|
||||
(key::FUNCTION, highlight(0x1e66f5)),
|
||||
(key::HINT, highlight(0x9ca0b0)),
|
||||
(key::KEYWORD, highlight(0x8839ef)),
|
||||
(key::LABEL, highlight(0x7287fd)),
|
||||
(key::LINK_TEXT, highlight_italic(0x1e66f5)),
|
||||
(key::LINK_URI, highlight(0x179299)),
|
||||
(key::NAMESPACE, highlight(0x4c4f69)),
|
||||
(key::NUMBER, highlight(0xfe640b)),
|
||||
(key::OPERATOR, highlight(0x04a5e5)),
|
||||
(key::PREDICTIVE, highlight_italic(0x9ca0b0)),
|
||||
(key::PREPROC, highlight(0x8839ef)),
|
||||
(key::PRIMARY, highlight(0x4c4f69)),
|
||||
(key::PROPERTY, highlight(0xdc8a78)),
|
||||
(key::PUNCTUATION, highlight(0x6c6f85)),
|
||||
(key::PUNCTUATION_BRACKET, highlight(0x7c7f93)),
|
||||
(key::PUNCTUATION_DELIMITER, highlight(0x7c7f93)),
|
||||
(key::PUNCTUATION_LIST_MARKER, highlight(0xd20f39)),
|
||||
(key::PUNCTUATION_MARKUP, highlight(0xd20f39)),
|
||||
(key::PUNCTUATION_SPECIAL, highlight(0xe64553)),
|
||||
(key::SELECTOR, highlight(0x40a02b)),
|
||||
(key::SELECTOR_PSEUDO, highlight(0x1e66f5)),
|
||||
(key::STRING, highlight(0x40a02b)),
|
||||
(key::STRING_ESCAPE, highlight(0xea76cb)),
|
||||
(key::STRING_REGEX, highlight(0xfe640b)),
|
||||
(key::STRING_SPECIAL, highlight(0xfe640b)),
|
||||
(key::STRING_SPECIAL_SYMBOL, highlight(0xfe640b)),
|
||||
(key::TAG, highlight(0x1e66f5)),
|
||||
(key::TEXT_LITERAL, highlight(0x40a02b)),
|
||||
(
|
||||
key::TITLE,
|
||||
highlight_weight(0xdc8a78, gpui::FontWeight::NORMAL),
|
||||
),
|
||||
(key::TYPE, highlight(0xdf8e1d)),
|
||||
(key::VARIABLE, highlight(0x4c4f69)),
|
||||
(key::VARIABLE_SPECIAL, highlight(0xfe640b)),
|
||||
(key::VARIANT, highlight(0x7287fd)),
|
||||
(key::DIFF_PLUS, highlight(0x40a02b)),
|
||||
(key::DIFF_MINUS, highlight(0xd20f39)),
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn mocha() -> Theme {
|
||||
pub(crate) fn mocha() -> Theme {
|
||||
Theme {
|
||||
id: "catppuccin-mocha",
|
||||
name: MOCHA_LABEL,
|
||||
@@ -117,5 +197,58 @@ pub(crate) const fn mocha() -> Theme {
|
||||
info_solid: hex(0x89b4fa),
|
||||
info_on_solid: hex(0x1e1e2e),
|
||||
},
|
||||
syntax: build([
|
||||
(key::ATTRIBUTE, highlight(0x94e2d5)),
|
||||
(key::BOOLEAN, highlight(0xfab387)),
|
||||
(key::COMMENT, highlight(0x6c7086)),
|
||||
(key::COMMENT_DOC, highlight(0x7f849c)),
|
||||
(key::CONSTANT, highlight(0xfab387)),
|
||||
(key::CONSTRUCTOR, highlight(0x74c7ec)),
|
||||
(key::EMBEDDED, highlight(0xcdd6f4)),
|
||||
(key::EMPHASIS, highlight(0x89b4fa)),
|
||||
(
|
||||
key::EMPHASIS_STRONG,
|
||||
highlight_weight(0xf9e2af, gpui::FontWeight::BOLD),
|
||||
),
|
||||
(key::ENUM, highlight(0x94e2d5)),
|
||||
(key::FUNCTION, highlight(0x89b4fa)),
|
||||
(key::HINT, highlight(0x9399b2)),
|
||||
(key::KEYWORD, highlight(0xcba6f7)),
|
||||
(key::LABEL, highlight(0xb4befe)),
|
||||
(key::LINK_TEXT, highlight_italic(0x89b4fa)),
|
||||
(key::LINK_URI, highlight(0x94e2d5)),
|
||||
(key::NAMESPACE, highlight(0xcdd6f4)),
|
||||
(key::NUMBER, highlight(0xfab387)),
|
||||
(key::OPERATOR, highlight(0x89dceb)),
|
||||
(key::PREDICTIVE, highlight_italic(0x9399b2)),
|
||||
(key::PREPROC, highlight(0xcba6f7)),
|
||||
(key::PRIMARY, highlight(0xcdd6f4)),
|
||||
(key::PROPERTY, highlight(0xf5e0dc)),
|
||||
(key::PUNCTUATION, highlight(0xa6adc8)),
|
||||
(key::PUNCTUATION_BRACKET, highlight(0x9399b2)),
|
||||
(key::PUNCTUATION_DELIMITER, highlight(0x9399b2)),
|
||||
(key::PUNCTUATION_LIST_MARKER, highlight(0xf38ba8)),
|
||||
(key::PUNCTUATION_MARKUP, highlight(0xf38ba8)),
|
||||
(key::PUNCTUATION_SPECIAL, highlight(0xeba0ac)),
|
||||
(key::SELECTOR, highlight(0xa6e3a1)),
|
||||
(key::SELECTOR_PSEUDO, highlight(0x89b4fa)),
|
||||
(key::STRING, highlight(0xa6e3a1)),
|
||||
(key::STRING_ESCAPE, highlight(0xf5c2e7)),
|
||||
(key::STRING_REGEX, highlight(0xfab387)),
|
||||
(key::STRING_SPECIAL, highlight(0xfab387)),
|
||||
(key::STRING_SPECIAL_SYMBOL, highlight(0xfab387)),
|
||||
(key::TAG, highlight(0x89b4fa)),
|
||||
(key::TEXT_LITERAL, highlight(0xa6e3a1)),
|
||||
(
|
||||
key::TITLE,
|
||||
highlight_weight(0xf5e0dc, gpui::FontWeight::NORMAL),
|
||||
),
|
||||
(key::TYPE, highlight(0xf9e2af)),
|
||||
(key::VARIABLE, highlight(0xcdd6f4)),
|
||||
(key::VARIABLE_SPECIAL, highlight(0xfab387)),
|
||||
(key::VARIANT, highlight(0xb4befe)),
|
||||
(key::DIFF_PLUS, highlight(0xa6e3a1)),
|
||||
(key::DIFF_MINUS, highlight(0xf38ba8)),
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
165
src/theme/syntax.rs
Normal file
165
src/theme/syntax.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use gpui::Rgba;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct ThemeSyntaxHighlight {
|
||||
pub color: Rgba,
|
||||
pub font_style: gpui::FontStyle,
|
||||
pub font_weight: Option<gpui::FontWeight>,
|
||||
}
|
||||
|
||||
pub const HIGHLIGHT_NAME_COUNT: usize = HIGHLIGHT_NAMES.len();
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct ThemeSyntax([ThemeSyntaxHighlight; HIGHLIGHT_NAME_COUNT]);
|
||||
|
||||
impl ThemeSyntax {
|
||||
pub fn resolve(&self, key: &str) -> ThemeSyntaxHighlight {
|
||||
Self::index_of(key)
|
||||
.and_then(|index| self.get(index))
|
||||
.unwrap_or_else(|| self.text_literal())
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> Option<ThemeSyntaxHighlight> {
|
||||
self.0.get(index).copied()
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[ThemeSyntaxHighlight] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn text_literal(&self) -> ThemeSyntaxHighlight {
|
||||
self.get(Self::index_of(key::TEXT_LITERAL).expect("missing text.literal index"))
|
||||
.expect("theme syntax must define text.literal")
|
||||
}
|
||||
|
||||
fn index_of(key: &str) -> Option<usize> {
|
||||
HIGHLIGHT_NAMES
|
||||
.iter()
|
||||
.position(|candidate| *candidate == key)
|
||||
}
|
||||
}
|
||||
|
||||
pub const HIGHLIGHT_NAMES: &[&str] = &[
|
||||
key::ATTRIBUTE,
|
||||
key::BOOLEAN,
|
||||
key::COMMENT,
|
||||
key::COMMENT_DOC,
|
||||
key::CONSTANT,
|
||||
key::CONSTRUCTOR,
|
||||
key::DIFF_MINUS,
|
||||
key::DIFF_PLUS,
|
||||
key::EMBEDDED,
|
||||
key::EMPHASIS,
|
||||
key::EMPHASIS_STRONG,
|
||||
key::ENUM,
|
||||
key::FUNCTION,
|
||||
key::HINT,
|
||||
key::KEYWORD,
|
||||
key::LABEL,
|
||||
key::LINK_TEXT,
|
||||
key::LINK_URI,
|
||||
key::NAMESPACE,
|
||||
key::NUMBER,
|
||||
key::OPERATOR,
|
||||
key::PREDICTIVE,
|
||||
key::PREPROC,
|
||||
key::PRIMARY,
|
||||
key::PROPERTY,
|
||||
key::PUNCTUATION,
|
||||
key::PUNCTUATION_BRACKET,
|
||||
key::PUNCTUATION_DELIMITER,
|
||||
key::PUNCTUATION_LIST_MARKER,
|
||||
key::PUNCTUATION_MARKUP,
|
||||
key::PUNCTUATION_SPECIAL,
|
||||
key::SELECTOR,
|
||||
key::SELECTOR_PSEUDO,
|
||||
key::STRING,
|
||||
key::STRING_ESCAPE,
|
||||
key::STRING_REGEX,
|
||||
key::STRING_SPECIAL,
|
||||
key::STRING_SPECIAL_SYMBOL,
|
||||
key::TAG,
|
||||
key::TEXT_LITERAL,
|
||||
key::TITLE,
|
||||
key::TYPE,
|
||||
key::VARIABLE,
|
||||
key::VARIABLE_SPECIAL,
|
||||
key::VARIANT,
|
||||
];
|
||||
|
||||
pub(crate) fn build(
|
||||
entries: impl IntoIterator<Item = (&'static str, ThemeSyntaxHighlight)>,
|
||||
) -> ThemeSyntax {
|
||||
let syntax_by_name: BTreeMap<&'static str, ThemeSyntaxHighlight> = entries
|
||||
.into_iter()
|
||||
.map(|(name, style)| (name, style))
|
||||
.collect();
|
||||
|
||||
debug_assert!(syntax_by_name.contains_key(key::TEXT_LITERAL));
|
||||
debug_assert!(
|
||||
syntax_by_name
|
||||
.keys()
|
||||
.all(|name| HIGHLIGHT_NAMES.contains(name))
|
||||
);
|
||||
|
||||
let fallback = *syntax_by_name
|
||||
.get(key::TEXT_LITERAL)
|
||||
.expect("theme syntax must define text.literal");
|
||||
|
||||
ThemeSyntax(std::array::from_fn(|index| {
|
||||
syntax_by_name
|
||||
.get(HIGHLIGHT_NAMES[index])
|
||||
.copied()
|
||||
.unwrap_or(fallback)
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) mod key {
|
||||
pub const ATTRIBUTE: &str = "attribute";
|
||||
pub const BOOLEAN: &str = "boolean";
|
||||
pub const COMMENT: &str = "comment";
|
||||
pub const COMMENT_DOC: &str = "comment.doc";
|
||||
pub const CONSTANT: &str = "constant";
|
||||
pub const CONSTRUCTOR: &str = "constructor";
|
||||
pub const DIFF_MINUS: &str = "diff.minus";
|
||||
pub const DIFF_PLUS: &str = "diff.plus";
|
||||
pub const EMBEDDED: &str = "embedded";
|
||||
pub const EMPHASIS: &str = "emphasis";
|
||||
pub const EMPHASIS_STRONG: &str = "emphasis.strong";
|
||||
pub const ENUM: &str = "enum";
|
||||
pub const FUNCTION: &str = "function";
|
||||
pub const HINT: &str = "hint";
|
||||
pub const KEYWORD: &str = "keyword";
|
||||
pub const LABEL: &str = "label";
|
||||
pub const LINK_TEXT: &str = "link_text";
|
||||
pub const LINK_URI: &str = "link_uri";
|
||||
pub const NAMESPACE: &str = "namespace";
|
||||
pub const NUMBER: &str = "number";
|
||||
pub const OPERATOR: &str = "operator";
|
||||
pub const PREDICTIVE: &str = "predictive";
|
||||
pub const PREPROC: &str = "preproc";
|
||||
pub const PRIMARY: &str = "primary";
|
||||
pub const PROPERTY: &str = "property";
|
||||
pub const PUNCTUATION: &str = "punctuation";
|
||||
pub const PUNCTUATION_BRACKET: &str = "punctuation.bracket";
|
||||
pub const PUNCTUATION_DELIMITER: &str = "punctuation.delimiter";
|
||||
pub const PUNCTUATION_LIST_MARKER: &str = "punctuation.list_marker";
|
||||
pub const PUNCTUATION_MARKUP: &str = "punctuation.markup";
|
||||
pub const PUNCTUATION_SPECIAL: &str = "punctuation.special";
|
||||
pub const SELECTOR: &str = "selector";
|
||||
pub const SELECTOR_PSEUDO: &str = "selector.pseudo";
|
||||
pub const STRING: &str = "string";
|
||||
pub const STRING_ESCAPE: &str = "string.escape";
|
||||
pub const STRING_REGEX: &str = "string.regex";
|
||||
pub const STRING_SPECIAL: &str = "string.special";
|
||||
pub const STRING_SPECIAL_SYMBOL: &str = "string.special.symbol";
|
||||
pub const TAG: &str = "tag";
|
||||
pub const TEXT_LITERAL: &str = "text.literal";
|
||||
pub const TITLE: &str = "title";
|
||||
pub const TYPE: &str = "type";
|
||||
pub const VARIABLE: &str = "variable";
|
||||
pub const VARIABLE_SPECIAL: &str = "variable.special";
|
||||
pub const VARIANT: &str = "variant";
|
||||
}
|
||||
Reference in New Issue
Block a user