mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new arrow top and arrow bot commands to jump to the top and bottom (#2294)
This commit is contained in:
parent
0c100ae5a6
commit
e9fcab3b37
5 changed files with 59 additions and 30 deletions
|
|
@ -29,8 +29,8 @@ keymap = [
|
|||
{ on = "<PageUp>", run = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = "<PageDown>", 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" },
|
||||
|
|
|
|||
|
|
@ -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::<isize>().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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Self, Self::Err> {
|
||||
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()?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CmdCow> 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<isize> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<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 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<Self, Self::Err> {
|
||||
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<Self, Self::Error> {
|
||||
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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue