input: Fix some Rope method call will crash. (#1213)
This commit is contained in:
parent
cfc2449820
commit
f35398d797
2 changed files with 32 additions and 7 deletions
|
|
@ -1,23 +1,40 @@
|
|||
pub(crate) trait RopeExt {
|
||||
/// Get the index of (line, column) (0-based) from the byte offset (0-based).
|
||||
/// If the offset is out of bounds, return the last line and column.
|
||||
///
|
||||
/// If the `offset` is out of bounds, it returns (0, 0).
|
||||
fn line_column(&self, byte_offset: usize) -> (usize, usize);
|
||||
/// Get the byte offset (0-based) from the line, column (0-based).
|
||||
///
|
||||
/// Return the last line, if line is out of bounds.
|
||||
/// Return the end column of line, if the column is out of bounds.
|
||||
fn line_column_to_byte(&self, line_ix: usize, column_ix: usize) -> usize;
|
||||
}
|
||||
|
||||
impl RopeExt for ropey::Rope {
|
||||
fn line_column(&self, offset: usize) -> (usize, usize) {
|
||||
let line_ix = self.byte_to_line(offset);
|
||||
let line_offset = offset.saturating_sub(self.line_to_byte(line_ix));
|
||||
let Ok(line_ix) = self.try_byte_to_line(offset) else {
|
||||
return (0, 0);
|
||||
};
|
||||
|
||||
let line = self.line(line_ix);
|
||||
let column_ix = line.byte_to_char(line_offset);
|
||||
let line_start_byte = self.line_to_byte(line_ix);
|
||||
let line_offset = offset.saturating_sub(line_start_byte);
|
||||
|
||||
let column_ix = line
|
||||
.try_byte_to_char(line_offset)
|
||||
.unwrap_or(line.len_chars());
|
||||
|
||||
(line_ix, column_ix)
|
||||
}
|
||||
|
||||
fn line_column_to_byte(&self, line_ix: usize, column_ix: usize) -> usize {
|
||||
let line_ix = self.len_lines().saturating_sub(1).min(line_ix);
|
||||
let line = self.line(line_ix);
|
||||
self.line_to_byte(line_ix) + line.char_to_byte(column_ix)
|
||||
|
||||
self.line_to_byte(line_ix)
|
||||
+ line
|
||||
.try_char_to_byte(column_ix)
|
||||
.unwrap_or(line.len_bytes().saturating_sub(1))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -565,10 +565,18 @@ impl InputState {
|
|||
let offset = self.cursor().offset;
|
||||
let was_preferred_column = self.preferred_column;
|
||||
|
||||
let line_ix = self.text.byte_to_line(offset);
|
||||
let Ok(line_ix) = self.text.try_byte_to_line(offset) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_line_ix = line_ix.saturating_add_signed(move_lines);
|
||||
let line = self.text.line(new_line_ix);
|
||||
let line_start_offset = self.text.line_to_byte(new_line_ix);
|
||||
let Some(line) = self.text.get_line(new_line_ix) else {
|
||||
return;
|
||||
};
|
||||
let Ok(line_start_offset) = self.text.try_line_to_byte(new_line_ix) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_column = self
|
||||
.preferred_column
|
||||
.unwrap_or_default()
|
||||
|
|
|
|||
Loading…
Reference in a new issue