From df95b239e78121ddf4314d47e1c20dad626752fb Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 18 Mar 2021 10:52:05 +0530 Subject: add history to command mode --- src/app.rs | 7 ++- src/command.rs | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 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> { } fn eval_command(&mut self) { + self.command_box.hist_append(); match self.command_box.text.as_str() { "(save)" => { let image = self.export(); @@ -648,7 +649,11 @@ impl<'ctx> AppState<'ctx> { Keycode::Delete => self.command_box.delete(), Keycode::Left => self.command_box.backward(), Keycode::Right => self.command_box.forward(), - Keycode::Return => self.eval_command(), + Keycode::Up => self.command_box.hist_prev(), + Keycode::Down => self.command_box.hist_next(), + Keycode::Return => { + self.eval_command(); + } Keycode::Escape => { self.command_box.clear(); 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 @@ #[derive(Debug)] pub struct CommandBox { - pub enabled: bool, - pub history: Vec, + pub history: History, + pub hist_idx: Option, pub text: String, pub cursor: usize, } -// cursor value of 0 is behind all text -// cursor value of n is after n characters (insert after index n - 1) -// cursor value of text.len() is after all text - impl CommandBox { pub fn new() -> Self { CommandBox { - enabled: false, - history: vec![], + history: History::new(64), + hist_idx: None, text: String::new(), cursor: 0, } @@ -26,6 +22,14 @@ impl CommandBox { } } + fn cursor_end(&mut self) { + self.cursor = self.text.len(); + } + + fn cursor_start(&mut self) { + self.cursor = 0; + } + pub fn backward(&mut self) { self.cursor = self.cursor.saturating_sub(1); } @@ -56,10 +60,73 @@ impl CommandBox { self.text.clear(); self.cursor = 0; } + + pub fn hist_append(&mut self) { + self.history.append(self.text.drain(..).collect()); + self.cursor_start(); + } + + fn get_from_hist(&self) -> String { + let size = self.history.items.len(); + self.history.items[size - 1 - self.hist_idx.unwrap()].clone() + } + + pub fn hist_prev(&mut self) { + if let Some(idx) = self.hist_idx { + if !(idx + 1 >= self.history.items.len()) { + self.hist_idx = Some(idx + 1); + self.text = self.get_from_hist(); + self.cursor_end(); + } + } else { + self.hist_idx = Some(0); + self.text = self.get_from_hist(); + self.cursor_end(); + } + } + + pub fn hist_next(&mut self) { + if let Some(idx) = self.hist_idx { + // most recent hist item, reset command box + if idx == 0 { + self.hist_idx = None; + self.text = "(".into(); + } else { + self.hist_idx = Some(idx - 1); + self.text = self.get_from_hist(); + } + self.cursor_end(); + } + } +} + +#[derive(Debug)] +pub struct History { + pub items: Vec, + pub max_size: usize, +} + +impl History { + pub fn new(max_size: usize) -> Self { + if max_size == 0 { + panic!(); + } + Self { + items: vec![], + max_size, + } + } + + pub fn append(&mut self, item: T) { + if self.items.len() >= self.max_size { + self.items.remove(0); + } + self.items.push(item); + } } #[cfg(test)] -mod tests { +mod command_tests { use super::*; fn setup_with(text: &str) -> CommandBox { @@ -131,4 +198,60 @@ mod tests { cmd.forward(); assert_eq!(cmd.cursor, 1); } + + #[test] + fn hist_append() { + let mut cmd = setup_with("hello"); + cmd.hist_append(); + cmd.push_str("another"); + cmd.hist_append(); + cmd.push_str("one"); + cmd.hist_append(); + assert_eq!(cmd.history.items.len(), 3); + } + + #[test] + fn hist_prev() { + let mut cmd = setup_with("hello"); + cmd.hist_append(); + cmd.push_str("another"); + cmd.hist_append(); + cmd.push_str("one"); + cmd.hist_append(); + + cmd.hist_prev(); + assert_eq!(&cmd.text, "one"); + cmd.hist_prev(); + assert_eq!(&cmd.text, "another"); + } + + #[test] + fn hist_next() { + let mut cmd = setup_with("hello"); + cmd.hist_append(); + cmd.push_str("another"); + cmd.hist_append(); + cmd.push_str("one"); + cmd.hist_append(); + + cmd.hist_prev(); + cmd.hist_prev(); + cmd.hist_next(); + assert_eq!(&cmd.text, "one"); + } +} + +#[cfg(test)] +mod history_tests { + use super::*; + #[test] + fn append() { + let mut h = History::::new(4); + h.append(5); + h.append(6); + h.append(7); + h.append(8); + h.append(9); + assert_eq!(h.items, vec![6, 7, 8, 9]); + } } -- cgit v1.2.3