From f4765b04d8646d7c837f07f0fdc6cf868d163da8 Mon Sep 17 00:00:00 2001 From: Luis Useche Date: Mon, 9 Sep 2024 08:15:31 -0700 Subject: [PATCH] WIP: Search location and total count. --- helix-term/src/commands.rs | 77 +++++++++++++++++++++------------ helix-term/src/ui/statusline.rs | 10 +++++ helix-view/src/document.rs | 4 ++ helix-view/src/editor.rs | 3 ++ 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 6e037a471ffc8..465646decb473 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2097,6 +2097,13 @@ fn search_impl( // it out, we need to add it back to the position of the selection. let doc = doc!(editor).text().slice(..); + if regex.find(doc.regex_input()).is_none() { + if show_warnings { + editor.set_error("No matches"); + } + return; + } + // use find_at to find the next match after the cursor, loop around the end // Careful, `Regex` uses `bytes` as offsets, not character indices! let mut mat = match direction { @@ -2104,47 +2111,61 @@ fn search_impl( Direction::Backward => regex.find_iter(doc.regex_input_at_bytes(..start)).last(), }; - if mat.is_none() { - if wrap_around { - mat = match direction { - Direction::Forward => regex.find(doc.regex_input()), - Direction::Backward => regex.find_iter(doc.regex_input_at_bytes(start..)).last(), - }; + if mat.is_none() && !wrap_around { + if show_warnings { + editor.set_error("No more matches"); } + return; + } + + // If we didn't find a match before, lets wrap the search. + if mat.is_none() { + mat = match direction { + Direction::Forward => regex.find(doc.regex_input()), + Direction::Backward => regex.find_iter(doc.regex_input_at_bytes(start..)).last(), + }; + if show_warnings { - if wrap_around && mat.is_some() { - editor.set_status("Wrapped around document"); - } else { - editor.set_error("No more matches"); - } + editor.set_status("Wrapped around document"); } } + let mat = mat.unwrap(); + + // Set the index of this match and total number of matchs in the doc. + let doc = doc!(editor).text().slice(..); + let mut all_matches = regex.find_iter(doc.regex_input()); + let (idx, _) = all_matches + .by_ref() + .enumerate() + .find(|(_, m)| *m == mat) + .unwrap(); + doc_mut!(editor).match_info = Some((idx + 1, all_matches.count() + idx + 1)); + + // Move the cursor to the match. let (view, doc) = current!(editor); let text = doc.text().slice(..); let selection = doc.selection(view.id); - if let Some(mat) = mat { - let start = text.byte_to_char(mat.start()); - let end = text.byte_to_char(mat.end()); + let start = text.byte_to_char(mat.start()); + let end = text.byte_to_char(mat.end()); - if end == 0 { - // skip empty matches that don't make sense - return; - } - - // Determine range direction based on the primary range - let primary = selection.primary(); - let range = Range::new(start, end).with_direction(primary.direction()); + if end == 0 { + // skip empty matches that don't make sense + return; + } - let selection = match movement { - Movement::Extend => selection.clone().push(range), - Movement::Move => selection.clone().replace(selection.primary_index(), range), - }; + // Determine range direction based on the primary range + let primary = selection.primary(); + let range = Range::new(start, end).with_direction(primary.direction()); - doc.set_selection(view.id, selection); - view.ensure_cursor_in_view_center(doc, scrolloff); + let selection = match movement { + Movement::Extend => selection.clone().push(range), + Movement::Move => selection.clone().replace(selection.primary_index(), range), }; + + doc.set_selection(view.id, selection); + view.ensure_cursor_in_view_center(doc, scrolloff); } fn search_completions(cx: &mut Context, reg: Option) -> Vec { diff --git a/helix-term/src/ui/statusline.rs b/helix-term/src/ui/statusline.rs index 7437cbd074e58..c8ffb9af31f79 100644 --- a/helix-term/src/ui/statusline.rs +++ b/helix-term/src/ui/statusline.rs @@ -163,6 +163,7 @@ where helix_view::editor::StatusLineElement::Spacer => render_spacer, helix_view::editor::StatusLineElement::VersionControl => render_version_control, helix_view::editor::StatusLineElement::Register => render_register, + helix_view::editor::StatusLineElement::SearchPosition => render_search_position, } } @@ -531,3 +532,12 @@ where write(context, format!(" reg={} ", reg), None) } } + +fn render_search_position(context: &mut RenderContext, write: F) +where + F: Fn(&mut RenderContext, String, Option