diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index bfda080..85c8087 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -25,11 +25,15 @@ impl TextBuffer { self.root.char_count } - pub fn pos_2d_to_1d(&self, pos: (uint, uint)) -> Option { - // TODO - return Option::None; + pub fn newline_count(&self) -> uint { + self.root.newline_count } + //pub fn pos_2d_to_1d(&self, pos: (uint, uint)) -> Option { + // // TODO + // return Option::None; + //} + pub fn pos_2d_to_closest_1d(&self, pos: (uint, uint)) -> uint { match self.root.pos_2d_to_closest_1d(0, pos) { text_node::IndexOrOffset::Index(i) => i, @@ -37,14 +41,18 @@ impl TextBuffer { } } - pub fn pos_2d_to_closest_2d(&self, pos: (uint, uint)) -> (uint, uint) { - // TODO - return (0, 0); - } + //pub fn pos_2d_to_closest_2d(&self, pos: (uint, uint)) -> (uint, uint) { + // // TODO + // return (0, 0); + //} - pub fn pos_1d_to_2d(&self, pos: uint) -> Option<(uint, uint)> { - // TODO - return Option::None; + //pub fn pos_1d_to_2d(&self, pos: uint) -> Option<(uint, uint)> { + // // TODO + // return Option::None; + //} + + pub fn pos_1d_to_closest_2d(&self, pos: uint) -> (uint, uint) { + self.root.pos_1d_to_closest_2d((0,0), pos) } /// Insert 'text' at char position 'pos'. diff --git a/src/buffer/text_node.rs b/src/buffer/text_node.rs index 91e6124..7152646 100644 --- a/src/buffer/text_node.rs +++ b/src/buffer/text_node.rs @@ -338,8 +338,9 @@ impl TextNode { let mut col = offset; for c in iter { - // Check if we've hit a relevant character - if line > pos.0 || (line == pos.0 && col >= pos.1) { + // Check if we've hit or passed the target column on + // the target line. + if line == pos.0 && col >= pos.1 { break; } @@ -347,10 +348,16 @@ impl TextNode { if c == '\n' { line += 1; col = 0; + + // Check if we've passed the target line + if line > pos.0 { + break; + } } else { col += 1; } + i += 1; } @@ -403,6 +410,89 @@ impl TextNode { } + /// Find the closest 2d text position that represents the given + /// 1d position well. + pub fn pos_1d_to_closest_2d(&self, offset_pos: (uint, uint), pos: uint) -> (uint, uint) { + match self.data { + TextNodeData::Leaf(ref tb) => { + let mut iter = tb.as_str().chars(); + let mut line = offset_pos.0; + let mut col = offset_pos.1; + let mut i: uint = 0; + + for c in iter { + if i == pos { + break; + } + + if c == '\n' { + line += 1; + col = 0; + } + else { + col += 1; + } + + i += 1; + } + + return (line, col); + }, + + TextNodeData::Branch(ref left, ref right) => { + if left.char_count > pos { + return left.pos_1d_to_closest_2d(offset_pos, pos); + } + else { + let mut line = offset_pos.0; + let mut col = offset_pos.1; + + if left.newline_count > 0 { + line += left.newline_count; + col = 0; + } + + col += left.tail_len(); + + return right.pos_1d_to_closest_2d((line, col), pos - left.char_count); + } + } + } + } + + + /// Returns the number of characters after the last newline in the node, + /// or the total character length of the node if there are no newlines. + pub fn tail_len(&self) -> uint { + match self.data { + TextNodeData::Leaf(ref tb) => { + let mut iter = tb.as_str().chars(); + let mut tlen = 0; + + for c in iter { + if c == '\n' { + tlen = 0; + } + else { + tlen += 1; + } + } + + return tlen; + }, + + TextNodeData::Branch(ref left, ref right) => { + if right.newline_count > 0 { + return right.tail_len(); + } + else { + return left.tail_len() + right.char_count; + } + } + } + } + + } impl fmt::Show for TextNode { diff --git a/src/editor.rs b/src/editor.rs index 4c82a00..bc766ab 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -104,6 +104,8 @@ impl Editor { pub fn cursor_right(&mut self) { self.cursor.1 += 1; + let p = self.buffer.pos_2d_to_closest_1d(self.cursor); + self.cursor = self.buffer.pos_1d_to_closest_2d(p); } pub fn cursor_up(&mut self) { @@ -113,6 +115,8 @@ impl Editor { } pub fn cursor_down(&mut self) { - self.cursor.0 += 1; + if self.cursor.0 < self.buffer.newline_count() { + self.cursor.0 += 1; + } } } diff --git a/src/term_ui.rs b/src/term_ui.rs index c4fbab2..2e435c9 100644 --- a/src/term_ui.rs +++ b/src/term_ui.rs @@ -190,7 +190,7 @@ impl TermUI { tb_iter.next_line(); line += 1; column = 0; - // TODO: handle pos incrementing here + pos = editor.buffer.pos_2d_to_closest_1d((line, column)); } } }