mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 10:29:35 +03:00
Draft search include/exclude logic
This commit is contained in:
parent
915154b047
commit
b5abac6af6
@ -4208,16 +4208,21 @@ impl Project {
|
|||||||
if matching_paths_tx.is_closed() {
|
if matching_paths_tx.is_closed() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
let matches = if !query
|
||||||
abs_path.clear();
|
.file_matches(Some(&entry.path))
|
||||||
abs_path.push(&snapshot.abs_path());
|
|
||||||
abs_path.push(&entry.path);
|
|
||||||
let matches = if let Some(file) =
|
|
||||||
fs.open_sync(&abs_path).await.log_err()
|
|
||||||
{
|
{
|
||||||
query.detect(file).unwrap_or(false)
|
|
||||||
} else {
|
|
||||||
false
|
false
|
||||||
|
} else {
|
||||||
|
abs_path.clear();
|
||||||
|
abs_path.push(&snapshot.abs_path());
|
||||||
|
abs_path.push(&entry.path);
|
||||||
|
if let Some(file) =
|
||||||
|
fs.open_sync(&abs_path).await.log_err()
|
||||||
|
{
|
||||||
|
query.detect(file).unwrap_or(false)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches {
|
if matches {
|
||||||
@ -4299,15 +4304,21 @@ impl Project {
|
|||||||
let mut buffers_rx = buffers_rx.clone();
|
let mut buffers_rx = buffers_rx.clone();
|
||||||
scope.spawn(async move {
|
scope.spawn(async move {
|
||||||
while let Some((buffer, snapshot)) = buffers_rx.next().await {
|
while let Some((buffer, snapshot)) = buffers_rx.next().await {
|
||||||
let buffer_matches = query
|
let buffer_matches = if query.file_matches(
|
||||||
.search(snapshot.as_rope())
|
snapshot.file().map(|file| file.path().as_ref()),
|
||||||
.await
|
) {
|
||||||
.iter()
|
query
|
||||||
.map(|range| {
|
.search(snapshot.as_rope())
|
||||||
snapshot.anchor_before(range.start)
|
.await
|
||||||
..snapshot.anchor_after(range.end)
|
.iter()
|
||||||
})
|
.map(|range| {
|
||||||
.collect::<Vec<_>>();
|
snapshot.anchor_before(range.start)
|
||||||
|
..snapshot.anchor_after(range.end)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
if !buffer_matches.is_empty() {
|
if !buffer_matches.is_empty() {
|
||||||
worker_matched_buffers
|
worker_matched_buffers
|
||||||
.insert(buffer.clone(), buffer_matches);
|
.insert(buffer.clone(), buffer_matches);
|
||||||
|
@ -8,10 +8,11 @@ use smol::future::yield_now;
|
|||||||
use std::{
|
use std::{
|
||||||
io::{BufRead, BufReader, Read},
|
io::{BufRead, BufReader, Read},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
|
path::Path,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SearchQuery {
|
pub enum SearchQuery {
|
||||||
Text {
|
Text {
|
||||||
search: Arc<AhoCorasick<usize>>,
|
search: Arc<AhoCorasick<usize>>,
|
||||||
@ -97,11 +98,13 @@ impl SearchQuery {
|
|||||||
message
|
message
|
||||||
.files_to_include
|
.files_to_include
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
message
|
message
|
||||||
.files_to_exclude
|
.files_to_exclude
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
)
|
)
|
||||||
@ -113,11 +116,13 @@ impl SearchQuery {
|
|||||||
message
|
message
|
||||||
.files_to_include
|
.files_to_include
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
message
|
message
|
||||||
.files_to_exclude
|
.files_to_exclude
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
))
|
))
|
||||||
@ -290,6 +295,7 @@ impl SearchQuery {
|
|||||||
} => files_to_include,
|
} => files_to_include,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn files_to_exclude(&self) -> &[glob::Pattern] {
|
pub fn files_to_exclude(&self) -> &[glob::Pattern] {
|
||||||
match self {
|
match self {
|
||||||
Self::Text {
|
Self::Text {
|
||||||
@ -300,4 +306,21 @@ impl SearchQuery {
|
|||||||
} => files_to_exclude,
|
} => files_to_exclude,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file_matches(&self, file_path: Option<&Path>) -> bool {
|
||||||
|
match file_path {
|
||||||
|
Some(file_path) => {
|
||||||
|
!self
|
||||||
|
.files_to_exclude()
|
||||||
|
.iter()
|
||||||
|
.any(|exclude_glob| exclude_glob.matches_path(file_path))
|
||||||
|
&& (self.files_to_include().is_empty()
|
||||||
|
|| self
|
||||||
|
.files_to_include()
|
||||||
|
.iter()
|
||||||
|
.any(|include_glob| include_glob.matches_path(file_path)))
|
||||||
|
}
|
||||||
|
None => self.files_to_include().is_empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,23 +555,30 @@ impl ProjectSearchView {
|
|||||||
|
|
||||||
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
|
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
|
||||||
let text = self.query_editor.read(cx).text(cx);
|
let text = self.query_editor.read(cx).text(cx);
|
||||||
let included_files = self
|
let Ok(included_files) = self
|
||||||
.included_files_editor
|
.included_files_editor
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.text(cx)
|
.text(cx)
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()
|
.collect::<Result<_, _>>() else {
|
||||||
// TODO kb validation
|
self.query_contains_error = true;
|
||||||
.unwrap_or_default();
|
cx.notify();
|
||||||
let excluded_files = self
|
return None
|
||||||
|
};
|
||||||
|
let Ok(excluded_files) = self
|
||||||
.excluded_files_editor
|
.excluded_files_editor
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.text(cx)
|
.text(cx)
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.filter(|glob_str| !glob_str.trim().is_empty())
|
||||||
.map(|glob_str| glob::Pattern::new(glob_str))
|
.map(|glob_str| glob::Pattern::new(glob_str))
|
||||||
.collect::<Result<_, _>>()
|
.collect::<Result<_, _>>() else {
|
||||||
.unwrap_or_default();
|
self.query_contains_error = true;
|
||||||
|
cx.notify();
|
||||||
|
return None
|
||||||
|
};
|
||||||
if self.regex {
|
if self.regex {
|
||||||
match SearchQuery::regex(
|
match SearchQuery::regex(
|
||||||
text,
|
text,
|
||||||
@ -928,11 +935,11 @@ impl View for ProjectSearchBar {
|
|||||||
let included_files_view = ChildView::new(&search.included_files_editor, cx)
|
let included_files_view = ChildView::new(&search.included_files_editor, cx)
|
||||||
.aligned()
|
.aligned()
|
||||||
.left()
|
.left()
|
||||||
.flex(1., true);
|
.flex(0.5, true);
|
||||||
let excluded_files_view = ChildView::new(&search.excluded_files_editor, cx)
|
let excluded_files_view = ChildView::new(&search.excluded_files_editor, cx)
|
||||||
.aligned()
|
.aligned()
|
||||||
.left()
|
.right()
|
||||||
.flex(1., true);
|
.flex(0.5, true);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
@ -983,25 +990,41 @@ impl View for ProjectSearchBar {
|
|||||||
.with_style(theme.search.option_button_group)
|
.with_style(theme.search.option_button_group)
|
||||||
.aligned(),
|
.aligned(),
|
||||||
)
|
)
|
||||||
|
// TODO kb better layout
|
||||||
.with_child(
|
.with_child(
|
||||||
// TODO kb better layout
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new("Include files:", theme.search.match_index.text.clone())
|
Label::new(
|
||||||
.contained()
|
"Include:",
|
||||||
.with_style(theme.search.match_index.container)
|
theme.search.include_exclude_inputs.text.clone(),
|
||||||
.aligned(),
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.search.include_exclude_inputs.container)
|
||||||
|
.aligned(),
|
||||||
)
|
)
|
||||||
.with_child(included_files_view)
|
.with_child(included_files_view)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.search.editor.input.container)
|
||||||
|
.aligned()
|
||||||
|
.constrained()
|
||||||
|
.with_min_width(theme.search.editor.min_width)
|
||||||
|
.with_max_width(theme.search.editor.max_width)
|
||||||
|
.flex(1., false),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new("Exclude files:", theme.search.match_index.text.clone())
|
Label::new(
|
||||||
.contained()
|
"Exclude:",
|
||||||
.with_style(theme.search.match_index.container)
|
theme.search.include_exclude_inputs.text.clone(),
|
||||||
.aligned(),
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.search.include_exclude_inputs.container)
|
||||||
|
.aligned(),
|
||||||
)
|
)
|
||||||
.with_child(excluded_files_view)
|
.with_child(excluded_files_view)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(editor_container)
|
.with_style(theme.search.editor.input.container)
|
||||||
.aligned()
|
.aligned()
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_min_width(theme.search.editor.min_width)
|
.with_min_width(theme.search.editor.min_width)
|
||||||
|
@ -319,6 +319,7 @@ pub struct Search {
|
|||||||
pub editor: FindEditor,
|
pub editor: FindEditor,
|
||||||
pub invalid_editor: ContainerStyle,
|
pub invalid_editor: ContainerStyle,
|
||||||
pub option_button_group: ContainerStyle,
|
pub option_button_group: ContainerStyle,
|
||||||
|
pub include_exclude_inputs: ContainedText,
|
||||||
pub option_button: Interactive<ContainedText>,
|
pub option_button: Interactive<ContainedText>,
|
||||||
pub match_background: Color,
|
pub match_background: Color,
|
||||||
pub match_index: ContainedText,
|
pub match_index: ContainedText,
|
||||||
|
@ -74,6 +74,10 @@ export default function search(colorScheme: ColorScheme) {
|
|||||||
right: 12,
|
right: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
includeExcludeInputs: {
|
||||||
|
...text(layer, "mono", "variant"),
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
resultsStatus: {
|
resultsStatus: {
|
||||||
...text(layer, "mono", "on"),
|
...text(layer, "mono", "on"),
|
||||||
size: 18,
|
size: 18,
|
||||||
|
Loading…
Reference in New Issue
Block a user