diff --git a/src/todo/editor.rs b/src/todo/editor.rs index 7d71186..39eb514 100644 --- a/src/todo/editor.rs +++ b/src/todo/editor.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use crate::app::Message; +use crate::todo::highlighter::TodoHighlightSettings; use crate::todo::highlighter::TodoHighlighter; use crate::todo::parser::Todo; @@ -33,6 +34,17 @@ impl Debug for TodoEditorError { struct TodoLine { content: Content, dirty: bool, + done: bool, +} + +impl TodoLine { + fn get_editor_setting(&self) -> TodoHighlightSettings { + if self.done { + TodoHighlightSettings::DescOnlyDone + } else { + TodoHighlightSettings::DescOnly + } + } } #[derive(Debug, Clone)] @@ -50,6 +62,7 @@ impl TodoEditor { .map(|item| TodoLine { content: Content::with_text(item.get_desc()), dirty: false, + done: item.is_done(), }) .collect(); Self { @@ -89,7 +102,9 @@ where col = col.push( TextEditor::new(&line.content) .on_action(move |action| Message::Edit(action, i)) - .highlight_with::((), |hl, _t| hl.to_format()), + .highlight_with::(line.get_editor_setting(), |hl, _t| { + hl.to_format() + }), ); } scrollable(col) diff --git a/src/todo/highlighter.rs b/src/todo/highlighter.rs index 5ff06f7..b14edb2 100644 --- a/src/todo/highlighter.rs +++ b/src/todo/highlighter.rs @@ -24,27 +24,83 @@ static TODOTHEME: LazyLock = LazyLock::new(|| get_current_t pub struct TodoHighlighter { syntax: &'static parsing::SyntaxReference, highlighter: highlighting::Highlighter<'static>, + + start_state: parsing::ParseState, + start_scope: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TodoHighlightSettings { + Full, + DescOnly, + DescOnlyDone, +} + +impl TodoHighlightSettings { + fn init_parser(&self, syntax: &parsing::SyntaxReference) -> parsing::ParseState { + match self { + TodoHighlightSettings::Full => parsing::ParseState::new(syntax), + TodoHighlightSettings::DescOnly => { + let mut parser = parsing::ParseState::new(syntax); + parser + .parse_line( + "​", // Zero-width space unicode to force parser into desc context + &*TODOSYNTAX, + ) + .expect("init static parser from TodoHighlightSettings"); + parser + } + TodoHighlightSettings::DescOnlyDone => { + let mut parser = parsing::ParseState::new(syntax); + parser + .parse_line( + "x ​", // done header + Zero-width space unicode to force parser into desc context + &*TODOSYNTAX, + ) + .expect("init static parser from TodoHighlightSettings"); + parser + } + } + } + + fn get_scope(&self) -> Option { + match self { + TodoHighlightSettings::Full => None, + TodoHighlightSettings::DescOnly => { + Some(parsing::Scope::new("text.todo").expect("static Scope")) + } + TodoHighlightSettings::DescOnlyDone => { + Some(parsing::Scope::new("comment.line").expect("static Scope")) + } + } + } } impl Highlighter for TodoHighlighter { - type Settings = (); + type Settings = TodoHighlightSettings; type Highlight = TodoHighlight; type Iterator<'a> = Box, Self::Highlight)> + 'a>; - fn new(_settings: &Self::Settings) -> Self { + fn new(settings: &Self::Settings) -> Self { let syntax = TODOSYNTAX.syntaxes().get(0).expect("Todo Syntax Reference"); let highlighter = highlighting::Highlighter::new(&*TODOTHEME); + Self { syntax, highlighter, + start_state: settings.init_parser(syntax), + start_scope: settings.get_scope(), } } - fn update(&mut self, _s: &Self::Settings) { + fn update(&mut self, s: &Self::Settings) { // Re-highlight (only one line for planit) self.change_line(0); + + self.start_state = s.init_parser(self.syntax); + self.start_scope = s.get_scope(); } fn change_line(&mut self, line: usize) { @@ -55,11 +111,17 @@ impl Highlighter for TodoHighlighter { } fn highlight_line(&mut self, line: &str) -> Self::Iterator<'_> { - let mut parser = parsing::ParseState::new(self.syntax); + let ops = self + .start_state + .parse_line(line, &*TODOSYNTAX) + .unwrap_or_default(); - let ops = parser.parse_line(line, &*TODOSYNTAX).unwrap_or_default(); - - Box::new(scope_iterator(ops, line, &self.highlighter)) + Box::new(scope_iterator( + ops, + line, + self.start_scope, + &self.highlighter, + )) } fn current_line(&self) -> usize { @@ -94,9 +156,13 @@ impl TodoHighlight { fn scope_iterator<'a>( ops: Vec<(usize, parsing::ScopeStackOp)>, line: &str, + start_scope: Option, highlighter: &'a highlighting::Highlighter<'static>, ) -> impl Iterator, TodoHighlight)> + 'a { let mut stack = parsing::ScopeStack::new(); + if let Some(scope) = start_scope { + stack.push(scope); + } ScopeRangeIterator { ops, line_length: line.len(),