Highlight include/exclude inputs when errors happen there

This commit is contained in:
Kirill Bulatov 2023-05-10 00:06:44 +03:00 committed by Kirill Bulatov
parent dfdf7e4866
commit eec60556ab
3 changed files with 67 additions and 23 deletions

View File

@ -22,6 +22,7 @@ use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
borrow::Cow,
collections::HashSet,
mem,
ops::Range,
path::PathBuf,
@ -76,6 +77,13 @@ struct ProjectSearch {
search_id: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum InputPanel {
Query,
Exclude,
Include,
}
pub struct ProjectSearchView {
model: ModelHandle<ProjectSearch>,
query_editor: ViewHandle<Editor>,
@ -83,7 +91,7 @@ pub struct ProjectSearchView {
case_sensitive: bool,
whole_word: bool,
regex: bool,
query_contains_error: bool,
panels_with_errors: HashSet<InputPanel>,
active_match_index: Option<usize>,
search_id: usize,
query_editor_was_focused: bool,
@ -493,7 +501,7 @@ impl ProjectSearchView {
case_sensitive,
whole_word,
regex,
query_contains_error: false,
panels_with_errors: HashSet::new(),
active_match_index: None,
query_editor_was_focused: false,
included_files_editor,
@ -564,7 +572,7 @@ impl ProjectSearchView {
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
let text = self.query_editor.read(cx).text(cx);
let Ok(included_files) = self
let included_files = match self
.included_files_editor
.read(cx)
.text(cx)
@ -572,12 +580,19 @@ impl ProjectSearchView {
.map(str::trim)
.filter(|glob_str| !glob_str.is_empty())
.map(|glob_str| glob::Pattern::new(glob_str))
.collect::<Result<_, _>>() else {
self.query_contains_error = true;
.collect::<Result<_, _>>()
{
Ok(included_files) => {
self.panels_with_errors.remove(&InputPanel::Include);
included_files
}
Err(_e) => {
self.panels_with_errors.insert(InputPanel::Include);
cx.notify();
return None
};
let Ok(excluded_files) = self
return None;
}
};
let excluded_files = match self
.excluded_files_editor
.read(cx)
.text(cx)
@ -585,11 +600,18 @@ impl ProjectSearchView {
.map(str::trim)
.filter(|glob_str| !glob_str.is_empty())
.map(|glob_str| glob::Pattern::new(glob_str))
.collect::<Result<_, _>>() else {
self.query_contains_error = true;
.collect::<Result<_, _>>()
{
Ok(excluded_files) => {
self.panels_with_errors.remove(&InputPanel::Exclude);
excluded_files
}
Err(_e) => {
self.panels_with_errors.insert(InputPanel::Exclude);
cx.notify();
return None
};
return None;
}
};
if self.regex {
match SearchQuery::regex(
text,
@ -598,9 +620,12 @@ impl ProjectSearchView {
included_files,
excluded_files,
) {
Ok(query) => Some(query),
Err(_) => {
self.query_contains_error = true;
Ok(query) => {
self.panels_with_errors.remove(&InputPanel::Query);
Some(query)
}
Err(_e) => {
self.panels_with_errors.insert(InputPanel::Query);
cx.notify();
None
}
@ -968,11 +993,23 @@ impl View for ProjectSearchBar {
if let Some(search) = self.active_project_search.as_ref() {
let search = search.read(cx);
let theme = cx.global::<Settings>().theme.clone();
let editor_container = if search.query_contains_error {
let query_container_style = if search.panels_with_errors.contains(&InputPanel::Query) {
theme.search.invalid_editor
} else {
theme.search.editor.input.container
};
let include_container_style =
if search.panels_with_errors.contains(&InputPanel::Include) {
theme.search.invalid_include_exclude_editor
} else {
theme.search.include_exclude_editor.input.container
};
let exclude_container_style =
if search.panels_with_errors.contains(&InputPanel::Exclude) {
theme.search.invalid_include_exclude_editor
} else {
theme.search.include_exclude_editor.input.container
};
let included_files_view = ChildView::new(&search.included_files_editor, cx)
.aligned()
@ -1010,7 +1047,7 @@ impl View for ProjectSearchBar {
.aligned()
}))
.contained()
.with_style(editor_container)
.with_style(query_container_style)
.aligned()
.constrained()
.with_min_width(theme.search.editor.min_width)
@ -1053,7 +1090,7 @@ impl View for ProjectSearchBar {
Flex::row()
.with_child(included_files_view)
.contained()
.with_style(theme.search.include_exclude_editor.input.container)
.with_style(include_container_style)
.aligned()
.constrained()
.with_min_width(theme.search.include_exclude_editor.min_width)
@ -1064,7 +1101,7 @@ impl View for ProjectSearchBar {
Flex::row()
.with_child(excluded_files_view)
.contained()
.with_style(theme.search.include_exclude_editor.input.container)
.with_style(exclude_container_style)
.aligned()
.constrained()
.with_min_width(theme.search.include_exclude_editor.min_width)

View File

@ -320,6 +320,7 @@ pub struct Search {
pub invalid_editor: ContainerStyle,
pub option_button_group: ContainerStyle,
pub include_exclude_editor: FindEditor,
pub invalid_include_exclude_editor: ContainerStyle,
pub include_exclude_inputs: ContainedText,
pub option_button: Interactive<ContainedText>,
pub match_background: Color,

View File

@ -26,6 +26,12 @@ export default function search(colorScheme: ColorScheme) {
},
}
const includeExcludeEditor = {
...editor,
minWidth: 100,
maxWidth: 250,
};
return {
// TODO: Add an activeMatchBackground on the rust side to differenciate between active and inactive
matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
@ -64,10 +70,10 @@ export default function search(colorScheme: ColorScheme) {
...editor,
border: border(layer, "negative"),
},
includeExcludeEditor: {
...editor,
minWidth: 100,
maxWidth: 250,
includeExcludeEditor,
invalidIncludeExcludeEditor: {
...includeExcludeEditor,
border: border(layer, "negative"),
},
matchIndex: {
...text(layer, "mono", "variant"),