aboutsummaryrefslogtreecommitdiff
path: root/src/config/model.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-08-10 01:20:09 +0300
committerGitHub <noreply@github.com>2026-08-10 01:20:09 +0300
commite48d83067a5a9b05dfd0a82761068866ab2d294d (patch)
tree159b92f857f85e40037879c7f32da4957093597b /src/config/model.rs
parente2aa86a9e8b6445488ef11b2c0a8b4c22a6f79ce (diff)
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 <david@hey.com>
Diffstat (limited to 'src/config/model.rs')
-rw-r--r--src/config/model.rs26
1 files changed, 24 insertions, 2 deletions
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<TabBarRightEntryConfig>,
+ /// 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]