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:
parent
b31903e838
commit
f56d3f0ad4
|
@ -70,14 +70,29 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Remove the text between grapheme positions 'pos_a' and 'pos_b'.
|
/// Remove the text before grapheme position 'pos' of length 'len'.
|
||||||
pub fn remove_text(&mut self, pos_a: usize, pos_b: usize) {
|
pub fn remove_text_before(&mut self, pos: usize, len: usize) {
|
||||||
let removed_text = self.string_from_range(pos_a, pos_b);
|
if pos >= len {
|
||||||
|
let removed_text = self.string_from_range(pos - len, pos);
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self._remove_text(pos_a, pos_b);
|
/// 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
|
// 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) {
|
fn _remove_text(&mut self, pos_a: usize, pos_b: usize) {
|
||||||
|
@ -146,8 +161,8 @@ impl Buffer {
|
||||||
// TODO: a more efficient implementation that directly
|
// TODO: a more efficient implementation that directly
|
||||||
// manipulates the node tree.
|
// manipulates the node tree.
|
||||||
let s = self.string_from_range(pos_a, pos_b);
|
let s = self.string_from_range(pos_a, pos_b);
|
||||||
self.remove_text(pos_a, pos_b);
|
self._remove_text(pos_a, pos_b);
|
||||||
self.insert_text(s.as_slice(), pos_to);
|
self._insert_text(s.as_slice(), pos_to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,12 +218,18 @@ impl Buffer {
|
||||||
return Some(p);
|
return Some(p);
|
||||||
},
|
},
|
||||||
|
|
||||||
RemoveText(ref s, p) => {
|
RemoveTextBefore(ref s, p) => {
|
||||||
let size = grapheme_count(s.as_slice());
|
let size = grapheme_count(s.as_slice());
|
||||||
self._insert_text(s.as_slice(), p);
|
self._insert_text(s.as_slice(), p);
|
||||||
return Some(p+size);
|
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) => {
|
MoveText(pa, pb, pto) => {
|
||||||
let size = pb - pa;
|
let size = pb - pa;
|
||||||
self._move_text(pto, pto + size, pa);
|
self._move_text(pto, pto + size, pa);
|
||||||
|
@ -236,7 +257,7 @@ impl Buffer {
|
||||||
return Some(p+size);
|
return Some(p+size);
|
||||||
},
|
},
|
||||||
|
|
||||||
RemoveText(ref s, p) => {
|
RemoveTextBefore(ref s, p) | RemoveTextAfter(ref s, p) => {
|
||||||
let size = grapheme_count(s.as_slice());
|
let size = grapheme_count(s.as_slice());
|
||||||
self._remove_text(p, p+size);
|
self._remove_text(p, p+size);
|
||||||
return Some(p);
|
return Some(p);
|
||||||
|
@ -782,7 +803,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
assert!(buf.text.line_count == 6);
|
assert!(buf.text.line_count == 6);
|
||||||
|
|
||||||
buf.remove_text(0, 3);
|
buf._remove_text(0, 3);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -826,7 +847,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
assert!(buf.text.line_count == 6);
|
assert!(buf.text.line_count == 6);
|
||||||
|
|
||||||
buf.remove_text(0, 12);
|
buf._remove_text(0, 12);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -861,7 +882,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
assert!(buf.text.line_count == 6);
|
assert!(buf.text.line_count == 6);
|
||||||
|
|
||||||
buf.remove_text(5, 17);
|
buf._remove_text(5, 17);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -896,7 +917,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
assert!(buf.text.line_count == 6);
|
assert!(buf.text.line_count == 6);
|
||||||
|
|
||||||
buf.remove_text(23, 29);
|
buf._remove_text(23, 29);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -937,7 +958,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
assert!(buf.text.line_count == 6);
|
assert!(buf.text.line_count == 6);
|
||||||
|
|
||||||
buf.remove_text(17, 29);
|
buf._remove_text(17, 29);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -972,7 +993,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
assert!(buf.text.line_count == 2);
|
assert!(buf.text.line_count == 2);
|
||||||
|
|
||||||
buf.remove_text(3, 12);
|
buf._remove_text(3, 12);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -993,7 +1014,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 15);
|
assert!(buf.grapheme_count() == 15);
|
||||||
assert!(buf.text.line_count == 3);
|
assert!(buf.text.line_count == 3);
|
||||||
|
|
||||||
buf.remove_text(5, 15);
|
buf._remove_text(5, 15);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -1016,7 +1037,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
assert!(buf.text.line_count == 2);
|
assert!(buf.text.line_count == 2);
|
||||||
|
|
||||||
buf.remove_text(3, 11);
|
buf._remove_text(3, 11);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -1038,7 +1059,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
assert!(buf.text.line_count == 2);
|
assert!(buf.text.line_count == 2);
|
||||||
|
|
||||||
buf.remove_text(8, 12);
|
buf._remove_text(8, 12);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -1064,7 +1085,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 11);
|
assert!(buf.grapheme_count() == 11);
|
||||||
assert!(buf.text.line_count == 4);
|
assert!(buf.text.line_count == 4);
|
||||||
|
|
||||||
buf.remove_text(4, 11);
|
buf._remove_text(4, 11);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
@ -1086,7 +1107,7 @@ mod tests {
|
||||||
assert!(buf.grapheme_count() == 10);
|
assert!(buf.grapheme_count() == 10);
|
||||||
assert!(buf.text.line_count == 1);
|
assert!(buf.text.line_count == 1);
|
||||||
|
|
||||||
buf.remove_text(9, 10);
|
buf._remove_text(9, 10);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter();
|
let mut iter = buf.grapheme_iter();
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ use std::collections::DList;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
InsertText(String, usize),
|
InsertText(String, usize),
|
||||||
RemoveText(String, usize),
|
RemoveTextBefore(String, usize),
|
||||||
|
RemoveTextAfter(String, usize),
|
||||||
MoveText(usize, usize, usize),
|
MoveText(usize, usize, usize),
|
||||||
CompositeOp(Vec<Operation>),
|
CompositeOp(Vec<Operation>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,17 +287,15 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos_b = self.cursor.range.0;
|
let len = min(self.cursor.range.0, grapheme_count);
|
||||||
let pos_a = if pos_b >= grapheme_count {pos_b - grapheme_count} else {0};
|
|
||||||
let tot_g = pos_b - pos_a;
|
|
||||||
|
|
||||||
// Remove text
|
// Remove text
|
||||||
self.buffer.remove_text(pos_a, pos_b);
|
self.buffer.remove_text_before(self.cursor.range.0, len);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
// Move cursor
|
// Move cursor
|
||||||
self.cursor.range.0 -= tot_g;
|
self.cursor.range.0 -= len;
|
||||||
self.cursor.range.1 -= tot_g;
|
self.cursor.range.1 -= len;
|
||||||
self.cursor.update_vis_start(&(self.buffer));
|
self.cursor.update_vis_start(&(self.buffer));
|
||||||
|
|
||||||
// Adjust view
|
// Adjust view
|
||||||
|
@ -310,11 +308,11 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos_a = self.cursor.range.1;
|
let max_len = if self.buffer.grapheme_count() > self.cursor.range.1 {self.buffer.grapheme_count() - self.cursor.range.1} else {0};
|
||||||
let pos_b = if (pos_a + grapheme_count) <= self.buffer.grapheme_count() {pos_a + grapheme_count} else {self.buffer.grapheme_count()};
|
let len = min(max_len, grapheme_count);
|
||||||
|
|
||||||
// Remove text
|
// Remove text
|
||||||
self.buffer.remove_text(pos_a, pos_b);
|
self.buffer.remove_text_after(self.cursor.range.1, len);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
// Move cursor
|
// Move cursor
|
||||||
|
@ -327,7 +325,7 @@ impl Editor {
|
||||||
pub fn remove_text_inside_cursor(&mut self) {
|
pub fn remove_text_inside_cursor(&mut self) {
|
||||||
// If selection, remove text
|
// If selection, remove text
|
||||||
if self.cursor.range.0 < self.cursor.range.1 {
|
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;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
todo.md
3
todo.md
|
@ -9,7 +9,8 @@
|
||||||
- Clean up text buffer interface:
|
- Clean up text buffer interface:
|
||||||
- Editing (these are undoable):
|
- Editing (these are undoable):
|
||||||
//- insert_text
|
//- insert_text
|
||||||
//- remove_text
|
//- remove_text_before
|
||||||
|
//- remove_text_after
|
||||||
//- move_text
|
//- move_text
|
||||||
- Undo functionality:
|
- Undo functionality:
|
||||||
//- Undo
|
//- Undo
|
||||||
|
|
Loading…
Reference in New Issue
Block a user