From 33bf80808420c0ca224f343a1f166b2b6c8dabd0 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sun, 9 Nov 2025 07:52:48 +0100 Subject: [PATCH] fish_tab_title: fix tab title accidentally including window title Also use the correct OSC number. Note that this only works on few terminals (such as iTerm2). Not sure if it's worth for us to have this feature but I guess multiple users have requested it. --- doc_src/terminal-compatibility.rst | 2 +- src/reader/reader.rs | 19 ++++++++----------- src/terminal.rs | 10 +++++----- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/doc_src/terminal-compatibility.rst b/doc_src/terminal-compatibility.rst index c801546e0..5e91af07a 100644 --- a/doc_src/terminal-compatibility.rst +++ b/doc_src/terminal-compatibility.rst @@ -221,7 +221,7 @@ Optional Commands - Set terminal window title (OSC 0). Used in :doc:`fish_title `. * - ``\e]2; Pt \x07`` - ts - - Set terminal tab title (OSC 2). Used in :doc:`fish_tab_title `. + - Set terminal tab title (OSC 1). Used in :doc:`fish_tab_title `. * - ``\e]7;file:// Pt / Pt \x07`` - - Report working directory (OSC 7). diff --git a/src/reader/reader.rs b/src/reader/reader.rs index 35ce0e60f..38d16464a 100644 --- a/src/reader/reader.rs +++ b/src/reader/reader.rs @@ -129,7 +129,7 @@ use crate::terminal::Outputter; use crate::terminal::TerminalCommand::{ self, ClearScreen, DecrstAlternateScreenBuffer, DecsetAlternateScreenBuffer, DecsetShowCursor, - Osc0WindowTitle, Osc2TabTitle, Osc133CommandFinished, Osc133CommandStart, QueryCursorPosition, + Osc0WindowTitle, Osc1TabTitle, Osc133CommandFinished, Osc133CommandStart, QueryCursorPosition, QueryKittyKeyboardProgressiveEnhancements, QueryPrimaryDeviceAttribute, QueryXtgettcap, QueryXtversion, }; @@ -4647,14 +4647,13 @@ pub fn reader_write_title( parser: &Parser, reset_cursor_position: bool, /* = true */ ) { - fn write_title<'a>( + fn write_title( parser: &Parser, out: &mut BufferedOutputter, cmd: &wstr, - osc: fn(&'a [WString]) -> TerminalCommand<'a>, + osc: fn(&[WString]) -> TerminalCommand<'_>, function_name: &wstr, fallback_title: Option<&wstr>, - title_buffer: &'a mut Vec, ) -> bool { let mut title_function_call; let mut title_command = fallback_title; @@ -4672,15 +4671,16 @@ fn write_title<'a>( let Some(title_command) = title_command else { return false; }; + let mut title_buffer = vec![]; let _ = exec_subshell( title_command, parser, - Some(title_buffer), + Some(&mut title_buffer), /*apply_exit_status=*/ false, ); if !title_buffer.is_empty() { - out.write_command(osc(&*title_buffer)); + out.write_command(osc(&title_buffer)); return true; } false @@ -4693,24 +4693,21 @@ fn write_title<'a>( let mut out = BufferedOutputter::new(Outputter::stdoutput()); let mut written = false; - let mut lst = vec![]; written |= write_title( parser, &mut out, cmd, - Osc0WindowTitle, + |title_buffer| Osc0WindowTitle(title_buffer), L!("fish_title"), Some(DEFAULT_TITLE), - &mut lst, ); written |= write_title( parser, &mut out, cmd, - Osc2TabTitle, + |title_buffer| Osc1TabTitle(title_buffer), L!("fish_tab_title"), /*default_title=*/ None, - &mut lst, ); out.reset_text_face(); diff --git a/src/terminal.rs b/src/terminal.rs index bc3807268..188a84ea4 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -102,7 +102,7 @@ pub(crate) enum TerminalCommand<'a> { // Note that OSC 7 and OSC 52 are written from fish script, and OSC 8 is written in our // man pages (via "man_show_urls"). Osc0WindowTitle(&'a [WString]), - Osc2TabTitle(&'a [WString]), + Osc1TabTitle(&'a [WString]), Osc133CommandStart(&'a wstr), Osc133PromptStart, Osc133CommandFinished(libc::c_int), @@ -176,8 +176,8 @@ fn write(out: &mut impl Output, sequence: &'static [u8]) -> bool { ModifyOtherKeysDisable => write(self, b"\x1b[>4;0m"), ApplicationKeypadModeEnable => write(self, b"\x1b="), ApplicationKeypadModeDisable => write(self, b"\x1b>"), - Osc0WindowTitle(title) => osc_0_or_2_terminal_title(self, false, title), - Osc2TabTitle(title) => osc_0_or_2_terminal_title(self, true, title), + Osc0WindowTitle(title) => osc_0_or_1_terminal_title(self, false, title), + Osc1TabTitle(title) => osc_0_or_1_terminal_title(self, true, title), Osc133PromptStart => osc_133_prompt_start(self), Osc133CommandStart(command) => osc_133_command_start(self, command), Osc133CommandFinished(s) => osc_133_command_finished(self, s), @@ -371,8 +371,8 @@ fn query_kitty_progressive_enhancements(out: &mut impl Output) -> bool { true } -fn osc_0_or_2_terminal_title(out: &mut impl Output, is_2: bool, title: &[WString]) -> bool { - out.write_bytes(if is_2 { b"\x1b]2;" } else { b"\x1b]0;" }); +fn osc_0_or_1_terminal_title(out: &mut impl Output, is_1: bool, title: &[WString]) -> bool { + out.write_bytes(if is_1 { b"\x1b]1;" } else { b"\x1b]0;" }); for title_line in title { out.write_bytes(&wcs2bytes(title_line)); }