Implement rudimentary undo/redo support

This commit is contained in:
mars 2023-04-18 20:05:28 -04:00
parent ae45c3392f
commit 9ab272823d
2 changed files with 45 additions and 4 deletions

View File

@ -130,10 +130,12 @@ pub fn visual_mode(state: &mut State) {
} }
pub fn insert_mode(state: &mut State) { pub fn insert_mode(state: &mut State) {
state.save_buffer();
state.mode = Mode::Insert(InsertState { append: false }); state.mode = Mode::Insert(InsertState { append: false });
} }
pub fn append_mode(state: &mut State) { pub fn append_mode(state: &mut State) {
state.save_buffer();
state.move_cursor(Direction::Right); state.move_cursor(Direction::Right);
state.mode = Mode::Insert(InsertState { append: true }); state.mode = Mode::Insert(InsertState { append: true });
} }
@ -149,24 +151,24 @@ pub fn insert_at_line_end(state: &mut State) {
} }
pub fn open_below(state: &mut State) { pub fn open_below(state: &mut State) {
insert_mode(state);
state.cursor.line += 1; state.cursor.line += 1;
state.cursor.column = 0; state.cursor.column = 0;
state.buffer.insert_char(state.cursor, '\n'); state.buffer.insert_char(state.cursor, '\n');
state.mode = Mode::Insert(InsertState { append: false });
} }
pub fn open_above(state: &mut State) { pub fn open_above(state: &mut State) {
insert_mode(state);
state.cursor.column = 0; state.cursor.column = 0;
state.buffer.insert_char(state.cursor, '\n'); state.buffer.insert_char(state.cursor, '\n');
state.mode = Mode::Insert(InsertState { append: false });
} }
pub fn undo(state: &mut State) { pub fn undo(state: &mut State) {
state.set_error("undo is unimplemented"); state.undo();
} }
pub fn redo(state: &mut State) { pub fn redo(state: &mut State) {
state.set_error("redo is unimplemented"); state.redo();
} }
pub fn delete_char_backward(state: &mut State) { pub fn delete_char_backward(state: &mut State) {

View File

@ -71,6 +71,8 @@ pub struct State {
pub styles: Arc<Mutex<StyleStore>>, pub styles: Arc<Mutex<StyleStore>>,
pub config: Config, pub config: Config,
pub buffer: Buffer, pub buffer: Buffer,
pub undo_buffers: Vec<Buffer>,
pub redo_buffers: Vec<Buffer>,
pub cursor: Cursor, pub cursor: Cursor,
pub file: Option<OsString>, pub file: Option<OsString>,
pub mode: Mode, pub mode: Mode,
@ -95,6 +97,8 @@ impl State {
styles, styles,
config: Default::default(), config: Default::default(),
buffer, buffer,
undo_buffers: Vec::new(),
redo_buffers: Vec::new(),
cursor: Cursor::default(), cursor: Cursor::default(),
file: file_name, file: file_name,
mode: Mode::default(), mode: Mode::default(),
@ -375,4 +379,39 @@ impl State {
self.scroll.line = self.cursor.line + 3 - self.size.1; self.scroll.line = self.cursor.line + 3 - self.size.1;
} }
} }
/// If modified, saves the current buffer in undo history and clears the redo history.
pub fn save_buffer(&mut self) {
/*if let Some(last) = self.undo_buffers.last() {
if *last.as_ref() == *self.buffer.as_ref() {
return;
}
}*/
let current = self.buffer.clone();
self.undo_buffers.push(current);
self.redo_buffers.clear();
}
/// Pops the last undo state from the history and pushes the current state to the redo buffers.
pub fn undo(&mut self) {
match self.undo_buffers.pop() {
None => self.set_error("Already at oldest change"),
Some(last) => {
let current = std::mem::replace(&mut self.buffer, last);
self.redo_buffers.push(current);
}
}
}
/// Pops the next redo state from the history and pushes the current state to the undo buffers.
pub fn redo(&mut self) {
match self.redo_buffers.pop() {
None => self.set_error("Already at newest change"),
Some(next) => {
let current = std::mem::replace(&mut self.buffer, next);
self.undo_buffers.push(current);
}
}
}
} }