T59: OSC 133 B stamps the line typed after a prompt with a link of its own, numbered by the commands ended, so a shell whose prompt prints nothing, as fish's empty prompt, takes clicks from its first typed cell, and fish's right prompt drawn again at each key keeps the line

This commit is contained in:
ZacharyZhang-NY committed 2026-10-19 16:09:11 -04:00
1 parent 9fa68b24a7
commit 84364ce03e
6 files changed
+247 -80

No files matched your search

+69 -2
View File
@@ -128,7 +128,7 @@ fn a_shell_that_takes_clicks_hears_the_press_where_it_landed() {
);
let right = term(
20,
&format!("{marked}ls\x1b7\x1b[1;17H\x1b]133;A\x07~/a\x1b]133;B\x07\x1b8"),
&format!("{marked}\x1b[1;17H\x1b]133;A\x07~/a\x1b]133;B\x07\x1b[1;3Hls"),
);
assert_eq!(
sent(&right, click(0, 18), false),
@@ -139,9 +139,10 @@ fn a_shell_that_takes_clicks_hears_the_press_where_it_landed() {
sent(&right, click(0, 3), false).as_deref(),
Some("\x1b[<0;4;1M")
);
assert_eq!(sent(&right, click(0, 1), false), None, "on the left prompt");
let empty = term(
20,
"\x1b7\x1b[1;17H\x1b]133;A;click_events=1\x07~/a\x1b]133;B\x07\x1b8ls",
"\x1b[1;17H\x1b]133;A;click_events=1\x07~/a\x1b]133;B\x07\x1b[1;1Hls",
);
let left = sent(&empty, click(0, 1), false);
assert_eq!(left.as_deref(), Some("\x1b[<0;2;1M"), "only a right prompt");
@@ -186,3 +187,69 @@ fn input_reads_the_line_its_prompt_started() {
Shell::Reading(Click::Relative)
);
}
#[test]
fn a_prompt_that_prints_nothing_starts_the_input_at_its_first_typed_cell() {
let empty = "\x1b]133;A;click_events=1\x07\x1b]133;B\x07";
let typed = term(20, &format!("echo hi\r\nhi\r\n{empty}abcdef"));
let at = sent(&typed, click(2, 3), false);
assert_eq!(at.as_deref(), Some("\x1b[<0;4;3M"), "on the d");
let relative = sent(&typed, click(2, 3), true);
assert_eq!(
relative.as_deref(),
Some("\x1b[<0;4;1M"),
"from the input's row"
);
assert_eq!(sent(&typed, click(1, 1), false), None, "output above");
assert_eq!(
sent(&typed, click(0, 2), false),
None,
"the line run before"
);
let moved = term(20, &format!("{empty}abcdef\x1b[6D"));
let back = sent(&moved, click(0, 4), false);
assert_eq!(
back.as_deref(),
Some("\x1b[<0;5;1M"),
"the cursor at the start"
);
let blank = term(20, &format!("echo hi\r\n{empty}"));
assert_eq!(
sent(&blank, click(0, 2), false),
None,
"nothing typed, nothing after"
);
}
#[test]
fn a_prompt_drawn_again_after_the_typed_text_keeps_its_line() {
let marked = "\x1b]133;A;click_events=1\x07";
let right = format!("\x1b[1;17H{marked}RIGHT\x1b]133;B\x07\x1b[1;7H");
let repainted = term(24, &format!("{marked}\x1b]133;B\x07abcdef{right}"));
let at = sent(&repainted, click(0, 3), false);
assert_eq!(
at.as_deref(),
Some("\x1b[<0;4;1M"),
"fish's right prompt again"
);
assert_eq!(
sent(&repainted, click(0, 17), false),
None,
"on that prompt"
);
let ran = "\x1b]133;C\x07\x1b]133;D;0\x07";
let after = format!("$ \x1b]133;B\x07echo hi{ran}\r\nhi\r\n{marked}\x1b]133;B\x07abcdef");
let below = term(20, &format!("{marked}{after}"));
assert_eq!(sent(&below, click(1, 1), false), None, "the output between");
assert_eq!(
sent(&below, click(0, 4), false),
None,
"the line run before"
);
let typed = sent(&below, click(2, 2), true);
assert_eq!(
typed.as_deref(),
Some("\x1b[<0;3;1M"),
"from the input's own row"
);
}