From d2a64f217176f67818e0f6b964a78b0029153887 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 28 Jan 2022 17:26:08 +0100 Subject: [PATCH] Optimize search when regex doesn't contain newlines Co-Authored-By: Nathan Sobo Co-Authored-By: Max Brunsfeld --- crates/find/src/find.rs | 52 ++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/crates/find/src/find.rs b/crates/find/src/find.rs index 90412fb99b60466120125ca1baeefce916ca2e3a..f57c531987fa8742ae95ffb7b41cd86960863807 100644 --- a/crates/find/src/find.rs +++ b/crates/find/src/find.rs @@ -115,7 +115,8 @@ impl Toolbar for FindBar { impl FindBar { fn new(settings: watch::Receiver, cx: &mut ViewContext) -> Self { let query_editor = cx.add_view(|cx| { - Editor::single_line( + Editor::auto_height( + 2, { let settings = settings.clone(); Arc::new(move |_| { @@ -349,16 +350,49 @@ async fn regex_search( let mut ranges = Vec::new(); - let regex = RegexBuilder::new(&query) - .case_insensitive(!case_sensitive) - .multi_line(true) - .build()?; - for (ix, mat) in regex.find_iter(&buffer.text()).enumerate() { - if (ix + 1) % YIELD_INTERVAL == 0 { - yield_now().await; + if query.contains("\n") || query.contains("\\n") { + let regex = RegexBuilder::new(&query) + .case_insensitive(!case_sensitive) + .multi_line(true) + .build()?; + for (ix, mat) in regex.find_iter(&buffer.text()).enumerate() { + if (ix + 1) % YIELD_INTERVAL == 0 { + yield_now().await; + } + + ranges.push(buffer.anchor_after(mat.start())..buffer.anchor_before(mat.end())); } + } else { + let regex = RegexBuilder::new(&query) + .case_insensitive(!case_sensitive) + .build()?; + + let mut line = String::new(); + let mut line_offset = 0; + for (chunk_ix, chunk) in buffer + .chunks(0..buffer.len(), None) + .map(|c| c.text) + .chain(["\n"]) + .enumerate() + { + if (chunk_ix + 1) % YIELD_INTERVAL == 0 { + yield_now().await; + } - ranges.push(buffer.anchor_after(mat.start())..buffer.anchor_before(mat.end())); + for (newline_ix, text) in chunk.split('\n').enumerate() { + if newline_ix > 0 { + for mat in regex.find_iter(&line) { + let start = line_offset + mat.start(); + let end = line_offset + mat.end(); + ranges.push(buffer.anchor_after(start)..buffer.anchor_before(end)); + } + + line_offset += line.len() + 1; + line.clear(); + } + line.push_str(text); + } + } } Ok(ranges)