From e9fcab3b375afef4b0083687388b90e060a55a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Wed, 5 Feb 2025 21:35:15 +0800 Subject: [PATCH] feat: new `arrow top` and `arrow bot` commands to jump to the top and bottom (#2294) --- yazi-config/preset/keymap-default.toml | 4 +-- yazi-config/src/lib.rs | 11 ++++++ yazi-core/src/input/commands/move_.rs | 6 ++-- yazi-core/src/tab/commands/arrow.rs | 22 +++++++----- yazi-fs/src/step.rs | 46 ++++++++++++++++---------- 5 files changed, 59 insertions(+), 30 deletions(-) diff --git a/yazi-config/preset/keymap-default.toml b/yazi-config/preset/keymap-default.toml index 23d7ff3e..31f0cc97 100644 --- a/yazi-config/preset/keymap-default.toml +++ b/yazi-config/preset/keymap-default.toml @@ -29,8 +29,8 @@ keymap = [ { on = "", run = "arrow -100%", desc = "Move cursor up one page" }, { on = "", run = "arrow 100%", desc = "Move cursor down one page" }, - { on = [ "g", "g" ], run = "arrow -99999999", desc = "Move cursor to the top" }, - { on = "G", run = "arrow 99999999", desc = "Move cursor to the bottom" }, + { on = [ "g", "g" ], run = "arrow top", desc = "Move cursor to the top" }, + { on = "G", run = "arrow bot", desc = "Move cursor to the bottom" }, # Navigation { on = "h", run = "leave", desc = "Go back to the parent directory" }, diff --git a/yazi-config/src/lib.rs b/yazi-config/src/lib.rs index 008b2eb0..6294d067 100644 --- a/yazi-config/src/lib.rs +++ b/yazi-config/src/lib.rs @@ -28,6 +28,17 @@ pub fn init() -> anyhow::Result<()> { try_init(false)?; } + // TODO: remove this + for c in KEYMAP.manager.iter().flat_map(|c| c.run.iter()) { + if c.name == "arrow" + && c.first_str().unwrap_or_default().parse::().is_ok_and(|n| n <= -999 || n >= 999) + { + eprintln!("Deprecated command: `arrow -99999999` and `arrow 99999999` have been deprecated, please use `arrow top` and `arrow bot` instead, in your `keymap.toml`. + +See #2294 for more details: https://github.com/sxyazi/yazi/pull/2294"); + } + } + Ok(()) } diff --git a/yazi-core/src/input/commands/move_.rs b/yazi-core/src/input/commands/move_.rs index 10cc1e78..9edc5384 100644 --- a/yazi-core/src/input/commands/move_.rs +++ b/yazi-core/src/input/commands/move_.rs @@ -1,4 +1,4 @@ -use std::str::FromStr; +use std::{num::ParseIntError, str::FromStr}; use unicode_width::UnicodeWidthStr; use yazi_macro::render; @@ -76,14 +76,14 @@ impl Default for OptStep { } impl FromStr for OptStep { - type Err = (); + type Err = ParseIntError; fn from_str(s: &str) -> Result { Ok(match s { "bol" => Self::Bol, "eol" => Self::Eol, "first-char" => Self::FirstChar, - s => Self::Offset(s.parse().map_err(|_| ())?), + s => Self::Offset(s.parse()?), }) } } diff --git a/yazi-core/src/tab/commands/arrow.rs b/yazi-core/src/tab/commands/arrow.rs index 10a33ee4..ce697dd8 100644 --- a/yazi-core/src/tab/commands/arrow.rs +++ b/yazi-core/src/tab/commands/arrow.rs @@ -1,7 +1,7 @@ use yazi_fs::Step; use yazi_macro::render; use yazi_proxy::ManagerProxy; -use yazi_shared::event::{CmdCow, Data}; +use yazi_shared::event::CmdCow; use crate::tab::Tab; @@ -11,13 +11,7 @@ struct Opt { impl From for Opt { fn from(c: CmdCow) -> Self { - let step = match c.first() { - Some(Data::Integer(i)) => Step::from(*i as isize), - Some(Data::String(s)) => s.parse().unwrap_or_default(), - _ => Step::default(), - }; - - Self { step } + Self { step: c.first().and_then(|d| d.try_into().ok()).unwrap_or_default() } } } @@ -28,6 +22,18 @@ impl From for Opt { impl Tab { #[yazi_codegen::command] pub fn arrow(&mut self, opt: Opt) { + // TODO: remove this + if let Step::Fixed(n) = opt.step { + if n <= -999 || n >= 999 { + yazi_proxy::AppProxy::notify_warn( + "Deprecated command", + "`arrow -99999999` and `arrow 99999999` have been deprecated, please use `arrow top` and `arrow bot` instead. + +See #2294 for more details: https://github.com/sxyazi/yazi/pull/2294", + ); + } + } + if !self.current.arrow(opt.step) { return; } diff --git a/yazi-fs/src/step.rs b/yazi-fs/src/step.rs index 1379d415..25f8c6fe 100644 --- a/yazi-fs/src/step.rs +++ b/yazi-fs/src/step.rs @@ -1,7 +1,11 @@ use std::{num::ParseIntError, str::FromStr}; +use yazi_shared::event::Data; + #[derive(Clone, Copy)] pub enum Step { + Top, + Bot, Fixed(isize), Percent(i8), } @@ -10,34 +14,41 @@ 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 Step { - #[inline] - pub fn prev(n: usize) -> Self { Self::Fixed(-(n as isize)) } +impl FromStr for Step { + type Err = ParseIntError; - #[inline] - pub fn next(n: usize) -> Self { Self::Fixed(n as isize) } + fn from_str(s: &str) -> Result { + Ok(match s { + "top" => Self::Top, + "bot" => Self::Bot, + s if s.ends_with('%') => Self::Percent(s[..s.len() - 1].parse()?), + s => Self::Fixed(s.parse()?), + }) + } +} + +impl TryFrom<&Data> for Step { + type Error = ParseIntError; + + fn try_from(value: &Data) -> Result { + Ok(match value { + Data::Integer(i) => Self::from(*i as isize), + Data::String(s) => s.parse()?, + _ => "".parse()?, + }) + } } impl Step { #[inline] pub fn add(self, pos: usize, limit: usize) -> usize { let fixed = match self { + Self::Top => return 0, + Self::Bot => return usize::MAX, Self::Fixed(n) => n, Self::Percent(0) => 0, Self::Percent(n) => n as isize * limit as isize / 100, @@ -48,6 +59,7 @@ impl Step { #[inline] pub fn is_positive(self) -> bool { match self { + Self::Top | Self::Bot => false, Self::Fixed(n) => n > 0, Self::Percent(n) => n > 0, }