Split remove_text() into remove_text_before() and remove_text_after().

This is useful so that undo knows where to put the cursor.
This commit is contained in:
Nathan Vegdahl 2015-01-11 00:59:02 -08:00
parent b31903e838
commit f56d3f0ad4
4 changed files with 53 additions and 32 deletions

View File

@ -70,14 +70,29 @@ impl Buffer {
}
/// Remove the text between grapheme positions 'pos_a' and 'pos_b'.
pub fn remove_text(&mut self, pos_a: usize, pos_b: usize) {
let removed_text = self.string_from_range(pos_a, pos_b);
/// Remove the text before grapheme position 'pos' of length 'len'.
pub fn remove_text_before(&mut self, pos: usize, len: usize) {
if pos >= len {
let removed_text = self.string_from_range(pos - len, pos);
self._remove_text(pos_a, pos_b);
self._remove_text(pos - len, pos);
// Push operation to the undo stack
self.undo_stack.push(RemoveTextBefore(removed_text, pos - len));
}
else {
panic!("Buffer::remove_text_before(): attempt to remove text before beginning of buffer.");
}
}
/// Remove the text after grapheme position 'pos' of length 'len'.
pub fn remove_text_after(&mut self, pos: usize, len: usize) {
let removed_text = self.string_from_range(pos, pos + len);
self._remove_text(pos, pos + len);
// Push operation to the undo stack
self.undo_stack.push(RemoveText(removed_text, pos_a));
self.undo_stack.push(RemoveTextAfter(removed_text, pos));
}
fn _remove_text(&mut self, pos_a: usize, pos_b: usize) {
@ -146,8 +161,8 @@ impl Buffer {
// TODO: a more efficient implementation that directly
// manipulates the node tree.
let s = self.string_from_range(pos_a, pos_b);
self.remove_text(pos_a, pos_b);
self.insert_text(s.as_slice(), pos_to);
self._remove_text(pos_a, pos_b);
self._insert_text(s.as_slice(), pos_to);
}
}
@ -203,12 +218,18 @@ impl Buffer {
return Some(p);
},
RemoveText(ref s, p) => {
RemoveTextBefore(ref s, p) => {
let size = grapheme_count(s.as_slice());
self._insert_text(s.as_slice(), p);
return Some(p+size);
},
RemoveTextAfter(ref s, p) => {
let size = grapheme_count(s.as_slice());
self._insert_text(s.as_slice(), p);
return Some(p);
},
MoveText(pa, pb, pto) => {
let size = pb - pa;
self._move_text(pto, pto + size, pa);
@ -236,7 +257,7 @@ impl Buffer {
return Some(p+size);
},
RemoveText(ref s, p) => {
RemoveTextBefore(ref s, p) | RemoveTextAfter(ref s, p) => {
let size = grapheme_count(s.as_slice());
self._remove_text(p, p+size);
return Some(p);
@ -782,7 +803,7 @@ mod tests {
assert!(buf.grapheme_count() == 29);
assert!(buf.text.line_count == 6);
buf.remove_text(0, 3);
buf._remove_text(0, 3);
let mut iter = buf.grapheme_iter();
@ -826,7 +847,7 @@ mod tests {
assert!(buf.grapheme_count() == 29);
assert!(buf.text.line_count == 6);
buf.remove_text(0, 12);
buf._remove_text(0, 12);
let mut iter = buf.grapheme_iter();
@ -861,7 +882,7 @@ mod tests {
assert!(buf.grapheme_count() == 29);
assert!(buf.text.line_count == 6);
buf.remove_text(5, 17);
buf._remove_text(5, 17);
let mut iter = buf.grapheme_iter();
@ -896,7 +917,7 @@ mod tests {
assert!(buf.grapheme_count() == 29);
assert!(buf.text.line_count == 6);
buf.remove_text(23, 29);
buf._remove_text(23, 29);
let mut iter = buf.grapheme_iter();
@ -937,7 +958,7 @@ mod tests {
assert!(buf.grapheme_count() == 29);
assert!(buf.text.line_count == 6);
buf.remove_text(17, 29);
buf._remove_text(17, 29);
let mut iter = buf.grapheme_iter();
@ -972,7 +993,7 @@ mod tests {
assert!(buf.grapheme_count() == 12);
assert!(buf.text.line_count == 2);
buf.remove_text(3, 12);
buf._remove_text(3, 12);
let mut iter = buf.grapheme_iter();
@ -993,7 +1014,7 @@ mod tests {
assert!(buf.grapheme_count() == 15);
assert!(buf.text.line_count == 3);
buf.remove_text(5, 15);
buf._remove_text(5, 15);
let mut iter = buf.grapheme_iter();
@ -1016,7 +1037,7 @@ mod tests {
assert!(buf.grapheme_count() == 12);
assert!(buf.text.line_count == 2);
buf.remove_text(3, 11);
buf._remove_text(3, 11);
let mut iter = buf.grapheme_iter();
@ -1038,7 +1059,7 @@ mod tests {
assert!(buf.grapheme_count() == 12);
assert!(buf.text.line_count == 2);
buf.remove_text(8, 12);
buf._remove_text(8, 12);
let mut iter = buf.grapheme_iter();
@ -1064,7 +1085,7 @@ mod tests {
assert!(buf.grapheme_count() == 11);
assert!(buf.text.line_count == 4);
buf.remove_text(4, 11);
buf._remove_text(4, 11);
let mut iter = buf.grapheme_iter();
@ -1086,7 +1107,7 @@ mod tests {
assert!(buf.grapheme_count() == 10);
assert!(buf.text.line_count == 1);
buf.remove_text(9, 10);
buf._remove_text(9, 10);
let mut iter = buf.grapheme_iter();

View File

@ -5,7 +5,8 @@ use std::collections::DList;
#[derive(Clone)]
pub enum Operation {
InsertText(String, usize),
RemoveText(String, usize),
RemoveTextBefore(String, usize),
RemoveTextAfter(String, usize),
MoveText(usize, usize, usize),
CompositeOp(Vec<Operation>),
}

View File

@ -287,17 +287,15 @@ impl Editor {
return;
}
let pos_b = self.cursor.range.0;
let pos_a = if pos_b >= grapheme_count {pos_b - grapheme_count} else {0};
let tot_g = pos_b - pos_a;
let len = min(self.cursor.range.0, grapheme_count);
// Remove text
self.buffer.remove_text(pos_a, pos_b);
self.buffer.remove_text_before(self.cursor.range.0, len);
self.dirty = true;
// Move cursor
self.cursor.range.0 -= tot_g;
self.cursor.range.1 -= tot_g;
self.cursor.range.0 -= len;
self.cursor.range.1 -= len;
self.cursor.update_vis_start(&(self.buffer));
// Adjust view
@ -310,11 +308,11 @@ impl Editor {
return;
}
let pos_a = self.cursor.range.1;
let pos_b = if (pos_a + grapheme_count) <= self.buffer.grapheme_count() {pos_a + grapheme_count} else {self.buffer.grapheme_count()};
let max_len = if self.buffer.grapheme_count() > self.cursor.range.1 {self.buffer.grapheme_count() - self.cursor.range.1} else {0};
let len = min(max_len, grapheme_count);
// Remove text
self.buffer.remove_text(pos_a, pos_b);
self.buffer.remove_text_after(self.cursor.range.1, len);
self.dirty = true;
// Move cursor
@ -327,7 +325,7 @@ impl Editor {
pub fn remove_text_inside_cursor(&mut self) {
// If selection, remove text
if self.cursor.range.0 < self.cursor.range.1 {
self.buffer.remove_text(self.cursor.range.0, self.cursor.range.1);
self.buffer.remove_text_before(self.cursor.range.0, self.cursor.range.1 - self.cursor.range.0);
self.dirty = true;
}

View File

@ -9,7 +9,8 @@
- Clean up text buffer interface:
- Editing (these are undoable):
//- insert_text
//- remove_text
//- remove_text_before
//- remove_text_after
//- move_text
- Undo functionality:
//- Undo