Skip to content

Commit

Permalink
WIP: Search location and total count.
Browse files Browse the repository at this point in the history
  • Loading branch information
useche committed Sep 9, 2024
1 parent ac72adb commit f4765b0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 28 deletions.
77 changes: 49 additions & 28 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2097,54 +2097,75 @@ 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 {
Direction::Forward => regex.find(doc.regex_input_at_bytes(start..)),
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<char>) -> Vec<String> {
Expand Down
10 changes: 10 additions & 0 deletions helix-term/src/ui/statusline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -531,3 +532,12 @@ where
write(context, format!(" reg={} ", reg), None)
}
}

fn render_search_position<F>(context: &mut RenderContext, write: F)
where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,
{
if let Some((idx, count)) = context.doc.match_info {
write(context, format!(" {}/{} ", idx, count), None);
}
}
4 changes: 4 additions & 0 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ pub struct Document {

pub restore_cursor: bool,

/// Current search information.
pub match_info: Option<(usize, usize)>,

/// Current indent style.
pub indent_style: IndentStyle,

Expand Down Expand Up @@ -666,6 +669,7 @@ impl Document {
indent_style: DEFAULT_INDENT,
line_ending,
restore_cursor: false,
match_info: None,
syntax: None,
language: None,
changes,
Expand Down
3 changes: 3 additions & 0 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,9 @@ pub enum StatusLineElement {

/// Indicator for selected register
Register,

/// Search index and count
SearchPosition,
}

// Cursor shape is read and used on every rendered frame and so needs
Expand Down

0 comments on commit f4765b0

Please sign in to comment.