From f649074d36e5647a1e444998bb03a44a0a043fa1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 25 Feb 2022 15:27:34 +0100 Subject: [PATCH] Refine project find's UX Co-Authored-By: Nathan Sobo --- crates/editor/src/multi_buffer.rs | 6 +++ crates/find/src/project_find.rs | 60 +++++++++++++++++++---------- crates/sum_tree/src/cursor.rs | 28 ++++++++------ crates/sum_tree/src/sum_tree.rs | 8 ++++ crates/theme/src/theme.rs | 1 + crates/zed/assets/themes/_base.toml | 1 + 6 files changed, 73 insertions(+), 31 deletions(-) diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index f447350ec5..0868a8799f 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1175,6 +1175,12 @@ impl MultiBuffer { let mut buffers = Vec::new(); for _ in 0..mutation_count { + if rng.gen_bool(0.05) { + log::info!("Clearing multi-buffer"); + self.clear(cx); + continue; + } + let excerpt_ids = self .buffers .borrow() diff --git a/crates/find/src/project_find.rs b/crates/find/src/project_find.rs index ff34015d95..99f5105a38 100644 --- a/crates/find/src/project_find.rs +++ b/crates/find/src/project_find.rs @@ -30,7 +30,7 @@ pub fn init(cx: &mut MutableAppContext) { struct ProjectFind { project: ModelHandle, excerpts: ModelHandle, - pending_search: Task>, + pending_search: Option>>, highlighted_ranges: Vec>, } @@ -55,7 +55,7 @@ impl ProjectFind { Self { project, excerpts: cx.add_model(|_| MultiBuffer::new(replica_id)), - pending_search: Task::ready(None), + pending_search: None, highlighted_ranges: Default::default(), } } @@ -64,7 +64,8 @@ impl ProjectFind { let search = self .project .update(cx, |project, cx| project.search(query, cx)); - self.pending_search = cx.spawn_weak(|this, mut cx| async move { + self.highlighted_ranges.clear(); + self.pending_search = Some(cx.spawn_weak(|this, mut cx| async move { let matches = search.await; if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| { @@ -84,11 +85,13 @@ impl ProjectFind { this.highlighted_ranges.extend(ranges_to_highlight); } }); + this.pending_search.take(); cx.notify(); }); } None - }); + })); + cx.notify(); } } @@ -147,13 +150,31 @@ impl View for ProjectFindView { } fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + let model = &self.model.read(cx); + let results = if model.highlighted_ranges.is_empty() { + let theme = &self.settings.borrow().theme; + let text = if self.query_editor.read(cx).text(cx).is_empty() { + "" + } else if model.pending_search.is_some() { + "Searching..." + } else { + "No results" + }; + Label::new(text.to_string(), theme.find.results_status.clone()) + .aligned() + .contained() + .with_background_color(theme.editor.background) + .flexible(1., true) + .boxed() + } else { + ChildView::new(&self.results_editor) + .flexible(1., true) + .boxed() + }; + Flex::column() .with_child(self.render_query_editor(cx)) - .with_child( - ChildView::new(&self.results_editor) - .flexible(1., true) - .boxed(), - ) + .with_child(results) .boxed() } @@ -265,17 +286,16 @@ impl ProjectFindView { } fn on_model_changed(&mut self, _: ModelHandle, cx: &mut ViewContext) { - let theme = &self.settings.borrow().theme.find; - self.results_editor.update(cx, |editor, cx| { - let model = self.model.read(cx); - editor.highlight_ranges::( - model.highlighted_ranges.clone(), - theme.match_background, - cx, - ); - editor.select_ranges([0..0], Some(Autoscroll::Fit), cx); - }); - cx.focus(&self.results_editor); + let highlighted_ranges = self.model.read(cx).highlighted_ranges.clone(); + if !highlighted_ranges.is_empty() { + let theme = &self.settings.borrow().theme.find; + self.results_editor.update(cx, |editor, cx| { + editor.highlight_ranges::(highlighted_ranges, theme.match_background, cx); + editor.select_ranges([0..0], Some(Autoscroll::Fit), cx); + }); + cx.focus(&self.results_editor); + } + cx.notify(); } fn render_query_editor(&self, cx: &mut RenderContext) -> ElementBox { diff --git a/crates/sum_tree/src/cursor.rs b/crates/sum_tree/src/cursor.rs index cbb6f7f6f5..fab2aa5251 100644 --- a/crates/sum_tree/src/cursor.rs +++ b/crates/sum_tree/src/cursor.rs @@ -34,13 +34,13 @@ where stack: ArrayVec::new(), position: D::default(), did_seek: false, - at_end: false, + at_end: tree.is_empty(), } } fn reset(&mut self) { self.did_seek = false; - self.at_end = false; + self.at_end = self.tree.is_empty(); self.stack.truncate(0); self.position = D::default(); } @@ -139,7 +139,7 @@ where if self.at_end { self.position = D::default(); self.descend_to_last_item(self.tree, cx); - self.at_end = false; + self.at_end = self.tree.is_empty(); } else { while let Some(entry) = self.stack.pop() { if entry.index > 0 { @@ -195,13 +195,15 @@ where { let mut descend = false; - if self.stack.is_empty() && !self.at_end { - self.stack.push(StackEntry { - tree: self.tree, - index: 0, - position: D::default(), - }); - descend = true; + if self.stack.is_empty() { + if !self.at_end { + self.stack.push(StackEntry { + tree: self.tree, + index: 0, + position: D::default(), + }); + descend = true; + } self.did_seek = true; } @@ -279,6 +281,10 @@ where cx: &::Context, ) { self.did_seek = true; + if subtree.is_empty() { + return; + } + loop { match subtree.0.as_ref() { Node::Internal { @@ -298,7 +304,7 @@ where subtree = child_trees.last().unwrap(); } Node::Leaf { item_summaries, .. } => { - let last_index = item_summaries.len().saturating_sub(1); + let last_index = item_summaries.len() - 1; for item_summary in &item_summaries[0..last_index] { self.position.add_summary(item_summary, cx); } diff --git a/crates/sum_tree/src/sum_tree.rs b/crates/sum_tree/src/sum_tree.rs index ea21672b10..c372ffc6b0 100644 --- a/crates/sum_tree/src/sum_tree.rs +++ b/crates/sum_tree/src/sum_tree.rs @@ -821,6 +821,14 @@ mod tests { assert_eq!(cursor.item(), None); assert_eq!(cursor.prev_item(), None); assert_eq!(cursor.start().sum, 0); + cursor.prev(&()); + assert_eq!(cursor.item(), None); + assert_eq!(cursor.prev_item(), None); + assert_eq!(cursor.start().sum, 0); + cursor.next(&()); + assert_eq!(cursor.item(), None); + assert_eq!(cursor.prev_item(), None); + assert_eq!(cursor.start().sum, 0); // Single-element tree let mut tree = SumTree::::new(); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 483d399276..babd9f6e20 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -107,6 +107,7 @@ pub struct Find { pub active_hovered_option_button: ContainedText, pub match_background: Color, pub match_index: ContainedText, + pub results_status: TextStyle, } #[derive(Clone, Deserialize, Default)] diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 479b577366..f7fd023f23 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -351,6 +351,7 @@ tab_summary_spacing = 10 [find] match_background = "$state.highlighted_line" background = "$surface.1" +results_status = { extends = "$text.0", size = 18 } [find.option_button] extends = "$text.1"