mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
fix(ui): keep workspace titles derived from workspace context
This commit is contained in:
+4
-11
@@ -535,17 +535,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
Double-click word/smart-select is unaffected; only link click and hover
|
||||
bridge hard wraps. (by @ayamir in #258)
|
||||
|
||||
- **A sidebar title no longer shows "zsh" over your repo name** — pane
|
||||
titles were allowed to fall back to the foreground process name before
|
||||
falling back to cwd/repo, but an idle terminal's foreground process is
|
||||
just the shell itself, so nearly every idle workspace displayed as "zsh"
|
||||
or "bash" instead of the more useful cwd-derived name — the opposite of
|
||||
what that fallback chain was for. Bare interactive-shell names (`zsh`,
|
||||
`bash`, `fish`, `pwsh`, `cmd`, and similar, matched case- and
|
||||
extension-insensitively) are now skipped when picking a title, so the
|
||||
process-name fallback only fires for something actually distinctive
|
||||
(`nvim`, a coding agent) and an idle shell falls all the way through to
|
||||
the cwd/repo name as intended. (by @ayamir in #285)
|
||||
- **A workspace title stays tied to the workspace** — foreground process and
|
||||
agent names no longer replace the workspace title in the sidebar or its
|
||||
switcher button. An explicit workspace name wins; otherwise the title is
|
||||
derived from the workspace's repo/cwd, with `Untitled` as the final fallback.
|
||||
|
||||
- **Fullwidth CJK punctuation no longer overlaps, and prompt-mark scanning
|
||||
is faster** — wide glyphs are now shaped independently instead of being
|
||||
|
||||
@@ -27,37 +27,6 @@ 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 {
|
||||
@@ -440,16 +409,4 @@ 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(""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,9 +257,6 @@ pub fn display_name_of(ws: &Workspace, panes: &[PaneRecord]) -> String {
|
||||
if let Some(name) = ws.name.as_deref().map(str::trim).filter(|n| !n.is_empty()) {
|
||||
return name.to_string();
|
||||
}
|
||||
if let Some(title) = pane_title_of(ws, panes) {
|
||||
return title.to_string();
|
||||
}
|
||||
subject_path_of(ws, panes)
|
||||
.and_then(|path| {
|
||||
std::path::Path::new(&path)
|
||||
@@ -270,15 +267,6 @@ pub fn display_name_of(ws: &Workspace, panes: &[PaneRecord]) -> String {
|
||||
.unwrap_or_else(|| "Untitled".to_string())
|
||||
}
|
||||
|
||||
fn pane_title_of<'a>(ws: &Workspace, panes: &'a [PaneRecord]) -> Option<&'a str> {
|
||||
ws.tabs
|
||||
.iter()
|
||||
.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() && !tty7_core::core::shells::is_bare_shell_name(title))
|
||||
}
|
||||
|
||||
pub fn subject_path_of(ws: &Workspace, panes: &[PaneRecord]) -> Option<String> {
|
||||
let mut counts: Vec<(&str, usize)> = Vec::new();
|
||||
for group in ws.tabs.iter().filter_map(|t| t.sidebar_group.as_deref()) {
|
||||
@@ -521,20 +509,17 @@ mod tests {
|
||||
assert_eq!(display_name_of(&ws, &panes), "scratch");
|
||||
|
||||
panes[0].title = "nvim".into();
|
||||
assert_eq!(display_name_of(&ws, &panes), "nvim");
|
||||
assert_eq!(
|
||||
display_name_of(&ws, &panes),
|
||||
"scratch",
|
||||
"a pane's process title must not rename its workspace"
|
||||
);
|
||||
|
||||
ws.tabs[0].sidebar_group = Some("/repo/tty7".into());
|
||||
assert_eq!(
|
||||
display_name_of(&ws, &panes),
|
||||
"nvim",
|
||||
"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"
|
||||
"the repo group wins over the raw cwd"
|
||||
);
|
||||
|
||||
ws.name = Some(" Release prep ".into());
|
||||
|
||||
+1
-18
@@ -232,11 +232,7 @@ impl Tty7App {
|
||||
}
|
||||
|
||||
crate::terminal::pane_liveness::sweep(cx);
|
||||
let current = self
|
||||
.tabs
|
||||
.get(self.active)
|
||||
.and_then(|tab| workspace_osc_title(tab, cx).or_else(|| workspace_agent_title(tab, cx)))
|
||||
.or_else(|| crate::ui::machine_mirror::display_name_for(cx, self.workspace))
|
||||
let current = crate::ui::machine_mirror::display_name_for(cx, self.workspace)
|
||||
.unwrap_or_else(|| "tty7".to_string());
|
||||
let monogram: String = current
|
||||
.chars()
|
||||
@@ -1086,19 +1082,6 @@ impl Tty7App {
|
||||
}
|
||||
}
|
||||
|
||||
fn workspace_osc_title(tab: &Tab, cx: &App) -> Option<String> {
|
||||
let title = tab.leaf_title(None, cx);
|
||||
let title = title.trim();
|
||||
if title.is_empty() || title == "tty7" || title.starts_with("tty7 — ") {
|
||||
return None;
|
||||
}
|
||||
Some(title.to_string())
|
||||
}
|
||||
|
||||
fn workspace_agent_title(tab: &Tab, cx: &App) -> Option<String> {
|
||||
tab.agent(cx).map(|agent| agent.display_name().to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user