fix(ui): don't let a bare shell name outrank the cwd/repo title

pane_title_of() picked any non-empty PaneRecord.title, but an idle
terminal's foreground process is just the shell itself (zsh, bash, ...).
That made almost every idle-shell workspace show up as "zsh" in the
sidebar instead of the far more useful cwd/repo-derived name, which
defeats the "cwd as final fallback" intent of this change.

Skip bare shell process names when picking a pane title, so the
process-name fallback only kicks in for genuinely distinctive
foreground processes (nvim, an agent, ...).
This commit is contained in:
l0ng-ai
2026-07-31 23:00:53 +08:00
committed by l0ng-ai
parent 3847e4d015
commit 9fd84bf555
2 changed files with 51 additions and 1 deletions
+43
View File
@@ -27,6 +27,37 @@ pub struct ShellInventory {
pub default_name: String,
}
/// Common interactive-shell process names, lowercase and without a
/// platform-specific extension. Anything that lands in here is what a pane
/// looks like at an idle prompt — not distinctive enough to stand in for a
/// pane's cwd/repo name when picking a display title.
const BARE_SHELL_NAMES: &[&str] = &[
"sh",
"bash",
"zsh",
"fish",
"dash",
"ksh",
"tcsh",
"csh",
"nu",
"elvish",
"xonsh",
"pwsh",
"powershell",
"cmd",
"wsl",
];
/// True when `name` is a bare interactive-shell process name (e.g. the
/// foreground process of an idle terminal), so callers that want a
/// *distinctive* title should skip it and fall back to something else.
pub fn is_bare_shell_name(name: &str) -> bool {
let lower = name.trim().to_ascii_lowercase();
let lower = lower.strip_suffix(".exe").unwrap_or(&lower);
BARE_SHELL_NAMES.contains(&lower)
}
pub fn inventory() -> ShellInventory {
let configured = crate::core::config::shell_command();
ShellInventory {
@@ -409,4 +440,16 @@ mod tests {
assert!(!default_shell_name(None).is_empty());
assert!(!default_shell_name(Some(" ")).is_empty());
}
#[test]
fn bare_shell_names_are_recognized_case_and_extension_insensitively() {
assert!(is_bare_shell_name("zsh"));
assert!(is_bare_shell_name("bash"));
assert!(is_bare_shell_name("PowerShell"));
assert!(is_bare_shell_name("pwsh.exe"));
assert!(is_bare_shell_name("CMD.EXE"));
assert!(!is_bare_shell_name("nvim"));
assert!(!is_bare_shell_name("claude"));
assert!(!is_bare_shell_name(""));
}
}
+8 -1
View File
@@ -276,7 +276,7 @@ fn pane_title_of<'a>(ws: &Workspace, panes: &'a [PaneRecord]) -> Option<&'a str>
.flat_map(|t| t.root.pane_ids())
.filter_map(|id| panes.iter().find(|p| p.id == id))
.map(|p| p.title.trim())
.find(|title| !title.is_empty())
.find(|title| !title.is_empty() && !tty7_core::core::shells::is_bare_shell_name(title))
}
pub fn subject_path_of(ws: &Workspace, panes: &[PaneRecord]) -> Option<String> {
@@ -530,6 +530,13 @@ mod tests {
"a live process name is more distinctive than the cwd group"
);
panes[0].title = "zsh".into();
assert_eq!(
display_name_of(&ws, &panes),
"tty7",
"an idle shell prompt is not distinctive — cwd/repo name should win"
);
ws.name = Some(" Release prep ".into());
assert_eq!(display_name_of(&ws, &panes), "Release prep");