From e48d83067a5a9b05dfd0a82761068866ab2d294d Mon Sep 17 00:00:00 2001 From: Can Celik Date: Mon, 10 Aug 2026 01:20:09 +0300 Subject: feat: add configurable tab bar status (#2586) * feat: show a zoom indicator in the desktop tab bar Reserve the right edge of the tab row for a ZOOM pill while the focused pane is zoomed, matching the accent style of the mode bars. The per-tab Z suffix stays; the pill makes the zoomed state visible at a glance like tmux's status-right flag. * feat: optionally show the hostname in the desktop tab bar Add ui.tab_bar_hostname to display the machine's hostname at the right edge of the tab row, like tmux's #h in status-right. The value resolves where the server renders, so remote sessions show the remote host. Off by default. * fix: strip control characters from the tab bar hostname * fix: hide the hostname when it would squeeze out the tab strip * feat: add configurable tab bar status * fix: harden tab bar status updates * fix: terminate tab bar status process trees * fix: disable status commands on unsupported platforms * fix: skip unchanged status command renders * fix: keep tab bar status opt-in by default --------- Co-authored-by: David Heinemeier Hansson --- src/config/model.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'src/config/model.rs') diff --git a/src/config/model.rs b/src/config/model.rs index 9bd83a96..16aa1d7d 100644 --- a/src/config/model.rs +++ b/src/config/model.rs @@ -5,8 +5,8 @@ use serde::{de, Deserialize, Deserializer, Serialize}; use super::{ ActionKeybinds, BindingConfig, CommandKeybindConfig, IndexedKeybind, Keybinds, SidebarConfig, - SoundConfig, ThemeConfig, DEFAULT_MOBILE_WIDTH_THRESHOLD, DEFAULT_MOUSE_SCROLL_LINES, - DEFAULT_SCROLLBACK_LIMIT_BYTES, + SoundConfig, TabBarRightEntryConfig, ThemeConfig, DEFAULT_MOBILE_WIDTH_THRESHOLD, + DEFAULT_MOUSE_SCROLL_LINES, DEFAULT_SCROLLBACK_LIMIT_BYTES, }; pub const MAX_TOAST_DELAY_SECONDS: u64 = 3600; @@ -874,6 +874,10 @@ pub struct UiConfig { pub hide_tab_bar_when_single_tab: bool, /// Desktop tab row placement. Default: top. pub tab_bar_position: TabBarPositionConfig, + /// Ordered entries shown at the right edge of the desktop tab row. Empty by default. + pub tab_bar_right: Vec, + /// Text inserted between visible right-side tab bar entries. Default: one space. + pub tab_bar_right_separator: String, /// Agent sidebar ordering. Saved values are "spaces" or "priority". Default: "spaces". pub agent_panel_sort: AgentPanelSortConfig, /// Retired setting that Herdr wrote before the workspace filter was removed. @@ -1088,6 +1092,8 @@ impl Default for UiConfig { show_agent_labels_on_pane_borders: false, hide_tab_bar_when_single_tab: false, tab_bar_position: TabBarPositionConfig::Top, + tab_bar_right: Vec::new(), + tab_bar_right_separator: " ".into(), agent_panel_sort: AgentPanelSortConfig::Spaces, _legacy_agent_panel_scope: None, status_indicators: StatusIndicatorStyle::Dots, @@ -1344,6 +1350,8 @@ status_indicators = "symbols" default_config.ui.tab_bar_position, TabBarPositionConfig::Top ); + assert!(default_config.ui.tab_bar_right.is_empty()); + assert_eq!(default_config.ui.tab_bar_right_separator, " "); let toml = r#" [ui] @@ -1354,6 +1362,14 @@ pane_gaps = true show_agent_labels_on_pane_borders = true hide_tab_bar_when_single_tab = true tab_bar_position = "bottom" +tab_bar_right = [ + { type = "zoom" }, + { type = "hostname" }, + { type = "datetime", format = "%H:%M" }, + { type = "text", text = "prod" }, + { type = "command", command = "status.sh", interval_seconds = 10, timeout_seconds = 3 }, +] +tab_bar_right_separator = " · " "#; let config: Config = toml::from_str(toml).unwrap(); assert!(!config.ui.pane_borders); @@ -1363,6 +1379,12 @@ tab_bar_position = "bottom" assert!(config.ui.show_agent_labels_on_pane_borders); assert!(config.ui.hide_tab_bar_when_single_tab); assert_eq!(config.ui.tab_bar_position, TabBarPositionConfig::Bottom); + assert_eq!(config.ui.tab_bar_right.len(), 5); + assert!(matches!( + config.ui.tab_bar_right[1], + TabBarRightEntryConfig::Hostname + )); + assert_eq!(config.ui.tab_bar_right_separator, " · "); } #[test] -- cgit v1.2.3