Skip to content

Commit f29f619

Browse files
authored
Fix parsing position cursor report escape sequences (#783)
The format should be: Cursor position report (CPR): Answer is ESC [ y ; x R, where x,y is the cursor location. But if "R" will goes before ";", then it will panic: > thread '<unnamed>' panicked at '`at` split index (is 53) should be <= len (is 31)', library/alloc/src/vec/mod.rs:2110:13 stack backtrace: 0: 0x2978e6ea - std::backtrace_rs::backtrace::libunwind::trace::ha9053a9a07ca49cb at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5 1: 0x2978e6ea - std::backtrace_rs::backtrace::trace_unsynchronized::h9c2852a457ad564e at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5 2: 0x2978e6ea - std::sys_common::backtrace::_print_fmt::h457936fbfaa0070f at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/sys_common/backtrace.rs:65:5 3: 0x2978e6ea - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h5779d7bf7f70cb0c at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/sys_common/backtrace.rs:44:22 4: 0x297f1dae - core::fmt::write::h5a4baaff1bcd3eb5 at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/fmt/mod.rs:1232:17 5: 0x29781695 - std::io::Write::write_fmt::h4bc1f301cb9e9cce at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/io/mod.rs:1684:15 6: 0x2978e4b5 - std::sys_common::backtrace::_print::h5fcdc36060f177e8 at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/sys_common/backtrace.rs:47:5 7: 0x2978e4b5 - std::sys_common::backtrace::print::h54ca9458b876c8bf at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/sys_common/backtrace.rs:34:9 8: 0x2979122f - std::panicking::default_hook::{{closure}}::hbe471161c7664ed6 at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:271:22 9: 0x29790f6b - std::panicking::default_hook::ha3500da57aa4ac4f at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:290:9 10: 0x297918e8 - std::panicking::rust_panic_with_hook::h50c09d000dc561d2 at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:692:13 11: 0x297917e9 - std::panicking::begin_panic_handler::{{closure}}::h9e2b2176e00e0d9c at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:583:13 12: 0x2978eb56 - std::sys_common::backtrace::__rust_end_short_backtrace::h5739b8e512c09d02 at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/sys_common/backtrace.rs:150:18 13: 0x297914f2 - rust_begin_unwind at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5 14: 0x297ee103 - core::panicking::panic_fmt::hf33a1475b4dc5c3e at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14 15: 0x297e26e6 - alloc::vec::Vec<T,A>::split_off::assert_failed::h5d4cf9fcf561634c at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/alloc/src/vec/mod.rs:2110:13 16: 0x301f7415 - alloc::vec::Vec<T,A>::split_off::ha953b379fad89c1d at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/alloc/src/vec/mod.rs:2114:13 17: 0x302039ee - tuikit::input::KeyBoard::parse_cursor_report::h8a29b19f3df8e0ff
1 parent 913deaf commit f29f619

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

skim-tuikit/src/input.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ impl KeyBoard {
438438
}
439439
}
440440

441+
// Cursor position report (CPR): Answer is ESC [ y ; x R, where x,y is the cursor location.
441442
fn parse_cursor_report(&mut self) -> Result<Key> {
442443
self.read_unread_bytes();
443444
let pos_semi = self.byte_buf.iter().position(|&b| b == b';');
@@ -447,21 +448,24 @@ impl KeyBoard {
447448
let pos_semi = pos_semi.unwrap();
448449
let pos_r = pos_r.unwrap();
449450

450-
let remain = self.byte_buf.split_off(pos_r + 1);
451-
let mut col_str = self.byte_buf.split_off(pos_semi + 1);
452-
let mut row_str = std::mem::replace(&mut self.byte_buf, remain);
451+
if pos_r > pos_semi {
452+
let remain = self.byte_buf.split_off(pos_r + 1);
453+
let mut col_str = self.byte_buf.split_off(pos_semi + 1);
454+
let mut row_str = std::mem::replace(&mut self.byte_buf, remain);
453455

454-
row_str.pop(); // remove the ';' character
455-
col_str.pop(); // remove the 'R' character
456-
let row = String::from_utf8(row_str)?;
457-
let col = String::from_utf8(col_str)?;
456+
row_str.pop(); // remove the ';' character
457+
col_str.pop(); // remove the 'R' character
458+
let row = String::from_utf8(row_str)?;
459+
let col = String::from_utf8(col_str)?;
458460

459-
let row_num = row.parse::<u16>()?;
460-
let col_num = col.parse::<u16>()?;
461-
Ok(CursorPos(row_num - 1, col_num - 1))
462-
} else {
463-
Err(TuikitError::NoCursorReportResponse)
461+
let row_num = row.parse::<u16>()?;
462+
let col_num = col.parse::<u16>()?;
463+
464+
return Ok(CursorPos(row_num - 1, col_num - 1));
465+
}
464466
}
467+
468+
return Err(TuikitError::NoCursorReportResponse);
465469
}
466470

467471
fn extended_escape(&mut self, seq2: u8) -> Result<Key> {

0 commit comments

Comments
 (0)