Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: scroll half/full page with arrow percentage supported, and new Vi-like <C-u>, <C-d>, <C-b>, and <C-f> keybindings added #213

Merged
merged 5 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" => {
Expand Down
5 changes: 5 additions & 0 deletions config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ keymap = [
{ on = [ "K" ], exec = "arrow -5", desc = "Move cursor up 5 lines" },
{ on = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },

{ on = [ "<C-u>" ], exec = "arrow -50%", desc = "Move cursor up half page" },
{ 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 = [ "l" ], exec = "enter", desc = "Enter the child directory" },

Expand Down
4 changes: 3 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ 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;

pub use blocker::*;
pub use event::*;
pub use highlighter::*;
pub use position::*;
pub use step::*;

pub fn init() { init_blocker(); }
18 changes: 11 additions & 7 deletions core/src/manager/folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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 {
Expand Down Expand Up @@ -58,28 +58,28 @@ impl Folder {
true
}

pub fn next(&mut self, step: usize) -> bool {
pub fn next(&mut self, step: Step) -> bool {
let len = self.files.len();
if len == 0 {
return false;
}

let old = self.cursor;
self.cursor = (self.cursor + step).min(len - 1);
let limit = MANAGER.layout.folder_height();
self.cursor = step.add(self.cursor, || limit).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);
}

old != self.cursor
}

pub fn prev(&mut self, step: usize) -> bool {
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, || MANAGER.layout.folder_height());
self.hovered = self.files.duplicate(self.cursor);
self.set_page(false);

Expand All @@ -105,7 +105,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(Step::from(new - self.cursor))
} else {
self.prev(Step::from(self.cursor - new))
}
}

#[inline]
Expand Down
14 changes: 5 additions & 9 deletions core/src/manager/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tokio::{pin, task::JoinHandle};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};

use super::{Finder, Folder, Mode, Preview, PreviewLock};
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, Step, BLOCKER};

pub struct Tab {
pub(super) mode: Mode,
Expand Down Expand Up @@ -67,12 +67,8 @@ impl Tab {
self.search_stop()
}

pub fn arrow(&mut self, step: isize) -> bool {
let ok = if step > 0 {
self.current.next(step as usize)
} else {
self.current.prev(step.unsigned_abs())
};
pub fn arrow(&mut self, step: Step) -> bool {
let ok = if step.is_positive() { self.current.next(step) } else { self.current.prev(step) };
if !ok {
return false;
}
Expand Down Expand Up @@ -248,7 +244,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);
Expand Down Expand Up @@ -280,7 +276,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
Expand Down
55 changes: 55 additions & 0 deletions core/src/step.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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<Self, Self::Err> {
Ok(if let Some(s) = s.strip_suffix('%') {
Self::Percent(s.parse()?)
} else {
Self::Fixed(s.parse()?)
})
}
}

impl From<isize> for Step {
fn from(n: isize) -> Self { Self::Fixed(n) }
}

impl From<usize> for Step {
fn from(n: usize) -> Self { Self::Fixed(n as isize) }
}

impl Step {
#[inline]
fn fixed<F: FnOnce() -> 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<F: FnOnce() -> 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 is_positive(&self) -> bool {
match *self {
Self::Fixed(n) => n > 0,
Self::Percent(n) => n > 0,
}
}
}