diff --git a/inlyne.default.toml b/inlyne.default.toml index 67ecab7a..15e6a370 100644 --- a/inlyne.default.toml +++ b/inlyne.default.toml @@ -91,6 +91,7 @@ code-highlighter = "github" # # Possible Modifiers: ["Alt", "Ctrl", "Os", "Shift"] # Possible Actions: [ +# "HistoryNext", "HistoryPrevious", # "ToTop", "ToBottom", # "ScrollUp", "ScrollDown", # "PageUp", "PageDown", diff --git a/src/history.rs b/src/history.rs index dfe0e715..bc5ec01f 100644 --- a/src/history.rs +++ b/src/history.rs @@ -1,7 +1,6 @@ -use smart_debug::SmartDebug; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; -#[derive(SmartDebug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub struct History { history: Vec, index: usize, @@ -9,39 +8,69 @@ pub struct History { impl History { pub fn new(path_buf: PathBuf) -> Self { - History { + Self { history: vec![path_buf], index: 0, } } - pub fn truncate(&mut self) { - if self.index + 1 < self.history.len() { - self.history.truncate(self.index + 1); - } + + pub fn get_path(&self) -> &Path { + self.history + .get(self.index) + .expect("History should always be in bounds") + .as_path() } - pub fn append(&mut self, file_path: PathBuf) { + + pub fn make_next(&mut self, file_path: PathBuf) { + self.history.truncate(self.index + 1); self.history.push(file_path); self.index += 1; } - pub fn get_path(&self) -> &PathBuf { - self.history - .get(self.index) - .expect("History should be bound checked for all possible indexes.") - } #[allow(clippy::should_implement_trait)] - pub fn next(&mut self) -> Option<&PathBuf> { + pub fn next(&mut self) -> Option<&Path> { if self.index + 1 == self.history.len() { - return None; + None + } else { + self.index += 1; + Some(self.get_path()) } - self.index += 1; - Some(self.get_path()) } - pub fn previous(&mut self) -> Option<&PathBuf> { + + pub fn previous(&mut self) -> Option<&Path> { if self.index == 0 { - return None; + None + } else { + self.index -= 1; + Some(self.get_path()) } - self.index -= 1; - Some(self.get_path()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sanity() { + let root = PathBuf::from("a"); + let fork1 = PathBuf::from("b"); + let fork2 = PathBuf::from("c"); + + let mut hist = History::new(root.clone()); + assert_eq!(hist.get_path(), root); + assert_eq!(hist.previous(), None); + + hist.make_next(fork1.clone()); + assert_eq!(hist.get_path(), fork1); + + assert_eq!(hist.previous().unwrap(), root); + hist.make_next(fork2.clone()); + assert_eq!(hist.get_path(), fork2); + + assert_eq!(hist.previous().unwrap(), root); + assert_eq!(hist.previous(), None); + assert_eq!(hist.next().unwrap(), fork2); + assert_eq!(hist.next(), None); } } diff --git a/src/keybindings/action.rs b/src/keybindings/action.rs index aeac850f..1962bd2d 100644 --- a/src/keybindings/action.rs +++ b/src/keybindings/action.rs @@ -1,6 +1,6 @@ #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Action { - Navigate(Navigation), + History(HistDirection), ToEdge(VertDirection), Scroll(VertDirection), Page(VertDirection), @@ -9,6 +9,12 @@ pub enum Action { Quit, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum HistDirection { + Next, + Prev, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum VertDirection { Up, @@ -21,9 +27,3 @@ pub enum Zoom { Out, Reset, } - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Navigation { - Previous, - Next, -} diff --git a/src/keybindings/defaults.rs b/src/keybindings/defaults.rs index 93021fd3..28bf713c 100644 --- a/src/keybindings/defaults.rs +++ b/src/keybindings/defaults.rs @@ -1,4 +1,6 @@ -use super::action::{Action, Navigation, VertDirection, Zoom}; +use crate::keybindings::action::HistDirection; + +use super::action::{Action, VertDirection, Zoom}; use super::{Key, KeyCombo, ModifiedKey}; use winit::event::{ModifiersState, VirtualKeyCode as VirtKey}; @@ -34,17 +36,17 @@ pub fn defaults() -> Vec<(Action, KeyCombo)> { ctrl_or_command, )]), ), - // Navigate to next file: Ctrl+Right + // Navigate to next file: Alt+Right ( - Action::Navigate(Navigation::Next), + Action::History(HistDirection::Next), KeyCombo(vec![ModifiedKey( Key::from(VirtKey::Right), ModifiersState::ALT, )]), ), - // Navigate to previous file: Ctrl+Left + // Navigate to previous file: Alt+Left ( - Action::Navigate(Navigation::Previous), + Action::History(HistDirection::Prev), KeyCombo(vec![ModifiedKey( Key::from(VirtKey::Left), ModifiersState::ALT, @@ -127,17 +129,17 @@ pub fn defaults() -> Vec<(Action, KeyCombo)> { ModifiedKey(Key::from(VirtKey::Q), ModifiersState::SHIFT), ]), ), - // Navigate to next file: Ctrl+Right + // Navigate to next file: bn ( - Action::Navigate(Navigation::Next), + Action::History(HistDirection::Next), KeyCombo(vec![ ModifiedKey::from(VirtKey::B), ModifiedKey::from(VirtKey::N), ]), ), - // Navigate to previous file: Ctrl+Left + // Navigate to previous file: bp ( - Action::Navigate(Navigation::Previous), + Action::History(HistDirection::Prev), KeyCombo(vec![ ModifiedKey::from(VirtKey::B), ModifiedKey::from(VirtKey::P), diff --git a/src/keybindings/serialization.rs b/src/keybindings/serialization.rs index 561d932b..801477a4 100644 --- a/src/keybindings/serialization.rs +++ b/src/keybindings/serialization.rs @@ -1,5 +1,7 @@ use std::str::FromStr; +use crate::keybindings::action::HistDirection; + use super::action::{Action, VertDirection, Zoom}; use super::{Key, KeyCombo, ModifiedKey}; @@ -13,6 +15,8 @@ impl<'de> Deserialize<'de> for Action { { #[derive(Deserialize)] enum FlatAction { + HistoryNext, + HistoryPrevious, ToTop, ToBottom, ScrollUp, @@ -27,6 +31,8 @@ impl<'de> Deserialize<'de> for Action { } let action = match FlatAction::deserialize(deserializer)? { + FlatAction::HistoryNext => Action::History(HistDirection::Next), + FlatAction::HistoryPrevious => Action::History(HistDirection::Prev), FlatAction::ToTop => Action::ToEdge(VertDirection::Up), FlatAction::ToBottom => Action::ToEdge(VertDirection::Down), FlatAction::ScrollUp => Action::Scroll(VertDirection::Up), diff --git a/src/main.rs b/src/main.rs index 7e9849a9..d0df487f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,7 +39,7 @@ use std::sync::{Arc, Mutex}; use file_watcher::Watcher; use image::{Image, ImageData}; use interpreter::HtmlInterpreter; -use keybindings::action::{Action, Navigation, VertDirection, Zoom}; +use keybindings::action::{Action, HistDirection, VertDirection, Zoom}; use keybindings::{Key, KeyCombos, ModifiedKey}; use opts::{Args, Config, Opts}; use positioner::{Positioned, Row, Section, Spacer, DEFAULT_MARGIN, DEFAULT_PADDING}; @@ -180,11 +180,11 @@ impl Inlyne { pub fn new(opts: Opts) -> anyhow::Result { let keycombos = KeyCombos::new(opts.keybindings.clone())?; - let file_path = opts.history.get_path(); + let file_path = opts.history.get_path().to_owned(); let event_loop = EventLoopBuilder::::with_user_event().build(); let window = Arc::new(Window::new(&event_loop).unwrap()); - match root_filepath_to_vcs_dir(file_path) { + match root_filepath_to_vcs_dir(&file_path) { Some(path) => window.set_title(&format!("Inlyne - {}", path.to_string_lossy())), None => window.set_title("Inlyne"), } @@ -198,7 +198,7 @@ impl Inlyne { let element_queue = Arc::new(Mutex::new(VecDeque::new())); let image_cache = Arc::new(Mutex::new(HashMap::new())); - let md_string = read_to_string(file_path) + let md_string = read_to_string(&file_path) .with_context(|| format!("Could not read file at '{}'", file_path.display()))?; let interpreter = HtmlInterpreter::new( @@ -522,8 +522,7 @@ impl Inlyne { &path, contents, ); - self.opts.history.truncate(); - self.opts.history.append(path); + self.opts.history.make_next(path); self.renderer.set_scroll_y(0.); } Err(err) => { @@ -629,10 +628,10 @@ impl Inlyne { Action::Copy => clipboard .set_contents(selection_cache.trim().to_owned()), Action::Quit => *control_flow = ControlFlow::Exit, - Action::Navigate(navigation_action) => { - let changed_path = match navigation_action { - Navigation::Next => self.opts.history.next(), - Navigation::Previous => self.opts.history.previous(), + Action::History(hist_dir) => { + let changed_path = match hist_dir { + HistDirection::Next => self.opts.history.next(), + HistDirection::Prev => self.opts.history.previous(), }; let Some(file_path) = changed_path else { return;