Renamed and documented the buffer position conversion functions.

This commit is contained in:
Nathan Vegdahl 2015-01-10 16:34:28 -08:00
parent 6b5b63dba1
commit 8b1f1b1e96
3 changed files with 63 additions and 41 deletions

View File

@ -205,35 +205,57 @@ impl Buffer {
// Position conversions
//------------------------------------------------------------------------
pub fn pos_2d_to_closest_1d(&self, pos: (usize, usize)) -> usize {
return self.text.pos_2d_to_closest_1d_recursive(pos);
}
pub fn pos_vis_2d_to_closest_1d(&self, pos: (usize, usize), tab_width: usize) -> usize {
if pos.0 >= self.line_count() {
return self.grapheme_count();
}
else {
let gs = self.pos_2d_to_closest_1d((pos.0, 0));
let h = self.get_line(pos.0).vis_pos_to_closest_grapheme_index(pos.1, tab_width);
return gs + h;
}
}
pub fn pos_1d_to_closest_2d(&self, pos: usize) -> (usize, usize) {
/// 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 index_to_line_col(&self, pos: usize) -> (usize, usize) {
return self.text.pos_1d_to_closest_2d_recursive(pos);
}
pub fn pos_1d_to_closest_vis_2d(&self, pos: usize, tab_width: usize) -> (usize, usize) {
/// 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_index(&self, pos: (usize, usize)) -> usize {
return self.text.pos_2d_to_closest_1d_recursive(pos);
}
/// Converts a grapheme index into a visual line and column number.
///
/// If the index is off the end of the text, returns the visual line and
/// column number of the last valid text position.
pub fn index_to_v2d(&self, pos: usize, tab_width: usize) -> (usize, usize) {
let (v, h) = self.text.pos_1d_to_closest_2d_recursive(pos);
let vis_h = self.get_line(v).grapheme_index_to_closest_vis_pos(h, tab_width);
return (v, vis_h);
}
/// Converts a visual line and column number into a grapheme index.
///
/// If the visual column number given is outside of the text, returns the
/// index of the horizontally-closest valid position. If the visual line
/// number given is beyond the end of the buffer, returns the index of
/// the buffer's last valid position.
pub fn v2d_to_index(&self, pos: (usize, usize), tab_width: usize) -> usize {
if pos.0 >= self.line_count() {
return self.grapheme_count();
}
else {
let gs = self.line_col_to_index((pos.0, 0));
let h = self.get_line(pos.0).vis_pos_to_closest_grapheme_index(pos.1, tab_width);
return gs + h;
}
}
//------------------------------------------------------------------------
// Text reading functions
@ -1122,54 +1144,54 @@ mod tests {
#[test]
fn pos_2d_to_closest_1d_1() {
fn line_col_to_index_1() {
let mut buf = Buffer::new();
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.pos_2d_to_closest_1d((2, 3));
let pos = buf.line_col_to_index((2, 3));
assert!(pos == 12);
}
#[test]
fn pos_2d_to_closest_1d_2() {
fn line_col_to_index_2() {
let mut buf = Buffer::new();
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.pos_2d_to_closest_1d((2, 10));
let pos = buf.line_col_to_index((2, 10));
assert!(pos == 15);
}
#[test]
fn pos_2d_to_closest_1d_3() {
fn line_col_to_index_3() {
let mut buf = Buffer::new();
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.pos_2d_to_closest_1d((10, 2));
let pos = buf.line_col_to_index((10, 2));
assert!(pos == 29);
}
#[test]
fn pos_1d_to_closest_2d_1() {
fn index_to_line_col_1() {
let mut buf = Buffer::new();
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.pos_1d_to_closest_2d(5);
let pos = buf.index_to_line_col(5);
assert!(pos == (1, 2));
}
#[test]
fn pos_1d_to_closest_2d_2() {
fn index_to_line_col_2() {
let mut buf = Buffer::new();
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
let pos = buf.pos_1d_to_closest_2d(50);
let pos = buf.index_to_line_col(50);
assert!(pos == (5, 6));
}

View File

@ -27,7 +27,7 @@ impl Cursor {
}
pub fn update_vis_start(&mut self, buf: &Buffer, tab_width: usize) {
let (v, h) = buf.pos_1d_to_closest_2d(self.range.0);
let (v, h) = buf.index_to_line_col(self.range.0);
self.vis_start = buf.get_line(v).grapheme_index_to_closest_vis_pos(h, tab_width);
}
}
@ -213,7 +213,7 @@ impl Editor {
/// Moves the editor's view the minimum amount to show the cursor
pub fn move_view_to_cursor(&mut self) {
let (v, h) = self.buffer.pos_1d_to_closest_vis_2d(self.cursor.range.0, self.tab_width);
let (v, h) = self.buffer.index_to_v2d(self.cursor.range.0, self.tab_width);
// Horizontal
if h < self.view_pos.1 {
@ -251,7 +251,7 @@ impl Editor {
pub fn insert_tab_at_cursor(&mut self) {
if self.soft_tabs {
// Figure out how many spaces to insert
let (v, h) = self.buffer.pos_1d_to_closest_2d(self.cursor.range.0);
let (v, h) = self.buffer.index_to_line_col(self.cursor.range.0);
let vis_pos = self.buffer.get_line(v).grapheme_index_to_closest_vis_pos(h, self.tab_width);
let next_tab_stop = ((vis_pos / self.tab_width) + 1) * self.tab_width;
let space_count = min(next_tab_stop - vis_pos, 8);
@ -381,10 +381,10 @@ impl Editor {
}
pub fn cursor_up(&mut self, n: usize) {
let (v, _) = self.buffer.pos_1d_to_closest_vis_2d(self.cursor.range.0, self.tab_width);
let (v, _) = self.buffer.index_to_v2d(self.cursor.range.0, self.tab_width);
if v >= n {
self.cursor.range.0 = self.buffer.pos_vis_2d_to_closest_1d((v - n, self.cursor.vis_start), self.tab_width);
self.cursor.range.0 = self.buffer.v2d_to_index((v - n, self.cursor.vis_start), self.tab_width);
self.cursor.range.1 = self.cursor.range.0;
}
else {
@ -396,10 +396,10 @@ impl Editor {
}
pub fn cursor_down(&mut self, n: usize) {
let (v, _) = self.buffer.pos_1d_to_closest_vis_2d(self.cursor.range.0, self.tab_width);
let (v, _) = self.buffer.index_to_v2d(self.cursor.range.0, self.tab_width);
if v < (self.buffer.line_count() - n) {
self.cursor.range.0 = self.buffer.pos_vis_2d_to_closest_1d((v + n, self.cursor.vis_start), self.tab_width);
self.cursor.range.0 = self.buffer.v2d_to_index((v + n, self.cursor.vis_start), self.tab_width);
self.cursor.range.1 = self.cursor.range.0;
}
else {
@ -456,9 +456,9 @@ impl Editor {
}
pub fn jump_to_line(&mut self, n: usize) {
let pos = self.buffer.pos_2d_to_closest_1d((n, 0));
let (v, _) = self.buffer.pos_1d_to_closest_vis_2d(pos, self.tab_width);
self.cursor.range.0 = self.buffer.pos_vis_2d_to_closest_1d((v, self.cursor.vis_start), self.tab_width);
let pos = self.buffer.line_col_to_index((n, 0));
let (v, _) = self.buffer.index_to_v2d(pos, self.tab_width);
self.cursor.range.0 = self.buffer.v2d_to_index((v, self.cursor.vis_start), self.tab_width);
self.cursor.range.1 = self.cursor.range.0;
// Adjust view

View File

@ -353,7 +353,7 @@ impl TermUI {
vis_col_num += excess;
print_col_num += excess;
grapheme_index = editor.buffer.pos_vis_2d_to_closest_1d((vis_line_num, vis_col_num), editor.tab_width);
grapheme_index = editor.buffer.v2d_to_index((vis_line_num, vis_col_num), editor.tab_width);
for (g, pos, width) in g_iter {
print_col_num = pos - editor.view_pos.1;
@ -406,7 +406,7 @@ impl TermUI {
// Print cursor if it's at the end of the text, and thus wasn't printed
// already.
if editor.cursor.range.0 >= editor.buffer.grapheme_count() {
let vis_cursor_pos = editor.buffer.pos_1d_to_closest_vis_2d(editor.cursor.range.0, editor.tab_width);
let vis_cursor_pos = editor.buffer.index_to_v2d(editor.cursor.range.0, editor.tab_width);
if (vis_cursor_pos.0 >= editor.view_pos.0) && (vis_cursor_pos.1 >= editor.view_pos.1) {
let print_cursor_pos = (vis_cursor_pos.0 - editor.view_pos.0 + c1.0, vis_cursor_pos.1 - editor.view_pos.1 + c1.1);