From e7c4286962180f64d55ea50cadb7595c5d5d337a Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sun, 24 Sep 2023 16:08:16 +0800 Subject: [PATCH] .. --- config/preset/keymap.toml | 3 ++ core/src/lib.rs | 4 ++- core/src/manager/folder.rs | 42 +++++----------------------- core/src/manager/tab.rs | 11 ++------ core/src/step.rs | 56 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 core/src/step.rs diff --git a/config/preset/keymap.toml b/config/preset/keymap.toml index d9fe1d5e..939df807 100644 --- a/config/preset/keymap.toml +++ b/config/preset/keymap.toml @@ -10,6 +10,9 @@ keymap = [ { on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" }, { on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" }, + { on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = [ "" ], exec = "arrow -50%", desc = "Move cursor up half page" }, { on = [ "" ], exec = "arrow 50%", desc = "Move cursor down half page" }, { on = [ "" ], exec = "arrow -100%", desc = "Move cursor up one page" }, diff --git a/core/src/lib.rs b/core/src/lib.rs index 3696401f..e637118f 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -14,8 +14,9 @@ pub mod help; mod highlighter; pub mod input; pub mod manager; -pub mod position; +mod position; pub mod select; +mod step; pub mod tasks; pub mod which; @@ -23,5 +24,6 @@ pub use blocker::*; pub use event::*; pub use highlighter::*; pub use position::*; +pub use step::*; pub fn init() { init_blocker(); } diff --git a/core/src/manager/folder.rs b/core/src/manager/folder.rs index ddc494c5..172361f7 100644 --- a/core/src/manager/folder.rs +++ b/core/src/manager/folder.rs @@ -1,10 +1,8 @@ -use std::{num::ParseIntError, str::FromStr}; - use config::MANAGER; use ratatui::layout::Rect; use shared::Url; -use crate::{emit, files::{File, Files, FilesOp}}; +use crate::{emit, files::{File, Files, FilesOp}, Step}; #[derive(Default)] pub struct Folder { @@ -18,12 +16,6 @@ pub struct Folder { pub hovered: Option, } -#[derive(Default)] -pub struct Step { - pub(super) num: isize, - pub(super) percent: bool, -} - impl From for Folder { fn from(cwd: Url) -> Self { Self { cwd, ..Default::default() } } } @@ -32,19 +24,6 @@ impl From<&Url> for Folder { fn from(cwd: &Url) -> Self { Self::from(cwd.clone()) } } -impl FromStr for Step { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - Ok(Self { num: s.trim_end_matches('%').parse()?, percent: s.ends_with('%') }) - } -} - -impl From for Step { - #[inline] - fn from(num: isize) -> Self { Self { num, percent: false } } -} - impl Folder { pub fn update(&mut self, op: FilesOp) -> bool { let b = match op { @@ -79,18 +58,15 @@ impl Folder { true } - pub fn next(&mut self, mut step: usize, percent: bool) -> bool { + pub fn next(&mut self, step: Step) -> bool { let len = self.files.len(); if len == 0 { return false; } let limit = MANAGER.layout.folder_height(); - if percent { - step = ((limit * step) as f64 * 0.01) as usize; - } let old = self.cursor; - self.cursor = (self.cursor + step).min(len - 1); + self.cursor = step.add(self.cursor, || limit).min(len - 1); self.hovered = self.files.duplicate(self.cursor); self.set_page(false); @@ -101,13 +77,9 @@ impl Folder { old != self.cursor } - pub fn prev(&mut self, mut step: usize, percent: bool) -> bool { - if percent { - let limit = MANAGER.layout.folder_height(); - step = ((limit * step) as f64 * 0.01) as usize; - } + pub fn prev(&mut self, step: Step) -> bool { let old = self.cursor; - self.cursor = self.cursor.saturating_sub(step); + self.cursor = step.add(self.cursor, || 0); self.hovered = self.files.duplicate(self.cursor); self.set_page(false); @@ -134,9 +106,9 @@ impl Folder { pub fn hover(&mut self, url: &Url) -> bool { let new = self.files.position(url).unwrap_or(self.cursor); if new > self.cursor { - self.next(new - self.cursor, false) + self.next(Step::from(new - self.cursor)) } else { - self.prev(self.cursor - new, false) + self.prev(Step::from(self.cursor - new)) } } diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index bc576574..25f8b3e6 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -6,8 +6,8 @@ use shared::{Debounce, Defer, InputError, Url}; use tokio::{pin, task::JoinHandle}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use super::{Finder, Folder, Mode, Preview, PreviewLock, Step}; -use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, files::{File, FilesOp, FilesSorter}, input::InputOpt, Event, BLOCKER}; +use super::{Finder, Folder, Mode, Preview, PreviewLock}; +use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, files::{File, FilesOp, FilesSorter}, input::InputOpt, Event, Step, BLOCKER}; pub struct Tab { pub(super) mode: Mode, @@ -68,12 +68,7 @@ impl Tab { } pub fn arrow(&mut self, step: Step) -> bool { - let Step { num, percent } = step; - let ok = if step.num > 0 { - self.current.next(num as usize, percent) - } else { - self.current.prev(num.unsigned_abs(), percent) - }; + let ok = if step.positive() { self.current.next(step) } else { self.current.prev(step) }; if !ok { return false; } diff --git a/core/src/step.rs b/core/src/step.rs new file mode 100644 index 00000000..ce42743a --- /dev/null +++ b/core/src/step.rs @@ -0,0 +1,56 @@ +use std::{num::ParseIntError, str::FromStr}; + +pub enum Step { + Fixed(isize), + Percent(i8), +} + +impl Default for Step { + fn default() -> Self { Self::Fixed(0) } +} + +impl FromStr for Step { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + Ok(if let Some(s) = s.strip_suffix('%') { + Self::Percent(s.parse()?) + } else { + Self::Fixed(s.parse()?) + }) + } +} + +impl From for Step { + fn from(n: isize) -> Self { Self::Fixed(n) } +} + +impl From for Step { + fn from(n: usize) -> Self { Self::Fixed(n as isize) } +} + +impl Step { + #[inline] + fn fixed usize>(self, f: F) -> isize { + match self { + Self::Fixed(n) => n, + Self::Percent(0) => 0, + Self::Percent(n) => n as isize * f() as isize / 100, + } + } + + #[inline] + pub fn add usize>(self, pos: usize, f: F) -> usize { + let fixed = self.fixed(f); + if fixed > 0 { pos + fixed as usize } else { pos.saturating_sub(fixed.unsigned_abs()) } + } + + #[inline] + pub fn positive(&self) -> bool { + match self { + Self::Fixed(n) if *n > 0 => true, + Self::Percent(n) if *n > 0 => true, + _ => false, + } + } +}