From 07436b428420581c6232e3b84847a3d143174373 Mon Sep 17 00:00:00 2001
From: Vivek Pothina <19631108+ViveK-PothinA@users.noreply.github.com>
Date: Fri, 30 May 2025 08:32:54 -0700
Subject: [PATCH] breadcrumbs: Stylize filename in breadcrumbs when tab-bar is
off and file is dirty (#30507)
Closes [#18870](https://github.com/zed-industries/zed/issues/18870)
- I like to use Zed with tab_bar off
- when the file is modified there is no indicator when tab_bar is off
- this PR aims to fix that
Thanks to @Qkessler for initial PR - #22418
This is style decided in this discussion - #22418
@iamnbutler @mikayla-maki [subtle style
decided](https://github.com/zed-industries/zed/pull/22418#issuecomment-2605253667)
Release Notes:
- When tab_bar is off, filename in the breadcrumbs will be the indicator
when file is unsaved.
#### Changes
- when tab_bar is off and file is dirty (unsaved)
- when tab_bar is off and file is not dirty (saved)
- when tab_bar is on
Release Notes:
- Changed the highlighting of the current file to represent the current
saved state, when the tab bar is turned off.
---
Cargo.lock | 1 +
crates/breadcrumbs/Cargo.toml | 1 +
crates/breadcrumbs/src/breadcrumbs.rs | 65 ++++++++++++++++++++++++---
3 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index f2b80c980e..6aef35323e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2200,6 +2200,7 @@ dependencies = [
"editor",
"gpui",
"itertools 0.14.0",
+ "settings",
"theme",
"ui",
"workspace",
diff --git a/crates/breadcrumbs/Cargo.toml b/crates/breadcrumbs/Cargo.toml
index 36a713708f..c25cfc3c86 100644
--- a/crates/breadcrumbs/Cargo.toml
+++ b/crates/breadcrumbs/Cargo.toml
@@ -16,6 +16,7 @@ doctest = false
editor.workspace = true
gpui.workspace = true
itertools.workspace = true
+settings.workspace = true
theme.workspace = true
ui.workspace = true
workspace.workspace = true
diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs
index 57cb2a4df8..8eed7497da 100644
--- a/crates/breadcrumbs/src/breadcrumbs.rs
+++ b/crates/breadcrumbs/src/breadcrumbs.rs
@@ -1,14 +1,15 @@
use editor::Editor;
use gpui::{
- Context, Element, EventEmitter, Focusable, IntoElement, ParentElement, Render, StyledText,
- Subscription, Window,
+ Context, Element, EventEmitter, Focusable, FontWeight, IntoElement, ParentElement, Render,
+ StyledText, Subscription, Window,
};
use itertools::Itertools;
+use settings::Settings;
use std::cmp;
use theme::ActiveTheme;
use ui::{ButtonLike, ButtonStyle, Label, Tooltip, prelude::*};
use workspace::{
- ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
+ TabBarSettings, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
item::{BreadcrumbText, ItemEvent, ItemHandle},
};
@@ -71,16 +72,23 @@ impl Render for Breadcrumbs {
);
}
- let highlighted_segments = segments.into_iter().map(|segment| {
+ let highlighted_segments = segments.into_iter().enumerate().map(|(index, segment)| {
let mut text_style = window.text_style();
- if let Some(font) = segment.font {
- text_style.font_family = font.family;
- text_style.font_features = font.features;
+ if let Some(ref font) = segment.font {
+ text_style.font_family = font.family.clone();
+ text_style.font_features = font.features.clone();
text_style.font_style = font.style;
text_style.font_weight = font.weight;
}
text_style.color = Color::Muted.color(cx);
+ if index == 0 && !TabBarSettings::get_global(cx).show && active_item.is_dirty(cx) {
+ if let Some(styled_element) = apply_dirty_filename_style(&segment, &text_style, cx)
+ {
+ return styled_element;
+ }
+ }
+
StyledText::new(segment.text.replace('\n', "⏎"))
.with_default_highlights(&text_style, segment.highlights.unwrap_or_default())
.into_any()
@@ -184,3 +192,46 @@ impl ToolbarItemView for Breadcrumbs {
self.pane_focused = pane_focused;
}
}
+
+fn apply_dirty_filename_style(
+ segment: &BreadcrumbText,
+ text_style: &gpui::TextStyle,
+ cx: &mut Context,
+) -> Option {
+ let text = segment.text.replace('\n', "⏎");
+
+ let filename_position = std::path::Path::new(&segment.text)
+ .file_name()
+ .and_then(|f| {
+ let filename_str = f.to_string_lossy();
+ segment.text.rfind(filename_str.as_ref())
+ })?;
+
+ let bold_weight = FontWeight::BOLD;
+ let default_color = Color::Default.color(cx);
+
+ if filename_position == 0 {
+ let mut filename_style = text_style.clone();
+ filename_style.font_weight = bold_weight;
+ filename_style.color = default_color;
+
+ return Some(
+ StyledText::new(text)
+ .with_default_highlights(&filename_style, [])
+ .into_any(),
+ );
+ }
+
+ let highlight_style = gpui::HighlightStyle {
+ font_weight: Some(bold_weight),
+ color: Some(default_color),
+ ..Default::default()
+ };
+
+ let highlight = vec![(filename_position..text.len(), highlight_style)];
+ Some(
+ StyledText::new(text)
+ .with_default_highlights(&text_style, highlight)
+ .into_any(),
+ )
+}