From 826027445999fbfe2ce347baef5f75da522aac86 Mon Sep 17 00:00:00 2001 From: TD-Sky Date: Sat, 23 Sep 2023 16:00:21 +0800 Subject: [PATCH] feat(arrow): move cursor in percentage of page --- app/src/executor.rs | 2 +- config/preset/keymap.toml | 6 ++++-- core/src/manager/folder.rs | 40 ++++++++++++++++++++++++++++++++++---- core/src/manager/tab.rs | 15 +++++++------- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/app/src/executor.rs b/app/src/executor.rs index 3203a0da..51e928db 100644 --- a/app/src/executor.rs +++ b/app/src/executor.rs @@ -61,7 +61,7 @@ impl Executor { // Navigation "arrow" => { - let step = exec.args.get(0).and_then(|s| s.parse().ok()).unwrap_or(0); + let step = exec.args.get(0).and_then(|s| s.parse().ok()).unwrap_or_default(); cx.manager.active_mut().arrow(step) } "peek" => { diff --git a/config/preset/keymap.toml b/config/preset/keymap.toml index 461e8099..d9fe1d5e 100644 --- a/config/preset/keymap.toml +++ b/config/preset/keymap.toml @@ -10,8 +10,10 @@ 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" }, + { on = [ "" ], exec = "arrow 100%", desc = "Move cursor down one page" }, { on = [ "h" ], exec = "leave", desc = "Go back to the parent directory" }, { on = [ "l" ], exec = "enter", desc = "Enter the child directory" }, diff --git a/core/src/manager/folder.rs b/core/src/manager/folder.rs index 9d1a832e..ddc494c5 100644 --- a/core/src/manager/folder.rs +++ b/core/src/manager/folder.rs @@ -1,3 +1,5 @@ +use std::{num::ParseIntError, str::FromStr}; + use config::MANAGER; use ratatui::layout::Rect; use shared::Url; @@ -16,6 +18,12 @@ 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() } } } @@ -24,6 +32,19 @@ 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 { @@ -58,18 +79,21 @@ impl Folder { true } - pub fn next(&mut self, step: usize) -> bool { + pub fn next(&mut self, mut step: usize, percent: bool) -> 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.hovered = self.files.duplicate(self.cursor); self.set_page(false); - let limit = MANAGER.layout.folder_height(); if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) { self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old); } @@ -77,7 +101,11 @@ impl Folder { old != self.cursor } - pub fn prev(&mut self, step: usize) -> bool { + 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; + } let old = self.cursor; self.cursor = self.cursor.saturating_sub(step); self.hovered = self.files.duplicate(self.cursor); @@ -105,7 +133,11 @@ 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) } else { self.prev(self.cursor - new) } + if new > self.cursor { + self.next(new - self.cursor, false) + } else { + self.prev(self.cursor - new, false) + } } #[inline] diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index 4e5971c1..bc576574 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -6,7 +6,7 @@ use shared::{Debounce, Defer, InputError, Url}; use tokio::{pin, task::JoinHandle}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use super::{Finder, Folder, Mode, Preview, PreviewLock}; +use super::{Finder, Folder, Mode, Preview, PreviewLock, Step}; use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, files::{File, FilesOp, FilesSorter}, input::InputOpt, Event, BLOCKER}; pub struct Tab { @@ -67,11 +67,12 @@ impl Tab { self.search_stop() } - pub fn arrow(&mut self, step: isize) -> bool { - let ok = if step > 0 { - self.current.next(step as usize) + 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(step.unsigned_abs()) + self.current.prev(num.unsigned_abs(), percent) }; if !ok { return false; @@ -248,7 +249,7 @@ impl Tab { }; if let Some(step) = finder.ring(&self.current.files, self.current.cursor(), prev) { - self.arrow(step); + self.arrow(step.into()); } self.finder = Some(finder); @@ -280,7 +281,7 @@ impl Tab { let mut b = finder.catchup(&self.current.files); if let Some(step) = finder.arrow(&self.current.files, self.current.cursor(), prev) { - b |= self.arrow(step); + b |= self.arrow(step.into()); } b