aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-03-18 05:22:05 +0000
committerAkshay <[email protected]>2021-03-18 05:22:05 +0000
commitdf95b239e78121ddf4314d47e1c20dad626752fb (patch)
tree767a36a8f248cdae1c98df330f09c3b6f556c840
parent7615546fb0157c3ec9d2f25ec9837ee0b6cb7e9a (diff)
add history to command mode
-rw-r--r--src/app.rs7
-rw-r--r--src/command.rs141
2 files changed, 138 insertions, 10 deletions
diff --git a/src/app.rs b/src/app.rs
index 0eac084..9ba93f4 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -248,6 +248,7 @@ impl<'ctx> AppState<'ctx> {
248 } 248 }
249 249
250 fn eval_command(&mut self) { 250 fn eval_command(&mut self) {
251 self.command_box.hist_append();
251 match self.command_box.text.as_str() { 252 match self.command_box.text.as_str() {
252 "(save)" => { 253 "(save)" => {
253 let image = self.export(); 254 let image = self.export();
@@ -648,7 +649,11 @@ impl<'ctx> AppState<'ctx> {
648 Keycode::Delete => self.command_box.delete(), 649 Keycode::Delete => self.command_box.delete(),
649 Keycode::Left => self.command_box.backward(), 650 Keycode::Left => self.command_box.backward(),
650 Keycode::Right => self.command_box.forward(), 651 Keycode::Right => self.command_box.forward(),
651 Keycode::Return => self.eval_command(), 652 Keycode::Up => self.command_box.hist_prev(),
653 Keycode::Down => self.command_box.hist_next(),
654 Keycode::Return => {
655 self.eval_command();
656 }
652 Keycode::Escape => { 657 Keycode::Escape => {
653 self.command_box.clear(); 658 self.command_box.clear();
654 self.mode = Mode::Draw; 659 self.mode = Mode::Draw;
diff --git a/src/command.rs b/src/command.rs
index 3beb700..064d767 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -1,20 +1,16 @@
1#[derive(Debug)] 1#[derive(Debug)]
2pub struct CommandBox { 2pub struct CommandBox {
3 pub enabled: bool, 3 pub history: History<String>,
4 pub history: Vec<String>, 4 pub hist_idx: Option<usize>,
5 pub text: String, 5 pub text: String,
6 pub cursor: usize, 6 pub cursor: usize,
7} 7}
8 8
9// cursor value of 0 is behind all text
10// cursor value of n is after n characters (insert after index n - 1)
11// cursor value of text.len() is after all text
12
13impl CommandBox { 9impl CommandBox {
14 pub fn new() -> Self { 10 pub fn new() -> Self {
15 CommandBox { 11 CommandBox {
16 enabled: false, 12 history: History::new(64),
17 history: vec![], 13 hist_idx: None,
18 text: String::new(), 14 text: String::new(),
19 cursor: 0, 15 cursor: 0,
20 } 16 }
@@ -26,6 +22,14 @@ impl CommandBox {
26 } 22 }
27 } 23 }
28 24
25 fn cursor_end(&mut self) {
26 self.cursor = self.text.len();
27 }
28
29 fn cursor_start(&mut self) {
30 self.cursor = 0;
31 }
32
29 pub fn backward(&mut self) { 33 pub fn backward(&mut self) {
30 self.cursor = self.cursor.saturating_sub(1); 34 self.cursor = self.cursor.saturating_sub(1);
31 } 35 }
@@ -56,10 +60,73 @@ impl CommandBox {
56 self.text.clear(); 60 self.text.clear();
57 self.cursor = 0; 61 self.cursor = 0;
58 } 62 }
63
64 pub fn hist_append(&mut self) {
65 self.history.append(self.text.drain(..).collect());
66 self.cursor_start();
67 }
68
69 fn get_from_hist(&self) -> String {
70 let size = self.history.items.len();
71 self.history.items[size - 1 - self.hist_idx.unwrap()].clone()
72 }
73
74 pub fn hist_prev(&mut self) {
75 if let Some(idx) = self.hist_idx {
76 if !(idx + 1 >= self.history.items.len()) {
77 self.hist_idx = Some(idx + 1);
78 self.text = self.get_from_hist();
79 self.cursor_end();
80 }
81 } else {
82 self.hist_idx = Some(0);
83 self.text = self.get_from_hist();
84 self.cursor_end();
85 }
86 }
87
88 pub fn hist_next(&mut self) {
89 if let Some(idx) = self.hist_idx {
90 // most recent hist item, reset command box
91 if idx == 0 {
92 self.hist_idx = None;
93 self.text = "(".into();
94 } else {
95 self.hist_idx = Some(idx - 1);
96 self.text = self.get_from_hist();
97 }
98 self.cursor_end();
99 }
100 }
101}
102
103#[derive(Debug)]
104pub struct History<T> {
105 pub items: Vec<T>,
106 pub max_size: usize,
107}
108
109impl<T> History<T> {
110 pub fn new(max_size: usize) -> Self {
111 if max_size == 0 {
112 panic!();
113 }
114 Self {
115 items: vec![],
116 max_size,
117 }
118 }
119
120 pub fn append(&mut self, item: T) {
121 if self.items.len() >= self.max_size {
122 self.items.remove(0);
123 }
124 self.items.push(item);
125 }
59} 126}
60 127
61#[cfg(test)] 128#[cfg(test)]
62mod tests { 129mod command_tests {
63 use super::*; 130 use super::*;
64 131
65 fn setup_with(text: &str) -> CommandBox { 132 fn setup_with(text: &str) -> CommandBox {
@@ -131,4 +198,60 @@ mod tests {
131 cmd.forward(); 198 cmd.forward();
132 assert_eq!(cmd.cursor, 1); 199 assert_eq!(cmd.cursor, 1);
133 } 200 }
201
202 #[test]
203 fn hist_append() {
204 let mut cmd = setup_with("hello");
205 cmd.hist_append();
206 cmd.push_str("another");
207 cmd.hist_append();
208 cmd.push_str("one");
209 cmd.hist_append();
210 assert_eq!(cmd.history.items.len(), 3);
211 }
212
213 #[test]
214 fn hist_prev() {
215 let mut cmd = setup_with("hello");
216 cmd.hist_append();
217 cmd.push_str("another");
218 cmd.hist_append();
219 cmd.push_str("one");
220 cmd.hist_append();
221
222 cmd.hist_prev();
223 assert_eq!(&cmd.text, "one");
224 cmd.hist_prev();
225 assert_eq!(&cmd.text, "another");
226 }
227
228 #[test]
229 fn hist_next() {
230 let mut cmd = setup_with("hello");
231 cmd.hist_append();
232 cmd.push_str("another");
233 cmd.hist_append();
234 cmd.push_str("one");
235 cmd.hist_append();
236
237 cmd.hist_prev();
238 cmd.hist_prev();
239 cmd.hist_next();
240 assert_eq!(&cmd.text, "one");
241 }
242}
243
244#[cfg(test)]
245mod history_tests {
246 use super::*;
247 #[test]
248 fn append() {
249 let mut h = History::<u32>::new(4);
250 h.append(5);
251 h.append(6);
252 h.append(7);
253 h.append(8);
254 h.append(9);
255 assert_eq!(h.items, vec![6, 7, 8, 9]);
256 }
134} 257}