From 2b4067f9259de0962676490f5f8007be8fa6bddf Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:07:17 +0800 Subject: [PATCH] docs(cli): correct what the table sanitiser is actually defending Two claims in yesterday's comment were worth checking, and one was wrong. A path really is a live vector. I made a directory called `evil[31mdir`, opened a pane in it, and it lands in the CWD column of `pane ls` -- now as `evil?[31mdir`, zero escape bytes. That is a hostile name arriving from the filesystem rather than from a rename the reader typed, which is the case worth defending. A tab's OSC title is not, or not any more: the daemon already folds control characters to spaces before storing one, because gpui paints a label's tail over whatever sits below it when the title contains a newline. So titles reach the CLI clean, and the comment overstated the case by naming them. The sanitiser still covers them and deliberately does not lean on the folding -- that exists for the GUI and could reasonably move -- but the comment now says which is which. Also stops a nearby test asserting `chars().count() == 40` on a clamp that bounds columns. Its title is ASCII so the two agree and it passed either way, but read on its own it states the contract the previous commit just finished correcting. --- crates/tty7-cli/src/output.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/crates/tty7-cli/src/output.rs b/crates/tty7-cli/src/output.rs index 286c71cb..c9669cbf 100644 --- a/crates/tty7-cli/src/output.rs +++ b/crates/tty7-cli/src/output.rs @@ -87,13 +87,18 @@ fn width(s: &str) -> usize { /// Text with nothing in it that a terminal would obey. /// /// Tables and error messages alike print names the CLI did not choose: a -/// workspace or tab name, -/// a path, and — by way of [`tab_label`] — a tab's OSC title, which is set by -/// whatever program is running in the pane. An escape sequence reaching the -/// terminal from any of them is a program deciding what the reader's screen -/// does, and `\x1b[2J` in a directory name is the old `ls` trick, not a new -/// one. It also throws the columns out: an escape is bytes with no width, so -/// the padding counts characters the reader never sees. +/// workspace or tab name, and a path. A directory really can be called +/// `evil\x1b[31mdir` — that is the old `ls` trick, not a new one — and opening +/// a pane in one puts it in the CWD column. An escape arriving there is a +/// program deciding what the reader's screen does, and it throws the columns +/// out as well: an escape is bytes with no width, so the padding counts +/// characters the reader never sees. +/// +/// A tab's OSC title is the other thing a program chooses, and it reaches the +/// CLI already folded — the daemon turns control characters into spaces when +/// it stores one, because gpui breaks a label on a newline. This does not +/// lean on that: the folding is there for the GUI's sake and could reasonably +/// move. /// /// Only control characters, which is the set that a terminal acts on. Bidi /// overrides reorder a name without obeying anything, and are left alone: the @@ -572,7 +577,9 @@ mod tests { ); let long = "wondering ".repeat(8); let clamped = tab_label(&view(&|v| v.osc_title = Some(long.clone()))); - assert_eq!(clamped.chars().count(), 40); + // Columns, which happen to equal characters for this ASCII title — + // saying `chars` here would read as the contract, and it is not. + assert_eq!(width(&clamped), 40); assert!(clamped.ends_with('…')); assert_eq!( tab_label(&view(&|v| v.cwd = Some("/Users/me/repo/tty7".into()))),