diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 00691d461..ad2fc69ce 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -32,6 +32,8 @@ This release of fish fixes a number of issues identified in fish 4.0.2: - The routines to save history and universal variables have seen some robustness improvements. - Vi mode: The cursor position after pasting via :kbd:`p` has been corrected. - Vi mode: Trying to replace the last character via :kbd:`r` no longer replaces the last-but-one character (:issue:`11484`), +- To work around terminals that fail to parse OSC sequences, a temporary feature flag has been added. + It allows you to disable prompt marking (OSC 133) by running (once) ``set -Ua fish_features no-mark-prompt" and restarting fish (:issue:`11749`). fish 4.0.2 (released April 20, 2025) ==================================== diff --git a/src/future_feature_flags.rs b/src/future_feature_flags.rs index 38000e38a..dbef7638b 100644 --- a/src/future_feature_flags.rs +++ b/src/future_feature_flags.rs @@ -30,6 +30,9 @@ pub enum FeatureFlag { /// Whether keyboard protocols (kitty's CSI x u, xterm's modifyOtherKeys) are used keyboard_protocols, + + /// Whether to write OSC 133 prompt markers + mark_prompt, } struct Features { @@ -118,6 +121,14 @@ pub struct FeatureMetadata { default_value: true, read_only: false, }, + FeatureMetadata { + flag: FeatureFlag::mark_prompt, + name: L!("mark-prompt"), + groups: L!("4.0"), + description: L!("Write OSC 133 prompt markers to the terminal"), + default_value: true, + read_only: false, + }, ]; thread_local!( @@ -180,6 +191,7 @@ const fn new() -> Self { AtomicBool::new(METADATA[4].default_value), AtomicBool::new(METADATA[5].default_value), AtomicBool::new(METADATA[6].default_value), + AtomicBool::new(METADATA[7].default_value), ], } } diff --git a/src/reader.rs b/src/reader.rs index 496982ad3..783aaa1b2 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -66,6 +66,7 @@ use crate::flog::{FLOG, FLOGF}; #[allow(unused_imports)] use crate::future::IsSomeAnd; +use crate::future_feature_flags::{feature_test, FeatureFlag}; use crate::global_safety::RelaxedAtomicBool; use crate::highlight::{ autosuggest_validate_from_history, highlight_shell, HighlightRole, HighlightSpec, @@ -664,13 +665,15 @@ fn read_i(parser: &Parser) -> i32 { data.command_line.clear(); data.update_buff_pos(EditableLineTag::Commandline, None); data.command_line_changed(EditableLineTag::Commandline); - // OSC 133 "Command start" - write!( - BufferedOuputter::new(&mut Outputter::stdoutput().borrow_mut()), - "\x1b]133;C;cmdline_url={}\x07", - escape_string(&command, EscapeStringStyle::Url), - ) - .unwrap(); + if feature_test(FeatureFlag::mark_prompt) { + // OSC 133 "Command start" + write!( + BufferedOuputter::new(&mut Outputter::stdoutput().borrow_mut()), + "\x1b]133;C;cmdline_url={}\x07", + escape_string(&command, EscapeStringStyle::Url), + ) + .unwrap(); + } event::fire_generic(parser, L!("fish_preexec").to_owned(), vec![command.clone()]); let eval_res = reader_run_command(parser, &command); signal_clear_cancel(); @@ -683,12 +686,14 @@ fn read_i(parser: &Parser) -> i32 { parser.libdata_mut().exit_current_script = false; // OSC 133 "Command finished" - write!( - BufferedOuputter::new(&mut Outputter::stdoutput().borrow_mut()), - "\x1b]133;D;{}\x07", - parser.get_last_status() - ) - .unwrap(); + if feature_test(FeatureFlag::mark_prompt) { + write!( + BufferedOuputter::new(&mut Outputter::stdoutput().borrow_mut()), + "\x1b]133;D;{}\x07", + parser.get_last_status() + ) + .unwrap(); + } event::fire_generic(parser, L!("fish_postexec").to_owned(), vec![command]); // Allow any pending history items to be returned in the history array. data.history.resolve_pending(); diff --git a/src/screen.rs b/src/screen.rs index 158512e1e..edcbb1c65 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -7,6 +7,7 @@ //! The current implementation is less smart than ncurses allows and can not for example move blocks //! of text around to handle text insertion. +use crate::future_feature_flags::{feature_test, FeatureFlag}; use crate::pager::{PageRendering, Pager, PAGER_MIN_HEIGHT}; use std::cell::RefCell; use std::collections::LinkedList; @@ -931,8 +932,11 @@ fn update( } else if left_prompt != zelf.actual_left_prompt || (zelf.scrolled && is_final_rendering) { zelf.r#move(0, 0); let mut start = 0; - let osc_133_prompt_start = - |zelf: &mut Screen| zelf.write_bytes(b"\x1b]133;A;special_key=1\x07"); + let osc_133_prompt_start = |zelf: &mut Screen| { + if feature_test(FeatureFlag::mark_prompt) { + zelf.write_bytes(b"\x1b]133;A;special_key=1\x07"); + } + }; if left_prompt_layout.line_breaks.is_empty() { osc_133_prompt_start(&mut zelf); } diff --git a/tests/checks/status.fish b/tests/checks/status.fish index 7626d437e..82bc2950a 100644 --- a/tests/checks/status.fish +++ b/tests/checks/status.fish @@ -63,6 +63,7 @@ status features #CHECK: remove-percent-self off 4.0 %self is no longer expanded (use $fish_pid) #CHECK: test-require-arg off 4.0 builtin test requires an argument #CHECK: keyboard-protocols on 4.0 Use keyboard protocols (kitty, xterm's modifyotherkeys +#CHECK: mark-prompt on 4.0 Write OSC 133 prompt markers to the terminal status test-feature stderr-nocaret echo $status #CHECK: 0