Added Rope methods for converting between grapheme indices and line/column indices.
This commit is contained in:
parent
759b23db4d
commit
0ee364f6ce
|
@ -11,7 +11,7 @@ use string_utils::{
|
||||||
is_line_ending
|
is_line_ending
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MIN_NODE_SIZE: usize = 1;
|
pub const MIN_NODE_SIZE: usize = 64;
|
||||||
pub const MAX_NODE_SIZE: usize = MIN_NODE_SIZE * 2;
|
pub const MAX_NODE_SIZE: usize = MIN_NODE_SIZE * 2;
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,6 +220,45 @@ impl Rope {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Converts a grapheme index into a line number and grapheme-column
|
||||||
|
/// number.
|
||||||
|
///
|
||||||
|
/// If the index is off the end of the text, returns the line and column
|
||||||
|
/// number of the last valid text position.
|
||||||
|
pub fn grapheme_index_to_line_col(&self, pos: usize) -> (usize, usize) {
|
||||||
|
let p = min(pos, self.grapheme_count_);
|
||||||
|
let line = self.grapheme_index_to_line_index(p);
|
||||||
|
let line_pos = self.line_index_to_grapheme_index(line);
|
||||||
|
return (line, p - line_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Converts a line number and grapheme-column number into a grapheme
|
||||||
|
/// index.
|
||||||
|
///
|
||||||
|
/// If the column number given is beyond the end of the line, returns the
|
||||||
|
/// index of the line's last valid position. If the line number given is
|
||||||
|
/// beyond the end of the buffer, returns the index of the buffer's last
|
||||||
|
/// valid position.
|
||||||
|
pub fn line_col_to_grapheme_index(&self, pos: (usize, usize)) -> usize {
|
||||||
|
if pos.0 <= self.line_ending_count {
|
||||||
|
let l_begin_pos = self.line_index_to_grapheme_index(pos.0);
|
||||||
|
|
||||||
|
let l_end_pos = if pos.0 < self.line_ending_count {
|
||||||
|
self.line_index_to_grapheme_index(pos.0 + 1) - 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.grapheme_count_
|
||||||
|
};
|
||||||
|
|
||||||
|
return min(l_begin_pos + pos.1, l_end_pos);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return self.grapheme_count_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Inserts the given text at the given grapheme index.
|
/// Inserts the given text at the given grapheme index.
|
||||||
/// For small lengths of 'text' runs in O(log N) time.
|
/// For small lengths of 'text' runs in O(log N) time.
|
||||||
/// For large lengths of 'text', dunno. But it seems to perform
|
/// For large lengths of 'text', dunno. But it seems to perform
|
||||||
|
@ -1070,6 +1109,36 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn grapheme_index_to_line_col_1() {
|
||||||
|
let rope = Rope::new_from_str("Hello\nworld!\n");
|
||||||
|
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(0), (0,0));
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(5), (0,5));
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(6), (1,0));
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(12), (1,6));
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(13), (2,0));
|
||||||
|
assert_eq!(rope.grapheme_index_to_line_col(14), (2,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn line_col_to_grapheme_index_1() {
|
||||||
|
let rope = Rope::new_from_str("Hello\nworld!\n");
|
||||||
|
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((0,0)), 0);
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((0,5)), 5);
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((0,6)), 5);
|
||||||
|
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((1,0)), 6);
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((1,6)), 12);
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((1,7)), 12);
|
||||||
|
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((2,0)), 13);
|
||||||
|
assert_eq!(rope.line_col_to_grapheme_index((2,1)), 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_string() {
|
fn to_string() {
|
||||||
let rope = Rope::new_from_str("Hello there good people of the world!");
|
let rope = Rope::new_from_str("Hello there good people of the world!");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user