1
0
зеркало из https://github.com/glebtv/tui-textarea.git synced 2026-09-08 16:35:49 +03:00

implement undo as redo of inverted edit

Этот коммит содержится в:
rhysd
2022-06-09 23:27:33 +09:00
родитель 05eec63bac
Коммит d847061951

Просмотреть файл

@@ -1,13 +1,15 @@
#[derive(Clone)]
pub enum EditKind { pub enum EditKind {
InsertChar(char, usize), InsertChar(char, usize),
DeleteChar(char, usize), DeleteChar(char, usize),
InsertNewline(usize), InsertNewline(usize),
DeleteNewline(usize), DeleteNewline(usize),
Insert(String, usize), Insert(String, usize),
Remove(String, usize),
} }
impl EditKind { impl EditKind {
fn redo(&self, row: usize, lines: &mut Vec<String>) { fn apply(&self, row: usize, lines: &mut Vec<String>) {
match self { match self {
EditKind::InsertChar(c, i) => { EditKind::InsertChar(c, i) => {
lines[row].insert(*i, *c); lines[row].insert(*i, *c);
@@ -33,19 +35,22 @@ impl EditKind {
EditKind::Insert(s, i) => { EditKind::Insert(s, i) => {
lines[row].insert_str(*i, s.as_str()); lines[row].insert_str(*i, s.as_str());
} }
EditKind::Remove(s, i) => {
let end = *i + s.len();
lines[row].replace_range(*i..end, "");
}
} }
} }
fn undo(&self, row: usize, lines: &mut Vec<String>) { fn invert(&self) -> Self {
use EditKind::*; use EditKind::*;
match self { match self.clone() {
InsertChar(c, i) => DeleteChar(*c, *i).redo(row, lines), InsertChar(c, i) => DeleteChar(c, i),
DeleteChar(c, i) => InsertChar(*c, *i).redo(row, lines), DeleteChar(c, i) => InsertChar(c, i),
InsertNewline(i) => DeleteNewline(*i).redo(row, lines), InsertNewline(i) => DeleteNewline(i),
DeleteNewline(i) => InsertNewline(*i).redo(row, lines), DeleteNewline(i) => InsertNewline(i),
Insert(s, i) => { Insert(s, i) => Remove(s, i),
lines[row].replace_range(*i..s.len(), ""); Remove(s, i) => Insert(s, i),
}
} }
} }
} }
@@ -71,12 +76,12 @@ impl Edit {
pub fn redo(&self, lines: &mut Vec<String>) { pub fn redo(&self, lines: &mut Vec<String>) {
let (row, _) = self.cursor_before; let (row, _) = self.cursor_before;
self.kind.redo(row, lines) self.kind.apply(row, lines);
} }
pub fn undo(&self, lines: &mut Vec<String>) { pub fn undo(&self, lines: &mut Vec<String>) {
let (row, _) = self.cursor_after; let (row, _) = self.cursor_after;
self.kind.undo(row, lines) self.kind.invert().apply(row, lines); // Undo is redo of inverted edit
} }
pub fn cursor_before(&self) -> (usize, usize) { pub fn cursor_before(&self) -> (usize, usize) {