This commit is contained in:
sxyazi 2023-09-24 16:08:16 +08:00
parent 8260274459
commit e7c4286962
No known key found for this signature in database
5 changed files with 72 additions and 44 deletions

View file

@ -10,6 +10,9 @@ 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 = [ "J" ], exec = "arrow 5", desc = "Move cursor down 5 lines" },
{ on = [ "<C-u>" ], exec = "arrow -50%", desc = "Move cursor up half page" }, { 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-d>" ], exec = "arrow 50%", desc = "Move cursor down half page" },
{ on = [ "<C-b>" ], exec = "arrow -100%", desc = "Move cursor up one page" }, { on = [ "<C-b>" ], exec = "arrow -100%", desc = "Move cursor up one page" },

View file

@ -14,8 +14,9 @@ pub mod help;
mod highlighter; mod highlighter;
pub mod input; pub mod input;
pub mod manager; pub mod manager;
pub mod position; mod position;
pub mod select; pub mod select;
mod step;
pub mod tasks; pub mod tasks;
pub mod which; pub mod which;
@ -23,5 +24,6 @@ pub use blocker::*;
pub use event::*; pub use event::*;
pub use highlighter::*; pub use highlighter::*;
pub use position::*; pub use position::*;
pub use step::*;
pub fn init() { init_blocker(); } pub fn init() { init_blocker(); }

View file

@ -1,10 +1,8 @@
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;
use crate::{emit, files::{File, Files, FilesOp}}; use crate::{emit, files::{File, Files, FilesOp}, Step};
#[derive(Default)] #[derive(Default)]
pub struct Folder { pub struct Folder {
@ -18,12 +16,6 @@ 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() } }
} }
@ -32,19 +24,6 @@ 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 {
@ -79,18 +58,15 @@ impl Folder {
true 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(); let len = self.files.len();
if len == 0 { if len == 0 {
return false; return false;
} }
let limit = MANAGER.layout.folder_height(); 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 = step.add(self.cursor, || limit).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);
@ -101,13 +77,9 @@ impl Folder {
old != self.cursor old != self.cursor
} }
pub fn prev(&mut self, mut step: usize, percent: bool) -> bool { pub fn prev(&mut self, step: Step) -> 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 = step.add(self.cursor, || 0);
self.hovered = self.files.duplicate(self.cursor); self.hovered = self.files.duplicate(self.cursor);
self.set_page(false); self.set_page(false);
@ -134,9 +106,9 @@ 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 { if new > self.cursor {
self.next(new - self.cursor, false) self.next(Step::from(new - self.cursor))
} else { } else {
self.prev(self.cursor - new, false) self.prev(Step::from(self.cursor - new))
} }
} }

View file

@ -6,8 +6,8 @@ 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, Step}; 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 struct Tab {
pub(super) mode: Mode, pub(super) mode: Mode,
@ -68,12 +68,7 @@ impl Tab {
} }
pub fn arrow(&mut self, step: Step) -> bool { pub fn arrow(&mut self, step: Step) -> bool {
let Step { num, percent } = step; let ok = if step.positive() { self.current.next(step) } else { self.current.prev(step) };
let ok = if step.num > 0 {
self.current.next(num as usize, percent)
} else {
self.current.prev(num.unsigned_abs(), percent)
};
if !ok { if !ok {
return false; return false;
} }

56
core/src/step.rs Normal file
View file

@ -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<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 positive(&self) -> bool {
match self {
Self::Fixed(n) if *n > 0 => true,
Self::Percent(n) if *n > 0 => true,
_ => false,
}
}
}