search buffer contents during global search (#5652)

pull/7605/head
Pascal Kuthe 1 year ago committed by GitHub
parent 541d2b76d6
commit 1adb19464f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -41,7 +41,9 @@ pub use helix_loader::find_workspace;
pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> {
line.chars().position(|ch| !ch.is_whitespace())
}
mod rope_reader;
pub use rope_reader::RopeReader;
pub use ropey::{self, str_utils, Rope, RopeBuilder, RopeSlice};
// pub use tendril::StrTendril as Tendril;

@ -0,0 +1,37 @@
use std::io;
use ropey::iter::Chunks;
use ropey::RopeSlice;
pub struct RopeReader<'a> {
current_chunk: &'a [u8],
chunks: Chunks<'a>,
}
impl<'a> RopeReader<'a> {
pub fn new(rope: RopeSlice<'a>) -> RopeReader<'a> {
RopeReader {
current_chunk: &[],
chunks: rope.chunks(),
}
}
}
impl io::Read for RopeReader<'_> {
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
let buf_len = buf.len();
loop {
let read_bytes = self.current_chunk.read(buf)?;
buf = &mut buf[read_bytes..];
if buf.is_empty() {
return Ok(buf_len);
}
if let Some(next_chunk) = self.chunks.next() {
self.current_chunk = next_chunk.as_bytes();
} else {
return Ok(buf_len - buf.len());
}
}
}
}

@ -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<DirEntry, ignore::Error>| -> 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!(

Loading…
Cancel
Save