mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-24 05:41:14 -03:00
Use ST (\x1b\\) as OSC terminator
The test balloon in 012007ce7b (Test balloon for ST OSC terminator,
2025-11-18) released in 4.3.0 did not trigger problem reports.
Bravely switch over to the standard ST rather than xterm's BEL.
Closes #12032
This commit is contained in:
@@ -8,7 +8,6 @@ while others enable optional features and may be ignored by the terminal.
|
||||
The terminal must be able to parse Control Sequence Introducer (CSI) commands, Operating System Commands (OSC) and :ref:`optionally <term-compat-dcs-gnu-screen>` Device Control Strings (DCS).
|
||||
These are defined by ECMA-48.
|
||||
If a valid CSI, OSC or DCS sequence does not represent a command implemented by the terminal, the terminal must ignore it.
|
||||
For historical reasons, OSC sequences may be terminated with ``\x07`` instead of ``\e\\``.
|
||||
|
||||
Control sequences are denoted in a fish-like syntax.
|
||||
Special characters other than ``\`` are not escaped.
|
||||
|
||||
@@ -2099,16 +2099,18 @@ fn test_escape_code_length() {
|
||||
|
||||
// iTerm2 escape sequences.
|
||||
assert_eq!(
|
||||
lc.escape_code_length(L!("\x1B]50;CurrentDir=test/foo\x07NOT_PART_OF_SEQUENCE")),
|
||||
25
|
||||
lc.escape_code_length(L!("\x1B]50;CurrentDir=test/foo\x1b\\NOT_PART_OF_SEQUENCE")),
|
||||
26
|
||||
);
|
||||
assert_eq!(
|
||||
lc.escape_code_length(L!("\x1B]50;SetMark\x07NOT_PART_OF_SEQUENCE")),
|
||||
13
|
||||
lc.escape_code_length(L!("\x1B]50;SetMark\x1b\\NOT_PART_OF_SEQUENCE")),
|
||||
14
|
||||
);
|
||||
assert_eq!(
|
||||
lc.escape_code_length(L!("\x1B]6;1;bg;red;brightness;255\x07NOT_PART_OF_SEQUENCE")),
|
||||
28
|
||||
lc.escape_code_length(L!(
|
||||
"\x1B]6;1;bg;red;brightness;255\x1b\\NOT_PART_OF_SEQUENCE"
|
||||
)),
|
||||
29
|
||||
);
|
||||
assert_eq!(
|
||||
lc.escape_code_length(L!("\x1B]Pg4040ff\x1B\\NOT_PART_OF_SEQUENCE")),
|
||||
@@ -2273,22 +2275,7 @@ fn test_prompt_truncation() {
|
||||
|
||||
// Escape sequences are not truncated.
|
||||
let layout = cache.calc_prompt_layout(
|
||||
L!("\x1B]50;CurrentDir=test/foo\x07NOT_PART_OF_SEQUENCE"),
|
||||
Some(&mut trunc),
|
||||
4,
|
||||
);
|
||||
assert_eq!(
|
||||
layout,
|
||||
PromptLayout {
|
||||
line_starts: vec![0],
|
||||
last_line_width: 4,
|
||||
},
|
||||
);
|
||||
assert_eq!(trunc, ellipsis() + L!("\x1B]50;CurrentDir=test/foo\x07NCE"));
|
||||
|
||||
// Newlines in escape sequences are skipped.
|
||||
let layout = cache.calc_prompt_layout(
|
||||
L!("\x1B]50;CurrentDir=\ntest/foo\x07NOT_PART_OF_SEQUENCE"),
|
||||
L!("\x1B]50;CurrentDir=test/foo\x1b\\NOT_PART_OF_SEQUENCE"),
|
||||
Some(&mut trunc),
|
||||
4,
|
||||
);
|
||||
@@ -2301,7 +2288,25 @@ fn test_prompt_truncation() {
|
||||
);
|
||||
assert_eq!(
|
||||
trunc,
|
||||
ellipsis() + L!("\x1B]50;CurrentDir=\ntest/foo\x07NCE")
|
||||
ellipsis() + L!("\x1B]50;CurrentDir=test/foo\x1b\\NCE")
|
||||
);
|
||||
|
||||
// Newlines in escape sequences are skipped.
|
||||
let layout = cache.calc_prompt_layout(
|
||||
L!("\x1B]50;CurrentDir=\ntest/foo\x1b\\NOT_PART_OF_SEQUENCE"),
|
||||
Some(&mut trunc),
|
||||
4,
|
||||
);
|
||||
assert_eq!(
|
||||
layout,
|
||||
PromptLayout {
|
||||
line_starts: vec![0],
|
||||
last_line_width: 4,
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
trunc,
|
||||
ellipsis() + L!("\x1B]50;CurrentDir=\ntest/foo\x1b\\NCE")
|
||||
);
|
||||
|
||||
// We will truncate down to one character if we have to.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::global_safety::RelaxedAtomicBool;
|
||||
// Generic output functions.
|
||||
use crate::prelude::*;
|
||||
use crate::{
|
||||
@@ -179,7 +178,7 @@ fn osc_0_or_1_terminal_title(out: &mut Outputter, is_1: bool, title: &[WString])
|
||||
for title_line in title {
|
||||
out.write_bytes(&wcs2bytes(title_line));
|
||||
}
|
||||
out.write_bytes(b"\x07"); // BEL
|
||||
out.write_bytes(b"\x1b\\"); // BEL
|
||||
true
|
||||
}
|
||||
|
||||
@@ -187,12 +186,7 @@ fn osc_133_prompt_start(out: &mut Outputter) -> bool {
|
||||
if !fish_feature_flags::feature_test(FeatureFlag::MarkPrompt) {
|
||||
return false;
|
||||
}
|
||||
static TEST_BALLOON: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
if !TEST_BALLOON.swap(true) {
|
||||
write_to_output!(out, "\x1b]133;A;click_events=1\x1b\\");
|
||||
} else {
|
||||
write_to_output!(out, "\x1b]133;A;click_events=1\x07");
|
||||
}
|
||||
write_to_output!(out, "\x1b]133;A;click_events=1\x1b\\");
|
||||
true
|
||||
}
|
||||
|
||||
@@ -200,7 +194,7 @@ fn osc_133_prompt_end(out: &mut Outputter) -> bool {
|
||||
if !fish_feature_flags::feature_test(FeatureFlag::MarkPrompt) {
|
||||
return false;
|
||||
}
|
||||
write_to_output!(out, "\x1b]133;B\x07");
|
||||
write_to_output!(out, "\x1b]133;B\x1b\\");
|
||||
true
|
||||
}
|
||||
|
||||
@@ -210,7 +204,7 @@ fn osc_133_command_start(out: &mut Outputter, command: &wstr) -> bool {
|
||||
}
|
||||
write_to_output!(
|
||||
out,
|
||||
"\x1b]133;C;cmdline_url={}\x07",
|
||||
"\x1b]133;C;cmdline_url={}\x1b\\",
|
||||
escape_string(command, EscapeStringStyle::Url),
|
||||
);
|
||||
true
|
||||
@@ -220,7 +214,7 @@ fn osc_133_command_finished(out: &mut Outputter, exit_status: libc::c_int) -> bo
|
||||
if !fish_feature_flags::feature_test(FeatureFlag::MarkPrompt) {
|
||||
return false;
|
||||
}
|
||||
write_to_output!(out, "\x1b]133;D;{}\x07", exit_status);
|
||||
write_to_output!(out, "\x1b]133;D;{}\x1b\\", exit_status);
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user