Only show breadcrumbs for terminals when there's a title (#20997)

Kirill Bulatov and Thorsten Ball created

Closes https://github.com/zed-industries/zed/issues/20475

Release Notes:

- Fixed terminal title and breadcrumbs behavior

---------

Co-authored-by: Thorsten Ball <thorsten@zed.dev>

Change summary

Cargo.lock                                 |  1 +
assets/settings/default.json               |  8 ++++++--
crates/diagnostics/src/diagnostics.rs      |  2 +-
crates/editor/src/items.rs                 |  2 +-
crates/image_viewer/src/image_viewer.rs    |  2 +-
crates/search/src/project_search.rs        |  2 +-
crates/terminal/src/terminal_settings.rs   | 10 +++++++---
crates/terminal_view/Cargo.toml            |  3 ++-
crates/terminal_view/src/terminal_panel.rs |  8 ++++++--
crates/terminal_view/src/terminal_view.rs  | 10 +++++-----
crates/workspace/src/item.rs               |  4 ++--
docs/src/configuring-zed.md                | 14 ++++++++++----
12 files changed, 43 insertions(+), 23 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -12282,6 +12282,7 @@ name = "terminal_view"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "breadcrumbs",
  "client",
  "collections",
  "db",

assets/settings/default.json 🔗

@@ -847,8 +847,12 @@
       }
     },
     "toolbar": {
-      // Whether to display the terminal title in its toolbar.
-      "title": true
+      // Whether to display the terminal title in its toolbar's breadcrumbs.
+      // Only shown if the terminal title is not empty.
+      //
+      // The shell running in the terminal needs to be configured to emit the title.
+      // Example: `echo -e "\e]2;New Title\007";`
+      "breadcrumbs": true
     }
     // Set the terminal's font size. If this option is not included,
     // the terminal will default to matching the buffer's font size.

crates/diagnostics/src/diagnostics.rs 🔗

@@ -776,7 +776,7 @@ impl Item for ProjectDiagnosticsEditor {
         }
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
+    fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
         ToolbarItemLocation::PrimaryLeft
     }
 

crates/editor/src/items.rs 🔗

