undo/redo

This commit is contained in:
alice pellerin
2026-03-18 16:28:15 -05:00
parent 725e6784ab
commit 7695d23984
5 changed files with 108 additions and 7 deletions
+53 -3
View File
@@ -3,6 +3,12 @@ use crate::{app::App, cursor::Cursor};
#[derive(Debug)]
pub enum EditAction {
// this is a hacky workaround to allow disjoint borrows for
// undoing/redoing edits. because the undo/redo operations need
// to borrow an EditAction from edit_history, but should never touch
// edit_history themselves, we can swap out the action in question,
// then swap it back in once the undo/redo is done
Placeholder,
Delete {
cursor: Cursor,
old_data: Vec<u8>
@@ -11,17 +17,31 @@ pub enum EditAction {
cursor: Cursor,
old_data: Vec<u8>,
new_byte: u8
}
},
// Insert {
// cursor: Cursor,
// which side of cursor? append/insert
// new_data: Vec<u8>
// }
}
impl App {
pub fn execute_and_add(&mut self, edit_action: EditAction) {
assert!(!matches!(edit_action, EditAction::Placeholder));
self.execute_edit(&edit_action);
if let Some(date) = self.time_traveling {
self.edit_history.truncate(date);
self.time_traveling = None;
}
self.edit_history.push(edit_action);
}
fn execute_edit(&mut self, edit_action: &EditAction) {
pub fn execute_edit(&mut self, edit_action: &EditAction) {
match edit_action {
EditAction::Placeholder => unreachable!(),
EditAction::Delete { cursor, .. } => self.delete_at(*cursor),
EditAction::Replace {
cursor, old_data: _, new_byte
@@ -29,6 +49,16 @@ impl App {
}
}
pub fn undo_edit(&mut self, edit_action: &EditAction) {
match edit_action {
EditAction::Placeholder => unreachable!(),
EditAction::Delete { cursor, old_data } => self.undo_delete_at(*cursor, old_data),
EditAction::Replace {
cursor, old_data, ..
} => self.undo_replace_at_with(*cursor, old_data),
}
}
fn delete_at(&mut self, cursor: Cursor) {
self.contents.drain(cursor.range());
@@ -36,8 +66,28 @@ impl App {
self.cursor.collapse();
}
fn undo_delete_at(&mut self, cursor: Cursor, old_data: &[u8]) {
let cursor_start = min(cursor.head, cursor.tail);
self.contents.splice(
cursor_start..cursor_start,
old_data.iter().copied()
);
self.cursor = cursor;
}
fn replace_at_with(&mut self, cursor: Cursor, new_byte: u8) {
self.contents[self.cursor.range()].fill(new_byte);
self.contents[cursor.range()].fill(new_byte);
self.cursor = cursor;
}
fn undo_replace_at_with(&mut self, cursor: Cursor, old_data: &[u8]) {
self.contents.splice(
cursor.range(),
old_data.iter().copied()
);
self.cursor = cursor;
}