From 2bd0665615a0d09d14710f7b4e5a75b1a4e1f7ae Mon Sep 17 00:00:00 2001 From: rhysd Date: Sat, 11 Jun 2022 14:13:31 +0900 Subject: [PATCH] move `Edit` and `EditKind` into history.rs since they are used only for undo/redo --- src/edit.rs | 91 ---------------------------------------------- src/history.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 1 - src/textarea.rs | 9 ++--- 4 files changed, 98 insertions(+), 100 deletions(-) delete mode 100644 src/edit.rs diff --git a/src/edit.rs b/src/edit.rs deleted file mode 100644 index c5dfb9e..0000000 --- a/src/edit.rs +++ /dev/null @@ -1,91 +0,0 @@ -#[derive(Clone)] -pub enum EditKind { - InsertChar(char, usize), - DeleteChar(char, usize), - InsertNewline(usize), - DeleteNewline(usize), - Insert(String, usize), - Remove(String, usize), -} - -impl EditKind { - fn apply(&self, row: usize, lines: &mut Vec) { - match self { - EditKind::InsertChar(c, i) => { - lines[row].insert(*i, *c); - } - EditKind::DeleteChar(_, i) => { - lines[row].remove(*i); - } - EditKind::InsertNewline(i) => { - let line = &mut lines[row]; - let next_line = line[*i..].to_string(); - line.truncate(*i); - lines.insert(row + 1, next_line); - } - EditKind::DeleteNewline(_) => { - if row > 0 { - let line = lines.remove(row); - lines[row - 1].push_str(&line); - } - } - EditKind::Insert(s, i) => { - lines[row].insert_str(*i, s.as_str()); - } - EditKind::Remove(s, i) => { - let end = *i + s.len(); - lines[row].replace_range(*i..end, ""); - } - } - } - - fn invert(&self) -> Self { - use EditKind::*; - match self.clone() { - InsertChar(c, i) => DeleteChar(c, i), - DeleteChar(c, i) => InsertChar(c, i), - InsertNewline(i) => DeleteNewline(i), - DeleteNewline(i) => InsertNewline(i), - Insert(s, i) => Remove(s, i), - Remove(s, i) => Insert(s, i), - } - } -} - -pub struct Edit { - kind: EditKind, - cursor_before: (usize, usize), - cursor_after: (usize, usize), -} - -impl Edit { - pub fn new( - kind: EditKind, - cursor_before: (usize, usize), - cursor_after: (usize, usize), - ) -> Self { - Self { - kind, - cursor_before, - cursor_after, - } - } - - pub fn redo(&self, lines: &mut Vec) { - let (row, _) = self.cursor_before; - self.kind.apply(row, lines); - } - - pub fn undo(&self, lines: &mut Vec) { - let (row, _) = self.cursor_after; - self.kind.invert().apply(row, lines); // Undo is redo of inverted edit - } - - pub fn cursor_before(&self) -> (usize, usize) { - self.cursor_before - } - - pub fn cursor_after(&self) -> (usize, usize) { - self.cursor_after - } -} diff --git a/src/history.rs b/src/history.rs index 5da0766..fdccb2a 100644 --- a/src/history.rs +++ b/src/history.rs @@ -1,13 +1,104 @@ -use crate::edit::Edit; use std::collections::VecDeque; -pub struct EditHistory { +#[derive(Clone)] +pub enum EditKind { + InsertChar(char, usize), + DeleteChar(char, usize), + InsertNewline(usize), + DeleteNewline(usize), + Insert(String, usize), + Remove(String, usize), +} + +impl EditKind { + fn apply(&self, row: usize, lines: &mut Vec) { + match self { + EditKind::InsertChar(c, i) => { + lines[row].insert(*i, *c); + } + EditKind::DeleteChar(_, i) => { + lines[row].remove(*i); + } + EditKind::InsertNewline(i) => { + let line = &mut lines[row]; + let next_line = line[*i..].to_string(); + line.truncate(*i); + lines.insert(row + 1, next_line); + } + EditKind::DeleteNewline(_) => { + if row > 0 { + let line = lines.remove(row); + lines[row - 1].push_str(&line); + } + } + EditKind::Insert(s, i) => { + lines[row].insert_str(*i, s.as_str()); + } + EditKind::Remove(s, i) => { + let end = *i + s.len(); + lines[row].replace_range(*i..end, ""); + } + } + } + + fn invert(&self) -> Self { + use EditKind::*; + match self.clone() { + InsertChar(c, i) => DeleteChar(c, i), + DeleteChar(c, i) => InsertChar(c, i), + InsertNewline(i) => DeleteNewline(i), + DeleteNewline(i) => InsertNewline(i), + Insert(s, i) => Remove(s, i), + Remove(s, i) => Insert(s, i), + } + } +} + +pub struct Edit { + kind: EditKind, + cursor_before: (usize, usize), + cursor_after: (usize, usize), +} + +impl Edit { + pub fn new( + kind: EditKind, + cursor_before: (usize, usize), + cursor_after: (usize, usize), + ) -> Self { + Self { + kind, + cursor_before, + cursor_after, + } + } + + pub fn redo(&self, lines: &mut Vec) { + let (row, _) = self.cursor_before; + self.kind.apply(row, lines); + } + + pub fn undo(&self, lines: &mut Vec) { + let (row, _) = self.cursor_after; + self.kind.invert().apply(row, lines); // Undo is redo of inverted edit + } + + pub fn cursor_before(&self) -> (usize, usize) { + self.cursor_before + } + + pub fn cursor_after(&self) -> (usize, usize) { + self.cursor_after + } +} + +pub struct History { index: usize, max_items: usize, edits: VecDeque, } -impl EditHistory { +impl History { pub fn new(max_items: usize) -> Self { Self { index: 0, diff --git a/src/lib.rs b/src/lib.rs index a1d3bd8..b4bb7a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ mod cursor; -mod edit; mod history; mod input; mod textarea; diff --git a/src/textarea.rs b/src/textarea.rs index 7ef6562..d206fb1 100644 --- a/src/textarea.rs +++ b/src/textarea.rs @@ -1,6 +1,5 @@ use crate::cursor::CursorMove; -use crate::edit::{Edit, EditKind}; -use crate::history::EditHistory; +use crate::history::{Edit, EditKind, History}; use crate::input::{Input, Key}; use std::sync::atomic::{AtomicU16, Ordering}; use tui::buffer::Buffer; @@ -15,7 +14,7 @@ pub struct TextArea<'a> { style: Style, cursor: (usize, usize), // 0-base tab: &'a str, - history: EditHistory, + history: History, cursor_line_style: Style, scroll_top: (AtomicU16, AtomicU16), } @@ -47,7 +46,7 @@ impl<'a> TextArea<'a> { style: Style::default(), cursor: (0, 0), tab: " ", - history: EditHistory::new(50), + history: History::new(50), cursor_line_style: Style::default().add_modifier(Modifier::UNDERLINED), scroll_top: (AtomicU16::new(0), AtomicU16::new(0)), } @@ -453,7 +452,7 @@ impl<'a> TextArea<'a> { } pub fn set_max_histories(&mut self, max: usize) { - self.history = EditHistory::new(max); + self.history = History::new(max); } pub fn set_cursor_line_style(&mut self, style: Style) {