Skip to content

Commit

Permalink
feat: History and navigation via shortcuts. (#258)
Browse files Browse the repository at this point in the history
* feat: Added history and navigation via shortcuts.

Signed-off-by: konrad <kokos.kekse@gmail.com>

* Fix: mute clippy complaint

Co-authored-by: CosmicHorror <CosmicHorrorDev@pm.me>

* Add: Vim like binding for Previous and Next file.

Signed-off-by: konrad <kokos.kekse@gmail.com>

---------

Signed-off-by: konrad <kokos.kekse@gmail.com>
Co-authored-by: CosmicHorror <CosmicHorrorDev@pm.me>
  • Loading branch information
kokoISnoTarget and CosmicHorrorDev authored Mar 9, 2024
1 parent d134028 commit 15e7d49
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 18 deletions.
47 changes: 47 additions & 0 deletions src/history.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use smart_debug::SmartDebug;
use std::path::PathBuf;

#[derive(SmartDebug, Clone, PartialEq)]
pub struct History {
history: Vec<PathBuf>,
index: usize,
}

impl History {
pub fn new(path_buf: PathBuf) -> Self {
History {
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 append(&mut self, file_path: PathBuf) {
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> {
if self.index + 1 == self.history.len() {
return None;
}
self.index += 1;
Some(self.get_path())
}
pub fn previous(&mut self) -> Option<&PathBuf> {
if self.index == 0 {
return None;
}
self.index -= 1;
Some(self.get_path())
}
}
7 changes: 7 additions & 0 deletions src/keybindings/action.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Action {
Navigate(Navigation),
ToEdge(VertDirection),
Scroll(VertDirection),
Page(VertDirection),
Expand All @@ -20,3 +21,9 @@ pub enum Zoom {
Out,
Reset,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Navigation {
Previous,
Next,
}
34 changes: 33 additions & 1 deletion src/keybindings/defaults.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::action::{Action, VertDirection, Zoom};
use super::action::{Action, Navigation, VertDirection, Zoom};
use super::{Key, KeyCombo, ModifiedKey};

use winit::event::{ModifiersState, VirtualKeyCode as VirtKey};
Expand Down Expand Up @@ -34,6 +34,22 @@ pub fn defaults() -> Vec<(Action, KeyCombo)> {
ctrl_or_command,
)]),
),
// Navigate to next file: Ctrl+Right
(
Action::Navigate(Navigation::Next),
KeyCombo(vec![ModifiedKey(
Key::from(VirtKey::Right),
ModifiersState::ALT,
)]),
),
// Navigate to previous file: Ctrl+Left
(
Action::Navigate(Navigation::Previous),
KeyCombo(vec![ModifiedKey(
Key::from(VirtKey::Left),
ModifiersState::ALT,
)]),
),
// Scroll up: Up-arrow
(
Action::Scroll(VertDirection::Up),
Expand Down Expand Up @@ -111,5 +127,21 @@ pub fn defaults() -> Vec<(Action, KeyCombo)> {
ModifiedKey(Key::from(VirtKey::Q), ModifiersState::SHIFT),
]),
),
// Navigate to next file: Ctrl+Right
(
Action::Navigate(Navigation::Next),
KeyCombo(vec![
ModifiedKey::from(VirtKey::B),
ModifiedKey::from(VirtKey::N),
]),
),
// Navigate to previous file: Ctrl+Left
(
Action::Navigate(Navigation::Previous),
KeyCombo(vec![
ModifiedKey::from(VirtKey::B),
ModifiedKey::from(VirtKey::P),
]),
),
]
}
54 changes: 41 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod color;
mod debug_impls;
mod file_watcher;
pub mod fonts;
pub mod history;
pub mod image;
pub mod interpreter;
mod keybindings;
Expand All @@ -38,7 +39,7 @@ use std::sync::{Arc, Mutex};
use file_watcher::Watcher;
use image::{Image, ImageData};
use interpreter::HtmlInterpreter;
use keybindings::action::{Action, VertDirection, Zoom};
use keybindings::action::{Action, Navigation, VertDirection, Zoom};
use keybindings::{Key, KeyCombos, ModifiedKey};
use opts::{Args, Config, Opts};
use positioner::{Positioned, Row, Section, Spacer, DEFAULT_MARGIN, DEFAULT_PADDING};
Expand Down Expand Up @@ -179,9 +180,11 @@ impl Inlyne {
pub fn new(opts: Opts) -> anyhow::Result<Self> {
let keycombos = KeyCombos::new(opts.keybindings.clone())?;

let file_path = opts.history.get_path();

let event_loop = EventLoopBuilder::<InlyneEvent>::with_user_event().build();
let window = Arc::new(Window::new(&event_loop).unwrap());
match root_filepath_to_vcs_dir(&opts.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"),
}
Expand All @@ -195,16 +198,16 @@ 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(&opts.file_path)
.with_context(|| format!("Could not read file at '{}'", opts.file_path.display()))?;
let md_string = read_to_string(file_path)
.with_context(|| format!("Could not read file at '{}'", file_path.display()))?;

let interpreter = HtmlInterpreter::new(
window.clone(),
element_queue.clone(),
renderer.theme.clone(),
renderer.surface_format,
renderer.hidpi_scale,
opts.file_path.clone(),
file_path.clone(),
image_cache.clone(),
event_loop.create_proxy(),
opts.color_scheme,
Expand All @@ -218,7 +221,7 @@ impl Inlyne {

let lines_to_scroll = opts.lines_to_scroll;

let watcher = Watcher::spawn(event_loop.create_proxy(), opts.file_path.clone());
let watcher = Watcher::spawn(event_loop.create_proxy(), file_path.clone());

Ok(Self {
opts,
Expand Down Expand Up @@ -301,12 +304,12 @@ impl Inlyne {
self.image_cache.lock().unwrap().insert(src, image_data);
self.need_repositioning = true;
}
InlyneEvent::FileReload => match read_to_string(&self.opts.file_path) {
InlyneEvent::FileReload => match read_to_string(self.opts.history.get_path()) {
Ok(contents) => self.load_file(contents),
Err(err) => {
tracing::warn!(
"Failed reloading file at {}\nError: {}",
self.opts.file_path.display(),
self.opts.history.get_path().display(),
err
);
}
Expand Down Expand Up @@ -487,7 +490,8 @@ impl Inlyne {
// Simply canonicalizing it doesn't suffice and leads to "no such file or directory"
let current_parent = self
.opts
.file_path
.history
.get_path()
.parent()
.expect("no current parent");
let mut normalized_link = path.as_path();
Expand All @@ -514,13 +518,12 @@ impl Inlyne {
} else {
match read_to_string(&path) {
Ok(contents) => {
self.opts.file_path = path;
self.watcher.update_file(
&self.opts.file_path,
&path,
contents,
);
// TODO: Once and if history is implemented,
// old scroll_y might be stored there
self.opts.history.truncate();
self.opts.history.append(path);
self.renderer.set_scroll_y(0.);
}
Err(err) => {
Expand Down Expand Up @@ -626,6 +629,31 @@ 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(),
};
let Some(file_path) = changed_path else {
return;
};
match read_to_string(file_path) {
Ok(contents) => {
self.watcher.update_file(
file_path,
contents,
);
self.renderer.set_scroll_y(0.0);
}
Err(err) => {
tracing::warn!(
"Failed loading markdown file at {}\nError: {}",
file_path.display(),
err,
);
}
}
}
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/opts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ mod config;
#[cfg(test)]
mod tests;

use std::path::{Path, PathBuf};
use std::path::Path;

use crate::color;
pub use cli::{Args, ThemeType};
pub use config::{Config, FontOptions, KeybindingsSection};

use crate::history::History;
use anyhow::Result;
use serde::Deserialize;
use smart_debug::SmartDebug;
Expand Down Expand Up @@ -40,7 +41,7 @@ impl ResolvedTheme {

#[derive(SmartDebug, PartialEq)]
pub struct Opts {
pub file_path: PathBuf,
pub history: History,
#[debug(skip)]
pub theme: color::Theme,
pub scale: Option<f32>,
Expand Down Expand Up @@ -121,7 +122,7 @@ impl Opts {
let lines_to_scroll = lines_to_scroll.into();

Ok(Self {
file_path,
history: History::new(file_path),
theme,
scale,
page_width,
Expand Down
3 changes: 2 additions & 1 deletion src/opts/tests/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::opts::config::{self, FontOptions, LinesToScroll};
use crate::opts::{cli, Args, Opts, ResolvedTheme, ThemeType};
use crate::test_utils::init_test_log;

use crate::history::History;
use pretty_assertions::assert_eq;

fn gen_args(args: Vec<&str>) -> Vec<OsString> {
Expand All @@ -18,7 +19,7 @@ fn gen_args(args: Vec<&str>) -> Vec<OsString> {
impl Opts {
fn mostly_default(file_path: impl Into<PathBuf>) -> Self {
Self {
file_path: file_path.into(),
history: History::new(file_path.into()),
theme: ResolvedTheme::Light.as_theme(),
scale: None,
page_width: None,
Expand Down

0 comments on commit 15e7d49

Please sign in to comment.