From 1adb19464f002926e1042027b41acef4c81585f6 Mon Sep 17 00:00:00 2001 From: Pascal Kuthe Date: Tue, 11 Jul 2023 14:26:11 +0200 Subject: search buffer contents during global search (#5652) --- helix-term/src/commands.rs | 51 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'helix-term/src/commands.rs') diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index b90f418a..ae715887 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -29,7 +29,7 @@ use helix_core::{ tree_sitter::Node, unicode::width::UnicodeWidthChar, visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes, - RopeSlice, Selection, SmallVec, Tendril, Transaction, + RopeReader, RopeSlice, Selection, SmallVec, Tendril, Transaction, }; use helix_view::{ clipboard::ClipboardType, @@ -2062,11 +2062,16 @@ fn global_search(cx: &mut Context) { .map(|comp| (0.., std::borrow::Cow::Owned(comp.clone()))) .collect() }, - move |_editor, regex, event| { + move |editor, regex, event| { if event != PromptEvent::Validate { return; } + let documents: Vec<_> = editor + .documents() + .map(|doc| (doc.path(), doc.text())) + .collect(); + if let Ok(matcher) = RegexMatcherBuilder::new() .case_smart(smart_case) .build(regex.as_str()) @@ -2099,6 +2104,7 @@ fn global_search(cx: &mut Context) { let mut searcher = searcher.clone(); let matcher = matcher.clone(); let all_matches_sx = all_matches_sx.clone(); + let documents = &documents; Box::new(move |entry: Result| -> WalkState { let entry = match entry { Ok(entry) => entry, @@ -2111,17 +2117,36 @@ fn global_search(cx: &mut Context) { _ => return WalkState::Continue, }; - let result = searcher.search_path( - &matcher, - entry.path(), - sinks::UTF8(|line_num, _| { - all_matches_sx - .send(FileResult::new(entry.path(), line_num as usize - 1)) - .unwrap(); - - Ok(true) - }), - ); + let sink = sinks::UTF8(|line_num, _| { + all_matches_sx + .send(FileResult::new(entry.path(), line_num as usize - 1)) + .unwrap(); + + Ok(true) + }); + let doc = documents.iter().find(|&(doc_path, _)| { + doc_path.map_or(false, |doc_path| doc_path == entry.path()) + }); + + let result = if let Some((_, doc)) = doc { + // there is already a buffer for this file + // search the buffer instead of the file because it's faster + // and captures new edits without requireing a save + if searcher.multi_line_with_matcher(&matcher) { + // in this case a continous buffer is required + // convert the rope to a string + let text = doc.to_string(); + searcher.search_slice(&matcher, text.as_bytes(), sink) + } else { + searcher.search_reader( + &matcher, + RopeReader::new(doc.slice(..)), + sink, + ) + } + } else { + searcher.search_path(&matcher, entry.path(), sink) + }; if let Err(err) = result { log::error!( -- cgit v1.2.3-70-g09d2