From 872253edc2f1f69917d901bb2a812755fd08f8c0 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Mon, 15 Mar 2021 14:53:08 -0400 Subject: [PATCH] Highlight search results --- src/document.rs | 20 +++++++++++++------- src/editor.rs | 4 ++++ src/highlighting.rs | 2 ++ src/row.rs | 36 +++++++++++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/document.rs b/src/document.rs index 5686848..3390f8f 100644 --- a/src/document.rs +++ b/src/document.rs @@ -19,7 +19,7 @@ impl Document { for value in contents.lines() { let mut row = Row::from(value); - row.highlight(); + row.highlight(None); rows.push(row); } @@ -58,13 +58,13 @@ impl Document { if at.y == self.rows.len() { let mut row = Row::default(); row.insert(0, c); - row.highlight(); + row.highlight(None); self.rows.push(row); } else { #[allow(clippy::indexing_slicing)] let row = &mut self.rows[at.y]; row.insert(at.x, c); - row.highlight(); + row.highlight(None); } } @@ -82,11 +82,11 @@ impl Document { let next_row = self.rows.remove(at.y + 1); let row = &mut self.rows[at.y]; row.append(&next_row); - row.highlight(); + row.highlight(None); } else { let row = &mut self.rows[at.y]; row.delete(at.x); - row.highlight(); + row.highlight(None); } } @@ -106,6 +106,12 @@ impl Document { Ok(()) } + pub fn highlight(&mut self, word: Option<&str>) { + for row in &mut self.rows { + row.highlight(word); + } + } + pub fn is_dirty(&self) -> bool { self.dirty } @@ -159,8 +165,8 @@ impl Document { let current_row = &mut self.rows[at.y]; let mut new_row = current_row.split(at.x); - current_row.highlight(); - new_row.highlight(); + current_row.highlight(None); + new_row.highlight(None); #[allow(clippy::integer_arithmetic)] self.rows.insert(at.y + 1, new_row); diff --git a/src/editor.rs b/src/editor.rs index a7ab8fd..6e55326 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -215,6 +215,8 @@ impl Editor { } else if moved { editor.move_cursor(Key::Left); } + + editor.document.highlight(Some(query)); }, ) .unwrap_or(None); @@ -223,6 +225,8 @@ impl Editor { self.cursor_position = old_position; self.scroll(); } + + self.document.highlight(None); } fn process_keypress(&mut self) -> Result<(), std::io::Error> { diff --git a/src/highlighting.rs b/src/highlighting.rs index e7255e4..b0e3d31 100644 --- a/src/highlighting.rs +++ b/src/highlighting.rs @@ -4,12 +4,14 @@ use termion::color; pub enum Type { None, Number, + Match, } impl Type { pub fn to_color(&self) -> impl color::Color { match self { Type::Number => color::Rgb(220, 163, 163), + Type::Match => color::Rgb(38, 139, 210), _ => color::Rgb(255, 255, 255), } } diff --git a/src/row.rs b/src/row.rs index 9ecc186..b71099c 100644 --- a/src/row.rs +++ b/src/row.rs @@ -155,7 +155,7 @@ impl Row { } pub fn find(&self, query: &str, at: usize, direction: SearchDirection) -> Option { - if at > self.len { + if at > self.len || query.is_empty() { return None; } @@ -189,15 +189,45 @@ impl Row { None } - pub fn highlight(&mut self) { + pub fn highlight(&mut self, word: Option<&str>) { let mut highlighting = Vec::new(); + let chars: Vec = self.string.chars().collect(); + let mut matches = Vec::new(); + let mut search_index = 0; + + if let Some(word) = word { + while let Some(search_match) = self.find(word, search_index, SearchDirection::Forward) { + matches.push(search_match); + + if let Some(next_index) = search_match.checked_add(word[..].graphemes(true).count()) + { + search_index = next_index + } else { + break; + } + } + } + + let mut index = 0; + while let Some(c) = chars.get(index) { + if let Some(word) = word { + if matches.contains(&index) { + for _ in word[..].graphemes(true) { + index += 1; + highlighting.push(highlighting::Type::Match); + } + + continue; + } + } - for c in self.string.chars() { if c.is_ascii_digit() { highlighting.push(highlighting::Type::Number) } else { highlighting.push(highlighting::Type::None) } + + index += 1; } self.highlighting = highlighting;