diff --git a/crates/ui/src/highlighter/highlight.rs b/crates/ui/src/highlighter/highlight.rs index f8def525..fe82e4bd 100644 --- a/crates/ui/src/highlighter/highlight.rs +++ b/crates/ui/src/highlighter/highlight.rs @@ -75,16 +75,16 @@ impl<'a> Highlighter<'a> { } } - /// Highlight a text and returns a vector of ranges and highlight styles - pub fn highlight(&self, text: &str) -> Vec<(Range, HighlightStyle)> { + /// Highlight a line and returns a vector of ranges and highlight styles + pub fn highlight(&self, line: &str) -> Vec<(Range, HighlightStyle)> { let mut parser = parsing::ParseState::new(self.syntax); let mut stack = parsing::ScopeStack::new(); - let ops = parser.parse_line(text, &SYNTAXES).unwrap_or_default(); + let ops = parser.parse_line(line, &SYNTAXES).unwrap_or_default(); ScopeRangeIterator { ops, - line_length: text.len(), + line_length: line.len(), index: 0, last_str_index: 0, } diff --git a/crates/ui/src/highlighter/themes/dark.tmTheme b/crates/ui/src/highlighter/themes/dark.tmTheme index 0068ece3..8c47c716 100644 --- a/crates/ui/src/highlighter/themes/dark.tmTheme +++ b/crates/ui/src/highlighter/themes/dark.tmTheme @@ -1,597 +1,324 @@ - + - - author - Michael Sheets - gutterSettings - - background - #2F2F31 - divider - #414143 - foreground - #8F8F8F - selectionBackground - #414143 - selectionBorder - #484848 - selectionForeground - #BABABA - - name - Twilight - semanticClass - theme.dark.twilight - settings - - - settings - - background - #181818 - caret - #A7A7A7 - foreground - #F8F8F8 - invisibles - #FFFFFF40 - lineHighlight - #FFFFFF08 - selection - #DDF0FF33 - - - - name - Foldings - scope - deco.folding - settings - - foreground - #5A6A65 - - - - name - Comment - scope - comment - settings - - fontStyle - italic - foreground - #5F5A60 - - - - name - Constant - scope - constant - settings - - foreground - #CF6A4C - - - - name - Entity - scope - entity - settings - - fontStyle - - foreground - #9B703F - - - - name - Keyword - scope - keyword - settings - - fontStyle - - foreground - #CDA869 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #F9EE98 - - - - name - String - scope - string - settings - - fontStyle - - foreground - #8F9D6A - - - - name - Support - scope - support - settings - - fontStyle - - foreground - #9B859D - - - - name - Variable - scope - variable - settings - - foreground - #7587A6 - - - - name - Invalid – Deprecated - scope - invalid.deprecated - settings - - fontStyle - italic underline - foreground - #D2A8A1 - - - - name - Invalid – Illegal - scope - invalid.illegal - settings - - background - #562D56BF - foreground - #F8F8F8 - - - - name - ----------------------------------- - settings - - - - name - ♦ Embedded Source - scope - meta.embedded.block, punctuation.whitespace.embedded - settings - - background - #B0B3BA14 - - - - name - ♦ Embedded Source (Bright) - scope - meta.embedded.line - settings - - background - #B1B3BA21 - - - - name - ♦ Entity inherited-class - scope - entity.other.inherited-class - settings - - fontStyle - italic - foreground - #9B5C2E - - - - name - ♦ String embedded-source - scope - string meta.embedded - settings - - fontStyle - - foreground - #DAEFA3 - - - - name - ♦ String constant - scope - string constant - settings - - foreground - #DDF2A4 - - - - name - ♦ String.regexp - scope - string.regexp - settings - - fontStyle - - foreground - #E9C062 - - - - name - ♦ String.regexp.«special» - scope - string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repetition - settings - - foreground - #CF7D34 - - - - name - ♦ String variable - scope - string variable - settings - - foreground - #8A9A95 - - - - name - ♦ Support.function - scope - support.function - settings - - fontStyle - - foreground - #DAD085 - - - - name - ♦ Support.constant - scope - support.constant - settings - - fontStyle - - foreground - #CF6A4C - - - - name - c C/C++ Preprocessor Line - scope - meta.preprocessor.c, source.swift meta.preprocessor - settings - - foreground - #8996A8 - - - - name - c C/C++ Preprocessor Directive - scope - meta.preprocessor.c keyword, source.swift meta.preprocessor keyword - settings - - foreground - #AFC4DB - - - - name - ✘ Doctype/XML Processing - scope - meta.tag.metadata.doctype, meta.tag.metadata.doctype entity, meta.tag.metadata.doctype string, meta.tag.metadata.processing.xml, meta.tag.metadata.processing.xml entity, meta.tag.metadata.processing.xml string - settings - - foreground - #494949 - - - - name - ✘ Meta.tag.«all» - scope - declaration.tag, declaration.tag entity, meta.tag, meta.tag entity - settings - - foreground - #AC885B - - - - name - ✘ Meta.tag.inline - scope - declaration.tag.inline, declaration.tag.inline entity, meta.tag.inline, meta.tag.inline entity - settings - - foreground - #E0C589 - - - - name - § css tag-name - scope - meta.selector.css entity.name.tag - settings - - foreground - #CDA869 - - - - name - § css:pseudo-class - scope - meta.selector.css entity.other.attribute-name.tag.pseudo-class - settings - - foreground - #8F9D6A - - - - name - § css#id - scope - meta.selector.css entity.other.attribute-name.id - settings - - foreground - #8B98AB - - - - name - § css.class - scope - meta.selector.css entity.other.attribute-name.class - settings - - foreground - #9B703F - - - - name - § css property-name: - scope - support.type.property-name.css - settings - - foreground - #C5AF75 - - - - name - § css property-value; - scope - meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css - settings - - foreground - #F9EE98 - - - - name - § css @at-rule - scope - meta.preprocessor.at-rule keyword.control.at-rule - settings - - foreground - #8693A5 - - - - name - § css additional-constants - scope - meta.property-value support.constant.named-color.css, meta.property-value constant - settings - - foreground - #CA7840 - - - - name - § css constructor.argument - scope - meta.constructor.argument.css - settings - - foreground - #8F9D6A - - - - name - ⎇ diff.header - scope - meta.diff, meta.diff.header, meta.separator, meta.diff.range, meta.diff.index - settings - - background - #0E2231 - fontStyle - italic - foreground - #F8F8F8 - - - - name - ⎇ diff.deleted - scope - markup.deleted - settings - - background - #420E09 - foreground - #F8F8F8 - - - - name - ⎇ diff.changed - scope - markup.changed - settings - - background - #4A410D - foreground - #F8F8F8 - - - - name - ⎇ diff.inserted - scope - markup.inserted - settings - - background - #253B22 - foreground - #F8F8F8 - - - - name - Markup: List - scope - markup.list - settings - - foreground - #F9EE98 - - - - name - Markup: Heading - scope - markup.heading - settings - - foreground - #CF6A4C - - - - name - Markup: Raw Block - scope - markup.raw.block - settings - - background - #B0B3BA14 - - - - name - Test: 1 - scope - meta.test1 - settings - - background - #0E2231C5 - - - - name - Test: 2 - scope - meta.test2 - settings - - background - #420E0990 - - - - name - Test: 3 - scope - meta.test3 - settings - - background - #4A410D90 - - - - name - Test: 4 - scope - meta.test4 - settings - - background - #253B2290 - - - - uuid - 766026CB-703D-4610-B070-8DE07D967C5F - + + name + macOS Classic Dark + semanticClass + theme.dark.mac-classic + settings + + + + settings + + background + #131313 + caret + #CACCCA + foreground + #DDDDDD + invisibles + #9E9E9E + lineHighlight + #272727 + selection + #72CFFE3D + + + + + + name + Attribute + scope + entity.other.attribute-name + settings + + foreground + #BE9A52 + + + + + + name + Boolean + scope + constant.language.boolean, constant.numeric.boolean + settings + + foreground + #E1D797 + + + + + + name + Comment + scope + comment, comment.block.documentation + settings + + foreground + #9E9E9E + + + + + + name + Constant + scope + constant, constant.other, constant.language + settings + + foreground + #E1D797 + + + + + + name + Constructor + scope + entity.name.function.constructor + settings + + foreground + #b5af9a + + + + + + name + Embedded + scope + meta.embedded, text source + settings + + foreground + #CACCCA + + + + + + name + Function Name + scope + entity.name.function, support.function, support.function.any-method + settings + + foreground + #E1D797 + + + + + + name + Keyword + scope + keyword, storage + settings + + foreground + #E19773 + + + + + + name + Class + scope + support.class, support.type, entity.name.class, entity.name.type.class, meta.class + settings + + foreground + #A86D3B + + + + + + name + Link Text + scope + markup.underline.link, string.other.link + settings + + foreground + #A86D3B + + + + + + name + Link URI + scope + string.other.link.title, string.other.link.description + settings + + fontStyle + italic + foreground + #6F6D66 + + + + + + name + Number + scope + constant.numeric + settings + + foreground + #E19773 + + + + + + name + String + scope + string, string.quoted + settings + + foreground + #76BA53 + + + + + + name + String Escape / Regex + scope + string.escape, string.regex + settings + + foreground + #76BA53 + + + + + + name + String Special + scope + string.special, string.special.symbol + settings + + foreground + #E1D797 + + + + + + name + Tag + scope + meta.tag, declaration.tag + settings + + foreground + #B5AF9A + + + + + + name + Text Literal + scope + text.literal + settings + + foreground + #E1D797 + + + + + + name + Title + scope + entity.name.section, entity.name.title + settings + + foreground + #A76D3B + + + + + + name + Type + scope + entity.name.type + settings + + fontStyle + underline + foreground + #A86D3B + + + + + + name + Property + scope + variable.other.property + settings + + foreground + #CACCCA + + + + + + name + Variable + scope + variable.language, variable.other + settings + + foreground + #DDDDDD + + + + + + name + Variable Special + scope + variable.other.readwrite, variable.other.other + settings + + foreground + #E19773 + + + + + uuid + 82d2fb7d-4049-44ec-a5b1-135fd5f7ce9f + diff --git a/crates/ui/src/highlighter/themes/light.tmTheme b/crates/ui/src/highlighter/themes/light.tmTheme index 74b740f1..a75a8794 100644 --- a/crates/ui/src/highlighter/themes/light.tmTheme +++ b/crates/ui/src/highlighter/themes/light.tmTheme @@ -1,467 +1,325 @@ - + - - author - Chris Thomas - name - Mac Classic - semanticClass - theme.light.mac-classic - settings - - - settings - - background - #FFFFFF - caret - #000000 - foreground - #000000 - invisibles - #BFBFBF - lineHighlight - #00000012 - selection - #4D97FF54 - - - - name - Comment - scope - comment - settings - - fontStyle - italic - foreground - #0066FF - - - - name - Foldings - scope - deco.folding - settings - - foreground - #BFBFBF - - - - name - Keyword - scope - keyword, storage - settings - - fontStyle - bold - foreground - #0000FF - - - - name - Number - scope - constant.numeric - settings - - fontStyle - - foreground - #0000CD - - - - name - User-defined constant - scope - constant - settings - - fontStyle - bold - foreground - #C5060B - - - - name - Built-in constant - scope - constant.language - settings - - fontStyle - bold - foreground - #585CF6 - - - - name - Variable - scope - variable.language, variable.other - settings - - fontStyle - - foreground - #318495 - - - - name - String - scope - string - settings - - fontStyle - - foreground - #036A07 - - - - name - String interpolation - scope - constant.character.escape, string meta.embedded - settings - - fontStyle - - foreground - #26B31A - - - - name - Preprocessor line - scope - meta.preprocessor - settings - - fontStyle - - foreground - #1A921C - - - - name - Preprocessor directive - scope - keyword.control.import - settings - - fontStyle - bold - foreground - #0C450D - - - - name - Function name - scope - entity.name.function, support.function.any-method - settings - - fontStyle - bold - foreground - #0000A2 - - - - name - Type name - scope - entity.name.type - settings - - fontStyle - underline - - - - name - Inherited class name - scope - entity.other.inherited-class - settings - - fontStyle - italic - - - - name - Function parameter - scope - variable.parameter - settings - - fontStyle - italic - - - - name - Function argument and result types - scope - storage.type.method - settings - - fontStyle - - foreground - #70727E - - - - name - Section - scope - meta.section entity.name.section, declaration.section entity.name.section - settings - - fontStyle - italic - - - - name - Library function - scope - support.function - settings - - fontStyle - bold - foreground - #3C4C72 - - - - name - Library object - scope - support.class, support.type - settings - - fontStyle - bold - foreground - #6D79DE - - - - name - Library constant - scope - support.constant - settings - - fontStyle - bold - foreground - #06960E - - - - name - Library variable - scope - support.variable - settings - - fontStyle - bold - foreground - #21439C - - - - name - JS: Operator - scope - keyword.operator.js - settings - - foreground - #687687 - - - - name - Invalid - scope - invalid - settings - - background - #990000 - caret - #FFFFFF - foreground - #FFFFFF - selection - #4D97FF - - - - name - Invalid trailing whitespace - scope - invalid.deprecated.trailing-whitespace - settings - - background - #FFD0D0 - - - - name - Embedded source - scope - text source, string.unquoted, meta.embedded - settings - - background - #0000000D - - - - name - Embedded embedded source - scope - text source string.unquoted, text source text source - settings - - background - #0000000F - - - - name - Markup XML declaration - scope - meta.tag.preprocessor.xml - settings - - fontStyle - - foreground - #68685B - - - - name - Markup DOCTYPE - scope - meta.tag.metadata.doctype, meta.tag.metadata.doctype entity, meta.tag.metadata.doctype string, meta.tag.metadata.processing.xml, meta.tag.metadata.processing.xml entity, meta.tag.metadata.processing.xml string - settings - - fontStyle - - foreground - #888888 - - - - name - Markup DTD - scope - meta.tag.metadata.doctype string.quoted - settings - - fontStyle - italic - - - - name - Markup tag - scope - meta.tag, declaration.tag - settings - - fontStyle - - foreground - #1C02FF - - - - name - Markup name of tag - scope - entity.name.tag - settings - - fontStyle - bold - - - - name - Markup tag attribute - scope - entity.other.attribute-name - settings - - fontStyle - italic - - - - name - Markup: Heading - scope - markup.heading - settings - - fontStyle - bold - foreground - #0C07FF - - - - name - Markup: Quote - scope - markup.quote - settings - - fontStyle - italic - foreground - #000000 - - - - name - Markup: List - scope - markup.list - settings - - foreground - #B90690 - - - - uuid - 71D40D9D-AE48-11D9-920A-000D93589AF6 - + + name + macOS Classic Light + semanticClass + theme.light.mac-classic + settings + + + + settings + + background + #FFFFFF + caret + #000000 + foreground + #000000 + invisibles + #ACAFB1FF + lineHighlight + #F0F0F0 + selection + #3B9EE53D + + + + + + + + name + Attribute + scope + entity.other.attribute-name + settings + + foreground + #957931 + + + + + + name + Boolean + scope + constant.language.boolean, constant.numeric.boolean + settings + + foreground + #C5060B + + + + + + name + Comment + scope + comment, comment.block.documentation + settings + + foreground + #007FFF + + + + + + name + Constant + scope + constant, constant.other + settings + + foreground + #C5060B + + + + + + name + Constructor + scope + entity.name.function.constructor + settings + + foreground + #0433ff + + + + + + name + Embedded + scope + meta.embedded, text source + settings + + foreground + #333333 + + + + + + name + Function Name + scope + entity.name.function, support.function + settings + + foreground + #0000A2 + + + + + + name + Keyword + scope + keyword, storage + settings + + foreground + #0433FF + + + + + name + Class + scope + support.class, support.type, entity.name.class, entity.name.type.class, meta.class + settings + + foreground + #6f42c1 + + + + + + name + Link Text + scope + markup.underline.link, string.other.link + settings + + foreground + #0000A2 + + + + + + name + Link URI + scope + string.other.link.title, string.other.link.description + settings + + fontStyle + italic + foreground + #6A7293 + + + + + + name + Number + scope + constant.numeric + settings + + foreground + #0433FF + + + + + + name + String + scope + string, string.quoted + settings + + foreground + #036A07 + + + + + + name + String Escape / Regex + scope + string.escape, string.regex + settings + + foreground + #036A07 + + + + + + name + String Special + scope + string.special, string.special.symbol + settings + + foreground + #D21F07 + + + + + + name + Tag + scope + meta.tag, declaration.tag + settings + + foreground + #0433FF + + + + + + name + Text Literal + scope + text.literal + settings + + foreground + #6F42C1 + + + + + + name + Title + scope + entity.name.section, entity.name.title + settings + + foreground + #0433FF + + + + + + name + Type + scope + entity.name.type + settings + + fontStyle + underline + foreground + #6F42C1 + + + + + + name + Property + scope + variable.other.property + settings + + foreground + #333333 + + + + + + name + Variable + scope + variable.language, variable.other + settings + + foreground + #333333 + + + + + + name + Variable Special + scope + variable.other.readwrite, variable.other.other + settings + + foreground + #C5060B + + + + + uuid + 511e2b3a-2aa0-4bb1-b076-e2692581380e + diff --git a/crates/ui/src/input/code_highlighter.rs b/crates/ui/src/input/code_highlighter.rs new file mode 100644 index 00000000..d63b18a9 --- /dev/null +++ b/crates/ui/src/input/code_highlighter.rs @@ -0,0 +1,77 @@ +use std::{collections::HashMap, ops::Range, rc::Rc}; + +use gpui::{App, HighlightStyle, SharedString, TextRun, TextStyle}; + +use crate::highlighter::Highlighter; + +#[derive(Debug, Clone)] +pub(crate) struct LineHighlightStyle { + pub(crate) styles: Rc, HighlightStyle)>>, +} + +impl LineHighlightStyle { + pub(super) fn to_run(&self, text_style: &TextStyle) -> Vec { + self.styles + .iter() + .map(|(range, style)| text_style.clone().highlight(*style).to_run(range.len())) + // Add last `\n` Run with len 1 + .chain(std::iter::once(text_style.clone().to_run(1))) + .collect() + } +} + +#[derive(Clone)] +pub(super) struct CodeHighlighter { + highlighter: Rc>, + pub(super) text: SharedString, + /// The lines by split \n + pub(super) lines: Vec, + pub(super) cache: HashMap, +} + +impl CodeHighlighter { + pub(super) fn new(highlighter: Rc>) -> Self { + Self { + highlighter, + text: SharedString::default(), + lines: vec![], + cache: HashMap::new(), + } + } + + pub fn set_highlighter(&mut self, highlighter: Rc>, cx: &mut App) { + self.highlighter = highlighter; + self.lines.clear(); + self.cache.clear(); + self.update(self.text.clone(), true, cx); + } + + pub fn update(&mut self, text: SharedString, force: bool, _: &mut App) { + if self.text == text && !force { + return; + } + + let mut lines = vec![]; + let mut new_cache = HashMap::new(); + for line in text.lines() { + let cache_key = gpui::hash(&line); + + // cache hit + if let Some(line_style) = self.cache.get(&cache_key) { + new_cache.insert(cache_key, line_style.clone()); + lines.push(line_style.clone()); + } else { + // cache miss + let styles = Rc::new(self.highlighter.highlight(line)); + let line_style = LineHighlightStyle { styles }; + new_cache.insert(cache_key, line_style.clone()); + lines.push(line_style); + } + } + + // Ensure to recreate cache to remove unused caches. + self.cache = new_cache; + self.lines = lines; + self.text = text; + } +} diff --git a/crates/ui/src/input/element.rs b/crates/ui/src/input/element.rs index 0119c5a9..939aaa7a 100644 --- a/crates/ui/src/input/element.rs +++ b/crates/ui/src/input/element.rs @@ -1,16 +1,13 @@ -use std::ops::Range; - use gpui::{ - fill, hash, point, px, relative, size, App, Bounds, Corners, Element, ElementId, - ElementInputHandler, Entity, GlobalElementId, HighlightStyle, IntoElement, LayoutId, - MouseButton, MouseMoveEvent, PaintQuad, Path, Pixels, Point, SharedString, Style, TextAlign, - TextRun, UnderlineStyle, Window, WrappedLine, + fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler, + Entity, GlobalElementId, IntoElement, LayoutId, MouseButton, MouseMoveEvent, PaintQuad, Path, + Pixels, Point, SharedString, Style, TextAlign, TextRun, UnderlineStyle, Window, WrappedLine, }; use smallvec::SmallVec; use crate::{ActiveTheme as _, Root}; -use super::{mode::InputMode, InputState}; +use super::{code_highlighter::LineHighlightStyle, mode::InputMode, InputState}; const RIGHT_MARGIN: Pixels = px(5.); const BOTTOM_MARGIN_ROWS: usize = 1; @@ -310,35 +307,14 @@ impl TextElement { builder.build().ok() } - fn highlight_text(&self, cx: &mut App) -> Option, HighlightStyle)>> { - let input = self.input.read(cx); - let text = input.text.as_ref(); - - let cache_key = hash(&text); - - match &input.mode { - InputMode::CodeEditor { - highlighter, cache, .. - } => { - if cache.0 == cache_key { - return Some(cache.1.clone()); - } - - if let Some(highlighter) = highlighter { - let styles = highlighter.highlight(&text); - self.input.update(cx, |input, _cx| { - input - .mode - .set_code_editor_cache((cache_key, styles.clone())); - }); - - Some(styles) - } else { - None - } + fn highlight_lines(&mut self, cx: &mut App) -> Option> { + self.input.update(cx, |state, cx| match &mut state.mode { + InputMode::CodeEditor { highlighter, .. } => { + highlighter.update(state.text.clone(), false, cx); + Some(highlighter.lines.clone()) } _ => None, - } + }) } } @@ -432,17 +408,18 @@ impl Element for TextElement { window: &mut Window, cx: &mut App, ) -> Self::PrepaintState { - let highlights = self.highlight_text(cx); + let highlight_lines = self.highlight_lines(cx); let multi_line = self.input.read(cx).is_multi_line(); let line_height = window.line_height(); let input = self.input.read(cx); let text = input.text.clone(); + let is_empty = text.is_empty(); let placeholder = self.placeholder.clone(); let style = window.text_style(); let font_size = style.font_size.to_pixels(window.rem_size()); let mut bounds = bounds; - let (display_text, text_color) = if text.is_empty() { + let (display_text, text_color) = if is_empty { (placeholder, cx.theme().muted_foreground) } else if input.masked { ( @@ -531,22 +508,18 @@ impl Element for TextElement { .into_iter() .filter(|run| run.len > 0) .collect() - } else { - if let Some(highlights) = highlights { + } else if !is_empty { + if let Some(highlight_lines) = highlight_lines { let mut runs = vec![]; - for (range, style) in highlights { - let run = text_style - .clone() - .highlight(style) - .to_run(range.end - range.start); - if run.len > 0 { - runs.push(run); - } + for style in highlight_lines { + runs.extend(style.to_run(&text_style)); } - runs + runs.into_iter().filter(|run| run.len > 0).collect() } else { vec![run] } + } else { + vec![run] }; let wrap_width = if multi_line { diff --git a/crates/ui/src/input/mod.rs b/crates/ui/src/input/mod.rs index 01ed6ee6..d8f1e6cf 100644 --- a/crates/ui/src/input/mod.rs +++ b/crates/ui/src/input/mod.rs @@ -1,6 +1,7 @@ mod blink_cursor; mod change; mod clear_button; +mod code_highlighter; mod element; mod mask_pattern; mod mode; diff --git a/crates/ui/src/input/mode.rs b/crates/ui/src/input/mode.rs index 6c99235d..4d971349 100644 --- a/crates/ui/src/input/mode.rs +++ b/crates/ui/src/input/mode.rs @@ -1,10 +1,7 @@ -use gpui::{DefiniteLength, HighlightStyle, SharedString}; - -use std::ops::Range; -use std::rc::Rc; +use gpui::{DefiniteLength, SharedString}; +use super::code_highlighter::CodeHighlighter; use super::text_wrapper::TextWrapper; -use crate::highlighter::Highlighter; #[derive(Debug, Copy, Clone)] pub struct TabSize { @@ -48,8 +45,7 @@ pub enum InputMode { height: Option, /// Show line number line_number: bool, - highlighter: Option>>, - cache: (u64, Vec<(Range, HighlightStyle)>), + highlighter: CodeHighlighter, }, AutoGrow { rows: usize, @@ -134,15 +130,6 @@ impl InputMode { } } - pub(super) fn set_code_editor_cache( - &mut self, - cache: (u64, Vec<(Range, HighlightStyle)>), - ) { - if let InputMode::CodeEditor { cache: c, .. } = self { - *c = cache; - } - } - /// Return false if the mode is not [`InputMode::CodeEditor`]. #[allow(unused)] #[inline] diff --git a/crates/ui/src/input/state.rs b/crates/ui/src/input/state.rs index 94cb4d6d..6b2126ea 100644 --- a/crates/ui/src/input/state.rs +++ b/crates/ui/src/input/state.rs @@ -25,6 +25,7 @@ use gpui::{ use super::{ blink_cursor::BlinkCursor, change::Change, + code_highlighter::CodeHighlighter, element::TextElement, mask_pattern::MaskPattern, mode::{InputMode, TabSize}, @@ -362,12 +363,11 @@ impl InputState { /// - Auto Indent /// - Line Number pub fn code_editor(mut self, language: Option<&str>, theme: &'static HighlightTheme) -> Self { - let highlighter = Highlighter::new(language, theme); + let highlighter = Rc::new(Highlighter::new(language, theme)); self.mode = InputMode::CodeEditor { rows: 2, tab: TabSize::default(), - highlighter: Some(Rc::new(highlighter)), - cache: (0, vec![]), + highlighter: CodeHighlighter::new(highlighter), line_number: true, height: Some(relative(1.)), }; @@ -433,11 +433,8 @@ impl InputState { pub fn set_highlighter(&mut self, highlighter: Highlighter<'static>, cx: &mut Context) { let new_highlighter = Rc::new(highlighter); match &mut self.mode { - InputMode::CodeEditor { - highlighter, cache, .. - } => { - *highlighter = Some(new_highlighter); - *cache = (0, vec![]); + InputMode::CodeEditor { highlighter, .. } => { + highlighter.set_highlighter(new_highlighter, cx); } _ => {} } diff --git a/crates/ui/src/text/html.rs b/crates/ui/src/text/html.rs index ed26a1c8..f71aa3c4 100644 --- a/crates/ui/src/text/html.rs +++ b/crates/ui/src/text/html.rs @@ -468,7 +468,9 @@ fn parse_paragraph( 0..text.len(), InlineTextStyle { link: Some(LinkMark { - url: attr_value(&attrs, local_name!("href")).unwrap().into(), + url: attr_value(&attrs, local_name!("href")) + .unwrap_or_default() + .into(), title: attr_value(&attrs, local_name!("title")).map(Into::into), }), ..Default::default()