@@ -841,7 +841,7 @@ impl Item for Editor {
         self.pixel_position_of_newest_cursor
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
+    fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
         if self.show_breadcrumbs {
             ToolbarItemLocation::PrimaryLeft
         } else {

crates/image_viewer/src/image_viewer.rs 🔗

@@ -116,7 +116,7 @@ impl Item for ImageView {
             .map(Icon::from_path)
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
+    fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
         ToolbarItemLocation::PrimaryLeft
     }
 

crates/search/src/project_search.rs 🔗

@@ -536,7 +536,7 @@ impl Item for ProjectSearchView {
         }
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
+    fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
         if self.has_matches() {
             ToolbarItemLocation::Secondary
         } else {

crates/terminal/src/terminal_settings.rs 🔗

@@ -21,7 +21,7 @@ pub enum TerminalDockPosition {
 
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 pub struct Toolbar {
-    pub title: bool,
+    pub breadcrumbs: bool,
 }
 
 #[derive(Debug, Deserialize)]
@@ -286,10 +286,14 @@ pub enum WorkingDirectory {
 // Toolbar related settings
 #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 pub struct ToolbarContent {
-    /// Whether to display the terminal title in its toolbar.
+    /// Whether to display the terminal title in breadcrumbs inside the terminal pane.
+    /// Only shown if the terminal title is not empty.
+    ///
+    /// The shell running in the terminal needs to be configured to emit the title.
+    /// Example: `echo -e "\e]2;New Title\007";`
     ///
     /// Default: true
-    pub title: Option<bool>,
+    pub breadcrumbs: Option<bool>,
 }
 
 #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]

crates/terminal_view/Cargo.toml 🔗

@@ -14,8 +14,9 @@ doctest = false
 
 [dependencies]
 anyhow.workspace = true
-db.workspace = true
+breadcrumbs.workspace = true
 collections.workspace = true
+db.workspace = true
 dirs.workspace = true
 editor.workspace = true
 futures.workspace = true

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -1,6 +1,7 @@
 use std::{ops::ControlFlow, path::PathBuf, sync::Arc};
 
 use crate::{default_working_directory, TerminalView};
+use breadcrumbs::Breadcrumbs;
 use collections::{HashMap, HashSet};
 use db::kvp::KEY_VALUE_STORE;
 use futures::future::join_all;
@@ -138,8 +139,11 @@ impl TerminalPanel {
                 ControlFlow::Break(())
             });
             let buffer_search_bar = cx.new_view(search::BufferSearchBar::new);
-            pane.toolbar()
-                .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
+            let breadcrumbs = cx.new_view(|_| Breadcrumbs::new());
+            pane.toolbar().update(cx, |toolbar, cx| {
+                toolbar.add_item(buffer_search_bar, cx);
+                toolbar.add_item(breadcrumbs, cx);
+            });
             pane
         });
         let subscriptions = vec![

crates/terminal_view/src/terminal_view.rs 🔗

@@ -109,7 +109,7 @@ pub struct TerminalView {
     blink_epoch: usize,
     can_navigate_to_selected_word: bool,
     workspace_id: Option<WorkspaceId>,
-    show_title: bool,
+    show_breadcrumbs: bool,
     block_below_cursor: Option<Rc<BlockProperties>>,
     scroll_top: Pixels,
     _subscriptions: Vec<Subscription>,
@@ -189,7 +189,7 @@ impl TerminalView {
             blink_epoch: 0,
             can_navigate_to_selected_word: false,
             workspace_id,
-            show_title: TerminalSettings::get_global(cx).toolbar.title,
+            show_breadcrumbs: TerminalSettings::get_global(cx).toolbar.breadcrumbs,
             block_below_cursor: None,
             scroll_top: Pixels::ZERO,
             _subscriptions: vec![
@@ -259,7 +259,7 @@ impl TerminalView {
 
     fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
         let settings = TerminalSettings::get_global(cx);
-        self.show_title = settings.toolbar.title;
+        self.show_breadcrumbs = settings.toolbar.breadcrumbs;
 
         let new_cursor_shape = settings.cursor_shape.unwrap_or_default();
         let old_cursor_shape = self.cursor_shape;
@@ -1145,8 +1145,8 @@ impl Item for TerminalView {
         Some(Box::new(handle.clone()))
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
-        if self.show_title {
+    fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
+        if self.show_breadcrumbs && !self.terminal().read(cx).breadcrumb_text.trim().is_empty() {
             ToolbarItemLocation::PrimaryLeft
         } else {
             ToolbarItemLocation::Hidden

crates/workspace/src/item.rs 🔗

@@ -278,7 +278,7 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
         None
     }
 
-    fn breadcrumb_location(&self) -> ToolbarItemLocation {
+    fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation {
         ToolbarItemLocation::Hidden
     }
 
@@ -827,7 +827,7 @@ impl<T: Item> ItemHandle for View<T> {
     }
 
     fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
-        self.read(cx).breadcrumb_location()
+        self.read(cx).breadcrumb_location(cx)
     }
 
     fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {

docs/src/configuring-zed.md 🔗

@@ -1628,7 +1628,7 @@ List of `integer` column numbers
     "button": false,
     "shell": {},
     "toolbar": {
-      "title": true
+      "breadcrumbs": true
     },
     "working_directory": "current_project_directory"
   }
@@ -1946,7 +1946,7 @@ Disable with:
 
 ## Terminal: Toolbar
 
-- Description: Whether or not to show various elements in the terminal toolbar. It only affects terminals placed in the editor pane.
+- Description: Whether or not to show various elements in the terminal toolbar.
 - Setting: `toolbar`
 - Default:
 
@@ -1954,7 +1954,7 @@ Disable with:
 {
   "terminal": {
     "toolbar": {
-      "title": true
+      "breadcrumbs": true
     }
   }
 }
@@ -1962,7 +1962,13 @@ Disable with:
 
 **Options**
 
-At the moment, only the `title` option is available, it controls displaying of the terminal title that can be changed via `PROMPT_COMMAND`. If the title is hidden, the terminal toolbar is not displayed.
+At the moment, only the `breadcrumbs` option is available, it controls displaying of the terminal title that can be changed via `PROMPT_COMMAND`.
+
+If the terminal title is empty, the breadcrumbs won't be shown.
+
+The shell running in the terminal needs to be configured to emit the title.
+
+Example command to set the title: `echo -e "\e]2;New Title\007";`
 
 ### Terminal: Button