From 8da6e629143715196cb4755b4969c24a30623373 Mon Sep 17 00:00:00 2001 From: Andrew Lygin Date: Sat, 3 Feb 2024 23:40:54 +0300 Subject: [PATCH] Editor toolbar configuration (#7338) Adds settings for hiding breadcrumbs and quick action bar from the editor toolbar. If both elements are hidden, the toolbar disappears completely. Example: ```json "toolbar": { "breadcrumbs": true, "quick_actions": false } ``` - It intentionally doesn't hide breadcrumbs in other views (for instance, in the search result window) because their usage there differ from the main editor. - The editor controls how breadcrumbs are displayed in the toolbar, so implementation differs a bit for breadcrumbs and quick actions bar. Release Notes: - Added support for configuring the editor toolbar ([4756](https://github.com/zed-industries/zed/issues/4756)) --- Cargo.lock | 1 + assets/settings/default.json | 7 ++ crates/editor/src/editor.rs | 7 +- crates/editor/src/editor_settings.rs | 22 +++++ crates/editor/src/items.rs | 6 +- crates/quick_action_bar/Cargo.toml | 1 + .../quick_action_bar/src/quick_action_bar.rs | 88 ++++++++++++------- crates/workspace/src/toolbar.rs | 2 +- crates/zed/src/zed.rs | 2 +- docs/src/configuring_zed.md | 17 ++++ 10 files changed, 114 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 242e3d4704540ecc6f49f7d16fbc00a471bf3a97..ad58e4442533570bfc90c1fbefb5c70a6b1f1422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6064,6 +6064,7 @@ dependencies = [ "editor", "gpui", "search", + "settings", "ui", "workspace", ] diff --git a/assets/settings/default.json b/assets/settings/default.json index 3e1e35cc47d3037750156fc2008fbb080a200248..9387c58f1dce90c4c592032ebbc28069947731f0 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -109,6 +109,13 @@ // Share your project when you are the first to join a channel "share_on_join": true }, + // Toolbar related settings + "toolbar": { + // Whether to show breadcrumbs. + "breadcrumbs": true, + // Whether to show quick action buttons. + "quick_actions": true + }, // Scrollbar related settings "scrollbar": { // When to show the scrollbar in the editor. diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 9c84dd0fe9cad2059969aa7e82207f97f4eea2d2..9039cc4cf03c2cc62a523ebf0f353880eff9bf4c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -374,6 +374,7 @@ pub struct Editor { hovered_cursors: HashMap>, pub show_local_selections: bool, mode: EditorMode, + show_breadcrumbs: bool, show_gutter: bool, show_wrap_guides: Option, placeholder_text: Option>, @@ -1448,6 +1449,7 @@ impl Editor { blink_manager: blink_manager.clone(), show_local_selections: true, mode, + show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs, show_gutter: mode == EditorMode::Full, show_wrap_guides: None, placeholder_text: None, @@ -8762,8 +8764,9 @@ impl Editor { )), cx, ); - self.scroll_manager.vertical_scroll_margin = - EditorSettings::get_global(cx).vertical_scroll_margin; + let editor_settings = EditorSettings::get_global(cx); + self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin; + self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs; cx.notify(); } diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index ddbcd6e4a009c31119ca9e1779ad0ce2614a1c38..074003492fa02ea828f09b729143ba279c156e2c 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -10,6 +10,7 @@ pub struct EditorSettings { pub show_completion_documentation: bool, pub completion_documentation_secondary_query_debounce: u64, pub use_on_type_format: bool, + pub toolbar: Toolbar, pub scrollbar: Scrollbar, pub vertical_scroll_margin: f32, pub relative_line_numbers: bool, @@ -29,6 +30,12 @@ pub enum SeedQuerySetting { Never, } +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct Toolbar { + pub breadcrumbs: bool, + pub quick_actions: bool, +} + #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct Scrollbar { pub show: ShowScrollbar, @@ -86,6 +93,8 @@ pub struct EditorSettingsContent { /// /// Default: true pub use_on_type_format: Option, + /// Toolbar related settings + pub toolbar: Option, /// Scrollbar related settings pub scrollbar: Option, @@ -110,6 +119,19 @@ pub struct EditorSettingsContent { pub redact_private_values: Option, } +// Toolbar related settings +#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct ToolbarContent { + /// Whether to display breadcrumbs in the editor toolbar. + /// + /// Default: true + pub breadcrumbs: Option, + /// Whether to display quik action buttons in the editor toolbar. + /// + /// Default: true + pub quick_actions: Option, +} + /// Scrollbar related settings #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct ScrollbarContent { diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index e95d958db5a7f9eddf3c33d5616f3039c29fc811..418307df82db6e34134c385829f548e4c2fb31bc 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -800,7 +800,11 @@ impl Item for Editor { } fn breadcrumb_location(&self) -> ToolbarItemLocation { - ToolbarItemLocation::PrimaryLeft + if self.show_breadcrumbs { + ToolbarItemLocation::PrimaryLeft + } else { + ToolbarItemLocation::Hidden + } } fn breadcrumbs(&self, variant: &Theme, cx: &AppContext) -> Option> { diff --git a/crates/quick_action_bar/Cargo.toml b/crates/quick_action_bar/Cargo.toml index 56c92be8a1c2bc613bdd89b4d7bc36e9a9fa3100..07e081acd39a5a711758808287ceeb9b14bc3e1b 100644 --- a/crates/quick_action_bar/Cargo.toml +++ b/crates/quick_action_bar/Cargo.toml @@ -14,6 +14,7 @@ assistant = { path = "../assistant" } editor = { path = "../editor" } gpui = { path = "../gpui" } search = { path = "../search" } +settings = { path = "../settings" } ui = { path = "../ui" } workspace = { path = "../workspace" } diff --git a/crates/quick_action_bar/src/quick_action_bar.rs b/crates/quick_action_bar/src/quick_action_bar.rs index 3e49328c133231ef06bad3123467cd25af4fe97a..b7c783b344b17c0342aad03a5a4211e8c8caec56 100644 --- a/crates/quick_action_bar/src/quick_action_bar.rs +++ b/crates/quick_action_bar/src/quick_action_bar.rs @@ -1,11 +1,12 @@ use assistant::{AssistantPanel, InlineAssist}; -use editor::Editor; +use editor::{Editor, EditorSettings}; use gpui::{ Action, ClickEvent, ElementId, EventEmitter, InteractiveElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WeakView, }; use search::{buffer_search, BufferSearchBar}; +use settings::{Settings, SettingsStore}; use ui::{prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, Tooltip}; use workspace::{ item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, @@ -16,16 +17,26 @@ pub struct QuickActionBar { active_item: Option>, _inlay_hints_enabled_subscription: Option, workspace: WeakView, + show: bool, } impl QuickActionBar { - pub fn new(buffer_search_bar: View, workspace: &Workspace) -> Self { - Self { + pub fn new( + buffer_search_bar: View, + workspace: &Workspace, + cx: &mut ViewContext, + ) -> Self { + let mut this = Self { buffer_search_bar, active_item: None, _inlay_hints_enabled_subscription: None, workspace: workspace.weak_handle(), - } + show: true, + }; + this.apply_settings(cx); + cx.observe_global::(|this, cx| this.apply_settings(cx)) + .detach(); + this } fn active_editor(&self) -> Option> { @@ -33,6 +44,24 @@ impl QuickActionBar { .as_ref() .and_then(|item| item.downcast::()) } + + fn apply_settings(&mut self, cx: &mut ViewContext) { + let new_show = EditorSettings::get_global(cx).toolbar.quick_actions; + if new_show != self.show { + self.show = new_show; + cx.emit(ToolbarItemEvent::ChangeLocation( + self.get_toolbar_item_location(), + )); + } + } + + fn get_toolbar_item_location(&self) -> ToolbarItemLocation { + if self.show && self.active_editor().is_some() { + ToolbarItemLocation::PrimaryRight + } else { + ToolbarItemLocation::Hidden + } + } } impl Render for QuickActionBar { @@ -40,7 +69,6 @@ impl Render for QuickActionBar { let Some(editor) = self.active_editor() else { return div().id("empty quick action bar"); }; - let inlay_hints_button = Some(QuickActionBarButton::new( "toggle inlay hints", IconName::InlayHint, @@ -155,36 +183,28 @@ impl ToolbarItemView for QuickActionBar { active_pane_item: Option<&dyn ItemHandle>, cx: &mut ViewContext, ) -> ToolbarItemLocation { - match active_pane_item { - Some(active_item) => { - self.active_item = Some(active_item.boxed_clone()); - self._inlay_hints_enabled_subscription.take(); - - if let Some(editor) = active_item.downcast::() { - let mut inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); - let mut supports_inlay_hints = editor.read(cx).supports_inlay_hints(cx); - self._inlay_hints_enabled_subscription = - Some(cx.observe(&editor, move |_, editor, cx| { - let editor = editor.read(cx); - let new_inlay_hints_enabled = editor.inlay_hints_enabled(); - let new_supports_inlay_hints = editor.supports_inlay_hints(cx); - let should_notify = inlay_hints_enabled != new_inlay_hints_enabled - || supports_inlay_hints != new_supports_inlay_hints; - inlay_hints_enabled = new_inlay_hints_enabled; - supports_inlay_hints = new_supports_inlay_hints; - if should_notify { - cx.notify() - } - })); - ToolbarItemLocation::PrimaryRight - } else { - ToolbarItemLocation::Hidden - } - } - None => { - self.active_item = None; - ToolbarItemLocation::Hidden + self.active_item = active_pane_item.map(ItemHandle::boxed_clone); + if let Some(active_item) = active_pane_item { + self._inlay_hints_enabled_subscription.take(); + + if let Some(editor) = active_item.downcast::() { + let mut inlay_hints_enabled = editor.read(cx).inlay_hints_enabled(); + let mut supports_inlay_hints = editor.read(cx).supports_inlay_hints(cx); + self._inlay_hints_enabled_subscription = + Some(cx.observe(&editor, move |_, editor, cx| { + let editor = editor.read(cx); + let new_inlay_hints_enabled = editor.inlay_hints_enabled(); + let new_supports_inlay_hints = editor.supports_inlay_hints(cx); + let should_notify = inlay_hints_enabled != new_inlay_hints_enabled + || supports_inlay_hints != new_supports_inlay_hints; + inlay_hints_enabled = new_inlay_hints_enabled; + supports_inlay_hints = new_supports_inlay_hints; + if should_notify { + cx.notify() + } + })); } } + self.get_toolbar_item_location() } } diff --git a/crates/workspace/src/toolbar.rs b/crates/workspace/src/toolbar.rs index b127de8de5bea535658750e95bc181d5883cc1e2..d2b042668ed1d6721a5e4347b6c3ce321d93b657 100644 --- a/crates/workspace/src/toolbar.rs +++ b/crates/workspace/src/toolbar.rs @@ -127,7 +127,7 @@ impl Render for Toolbar { h_flex() // We're using `flex_none` here to prevent some flickering that can occur when the // size of the left items container changes. - .flex_none() + .when_else(has_left_items, Div::flex_none, Div::flex_auto) .justify_end() .children(self.right_items().map(|item| item.to_any())), ) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index d48b9438229071e2c121dfb9b2fb3fac6cf3ae46..443adac50d254a4014561ae666b701d8d7faf286 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -353,7 +353,7 @@ fn initialize_pane(workspace: &mut Workspace, pane: &View, cx: &mut ViewCo toolbar.add_item(buffer_search_bar.clone(), cx); let quick_action_bar = - cx.new_view(|_| QuickActionBar::new(buffer_search_bar, workspace)); + cx.new_view(|cx| QuickActionBar::new(buffer_search_bar, workspace, cx)); toolbar.add_item(quick_action_bar, cx); let diagnostic_editor_controls = cx.new_view(|_| diagnostics::ToolbarControls::new()); toolbar.add_item(diagnostic_editor_controls, cx); diff --git a/docs/src/configuring_zed.md b/docs/src/configuring_zed.md index 173fab8d690a11ec2bee5c339565ddd819232740..0a72e384ce0095f26e1c51a06894f5211bf8db3a 100644 --- a/docs/src/configuring_zed.md +++ b/docs/src/configuring_zed.md @@ -190,6 +190,23 @@ List of `string` values 2. Position the dock to the right of the workspace like a side panel: `right` 3. Position the dock full screen over the entire workspace: `expanded` +## Editor Toolbar + +- Description: Whether or not to show various elements in the editor toolbar. +- Setting: `toolbar` +- Default: + +```json +"toolbar": { + "breadcrumbs": true, + "quick_actions": true +}, +``` + +**Options** + +Each option controls displaying of a particular toolbar element. If all elements are hidden, the editor toolbar is not displayed. + ## Enable Language Server - Description: Whether or not to use language servers to provide code intelligence.