feat(arrow): move cursor in percentage of page

This commit is contained in:
TD-Sky 2023-09-23 16:00:21 +08:00
parent ec261a2708
commit 8260274459
4 changed files with 49 additions and 14 deletions

View file

@ -61,7 +61,7 @@ impl Executor {
// Navigation // Navigation
"arrow" => { "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) cx.manager.active_mut().arrow(step)
} }
"peek" => { "peek" => {

View file

@ -10,8 +10,10 @@ keymap = [
{ on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" }, { on = [ "k" ], exec = "arrow -1", desc = "Move cursor up" },
{ on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" }, { on = [ "j" ], exec = "arrow 1", desc = "Move cursor down" },
{ on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" }, { on = [ "<C-u>" ], exec = "arrow -50%", desc = "Move cursor up half page" },
{ on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" }, { on = [ "<C-d>" ], exec = "arrow 50%", desc = "Move cursor down half page" },
{ on = [ "<C-b>" ], exec = "arrow -100%", desc = "Move cursor up one page" },
{ on = [ "<C-f>" ], exec = "arrow 100%", desc = "Move cursor down one page" },
{ on = [ "h" ], exec = "leave", desc = "Go back to the parent directory" }, { on = [ "h" ], exec = "leave", desc = "Go back to the parent directory" },
{ on = [ "l" ], exec = "enter", desc = "Enter the child directory" }, { on = [ "l" ], exec = "enter", desc = "Enter the child directory" },

View file

@ -1,3 +1,5 @@
use std::{num::ParseIntError, str::FromStr};
use config::MANAGER; use config::MANAGER;
use ratatui::layout::Rect; use ratatui::layout::Rect;
use shared::Url; use shared::Url;
@ -16,6 +18,12 @@ pub struct Folder {
pub hovered: Option<File>, pub hovered: Option<File>,
} }
#[derive(Default)]
pub struct Step {
pub(super) num: isize,
pub(super) percent: bool,
}
impl From<Url> for Folder { impl From<Url> for Folder {
fn from(cwd: Url) -> Self { Self { cwd, ..Default::default() } } 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()) } fn from(cwd: &Url) -> Self { Self::from(cwd.clone()) }
} }
impl FromStr for Step {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self { num: s.trim_end_matches('%').parse()?, percent: s.ends_with('%') })
}
}
impl From<isize> for Step {
#[inline]
fn from(num: isize) -> Self { Self { num, percent: false } }
}
impl Folder { impl Folder {
pub fn update(&mut self, op: FilesOp) -> bool { pub fn update(&mut self, op: FilesOp) -> bool {
let b = match op { let b = match op {
@ -58,18 +79,21 @@ impl Folder {
true 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(); let len = self.files.len();
if len == 0 { if len == 0 {
return false; return false;
} }
let limit = MANAGER.layout.folder_height();
if percent {
step = ((limit * step) as f64 * 0.01) as usize;
}
let old = self.cursor; let old = self.cursor;
self.cursor = (self.cursor + step).min(len - 1); self.cursor = (self.cursor + step).min(len - 1);
self.hovered = self.files.duplicate(self.cursor); self.hovered = self.files.duplicate(self.cursor);
self.set_page(false); self.set_page(false);
let limit = MANAGER.layout.folder_height();
if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) { if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) {
self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old); self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old);
} }
@ -77,7 +101,11 @@ impl Folder {
old != self.cursor 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; let old = self.cursor;
self.cursor = self.cursor.saturating_sub(step); self.cursor = self.cursor.saturating_sub(step);
self.hovered = self.files.duplicate(self.cursor); self.hovered = self.files.duplicate(self.cursor);
@ -105,7 +133,11 @@ impl Folder {
pub fn hover(&mut self, url: &Url) -> bool { pub fn hover(&mut self, url: &Url) -> bool {
let new = self.files.position(url).unwrap_or(self.cursor); 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] #[inline]

View file

@ -6,7 +6,7 @@ use shared::{Debounce, Defer, InputError, Url};
use tokio::{pin, task::JoinHandle}; use tokio::{pin, task::JoinHandle};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; 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}; use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, files::{File, FilesOp, FilesSorter}, input::InputOpt, Event, BLOCKER};
pub struct Tab { pub struct Tab {
@ -67,11 +67,12 @@ impl Tab {
self.search_stop() self.search_stop()
} }
pub fn arrow(&mut self, step: isize) -> bool { pub fn arrow(&mut self, step: Step) -> bool {
let ok = if step > 0 { let Step { num, percent } = step;
self.current.next(step as usize) let ok = if step.num > 0 {
self.current.next(num as usize, percent)
} else { } else {
self.current.prev(step.unsigned_abs()) self.current.prev(num.unsigned_abs(), percent)
}; };
if !ok { if !ok {
return false; return false;
@ -248,7 +249,7 @@ impl Tab {
}; };
if let Some(step) = finder.ring(&self.current.files, self.current.cursor(), prev) { if let Some(step) = finder.ring(&self.current.files, self.current.cursor(), prev) {
self.arrow(step); self.arrow(step.into());
} }
self.finder = Some(finder); self.finder = Some(finder);
@ -280,7 +281,7 @@ impl Tab {
let mut b = finder.catchup(&self.current.files); let mut b = finder.catchup(&self.current.files);
if let Some(step) = finder.arrow(&self.current.files, self.current.cursor(), prev) { if let Some(step) = finder.arrow(&self.current.files, self.current.cursor(), prev) {
b |= self.arrow(step); b |= self.arrow(step.into());
} }
b b