summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/todo_file/src/history/history_item.rs9
-rw-r--r--src/todo_file/src/history/mod.rs29
-rw-r--r--src/todo_file/src/history/operation.rs1
-rw-r--r--src/todo_file/src/history/tests.rs160
-rw-r--r--src/todo_file/src/lib.rs59
5 files changed, 174 insertions, 84 deletions
diff --git a/src/todo_file/src/history/history_item.rs b/src/todo_file/src/history/history_item.rs
index b0014c4..9ea89dc 100644
--- a/src/todo_file/src/history/history_item.rs
+++ b/src/todo_file/src/history/history_item.rs
@@ -9,6 +9,15 @@ pub(crate) struct HistoryItem {
}
impl HistoryItem {
+ pub(crate) const fn new_load() -> Self {
+ Self {
+ operation: Operation::Load,
+ start_index: 0,
+ end_index: 0,
+ lines: vec![],
+ }
+ }
+
pub(crate) fn new_modify(start_index: usize, end_index: usize, lines: Vec<Line>) -> Self {
Self {
operation: Operation::Modify,
diff --git a/src/todo_file/src/history/mod.rs b/src/todo_file/src/history/mod.rs
index 68074b7..2020d85 100644
--- a/src/todo_file/src/history/mod.rs
+++ b/src/todo_file/src/history/mod.rs
@@ -23,13 +23,14 @@ impl History {
pub(crate) fn new(limit: u32) -> Self {
Self {
redo_history: VecDeque::new(),
- undo_history: VecDeque::new(),
+ undo_history: VecDeque::from([HistoryItem::new_load()]),
limit: limit.try_into().expect("History limit is too large"),
}
}
pub(crate) fn apply_operation(lines: &mut Vec<Line>, operation: &HistoryItem) -> HistoryItem {
match operation.operation {
+ Operation::Load => HistoryItem::new_load(),
Operation::Modify => {
let range = if operation.end_index <= operation.start_index {
operation.end_index..=operation.start_index
@@ -73,32 +74,40 @@ impl History {
}
}
- pub(crate) fn undo(&mut self, current: &mut Vec<Line>) -> Option<(usize, usize)> {
- self.undo_history.pop_back().map(|operation| {
- let history = Self::apply_operation(current, &operation);
+ pub(crate) fn undo(&mut self, current: &mut Vec<Line>) -> Option<(Operation, usize, usize)> {
+ self.undo_history.pop_back().map(|history_item| {
+ let history = Self::apply_operation(current, &history_item);
+ // do not remove load operation from undo history, as it acts as a sentinel value
+ if history.operation == Operation::Load {
+ self.undo_history.push_back(history_item);
+ return (history.operation, history.start_index, history.end_index);
+ }
let update_range = Self::get_last_index_range(&history, current.len());
self.redo_history.push_back(history);
- update_range
+ (history_item.operation, update_range.0, update_range.1)
})
}
- pub(crate) fn redo(&mut self, current: &mut Vec<Line>) -> Option<(usize, usize)> {
- self.redo_history.pop_back().map(|operation| {
- let history = Self::apply_operation(current, &operation);
+ pub(crate) fn redo(&mut self, current: &mut Vec<Line>) -> Option<(Operation, usize, usize)> {
+ self.redo_history.pop_back().map(|history_item| {
+ // the load operation is not handled here, as it is in `undo` because the load operation should never be
+ // added to the redo history
+ let history = Self::apply_operation(current, &history_item);
let update_range = Self::get_last_index_range(&history, current.len());
self.undo_history.push_back(history);
- update_range
+ (history_item.operation, update_range.0, update_range.1)
})
}
pub(crate) fn reset(&mut self) {
self.undo_history.clear();
+ self.undo_history.push_back(HistoryItem::new_load());
self.redo_history.clear();
}
fn get_last_index_range(history_item: &HistoryItem, list_length: usize) -> (usize, usize) {
match history_item.operation {
- Operation::Add | Operation::Modify => (history_item.start_index, history_item.end_index),
+ Operation::Add | Operation::Modify | Operation::Load => (history_item.start_index, history_item.end_index),
Operation::Remove => {
let index = min(history_item.start_index, history_item.end_index);
if index == 0 || list_length == 0 {
diff --git a/src/todo_file/src/history/operation.rs b/src/todo_file/src/history/operation.rs
index bf7575f..0ec048d 100644
--- a/src/todo_file/src/history/operation.rs
+++ b/src/todo_file/src/history/operation.rs
@@ -1,5 +1,6 @@
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum Operation {
+ Load,
Modify,
SwapUp,
SwapDown,
diff --git a/src/todo_file/src/history/tests.rs b/src/todo_file/src/history/tests.rs
index 2f4bbed..442bf5f 100644
--- a/src/todo_file/src/history/tests.rs
+++ b/src/todo_file/src/history/tests.rs
@@ -18,7 +18,11 @@ fn history_item_to_string(item: &HistoryItem) -> String {
}
fn _assert_history_items(actual: &[HistoryItem], expected: &[HistoryItem]) {
- let actual_strings: Vec<String> = actual.iter().map(history_item_to_string).collect();
+ let actual_strings: Vec<String> = actual
+ .iter()
+ .filter(|item| item.operation != Operation::Load)
+ .map(history_item_to_string)
+ .collect();
let expected_strings: Vec<String> = expected.iter().map(history_item_to_string).collect();
pretty_assertions::assert_str_eq!(actual_strings.join("\n"), expected_strings.join("\n"));
}
@@ -52,9 +56,10 @@ macro_rules! assert_todo_lines {
#[test]
fn new() {
- let history = History::new(100);
+ let mut history = History::new(100);
assert_eq!(history.limit, 100);
- assert_empty!(history.undo_history);
+ assert_eq!(history.undo_history.len(), 1);
+ assert_some_eq!(history.undo_history.pop_back(), HistoryItem::new_load());
assert_empty!(history.redo_history);
}
@@ -84,13 +89,28 @@ fn record_history_overflow_limit() {
}
#[test]
+fn undo_at_load() {
+ let mut history = History::new(10);
+ let mut lines = create_lines();
+ assert_some_eq!(history.undo(&mut lines), (Operation::Load, 0, 0));
+ assert_todo_lines!(
+ lines,
+ "pick aaa c1",
+ "pick bbb c2",
+ "pick ccc c3",
+ "pick ddd c4",
+ "pick eee c5"
+ );
+ assert_some_eq!(history.undo_history.pop_back(), HistoryItem::new_load());
+}
+#[test]
fn undo_redo_add_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(0, 0));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(lines, "pick bbb c2", "pick ccc c3", "pick ddd c4", "pick eee c5");
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -106,9 +126,9 @@ fn undo_redo_add_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(4, 4));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (3, 3));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 3, 3));
assert_todo_lines!(lines, "pick aaa c1", "pick bbb c2", "pick ccc c3", "pick ddd c4");
- assert_some_eq!(history.redo(&mut lines), (4, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -118,15 +138,14 @@ fn undo_redo_add_end() {
"pick eee c5"
);
}
-
#[test]
fn undo_redo_add_middle() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(2, 2));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 2, 2));
assert_todo_lines!(lines, "pick aaa c1", "pick bbb c2", "pick ddd c4", "pick eee c5");
- assert_some_eq!(history.redo(&mut lines), (2, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -136,15 +155,14 @@ fn undo_redo_add_middle() {
"pick eee c5"
);
}
-
#[test]
fn undo_redo_add_range_start_index_at_top() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(0, 1));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(lines, "pick ccc c3", "pick ddd c4", "pick eee c5");
- assert_some_eq!(history.redo(&mut lines), (0, 1));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 0, 1));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -160,9 +178,9 @@ fn undo_redo_add_range_end_index_at_top() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(1, 0));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(lines, "pick ccc c3", "pick ddd c4", "pick eee c5");
- assert_some_eq!(history.redo(&mut lines), (1, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 1, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -178,9 +196,9 @@ fn undo_redo_add_range_start_index_at_bottom() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(4, 3));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 2, 2));
assert_todo_lines!(lines, "pick aaa c1", "pick bbb c2", "pick ccc c3");
- assert_some_eq!(history.redo(&mut lines), (4, 3));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 4, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -196,9 +214,9 @@ fn undo_redo_add_range_end_index_at_bottom() {
let mut history = History::new(10);
history.record(HistoryItem::new_add(3, 4));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Add, 2, 2));
assert_todo_lines!(lines, "pick aaa c1", "pick bbb c2", "pick ccc c3");
- assert_some_eq!(history.redo(&mut lines), (3, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Remove, 3, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -208,13 +226,12 @@ fn undo_redo_add_range_end_index_at_bottom() {
"pick eee c5"
);
}
-
#[test]
fn undo_redo_remove_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_remove(0, 0, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 0, 0));
assert_todo_lines!(
lines,
"drop xxx cx",
@@ -224,7 +241,7 @@ fn undo_redo_remove_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -240,7 +257,7 @@ fn undo_redo_remove_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_remove(5, 5, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (5, 5));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 5, 5));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -250,7 +267,7 @@ fn undo_redo_remove_end() {
"pick eee c5",
"drop xxx cx"
);
- assert_some_eq!(history.redo(&mut lines), (4, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -266,7 +283,7 @@ fn undo_redo_remove_middle() {
let mut history = History::new(10);
history.record(HistoryItem::new_remove(2, 2, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -276,7 +293,7 @@ fn undo_redo_remove_middle() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (2, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -295,7 +312,7 @@ fn undo_redo_remove_range_start_index_top() {
Line::new("drop yyy cy").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 1));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 0, 1));
assert_todo_lines!(
lines,
"drop xxx cx",
@@ -306,7 +323,7 @@ fn undo_redo_remove_range_start_index_top() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -325,7 +342,7 @@ fn undo_redo_remove_range_start_index_bottom() {
Line::new("drop yyy cy").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (6, 5));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 6, 5));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -336,7 +353,7 @@ fn undo_redo_remove_range_start_index_bottom() {
"drop xxx cx",
"drop yyy cy"
);
- assert_some_eq!(history.redo(&mut lines), (4, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -355,7 +372,7 @@ fn undo_redo_remove_range_end_index_top() {
Line::new("drop yyy cy").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (1, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 1, 0));
assert_todo_lines!(
lines,
"drop xxx cx",
@@ -366,7 +383,7 @@ fn undo_redo_remove_range_end_index_top() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -385,7 +402,7 @@ fn undo_redo_remove_range_end_index_bottom() {
Line::new("drop yyy cy").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (5, 6));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Remove, 5, 6));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -396,7 +413,7 @@ fn undo_redo_remove_range_end_index_bottom() {
"drop xxx cx",
"drop yyy cy"
);
- assert_some_eq!(history.redo(&mut lines), (4, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Add, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -412,7 +429,7 @@ fn undo_redo_swap_up_single_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(1, 1));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (1, 1));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 1, 1));
assert_todo_lines!(
lines,
"pick bbb c2",
@@ -421,7 +438,7 @@ fn undo_redo_swap_up_single_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -437,7 +454,7 @@ fn undo_redo_swap_up_single_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(4, 4));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (4, 4));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -446,7 +463,7 @@ fn undo_redo_swap_up_single_index_end() {
"pick eee c5",
"pick ddd c4"
);
- assert_some_eq!(history.redo(&mut lines), (3, 3));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 3, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -462,7 +479,7 @@ fn undo_redo_swap_up_single_index_middle() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(2, 2));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -471,7 +488,7 @@ fn undo_redo_swap_up_single_index_middle() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (1, 1));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 1, 1));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -487,7 +504,7 @@ fn undo_redo_swap_up_range_down_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(1, 2));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (1, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 1, 2));
assert_todo_lines!(
lines,
"pick ccc c3",
@@ -496,7 +513,7 @@ fn undo_redo_swap_up_range_down_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 1));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 0, 1));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -512,7 +529,7 @@ fn undo_redo_swap_up_range_down_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(3, 4));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (3, 4));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 3, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -521,7 +538,7 @@ fn undo_redo_swap_up_range_down_index_end() {
"pick ccc c3",
"pick ddd c4"
);
- assert_some_eq!(history.redo(&mut lines), (2, 3));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 2, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -537,7 +554,7 @@ fn undo_redo_swap_up_range_up_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(2, 1));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 1));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 2, 1));
assert_todo_lines!(
lines,
"pick ccc c3",
@@ -546,7 +563,7 @@ fn undo_redo_swap_up_range_up_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (1, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 1, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -562,7 +579,7 @@ fn undo_redo_swap_up_range_up_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_up(4, 3));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (4, 3));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapUp, 4, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -571,7 +588,7 @@ fn undo_redo_swap_up_range_up_index_end() {
"pick ccc c3",
"pick ddd c4"
);
- assert_some_eq!(history.redo(&mut lines), (3, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapDown, 3, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -587,7 +604,7 @@ fn undo_redo_swap_down_range_down_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_down(0, 1));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 1));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapDown, 0, 1));
assert_todo_lines!(
lines,
"pick bbb c2",
@@ -596,7 +613,7 @@ fn undo_redo_swap_down_range_down_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (1, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapUp, 1, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -612,7 +629,7 @@ fn undo_redo_swap_down_range_down_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_down(2, 3));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 3));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapDown, 2, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -621,7 +638,7 @@ fn undo_redo_swap_down_range_down_index_end() {
"pick eee c5",
"pick ccc c3"
);
- assert_some_eq!(history.redo(&mut lines), (3, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapUp, 3, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -637,7 +654,7 @@ fn undo_redo_swap_down_range_up_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_down(1, 0));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (1, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapDown, 1, 0));
assert_todo_lines!(
lines,
"pick bbb c2",
@@ -646,7 +663,7 @@ fn undo_redo_swap_down_range_up_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (2, 1));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapUp, 2, 1));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -662,7 +679,7 @@ fn undo_redo_swap_down_range_up_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_swap_down(3, 2));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (3, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::SwapDown, 3, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -671,7 +688,7 @@ fn undo_redo_swap_down_range_up_index_end() {
"pick eee c5",
"pick ccc c3"
);
- assert_some_eq!(history.redo(&mut lines), (4, 3));
+ assert_some_eq!(history.redo(&mut lines), (Operation::SwapUp, 4, 3));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -687,7 +704,7 @@ fn undo_redo_modify_single_index_start() {
let mut history = History::new(10);
history.record(HistoryItem::new_modify(0, 0, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 0, 0));
assert_todo_lines!(
lines,
"drop xxx cx",
@@ -696,7 +713,7 @@ fn undo_redo_modify_single_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 0, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -712,7 +729,7 @@ fn undo_redo_modify_single_index_end() {
let mut history = History::new(10);
history.record(HistoryItem::new_modify(4, 4, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (4, 4));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -721,7 +738,7 @@ fn undo_redo_modify_single_index_end() {
"pick ddd c4",
"drop xxx cx"
);
- assert_some_eq!(history.redo(&mut lines), (4, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 4, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -737,7 +754,7 @@ fn undo_redo_modify_single_index_middle() {
let mut history = History::new(10);
history.record(HistoryItem::new_modify(2, 2, vec![Line::new("drop xxx cx").unwrap()]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -746,7 +763,7 @@ fn undo_redo_modify_single_index_middle() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (2, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 2, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -766,7 +783,7 @@ fn undo_redo_modify_range_down_index_start() {
Line::new("drop xx3 c3").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (0, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 0, 2));
assert_todo_lines!(
lines,
"drop xx1 c1",
@@ -775,7 +792,7 @@ fn undo_redo_modify_range_down_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (0, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 0, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -795,7 +812,7 @@ fn undo_redo_modify_range_down_index_end() {
Line::new("drop xx3 c3").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 4));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 2, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -804,7 +821,7 @@ fn undo_redo_modify_range_down_index_end() {
"drop xx2 c2",
"drop xx3 c3"
);
- assert_some_eq!(history.redo(&mut lines), (2, 4));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 2, 4));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -824,7 +841,7 @@ fn undo_redo_modify_range_up_index_start() {
Line::new("drop xx3 c3").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (2, 0));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 2, 0));
assert_todo_lines!(
lines,
"drop xx1 c1",
@@ -833,7 +850,7 @@ fn undo_redo_modify_range_up_index_start() {
"pick ddd c4",
"pick eee c5"
);
- assert_some_eq!(history.redo(&mut lines), (2, 0));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 2, 0));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -853,7 +870,7 @@ fn undo_redo_modify_range_up_index_end() {
Line::new("drop xx3 c3").unwrap(),
]));
let mut lines = create_lines();
- assert_some_eq!(history.undo(&mut lines), (4, 2));
+ assert_some_eq!(history.undo(&mut lines), (Operation::Modify, 4, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -862,7 +879,7 @@ fn undo_redo_modify_range_up_index_end() {
"drop xx2 c2",
"drop xx3 c3"
);
- assert_some_eq!(history.redo(&mut lines), (4, 2));
+ assert_some_eq!(history.redo(&mut lines), (Operation::Modify, 4, 2));
assert_todo_lines!(
lines,
"pick aaa c1",
@@ -879,6 +896,7 @@ fn reset() {
history.redo_history.push_front(HistoryItem::new_add(1, 1));
history.undo_history.push_front(HistoryItem::new_add(1, 1));
history.reset();
- assert_empty!(history.undo_history);
+ assert_eq!(history.undo_history.len(), 1);
+ assert_some_eq!(history.undo_history.pop_back(), HistoryItem::new_load());
assert_empty!(history.redo_history);
}
diff --git a/src/todo_file/src/lib.rs b/src/todo_file/src/lib.rs
index d249ec8..77fbd87 100644
--- a/src/todo_file/src/lib.rs
+++ b/src/todo_file/src/lib.rs
@@ -154,7 +154,10 @@ use self::{
history::{History, HistoryItem},
utils::{remove_range, swap_range_down, swap_range_up},
};
-use crate::errors::{FileReadErrorCause, IoError};
+use crate::{
+ errors::{FileReadErrorCause, IoError},
+ history::Operation,
+};
/// Represents a rebase file.
#[derive(Debug)]
@@ -391,14 +394,22 @@ impl TodoFile {
#[inline]
pub fn undo(&mut self) -> Option<(usize, usize)> {
self.version.increment();
- self.history.undo(&mut self.lines)
+ if let Some((operation, start, end)) = self.history.undo(&mut self.lines) {
+ return if operation == Operation::Load {
+ None
+ }
+ else {
+ Some((start, end))
+ };
+ }
+ None
}
/// Redo the last undone modification.
#[inline]
pub fn redo(&mut self) -> Option<(usize, usize)> {
self.version.increment();
- self.history.redo(&mut self.lines)
+ self.history.redo(&mut self.lines).map(|(_, start, end)| (start, end))
}
/// Get the current version
@@ -750,6 +761,32 @@ mod tests {
}
#[test]
+ fn undo_load_operation() {
+ let (mut todo_file, _) =
+ create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
+ assert_none!(todo_file.undo());
+ }
+
+ #[test]
+ fn undo_empty_history() {
+ let (mut todo_file, _) =
+ create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
+ // set short history, to remove load entry
+ todo_file.history = History::new(1);
+ todo_file.update_range(0, 0, &EditContext::new().action(Action::Drop));
+ _ = todo_file.undo(); // remove Drop operation
+ assert_none!(todo_file.undo());
+ }
+
+ #[test]
+ fn undo_operation() {
+ let (mut todo_file, _) =
+ create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
+ todo_file.update_range(0, 1, &EditContext::new().action(Action::Drop));
+ assert_some_eq!(todo_file.undo(), (0, 1));
+ }
+
+ #[test]
fn history_undo_redo() {
let (mut todo_file, _) =
create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
@@ -765,6 +802,22 @@ mod tests {
}
#[test]
+ fn redo_empty_history() {
+ let (mut todo_file, _) =
+ create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
+ assert_none!(todo_file.redo());
+ }
+
+ #[test]
+ fn redo_operation() {
+ let (mut todo_file, _) =
+ create_and_load_todo_file(&["pick aaa comment", "drop bbb comment", "edit ccc comment"]);
+ todo_file.update_range(0, 1, &EditContext::new().action(Action::Drop));
+ _ = todo_file.undo();
+ assert_some_eq!(todo_file.redo(), (0, 1));
+ }
+
+ #[test]
fn swap_up() {
let (mut todo_file, _) =
create_and_load_todo_file(&["pick aaa comment", "pick bbb comment", "pick ccc comment"]);