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

move Edit and EditKind into history.rs

since they are used only for undo/redo
Этот коммит содержится в:
rhysd
2022-06-11 14:13:31 +09:00
родитель b30caba358
Коммит 2bd0665615
4 изменённых файлов: 98 добавлений и 100 удалений

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

@@ -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<String>) {
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<String>) {
let (row, _) = self.cursor_before;
self.kind.apply(row, lines);
}
pub fn undo(&self, lines: &mut Vec<String>) {
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
}
}

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

@@ -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<String>) {
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<String>) {
let (row, _) = self.cursor_before;
self.kind.apply(row, lines);
}
pub fn undo(&self, lines: &mut Vec<String>) {
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<Edit>,
}
impl EditHistory {
impl History {
pub fn new(max_items: usize) -> Self {
Self {
index: 0,

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

@@ -1,5 +1,4 @@
mod cursor;
mod edit;
mod history;
mod input;
mod textarea;

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

@@ -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) {