From 5c3d563f0fb5093154d589851ef9d45bc7f154de Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 9 Aug 2023 20:24:06 +0300 Subject: [PATCH 01/13] Draft quick actions bar --- crates/editor/src/editor.rs | 33 +++++- crates/editor/src/inlay_hint_cache.rs | 2 +- crates/search/src/buffer_search.rs | 2 +- crates/theme/src/theme.rs | 1 + crates/zed/src/quick_action_bar.rs | 143 ++++++++++++++++++++++++++ crates/zed/src/zed.rs | 7 ++ styles/src/style_tree/workspace.ts | 4 + 7 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 crates/zed/src/quick_action_bar.rs diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 256ef2284cd6c3ffbb6f7e9746ddfb8e75a4bdfd..3c6103cd908b2fd0d5ebc6bd8cafe3c1a54a5ea9 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -302,10 +302,11 @@ actions!( Hover, Format, ToggleSoftWrap, + ToggleInlays, RevealInFinder, CopyPath, CopyRelativePath, - CopyHighlightJson + CopyHighlightJson, ] ); @@ -446,6 +447,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(Editor::toggle_code_actions); cx.add_action(Editor::open_excerpts); cx.add_action(Editor::toggle_soft_wrap); + cx.add_action(Editor::toggle_inlays); cx.add_action(Editor::reveal_in_finder); cx.add_action(Editor::copy_path); cx.add_action(Editor::copy_relative_path); @@ -1238,6 +1240,7 @@ enum GotoDefinitionKind { #[derive(Debug, Clone)] enum InlayRefreshReason { + Toggled(bool), SettingsChange(InlayHintSettings), NewLinesShown, BufferEdited(HashSet>), @@ -2669,12 +2672,40 @@ impl Editor { } } + pub fn toggle_inlays(&mut self, _: &ToggleInlays, cx: &mut ViewContext) { + self.inlay_hint_cache.enabled = !self.inlay_hint_cache.enabled; + self.refresh_inlays( + InlayRefreshReason::Toggled(self.inlay_hint_cache.enabled), + cx, + ) + } + + pub fn inlays_enabled(&self) -> bool { + self.inlay_hint_cache.enabled + } + fn refresh_inlays(&mut self, reason: InlayRefreshReason, cx: &mut ViewContext) { if self.project.is_none() || self.mode != EditorMode::Full { return; } let (invalidate_cache, required_languages) = match reason { + InlayRefreshReason::Toggled(enabled) => { + if enabled { + (InvalidationStrategy::RefreshRequested, None) + } else { + self.inlay_hint_cache.clear(); + self.splice_inlay_hints( + self.visible_inlay_hints(cx) + .iter() + .map(|inlay| inlay.id) + .collect(), + Vec::new(), + cx, + ); + return; + } + } InlayRefreshReason::SettingsChange(new_settings) => { match self.inlay_hint_cache.update_settings( &self.buffer, diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 8be72aec46d7c2192e10b235a9add2038c01684b..4327ff0d7330c96a3ddc662a2bcd985bf1373325 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -380,7 +380,7 @@ impl InlayHintCache { } } - fn clear(&mut self) { + pub fn clear(&mut self) { self.version += 1; self.update_tasks.clear(); self.hints.clear(); diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 36c9d3becd346314269a694f5e58a34f52bc1981..fc3c78afe233c1516fbfed4ef98df381a62f34f8 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -553,7 +553,7 @@ impl BufferSearchBar { .into_any() } - fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext) { + pub fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext) { let mut propagate_action = true; if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { search_bar.update(cx, |search_bar, cx| { diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 69fa7a09b3efa908b2da9a8a89e9fa533aba9505..30a2e8caec70ac6e922cf11d5e45060024122684 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -399,6 +399,7 @@ pub struct Toolbar { pub height: f32, pub item_spacing: f32, pub nav_button: Interactive, + pub toggleable_tool: Toggleable>, } #[derive(Clone, Deserialize, Default, JsonSchema)] diff --git a/crates/zed/src/quick_action_bar.rs b/crates/zed/src/quick_action_bar.rs new file mode 100644 index 0000000000000000000000000000000000000000..28dba9399f9073a2e8aa798c358bcaf8dd80350b --- /dev/null +++ b/crates/zed/src/quick_action_bar.rs @@ -0,0 +1,143 @@ +use editor::Editor; +use gpui::{ + elements::{Empty, Flex, MouseEventHandler, ParentElement, Svg}, + platform::{CursorStyle, MouseButton}, + Action, AnyElement, Element, Entity, EventContext, View, ViewContext, ViewHandle, +}; + +use search::{buffer_search, BufferSearchBar}; +use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView, Workspace}; + +pub struct QuickActionBar { + workspace: ViewHandle, + active_item: Option>, +} + +impl QuickActionBar { + pub fn new(workspace: ViewHandle) -> Self { + Self { + workspace, + active_item: None, + } + } + + fn active_editor(&self) -> Option> { + self.active_item + .as_ref() + .and_then(|item| item.downcast::()) + } +} + +impl Entity for QuickActionBar { + type Event = (); +} + +impl View for QuickActionBar { + fn ui_name() -> &'static str { + "QuickActionsBar" + } + + fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { + let Some(editor) = self.active_editor() else { return Empty::new().into_any(); }; + + let inlays_enabled = editor.read(cx).inlays_enabled(); + let mut bar = Flex::row().with_child(render_quick_action_bar_button( + 0, + "icons/hamburger_15.svg", + inlays_enabled, + ( + "Toggle inlays".to_string(), + Some(Box::new(editor::ToggleInlays)), + ), + cx, + |this, cx| { + if let Some(editor) = this.active_editor() { + editor.update(cx, |editor, cx| { + editor.toggle_inlays(&editor::ToggleInlays, cx); + }); + } + }, + )); + + if editor.read(cx).buffer().read(cx).is_singleton() { + let search_action = buffer_search::Deploy { focus: true }; + + // TODO kb: this opens the search bar in a differently focused pane (should be the same) + should be toggleable + let pane = self.workspace.read(cx).active_pane().clone(); + bar = bar.with_child(render_quick_action_bar_button( + 1, + "icons/magnifying_glass_12.svg", + false, + ( + "Search in buffer".to_string(), + Some(Box::new(search_action.clone())), + ), + cx, + move |_, cx| { + pane.update(cx, |pane, cx| { + BufferSearchBar::deploy(pane, &search_action, cx); + }); + }, + )); + } + + bar.into_any() + } +} + +fn render_quick_action_bar_button< + F: 'static + Fn(&mut QuickActionBar, &mut EventContext), +>( + index: usize, + icon: &'static str, + toggled: bool, + tooltip: (String, Option>), + cx: &mut ViewContext, + on_click: F, +) -> AnyElement { + enum QuickActionBarButton {} + + let theme = theme::current(cx); + let (tooltip_text, action) = tooltip; + + MouseEventHandler::::new(index, cx, |mouse_state, _| { + let style = theme + .workspace + .toolbar + .toggleable_tool + .in_state(toggled) + .style_for(mouse_state); + Svg::new(icon) + .with_color(style.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .constrained() + .with_width(style.button_width) + .with_height(style.button_width) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)) + .with_tooltip::(index, tooltip_text, action, theme.tooltip.clone(), cx) + .into_any_named("quick action bar button") +} + +impl ToolbarItemView for QuickActionBar { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + _: &mut ViewContext, + ) -> ToolbarItemLocation { + match active_pane_item { + Some(active_item) => { + dbg!("@@@@@@@@@@ TODO kb", active_item.id()); + self.active_item = Some(active_item.boxed_clone()); + ToolbarItemLocation::PrimaryRight { flex: None } + } + None => { + self.active_item = None; + ToolbarItemLocation::Hidden + } + } + } +} diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1c57174fe289bffe4f0b7e4d245bb017d38f68fc..5ff453484cda20fcb1f4be2a35b69feb0f9e0fd6 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -5,6 +5,8 @@ pub mod only_instance; #[cfg(any(test, feature = "test-support"))] pub mod test; +mod quick_action_bar; + use ai::AssistantPanel; use anyhow::Context; use assets::Assets; @@ -30,6 +32,7 @@ use gpui::{ pub use lsp; pub use project; use project_panel::ProjectPanel; +use quick_action_bar::QuickActionBar; use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize; use serde_json::to_string_pretty; @@ -255,12 +258,16 @@ pub fn initialize_workspace( workspace_handle.update(&mut cx, |workspace, cx| { let workspace_handle = cx.handle(); cx.subscribe(&workspace_handle, { + let workspace_handle = workspace_handle.clone(); move |workspace, _, event, cx| { if let workspace::Event::PaneAdded(pane) = event { pane.update(cx, |pane, cx| { pane.toolbar().update(cx, |toolbar, cx| { let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace)); toolbar.add_item(breadcrumbs, cx); + let quick_action_bar = + cx.add_view(|_| QuickActionBar::new(workspace_handle.clone())); + toolbar.add_item(quick_action_bar, cx); let buffer_search_bar = cx.add_view(BufferSearchBar::new); toolbar.add_item(buffer_search_bar, cx); let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); diff --git a/styles/src/style_tree/workspace.ts b/styles/src/style_tree/workspace.ts index 5aee3c987d34b75d25db5bc9ad69f4d2a0938f7b..4d44166eb8075ab4aae39fdc033b19b76f8fa7dd 100644 --- a/styles/src/style_tree/workspace.ts +++ b/styles/src/style_tree/workspace.ts @@ -12,6 +12,7 @@ import tabBar from "./tab_bar" import { interactive } from "../element" import { titlebar } from "./titlebar" import { useTheme } from "../theme" +import { toggleable_icon_button } from "../component/icon_button" export default function workspace(): any { const theme = useTheme() @@ -149,6 +150,9 @@ export default function workspace(): any { }, }, }), + toggleable_tool: toggleable_icon_button(theme, { + active_color: "accent", + }), padding: { left: 8, right: 8, top: 4, bottom: 4 }, }, breadcrumb_height: 24, From 6a326c1bd86a32ea9d4d0f4c9baa05773c60b1c0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 10 Aug 2023 00:15:37 +0300 Subject: [PATCH 02/13] Toggle buffer search via quick actions --- crates/zed/src/quick_action_bar.rs | 42 +++++++++++++++++++++--------- crates/zed/src/zed.rs | 7 +++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/crates/zed/src/quick_action_bar.rs b/crates/zed/src/quick_action_bar.rs index 28dba9399f9073a2e8aa798c358bcaf8dd80350b..c133f5ece44bc238912cbc91817095d2863cf4d3 100644 --- a/crates/zed/src/quick_action_bar.rs +++ b/crates/zed/src/quick_action_bar.rs @@ -6,17 +6,17 @@ use gpui::{ }; use search::{buffer_search, BufferSearchBar}; -use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView, Workspace}; +use workspace::{item::ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; pub struct QuickActionBar { - workspace: ViewHandle, + pane: ViewHandle, active_item: Option>, } impl QuickActionBar { - pub fn new(workspace: ViewHandle) -> Self { + pub fn new(pane: ViewHandle) -> Self { Self { - workspace, + pane, active_item: None, } } @@ -60,23 +60,40 @@ impl View for QuickActionBar { )); if editor.read(cx).buffer().read(cx).is_singleton() { + let buffer_search_bar = self + .pane + .read(cx) + .toolbar() + .read(cx) + .item_of_type::(); + let search_bar_shown = buffer_search_bar + .as_ref() + .map(|bar| !bar.read(cx).is_dismissed()) + .unwrap_or(false); + let search_action = buffer_search::Deploy { focus: true }; - // TODO kb: this opens the search bar in a differently focused pane (should be the same) + should be toggleable - let pane = self.workspace.read(cx).active_pane().clone(); bar = bar.with_child(render_quick_action_bar_button( 1, "icons/magnifying_glass_12.svg", - false, + search_bar_shown, ( - "Search in buffer".to_string(), + "Toggle buffer search".to_string(), Some(Box::new(search_action.clone())), ), cx, - move |_, cx| { - pane.update(cx, |pane, cx| { - BufferSearchBar::deploy(pane, &search_action, cx); - }); + move |this, cx| { + if search_bar_shown { + if let Some(buffer_search_bar) = buffer_search_bar.as_ref() { + buffer_search_bar.update(cx, |buffer_search_bar, cx| { + buffer_search_bar.dismiss(&buffer_search::Dismiss, cx); + }); + } + } else { + this.pane.update(cx, |pane, cx| { + BufferSearchBar::deploy(pane, &search_action, cx); + }); + } }, )); } @@ -130,7 +147,6 @@ impl ToolbarItemView for QuickActionBar { ) -> ToolbarItemLocation { match active_pane_item { Some(active_item) => { - dbg!("@@@@@@@@@@ TODO kb", active_item.id()); self.active_item = Some(active_item.boxed_clone()); ToolbarItemLocation::PrimaryRight { flex: None } } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 5ff453484cda20fcb1f4be2a35b69feb0f9e0fd6..47dff41729b1cb1c5c68d26a9da2330b7bddaf37 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -258,15 +258,14 @@ pub fn initialize_workspace( workspace_handle.update(&mut cx, |workspace, cx| { let workspace_handle = cx.handle(); cx.subscribe(&workspace_handle, { - let workspace_handle = workspace_handle.clone(); move |workspace, _, event, cx| { - if let workspace::Event::PaneAdded(pane) = event { - pane.update(cx, |pane, cx| { + if let workspace::Event::PaneAdded(pane_handle) = event { + pane_handle.update(cx, |pane, cx| { pane.toolbar().update(cx, |toolbar, cx| { let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace)); toolbar.add_item(breadcrumbs, cx); let quick_action_bar = - cx.add_view(|_| QuickActionBar::new(workspace_handle.clone())); + cx.add_view(|_| QuickActionBar::new(pane_handle.clone())); toolbar.add_item(quick_action_bar, cx); let buffer_search_bar = cx.add_view(BufferSearchBar::new); toolbar.add_item(buffer_search_bar, cx); From 0b93e490a550693f4b65faf61d30c8ae14943cb2 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 10 Aug 2023 12:28:17 +0300 Subject: [PATCH 03/13] Improve toggle UI, fix inlays update speed --- crates/editor/src/editor.rs | 11 ++++++----- crates/zed/src/quick_action_bar.rs | 10 +++++----- styles/src/style_tree/workspace.ts | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3c6103cd908b2fd0d5ebc6bd8cafe3c1a54a5ea9..ef02cee3d03babc9a1279d2654a19da830ed53ce 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1240,7 +1240,7 @@ enum GotoDefinitionKind { #[derive(Debug, Clone)] enum InlayRefreshReason { - Toggled(bool), + Toggle(bool), SettingsChange(InlayHintSettings), NewLinesShown, BufferEdited(HashSet>), @@ -2673,11 +2673,10 @@ impl Editor { } pub fn toggle_inlays(&mut self, _: &ToggleInlays, cx: &mut ViewContext) { - self.inlay_hint_cache.enabled = !self.inlay_hint_cache.enabled; self.refresh_inlays( - InlayRefreshReason::Toggled(self.inlay_hint_cache.enabled), + InlayRefreshReason::Toggle(!self.inlay_hint_cache.enabled), cx, - ) + ); } pub fn inlays_enabled(&self) -> bool { @@ -2690,7 +2689,8 @@ impl Editor { } let (invalidate_cache, required_languages) = match reason { - InlayRefreshReason::Toggled(enabled) => { + InlayRefreshReason::Toggle(enabled) => { + self.inlay_hint_cache.enabled = enabled; if enabled { (InvalidationStrategy::RefreshRequested, None) } else { @@ -2805,6 +2805,7 @@ impl Editor { self.display_map.update(cx, |display_map, cx| { display_map.splice_inlays(to_remove, to_insert, cx); }); + cx.notify(); } fn trigger_on_type_formatting( diff --git a/crates/zed/src/quick_action_bar.rs b/crates/zed/src/quick_action_bar.rs index c133f5ece44bc238912cbc91817095d2863cf4d3..6157ca9c47bb63d35d02f50cf3dc70347887e324 100644 --- a/crates/zed/src/quick_action_bar.rs +++ b/crates/zed/src/quick_action_bar.rs @@ -45,10 +45,7 @@ impl View for QuickActionBar { 0, "icons/hamburger_15.svg", inlays_enabled, - ( - "Toggle inlays".to_string(), - Some(Box::new(editor::ToggleInlays)), - ), + ("Inlays".to_string(), Some(Box::new(editor::ToggleInlays))), cx, |this, cx| { if let Some(editor) = this.active_editor() { @@ -78,7 +75,8 @@ impl View for QuickActionBar { "icons/magnifying_glass_12.svg", search_bar_shown, ( - "Toggle buffer search".to_string(), + "Buffer search".to_string(), + // TODO kb no keybinding is shown for search + toggle inlays does not update icon color Some(Box::new(search_action.clone())), ), cx, @@ -132,6 +130,8 @@ fn render_quick_action_bar_button< .constrained() .with_width(style.button_width) .with_height(style.button_width) + .contained() + .with_style(style.container) }) .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)) diff --git a/styles/src/style_tree/workspace.ts b/styles/src/style_tree/workspace.ts index 4d44166eb8075ab4aae39fdc033b19b76f8fa7dd..578dd23c6ecf30f3acef617fc6cf4140547980bf 100644 --- a/styles/src/style_tree/workspace.ts +++ b/styles/src/style_tree/workspace.ts @@ -151,6 +151,7 @@ export default function workspace(): any { }, }), toggleable_tool: toggleable_icon_button(theme, { + margin: { left: 8 }, active_color: "accent", }), padding: { left: 8, right: 8, top: 4, bottom: 4 }, From 0f650acc23a89239bb788801ffe40d8e6fdf3c5b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 10 Aug 2023 13:30:12 +0300 Subject: [PATCH 04/13] Repaint inlays icon on inlays cache disabling/enabling Co-Authored-By: Mikayla Maki --- crates/editor/src/inlay_hint_cache.rs | 2 +- crates/gpui/src/keymap_matcher/binding.rs | 8 ++++++-- crates/zed/src/quick_action_bar.rs | 21 ++++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 4327ff0d7330c96a3ddc662a2bcd985bf1373325..3385546971152e32ed5a3033e068b1c6a0f2fbba 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -24,7 +24,7 @@ pub struct InlayHintCache { hints: HashMap>>, allowed_hint_kinds: HashSet>, version: usize, - enabled: bool, + pub(super) enabled: bool, update_tasks: HashMap, } diff --git a/crates/gpui/src/keymap_matcher/binding.rs b/crates/gpui/src/keymap_matcher/binding.rs index 527052c85d3668d0716da84c1445880d81faca47..f7296d50fbe759dc25227c4fe55bb59a9158826f 100644 --- a/crates/gpui/src/keymap_matcher/binding.rs +++ b/crates/gpui/src/keymap_matcher/binding.rs @@ -88,8 +88,12 @@ impl Binding { action: &dyn Action, contexts: &[KeymapContext], ) -> Option> { - if self.action.eq(action) && self.match_context(contexts) { - Some(self.keystrokes.clone()) + if self.action.eq(action) { + if self.match_context(contexts) { + Some(self.keystrokes.clone()) + } else { + None + } } else { None } diff --git a/crates/zed/src/quick_action_bar.rs b/crates/zed/src/quick_action_bar.rs index 6157ca9c47bb63d35d02f50cf3dc70347887e324..245983dc49b4cada10efb0714ed827cf6016ccb7 100644 --- a/crates/zed/src/quick_action_bar.rs +++ b/crates/zed/src/quick_action_bar.rs @@ -2,7 +2,7 @@ use editor::Editor; use gpui::{ elements::{Empty, Flex, MouseEventHandler, ParentElement, Svg}, platform::{CursorStyle, MouseButton}, - Action, AnyElement, Element, Entity, EventContext, View, ViewContext, ViewHandle, + Action, AnyElement, Element, Entity, EventContext, Subscription, View, ViewContext, ViewHandle, }; use search::{buffer_search, BufferSearchBar}; @@ -11,6 +11,7 @@ use workspace::{item::ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; pub struct QuickActionBar { pane: ViewHandle, active_item: Option>, + _inlays_enabled_subscription: Option, } impl QuickActionBar { @@ -18,6 +19,7 @@ impl QuickActionBar { Self { pane, active_item: None, + _inlays_enabled_subscription: None, } } @@ -76,7 +78,6 @@ impl View for QuickActionBar { search_bar_shown, ( "Buffer search".to_string(), - // TODO kb no keybinding is shown for search + toggle inlays does not update icon color Some(Box::new(search_action.clone())), ), cx, @@ -143,11 +144,25 @@ impl ToolbarItemView for QuickActionBar { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn ItemHandle>, - _: &mut ViewContext, + cx: &mut ViewContext, ) -> ToolbarItemLocation { match active_pane_item { Some(active_item) => { self.active_item = Some(active_item.boxed_clone()); + self._inlays_enabled_subscription.take(); + + if let Some(editor) = active_item.downcast::() { + let mut inlays_enabled = editor.read(cx).inlays_enabled(); + self._inlays_enabled_subscription = + Some(cx.observe(&editor, move |_, editor, cx| { + let new_inlays_enabled = editor.read(cx).inlays_enabled(); + if inlays_enabled != new_inlays_enabled { + inlays_enabled = new_inlays_enabled; + cx.notify(); + } + })); + } + ToolbarItemLocation::PrimaryRight { flex: None } } None => { From 8926c23bdbed957369e517af897264f8dae930e6 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 11 Aug 2023 13:23:27 +0300 Subject: [PATCH 05/13] Extract quick_action_bar into its own crate --- Cargo.lock | 12 ++++++++++ crates/quick_action_bar/Cargo.toml | 22 +++++++++++++++++++ .../src/quick_action_bar.rs | 0 crates/zed/Cargo.toml | 1 + crates/zed/src/zed.rs | 2 -- 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 crates/quick_action_bar/Cargo.toml rename crates/{zed => quick_action_bar}/src/quick_action_bar.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 1b54bdda02a2c2335e2000cff3aeeec5a8ba9fec..51ca31bd9da7a1903398ff6387fd445dfd678cdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5714,6 +5714,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick_action_bar" +version = "0.1.0" +dependencies = [ + "editor", + "gpui", + "search", + "theme", + "workspace", +] + [[package]] name = "quote" version = "1.0.32" @@ -9922,6 +9933,7 @@ dependencies = [ "project", "project_panel", "project_symbols", + "quick_action_bar", "rand 0.8.5", "recent_projects", "regex", diff --git a/crates/quick_action_bar/Cargo.toml b/crates/quick_action_bar/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..6953ac0e028262fef96ddb71a6897946a81de90e --- /dev/null +++ b/crates/quick_action_bar/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "quick_action_bar" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/quick_action_bar.rs" +doctest = false + +[dependencies] +editor = { path = "../editor" } +gpui = { path = "../gpui" } +search = { path = "../search" } +theme = { path = "../theme" } +workspace = { path = "../workspace" } + +[dev-dependencies] +editor = { path = "../editor", features = ["test-support"] } +gpui = { path = "../gpui", features = ["test-support"] } +theme = { path = "../theme", features = ["test-support"] } +workspace = { path = "../workspace", features = ["test-support"] } diff --git a/crates/zed/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs similarity index 100% rename from crates/zed/src/quick_action_bar.rs rename to crates/quick_action_bar/src/quick_action_bar.rs diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index d0aebb15e75686069e0ae0b100147f81c150fd17..988648d4b155d182889273eb524b83b0e2d13d59 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -54,6 +54,7 @@ plugin_runtime = { path = "../plugin_runtime",optional = true } project = { path = "../project" } project_panel = { path = "../project_panel" } project_symbols = { path = "../project_symbols" } +quick_action_bar = { path = "../quick_action_bar" } recent_projects = { path = "../recent_projects" } rpc = { path = "../rpc" } settings = { path = "../settings" } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 47dff41729b1cb1c5c68d26a9da2330b7bddaf37..8d851909b31612deec42dc4faa088a6c6a677bd1 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -5,8 +5,6 @@ pub mod only_instance; #[cfg(any(test, feature = "test-support"))] pub mod test; -mod quick_action_bar; - use ai::AssistantPanel; use anyhow::Context; use assets::Assets; From 9c6135f47ad4b37a8d8bab305edc229f0453e8da Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 11 Aug 2023 13:51:14 +0300 Subject: [PATCH 06/13] Test hints toggle --- crates/editor/src/inlay_hint_cache.rs | 127 ++++++++++++++++++++++ crates/gpui/src/keymap_matcher/binding.rs | 8 +- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 3385546971152e32ed5a3033e068b1c6a0f2fbba..4c998c3afa606418c5a4e880d38944d50c9014f3 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -2683,6 +2683,127 @@ all hints should be invalidated and requeried for all of its visible excerpts" }); } + #[gpui::test] + async fn test_toggle_inlays(cx: &mut gpui::TestAppContext) { + init_test(cx, |settings| { + settings.defaults.inlay_hints = Some(InlayHintSettings { + enabled: false, + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, + }) + }); + + let (file_with_hints, editor, fake_server) = prepare_test_objects(cx).await; + + editor.update(cx, |editor, cx| { + editor.toggle_inlays(&crate::ToggleInlays, cx) + }); + cx.foreground().start_waiting(); + let lsp_request_count = Arc::new(AtomicU32::new(0)); + let closure_lsp_request_count = Arc::clone(&lsp_request_count); + fake_server + .handle_request::(move |params, _| { + let task_lsp_request_count = Arc::clone(&closure_lsp_request_count); + async move { + assert_eq!( + params.text_document.uri, + lsp::Url::from_file_path(file_with_hints).unwrap(), + ); + + let i = Arc::clone(&task_lsp_request_count).fetch_add(1, Ordering::SeqCst) + 1; + Ok(Some(vec![lsp::InlayHint { + position: lsp::Position::new(0, i), + label: lsp::InlayHintLabel::String(i.to_string()), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }])) + } + }) + .next() + .await; + cx.foreground().run_until_parked(); + editor.update(cx, |editor, cx| { + let expected_hints = vec!["1".to_string()]; + assert_eq!( + expected_hints, + cached_hint_labels(editor), + "Should display inlays after toggle despite them disabled in settings" + ); + assert_eq!(expected_hints, visible_hint_labels(editor, cx)); + assert_eq!( + editor.inlay_hint_cache().version, + 1, + "First toggle should be cache's first update" + ); + }); + + editor.update(cx, |editor, cx| { + editor.toggle_inlays(&crate::ToggleInlays, cx) + }); + cx.foreground().run_until_parked(); + editor.update(cx, |editor, cx| { + assert!( + cached_hint_labels(editor).is_empty(), + "Should clear hints after 2nd toggle" + ); + assert!(visible_hint_labels(editor, cx).is_empty()); + assert_eq!(editor.inlay_hint_cache().version, 2); + }); + + update_test_language_settings(cx, |settings| { + settings.defaults.inlay_hints = Some(InlayHintSettings { + enabled: true, + show_type_hints: true, + show_parameter_hints: true, + show_other_hints: true, + }) + }); + cx.foreground().run_until_parked(); + editor.update(cx, |editor, cx| { + let expected_hints = vec!["2".to_string()]; + assert_eq!( + expected_hints, + cached_hint_labels(editor), + "Should query LSP hints for the 2nd time after enabling hints in settings" + ); + assert_eq!(expected_hints, visible_hint_labels(editor, cx)); + assert_eq!(editor.inlay_hint_cache().version, 3); + }); + + editor.update(cx, |editor, cx| { + editor.toggle_inlays(&crate::ToggleInlays, cx) + }); + cx.foreground().run_until_parked(); + editor.update(cx, |editor, cx| { + assert!( + cached_hint_labels(editor).is_empty(), + "Should clear hints after enabling in settings and a 3rd toggle" + ); + assert!(visible_hint_labels(editor, cx).is_empty()); + assert_eq!(editor.inlay_hint_cache().version, 4); + }); + + editor.update(cx, |editor, cx| { + editor.toggle_inlays(&crate::ToggleInlays, cx) + }); + cx.foreground().run_until_parked(); + editor.update(cx, |editor, cx| { + let expected_hints = vec!["3".to_string()]; + assert_eq!( + expected_hints, + cached_hint_labels(editor), + "Should query LSP hints for the 3rd time after enabling hints in settings and toggling them back on" + ); + assert_eq!(expected_hints, visible_hint_labels(editor, cx)); + assert_eq!(editor.inlay_hint_cache().version, 5); + }); + } + pub(crate) fn init_test(cx: &mut TestAppContext, f: impl Fn(&mut AllLanguageSettingsContent)) { cx.foreground().forbid_parking(); @@ -2759,6 +2880,12 @@ all hints should be invalidated and requeried for all of its visible excerpts" .downcast::() .unwrap(); + editor.update(cx, |editor, cx| { + assert!(cached_hint_labels(editor).is_empty()); + assert!(visible_hint_labels(editor, cx).is_empty()); + assert_eq!(editor.inlay_hint_cache().version, 0); + }); + ("/a/main.rs", editor, fake_server) } diff --git a/crates/gpui/src/keymap_matcher/binding.rs b/crates/gpui/src/keymap_matcher/binding.rs index f7296d50fbe759dc25227c4fe55bb59a9158826f..527052c85d3668d0716da84c1445880d81faca47 100644 --- a/crates/gpui/src/keymap_matcher/binding.rs +++ b/crates/gpui/src/keymap_matcher/binding.rs @@ -88,12 +88,8 @@ impl Binding { action: &dyn Action, contexts: &[KeymapContext], ) -> Option> { - if self.action.eq(action) { - if self.match_context(contexts) { - Some(self.keystrokes.clone()) - } else { - None - } + if self.action.eq(action) && self.match_context(contexts) { + Some(self.keystrokes.clone()) } else { None } From 1938fd85e8029830af0760a588a742ea0e1457b2 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 11 Aug 2023 14:42:56 +0300 Subject: [PATCH 07/13] Do not leak pane handles --- .../quick_action_bar/src/quick_action_bar.rs | 36 ++++++------------- crates/search/src/buffer_search.rs | 25 ++++++++----- crates/zed/src/zed.rs | 10 +++--- 3 files changed, 32 insertions(+), 39 deletions(-) diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index 245983dc49b4cada10efb0714ed827cf6016ccb7..b506f8dc17c4ca29c6d7d3ab97cafa6101c7bb29 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -6,18 +6,18 @@ use gpui::{ }; use search::{buffer_search, BufferSearchBar}; -use workspace::{item::ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; +use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; pub struct QuickActionBar { - pane: ViewHandle, + buffer_search_bar: ViewHandle, active_item: Option>, _inlays_enabled_subscription: Option, } impl QuickActionBar { - pub fn new(pane: ViewHandle) -> Self { + pub fn new(buffer_search_bar: ViewHandle) -> Self { Self { - pane, + buffer_search_bar, active_item: None, _inlays_enabled_subscription: None, } @@ -59,17 +59,7 @@ impl View for QuickActionBar { )); if editor.read(cx).buffer().read(cx).is_singleton() { - let buffer_search_bar = self - .pane - .read(cx) - .toolbar() - .read(cx) - .item_of_type::(); - let search_bar_shown = buffer_search_bar - .as_ref() - .map(|bar| !bar.read(cx).is_dismissed()) - .unwrap_or(false); - + let search_bar_shown = !self.buffer_search_bar.read(cx).is_dismissed(); let search_action = buffer_search::Deploy { focus: true }; bar = bar.with_child(render_quick_action_bar_button( @@ -82,17 +72,13 @@ impl View for QuickActionBar { ), cx, move |this, cx| { - if search_bar_shown { - if let Some(buffer_search_bar) = buffer_search_bar.as_ref() { - buffer_search_bar.update(cx, |buffer_search_bar, cx| { - buffer_search_bar.dismiss(&buffer_search::Dismiss, cx); - }); + this.buffer_search_bar.update(cx, |buffer_search_bar, cx| { + if search_bar_shown { + buffer_search_bar.dismiss(&buffer_search::Dismiss, cx); + } else { + buffer_search_bar.deploy(&search_action, cx); } - } else { - this.pane.update(cx, |pane, cx| { - BufferSearchBar::deploy(pane, &search_action, cx); - }); - } + }); }, )); } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index fc3c78afe233c1516fbfed4ef98df381a62f34f8..d85d311b8f96f357680123cf4add0f79606f3fa1 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -36,7 +36,7 @@ pub enum Event { } pub fn init(cx: &mut AppContext) { - cx.add_action(BufferSearchBar::deploy); + cx.add_action(BufferSearchBar::deploy_bar); cx.add_action(BufferSearchBar::dismiss); cx.add_action(BufferSearchBar::focus_editor); cx.add_action(BufferSearchBar::select_next_match); @@ -327,6 +327,19 @@ impl BufferSearchBar { cx.notify(); } + pub fn deploy(&mut self, deploy: &Deploy, cx: &mut ViewContext) -> bool { + if self.show(cx) { + self.search_suggested(cx); + if deploy.focus { + self.select_query(cx); + cx.focus_self(); + } + return true; + } + + false + } + pub fn show(&mut self, cx: &mut ViewContext) -> bool { if self.active_searchable_item.is_none() { return false; @@ -553,21 +566,15 @@ impl BufferSearchBar { .into_any() } - pub fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext) { + fn deploy_bar(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext) { let mut propagate_action = true; if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { search_bar.update(cx, |search_bar, cx| { - if search_bar.show(cx) { - search_bar.search_suggested(cx); - if action.focus { - search_bar.select_query(cx); - cx.focus_self(); - } + if search_bar.deploy(action, cx) { propagate_action = false; } }); } - if propagate_action { cx.propagate_action(); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 8d851909b31612deec42dc4faa088a6c6a677bd1..de05c259c81d7c63ff856ab93d4162a34f992511 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -257,16 +257,16 @@ pub fn initialize_workspace( let workspace_handle = cx.handle(); cx.subscribe(&workspace_handle, { move |workspace, _, event, cx| { - if let workspace::Event::PaneAdded(pane_handle) = event { - pane_handle.update(cx, |pane, cx| { + if let workspace::Event::PaneAdded(pane) = event { + pane.update(cx, |pane, cx| { pane.toolbar().update(cx, |toolbar, cx| { let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace)); toolbar.add_item(breadcrumbs, cx); + let buffer_search_bar = cx.add_view(BufferSearchBar::new); + toolbar.add_item(buffer_search_bar.clone(), cx); let quick_action_bar = - cx.add_view(|_| QuickActionBar::new(pane_handle.clone())); + cx.add_view(|_| QuickActionBar::new(buffer_search_bar)); toolbar.add_item(quick_action_bar, cx); - let buffer_search_bar = cx.add_view(BufferSearchBar::new); - toolbar.add_item(buffer_search_bar, cx); let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); toolbar.add_item(project_search_bar, cx); let submit_feedback_button = From f9131f657efa31b764eb87d18b7fa3004226548f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 11 Aug 2023 17:51:37 +0300 Subject: [PATCH 08/13] Use InlayHint instead of Inlay where appropriate --- crates/collab/src/tests/integration_tests.rs | 4 +- crates/editor/src/editor.rs | 40 ++++++++++--------- crates/editor/src/inlay_hint_cache.rs | 10 ++--- crates/editor/src/scroll.rs | 6 +-- crates/project/src/project.rs | 8 ++-- .../quick_action_bar/src/quick_action_bar.rs | 27 +++++++------ 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 2224ecb8383c1c0da3845c9804a4c9dff3cbc469..a03e2ff16fc2fa325aeff79c058ded7c7dc5575c 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -7867,7 +7867,7 @@ async fn test_mutual_editor_inlay_hint_cache_update( .insert_tree( "/a", json!({ - "main.rs": "fn main() { a } // and some long comment to ensure inlays are not trimmed out", + "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out", "other.rs": "// Test file", }), ) @@ -8177,7 +8177,7 @@ async fn test_inlay_hint_refresh_is_forwarded( .insert_tree( "/a", json!({ - "main.rs": "fn main() { a } // and some long comment to ensure inlays are not trimmed out", + "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out", "other.rs": "// Test file", }), ) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ef02cee3d03babc9a1279d2654a19da830ed53ce..904e77c9f0fdd3dccb84758b97e0005573dcaee2 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -302,7 +302,7 @@ actions!( Hover, Format, ToggleSoftWrap, - ToggleInlays, + ToggleInlayHints, RevealInFinder, CopyPath, CopyRelativePath, @@ -447,7 +447,7 @@ pub fn init(cx: &mut AppContext) { cx.add_action(Editor::toggle_code_actions); cx.add_action(Editor::open_excerpts); cx.add_action(Editor::toggle_soft_wrap); - cx.add_action(Editor::toggle_inlays); + cx.add_action(Editor::toggle_inlay_hints); cx.add_action(Editor::reveal_in_finder); cx.add_action(Editor::copy_path); cx.add_action(Editor::copy_relative_path); @@ -1239,7 +1239,7 @@ enum GotoDefinitionKind { } #[derive(Debug, Clone)] -enum InlayRefreshReason { +enum InlayHintRefreshReason { Toggle(bool), SettingsChange(InlayHintSettings), NewLinesShown, @@ -1357,8 +1357,8 @@ impl Editor { })); } project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| { - if let project::Event::RefreshInlays = event { - editor.refresh_inlays(InlayRefreshReason::RefreshRequested, cx); + if let project::Event::RefreshInlayHints = event { + editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx); }; })); } @@ -2672,24 +2672,24 @@ impl Editor { } } - pub fn toggle_inlays(&mut self, _: &ToggleInlays, cx: &mut ViewContext) { - self.refresh_inlays( - InlayRefreshReason::Toggle(!self.inlay_hint_cache.enabled), + pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext) { + self.refresh_inlay_hints( + InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled), cx, ); } - pub fn inlays_enabled(&self) -> bool { + pub fn inlay_hints_enabled(&self) -> bool { self.inlay_hint_cache.enabled } - fn refresh_inlays(&mut self, reason: InlayRefreshReason, cx: &mut ViewContext) { + fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext) { if self.project.is_none() || self.mode != EditorMode::Full { return; } let (invalidate_cache, required_languages) = match reason { - InlayRefreshReason::Toggle(enabled) => { + InlayHintRefreshReason::Toggle(enabled) => { self.inlay_hint_cache.enabled = enabled; if enabled { (InvalidationStrategy::RefreshRequested, None) @@ -2706,7 +2706,7 @@ impl Editor { return; } } - InlayRefreshReason::SettingsChange(new_settings) => { + InlayHintRefreshReason::SettingsChange(new_settings) => { match self.inlay_hint_cache.update_settings( &self.buffer, new_settings, @@ -2724,11 +2724,13 @@ impl Editor { ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None), } } - InlayRefreshReason::NewLinesShown => (InvalidationStrategy::None, None), - InlayRefreshReason::BufferEdited(buffer_languages) => { + InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None), + InlayHintRefreshReason::BufferEdited(buffer_languages) => { (InvalidationStrategy::BufferEdited, Some(buffer_languages)) } - InlayRefreshReason::RefreshRequested => (InvalidationStrategy::RefreshRequested, None), + InlayHintRefreshReason::RefreshRequested => { + (InvalidationStrategy::RefreshRequested, None) + } }; if let Some(InlaySplice { @@ -7728,8 +7730,8 @@ impl Editor { .cloned() .collect::>(); if !languages_affected.is_empty() { - self.refresh_inlays( - InlayRefreshReason::BufferEdited(languages_affected), + self.refresh_inlay_hints( + InlayHintRefreshReason::BufferEdited(languages_affected), cx, ); } @@ -7767,8 +7769,8 @@ impl Editor { fn settings_changed(&mut self, cx: &mut ViewContext) { self.refresh_copilot_suggestions(true, cx); - self.refresh_inlays( - InlayRefreshReason::SettingsChange(inlay_hint_settings( + self.refresh_inlay_hints( + InlayHintRefreshReason::SettingsChange(inlay_hint_settings( self.selections.newest_anchor().head(), &self.buffer.read(cx).snapshot(cx), cx, diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 4c998c3afa606418c5a4e880d38944d50c9014f3..b5ccdb4f2d940afe4932a13be040160c8d4187d1 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -2684,7 +2684,7 @@ all hints should be invalidated and requeried for all of its visible excerpts" } #[gpui::test] - async fn test_toggle_inlays(cx: &mut gpui::TestAppContext) { + async fn test_toggle_inlay_hints(cx: &mut gpui::TestAppContext) { init_test(cx, |settings| { settings.defaults.inlay_hints = Some(InlayHintSettings { enabled: false, @@ -2697,7 +2697,7 @@ all hints should be invalidated and requeried for all of its visible excerpts" let (file_with_hints, editor, fake_server) = prepare_test_objects(cx).await; editor.update(cx, |editor, cx| { - editor.toggle_inlays(&crate::ToggleInlays, cx) + editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.foreground().start_waiting(); let lsp_request_count = Arc::new(AtomicU32::new(0)); @@ -2743,7 +2743,7 @@ all hints should be invalidated and requeried for all of its visible excerpts" }); editor.update(cx, |editor, cx| { - editor.toggle_inlays(&crate::ToggleInlays, cx) + editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.foreground().run_until_parked(); editor.update(cx, |editor, cx| { @@ -2776,7 +2776,7 @@ all hints should be invalidated and requeried for all of its visible excerpts" }); editor.update(cx, |editor, cx| { - editor.toggle_inlays(&crate::ToggleInlays, cx) + editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.foreground().run_until_parked(); editor.update(cx, |editor, cx| { @@ -2789,7 +2789,7 @@ all hints should be invalidated and requeried for all of its visible excerpts" }); editor.update(cx, |editor, cx| { - editor.toggle_inlays(&crate::ToggleInlays, cx) + editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.foreground().run_until_parked(); editor.update(cx, |editor, cx| { diff --git a/crates/editor/src/scroll.rs b/crates/editor/src/scroll.rs index 1f3adaf477fcb32793ec6c7baaf590953b2656cf..f5edb00d589f6e881b78e7327e53cdcba5ccde2f 100644 --- a/crates/editor/src/scroll.rs +++ b/crates/editor/src/scroll.rs @@ -19,7 +19,7 @@ use crate::{ display_map::{DisplaySnapshot, ToDisplayPoint}, hover_popover::hide_hover, persistence::DB, - Anchor, DisplayPoint, Editor, EditorMode, Event, InlayRefreshReason, MultiBufferSnapshot, + Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot, ToPoint, }; @@ -301,7 +301,7 @@ impl Editor { cx.spawn(|editor, mut cx| async move { editor .update(&mut cx, |editor, cx| { - editor.refresh_inlays(InlayRefreshReason::NewLinesShown, cx) + editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx) }) .ok() }) @@ -333,7 +333,7 @@ impl Editor { cx, ); - self.refresh_inlays(InlayRefreshReason::NewLinesShown, cx); + self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx); } pub fn scroll_position(&self, cx: &mut ViewContext) -> Vector2F { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 1aa2a2dd40c2d01b98860d39420c6ec4ab894728..933f259700964df58a6c303a27090127f1ff2261 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -282,7 +282,7 @@ pub enum Event { new_peer_id: proto::PeerId, }, CollaboratorLeft(proto::PeerId), - RefreshInlays, + RefreshInlayHints, } pub enum LanguageServerState { @@ -2872,7 +2872,7 @@ impl Project { .upgrade(&cx) .ok_or_else(|| anyhow!("project dropped"))?; this.update(&mut cx, |project, cx| { - cx.emit(Event::RefreshInlays); + cx.emit(Event::RefreshInlayHints); project.remote_id().map(|project_id| { project.client.send(proto::RefreshInlayHints { project_id }) }) @@ -3436,7 +3436,7 @@ impl Project { cx: &mut ModelContext, ) { if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) { - cx.emit(Event::RefreshInlays); + cx.emit(Event::RefreshInlayHints); status.pending_work.remove(&token); cx.notify(); } @@ -6810,7 +6810,7 @@ impl Project { mut cx: AsyncAppContext, ) -> Result { this.update(&mut cx, |_, cx| { - cx.emit(Event::RefreshInlays); + cx.emit(Event::RefreshInlayHints); }); Ok(proto::Ack {}) } diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index b506f8dc17c4ca29c6d7d3ab97cafa6101c7bb29..a2bddff3139ad387b57b90f8777da41a67319e00 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -11,7 +11,7 @@ use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; pub struct QuickActionBar { buffer_search_bar: ViewHandle, active_item: Option>, - _inlays_enabled_subscription: Option, + _inlay_hints_enabled_subscription: Option, } impl QuickActionBar { @@ -19,7 +19,7 @@ impl QuickActionBar { Self { buffer_search_bar, active_item: None, - _inlays_enabled_subscription: None, + _inlay_hints_enabled_subscription: None, } } @@ -42,17 +42,20 @@ impl View for QuickActionBar { fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { let Some(editor) = self.active_editor() else { return Empty::new().into_any(); }; - let inlays_enabled = editor.read(cx).inlays_enabled(); + let inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); let mut bar = Flex::row().with_child(render_quick_action_bar_button( 0, "icons/hamburger_15.svg", - inlays_enabled, - ("Inlays".to_string(), Some(Box::new(editor::ToggleInlays))), + inlay_hints_enabled, + ( + "Inlay hints".to_string(), + Some(Box::new(editor::ToggleInlayHints)), + ), cx, |this, cx| { if let Some(editor) = this.active_editor() { editor.update(cx, |editor, cx| { - editor.toggle_inlays(&editor::ToggleInlays, cx); + editor.toggle_inlay_hints(&editor::ToggleInlayHints, cx); }); } }, @@ -135,15 +138,15 @@ impl ToolbarItemView for QuickActionBar { match active_pane_item { Some(active_item) => { self.active_item = Some(active_item.boxed_clone()); - self._inlays_enabled_subscription.take(); + self._inlay_hints_enabled_subscription.take(); if let Some(editor) = active_item.downcast::() { - let mut inlays_enabled = editor.read(cx).inlays_enabled(); - self._inlays_enabled_subscription = + let mut inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); + self._inlay_hints_enabled_subscription = Some(cx.observe(&editor, move |_, editor, cx| { - let new_inlays_enabled = editor.read(cx).inlays_enabled(); - if inlays_enabled != new_inlays_enabled { - inlays_enabled = new_inlays_enabled; + let new_inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); + if inlay_hints_enabled != new_inlay_hints_enabled { + inlay_hints_enabled = new_inlay_hints_enabled; cx.notify(); } })); From 3ed50708ac09274b5074a86a110e0ce7ac0162b7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 16 Aug 2023 11:25:11 -0400 Subject: [PATCH 09/13] Add inlay_hint icon, update search icon, update tooltips --- assets/icons/inlay_hint.svg | 6 ++++++ crates/quick_action_bar/src/quick_action_bar.rs | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 assets/icons/inlay_hint.svg diff --git a/assets/icons/inlay_hint.svg b/assets/icons/inlay_hint.svg new file mode 100644 index 0000000000000000000000000000000000000000..571e2e478477b518a09a6da6794c44e1958b6a29 --- /dev/null +++ b/assets/icons/inlay_hint.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index a2bddff3139ad387b57b90f8777da41a67319e00..ab3ccacdb780da471b803fcb38b9ddfe1749e604 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -45,10 +45,10 @@ impl View for QuickActionBar { let inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); let mut bar = Flex::row().with_child(render_quick_action_bar_button( 0, - "icons/hamburger_15.svg", + "icons/inlay_hint.svg", inlay_hints_enabled, ( - "Inlay hints".to_string(), + "Toggle Inlay Hints".to_string(), Some(Box::new(editor::ToggleInlayHints)), ), cx, @@ -67,10 +67,10 @@ impl View for QuickActionBar { bar = bar.with_child(render_quick_action_bar_button( 1, - "icons/magnifying_glass_12.svg", + "icons/magnifying_glass.svg", search_bar_shown, ( - "Buffer search".to_string(), + "Buffer Search".to_string(), Some(Box::new(search_action.clone())), ), cx, From 7fcf9022b45960e1407cd81bc80cb9acd2aaebda Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 16 Aug 2023 19:25:51 +0300 Subject: [PATCH 10/13] Fix rebase issues --- crates/quick_action_bar/src/quick_action_bar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index ab3ccacdb780da471b803fcb38b9ddfe1749e604..3055399c139ddff1c469d58c4be979943c77b345 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -105,7 +105,7 @@ fn render_quick_action_bar_button< let theme = theme::current(cx); let (tooltip_text, action) = tooltip; - MouseEventHandler::::new(index, cx, |mouse_state, _| { + MouseEventHandler::new::(index, cx, |mouse_state, _| { let style = theme .workspace .toolbar From 5bb6a14d420071c25d1eaa05d79f460cfea02e27 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 16 Aug 2023 14:20:41 -0400 Subject: [PATCH 11/13] Update inlay_hint icon --- assets/icons/inlay_hint.svg | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/assets/icons/inlay_hint.svg b/assets/icons/inlay_hint.svg index 571e2e478477b518a09a6da6794c44e1958b6a29..c8e6bb2d3626e1dab08e91b41dc3625449294797 100644 --- a/assets/icons/inlay_hint.svg +++ b/assets/icons/inlay_hint.svg @@ -1,6 +1,5 @@ - - - - + + + From ef86c08174116d6b7a10b79ce15dcbb2715741b8 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 16 Aug 2023 14:24:36 -0400 Subject: [PATCH 12/13] Use the `ghost` variant for a flat button style in the toolbar --- styles/src/style_tree/workspace.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/src/style_tree/workspace.ts b/styles/src/style_tree/workspace.ts index 578dd23c6ecf30f3acef617fc6cf4140547980bf..d4eaeb99da3ba28bcebddd6efa5903beb3e0351c 100644 --- a/styles/src/style_tree/workspace.ts +++ b/styles/src/style_tree/workspace.ts @@ -152,6 +152,7 @@ export default function workspace(): any { }), toggleable_tool: toggleable_icon_button(theme, { margin: { left: 8 }, + variant: "ghost", active_color: "accent", }), padding: { left: 8, right: 8, top: 4, bottom: 4 }, From 7334bdccbff6065666c71dde8e7dee53497e939c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 16 Aug 2023 23:37:55 +0300 Subject: [PATCH 13/13] Better multibuffer tests --- crates/editor/src/inlay_hint_cache.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index b5ccdb4f2d940afe4932a13be040160c8d4187d1..70cccf21da391d9308ece455d0de09768f68f280 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -2001,7 +2001,7 @@ mod tests { }); } - #[gpui::test] + #[gpui::test(iterations = 10)] async fn test_multiple_excerpts_large_multibuffer( deterministic: Arc, cx: &mut gpui::TestAppContext, @@ -2335,10 +2335,12 @@ mod tests { all hints should be invalidated and requeried for all of its visible excerpts" ); assert_eq!(expected_layers, visible_hint_labels(editor, cx)); - assert_eq!( - editor.inlay_hint_cache().version, - last_scroll_update_version + expected_layers.len(), - "Due to every excerpt having one hint, cache should update per new excerpt received" + + let current_cache_version = editor.inlay_hint_cache().version; + let minimum_expected_version = last_scroll_update_version + expected_layers.len(); + assert!( + current_cache_version == minimum_expected_version || current_cache_version == minimum_expected_version + 1, + "Due to every excerpt having one hint, cache should update per new excerpt received + 1 potential sporadic update" ); }); }