T59: the newest line typed is the one of the highest number, not the lowest on the screen, so a prompt drawn at the top over older lines takes its clicks; a press goes no lower than that line's last row or the cursor's
This commit is contained in:
4 files changed
+30
-14
No files matched your search
+10
-8
@@ -92,7 +92,7 @@ pub fn arrows<T>(term: &Term<T>, click: Point) -> Option<i32> {
|
||||
})
|
||||
}
|
||||
|
||||
/// The left press, SGR, a shell that takes clicks hears for `click`, its row the screen's or counted from its prompt's first, as kitty and Ghostty send it; none on a prompt or before the input.
|
||||
/// The left press, SGR, a shell that takes clicks hears for `click`, its row the screen's or counted from its prompt's first, as kitty and Ghostty send it; none on a prompt, before the input or below it.
|
||||
pub fn press<T>(term: &Term<T>, click: Point, relative: bool) -> Option<Vec<u8>> {
|
||||
if term.mode().contains(TermMode::ALT_SCREEN) {
|
||||
return None;
|
||||
@@ -107,16 +107,18 @@ pub fn press<T>(term: &Term<T>, click: Point, relative: bool) -> Option<Vec<u8>>
|
||||
let end = (back.clone())
|
||||
.filter(|&at| at < cursor)
|
||||
.find(|&at| prompted(cell(at)));
|
||||
// The newest line typed, its first cell; a shell drawing its prompts again keeps its number.
|
||||
let mut typed = back.filter_map(|at| match part(cell(at)) {
|
||||
// The newest line typed, by its number, which only grows, its first and last cells; a shell drawing its prompts again keeps it.
|
||||
let typed = back.filter_map(|at| match part(cell(at)) {
|
||||
Some(Part::Input(line)) => Some((at, line)),
|
||||
_ => None,
|
||||
});
|
||||
let input = typed.next().map(|(last, line)| {
|
||||
let first =
|
||||
(typed.take_while(|&(_, other)| other == line).last()).map_or(last, |(first, _)| first);
|
||||
(first, line)
|
||||
let newest = typed.fold(None, |newest, (at, line)| match newest {
|
||||
Some((_, _, kept)) if kept > line => newest,
|
||||
Some((_, last, kept)) if kept == line => Some((at, last, line)),
|
||||
_ => Some((at, at, line)),
|
||||
});
|
||||
let input = newest.map(|(first, _, line)| (first, line));
|
||||
let bottom = newest.map_or(cursor.0, |(_, last, _)| last.0.max(cursor.0));
|
||||
// An older line typed between a prompt and the input leaves that prompt behind.
|
||||
let older = |end: (i32, usize), (input, line): ((i32, usize), u32)| {
|
||||
(end.0..=input.0)
|
||||
@@ -139,7 +141,7 @@ pub fn press<T>(term: &Term<T>, click: Point, relative: bool) -> Option<Vec<u8>>
|
||||
(None, Some((input, _))) => (at < input, input.0),
|
||||
(None, None) => return None,
|
||||
};
|
||||
if before || prompted(cell(at)) {
|
||||
if before || at.0 > bottom || prompted(cell(at)) {
|
||||
return None;
|
||||
}
|
||||
let row = if relative { at.0 - first } else { at.0 } + 1;
|
||||
|
||||
+18
-4
@@ -107,11 +107,10 @@ fn a_shell_that_takes_clicks_hears_the_press_where_it_landed() {
|
||||
sent(&typed, click(1, 7), true).as_deref(),
|
||||
Some("\x1b[<0;8;1M")
|
||||
);
|
||||
let below = sent(&typed, click(2, 3), true);
|
||||
assert_eq!(
|
||||
below.as_deref(),
|
||||
Some("\x1b[<0;4;2M"),
|
||||
"a row below goes too"
|
||||
sent(&typed, click(2, 3), true),
|
||||
None,
|
||||
"a row below the input"
|
||||
);
|
||||
assert_eq!(sent(&typed, click(0, 1), false), None, "before the prompt");
|
||||
assert_eq!(sent(&typed, click(1, 0), false), None, "on the prompt");
|
||||
@@ -253,3 +252,18 @@ fn a_prompt_drawn_again_after_the_typed_text_keeps_its_line() {
|
||||
"from the input's own row"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_newest_line_typed_is_known_by_its_number_not_its_place() {
|
||||
let marked = "\x1b]133;A;click_events=1\x07$ \x1b]133;B\x07";
|
||||
let ran = "\x1b]133;C\x07\x1b]133;D;0\x07";
|
||||
let home = format!("\r\n\r\n\r\n{marked}oldlower{ran}\x1b[H{marked}abcdef");
|
||||
let above = term(20, &home);
|
||||
let at = sent(&above, click(0, 5), false);
|
||||
assert_eq!(
|
||||
at.as_deref(),
|
||||
Some("\x1b[<0;6;1M"),
|
||||
"the prompt at the top, old input below"
|
||||
);
|
||||
assert_eq!(sent(&above, click(3, 4), false), None, "the old line below");
|
||||
}
|
||||
Reference in new issue
Block a user