From 13fde686ed30fbf3595ef54b355f3a9df16064ab Mon Sep 17 00:00:00 2001 From: XOR-op <17672363+XOR-op@users.noreply.github.com> Date: Thu, 27 Mar 2025 09:09:58 -0400 Subject: [PATCH] feat: support wrap around for arrow actions --- yazi-core/src/cmp/commands/arrow.rs | 33 ++++++++++++++----------- yazi-core/src/confirm/commands/arrow.rs | 28 +++++++-------------- yazi-core/src/pick/commands/arrow.rs | 29 ++++++++++++++-------- yazi-core/src/tasks/commands/arrow.rs | 16 +++++++----- 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/yazi-core/src/cmp/commands/arrow.rs b/yazi-core/src/cmp/commands/arrow.rs index 43722558..e203ce01 100644 --- a/yazi-core/src/cmp/commands/arrow.rs +++ b/yazi-core/src/cmp/commands/arrow.rs @@ -1,34 +1,39 @@ +use yazi_fs::Step; use yazi_macro::render; -use yazi_shared::event::{CmdCow, Data}; +use yazi_shared::event::CmdCow; use crate::cmp::Cmp; struct Opt { - step: isize, + step: Step, } impl From for Opt { - fn from(c: CmdCow) -> Self { Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) } } + fn from(c: CmdCow) -> Self { + Self { step: c.first().and_then(|d| d.try_into().ok()).unwrap_or_default() } + } } impl Cmp { #[yazi_codegen::command] pub fn arrow(&mut self, opt: Opt) { - if opt.step > 0 { - self.next(opt.step as usize); - } else { - self.prev(opt.step.unsigned_abs()); - } - } - - fn next(&mut self, step: usize) { let len = self.cands.len(); if len == 0 { return; } + let new = opt.step.add(self.cursor, self.cands.len(), self.limit()); + if new > self.cursor { + self.next(new); + } else { + self.prev(new); + } + } + + fn next(&mut self, new: usize) { + let len = self.cands.len(); let old = self.cursor; - self.cursor = (self.cursor + step).min(len - 1); + self.cursor = new.min(len - 1); let limit = self.limit(); if self.cursor >= len.min(self.offset + limit) { @@ -38,9 +43,9 @@ impl Cmp { render!(old != self.cursor); } - fn prev(&mut self, step: usize) { + fn prev(&mut self, new: usize) { let old = self.cursor; - self.cursor = self.cursor.saturating_sub(step); + self.cursor = new.min(self.cands.len().saturating_sub(1)); if self.cursor < self.offset { self.offset = self.offset.saturating_sub(old - self.cursor); diff --git a/yazi-core/src/confirm/commands/arrow.rs b/yazi-core/src/confirm/commands/arrow.rs index 5af73ac7..b2c29730 100644 --- a/yazi-core/src/confirm/commands/arrow.rs +++ b/yazi-core/src/confirm/commands/arrow.rs @@ -1,41 +1,31 @@ +use yazi_fs::Step; use yazi_macro::render; -use yazi_shared::event::{CmdCow, Data}; +use yazi_shared::event::CmdCow; use crate::{confirm::Confirm, mgr::Mgr}; struct Opt { - step: isize, + step: Step, } impl From for Opt { - fn from(c: CmdCow) -> Self { Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) } } + fn from(c: CmdCow) -> Self { + Self { step: c.first().and_then(|d| d.try_into().ok()).unwrap_or_default() } + } } impl Confirm { #[yazi_codegen::command] pub fn arrow(&mut self, opt: Opt, mgr: &Mgr) { - if opt.step > 0 { - self.next(opt.step as usize, mgr.area(self.position).width) - } else { - self.prev(opt.step.unsigned_abs()) - } - } - - fn next(&mut self, step: usize, width: u16) { + let width = mgr.area(self.position).width; let height = self.list.line_count(width); if height == 0 { return; } let old = self.offset; - self.offset = (self.offset + step).min(height - 1); - - render!(old != self.offset); - } - - fn prev(&mut self, step: usize) { - let old = self.offset; - self.offset -= step.min(self.offset); + let new = opt.step.add(self.offset, height, height); + self.offset = new.min(height - 1); render!(old != self.offset); } diff --git a/yazi-core/src/pick/commands/arrow.rs b/yazi-core/src/pick/commands/arrow.rs index 191837f8..423ea00e 100644 --- a/yazi-core/src/pick/commands/arrow.rs +++ b/yazi-core/src/pick/commands/arrow.rs @@ -1,30 +1,39 @@ +use yazi_fs::Step; use yazi_macro::render; -use yazi_shared::event::{CmdCow, Data}; +use yazi_shared::event::CmdCow; use crate::pick::Pick; struct Opt { - step: isize, + step: Step, } impl From for Opt { - fn from(c: CmdCow) -> Self { Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) } } + fn from(c: CmdCow) -> Self { + Self { step: c.first().and_then(|d| d.try_into().ok()).unwrap_or_default() } + } } impl Pick { #[yazi_codegen::command] pub fn arrow(&mut self, opt: Opt) { - if opt.step > 0 { self.next(opt.step as usize) } else { self.prev(opt.step.unsigned_abs()) } - } - - fn next(&mut self, step: usize) { let len = self.items.len(); if len == 0 { return; } + let new = opt.step.add(self.cursor, len, self.limit()); + if new > self.cursor { + self.next(new); + } else { + self.prev(new); + } + } + + fn next(&mut self, new: usize) { + let len = self.items.len(); let old = self.cursor; - self.cursor = (self.cursor + step).min(len - 1); + self.cursor = new.min(len - 1); let limit = self.limit(); if self.cursor >= len.min(self.offset + limit) { @@ -34,9 +43,9 @@ impl Pick { render!(old != self.cursor); } - fn prev(&mut self, step: usize) { + fn prev(&mut self, new: usize) { let old = self.cursor; - self.cursor = self.cursor.saturating_sub(step); + self.cursor = new.min(self.items.len().saturating_sub(1)); if self.cursor < self.offset { self.offset = self.offset.saturating_sub(old - self.cursor); diff --git a/yazi-core/src/tasks/commands/arrow.rs b/yazi-core/src/tasks/commands/arrow.rs index d1b8c527..95bc18cb 100644 --- a/yazi-core/src/tasks/commands/arrow.rs +++ b/yazi-core/src/tasks/commands/arrow.rs @@ -1,31 +1,35 @@ +use yazi_fs::Step; use yazi_macro::render; -use yazi_shared::event::{CmdCow, Data}; +use yazi_shared::event::CmdCow; use crate::tasks::Tasks; struct Opt { - step: isize, + step: Step, } impl From for Opt { - fn from(c: CmdCow) -> Self { Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) } } + fn from(c: CmdCow) -> Self { + Self { step: c.first().and_then(|d| d.try_into().ok()).unwrap_or_default() } + } } impl From for Opt { - fn from(step: isize) -> Self { Self { step } } + fn from(step: isize) -> Self { Self { step: step.into() } } } impl Tasks { #[yazi_codegen::command] pub fn arrow(&mut self, opt: Opt) { + let max = Self::limit().min(self.summaries.len()); let old = self.cursor; - if opt.step > 0 { + let new = opt.step.add(self.cursor, max, max); + if new > old { self.cursor += 1; } else { self.cursor = self.cursor.saturating_sub(1); } - let max = Self::limit().min(self.summaries.len()); self.cursor = self.cursor.min(max.saturating_sub(1)); render!(self.cursor != old); }