mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
eac62492aa
commit
f8b3ab0ce7
6 changed files with 97 additions and 56 deletions
48
yazi-core/src/select/commands/arrow.rs
Normal file
48
yazi-core/src/select/commands/arrow.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use yazi_config::keymap::Exec;
|
||||
|
||||
use crate::select::Select;
|
||||
|
||||
pub struct Opt {
|
||||
step: isize,
|
||||
}
|
||||
|
||||
impl From<&Exec> for Opt {
|
||||
fn from(e: &Exec) -> Self {
|
||||
Self { step: e.args.first().and_then(|s| s.parse().ok()).unwrap_or(0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Select {
|
||||
fn next(&mut self, step: usize) -> bool {
|
||||
let len = self.items.len();
|
||||
if len == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let old = self.cursor;
|
||||
self.cursor = (self.cursor + step).min(len - 1);
|
||||
|
||||
let limit = self.limit();
|
||||
if self.cursor >= len.min(self.offset + limit) {
|
||||
self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old);
|
||||
}
|
||||
|
||||
old != self.cursor
|
||||
}
|
||||
|
||||
fn prev(&mut self, step: usize) -> bool {
|
||||
let old = self.cursor;
|
||||
self.cursor = self.cursor.saturating_sub(step);
|
||||
|
||||
if self.cursor < self.offset {
|
||||
self.offset = self.offset.saturating_sub(old - self.cursor);
|
||||
}
|
||||
|
||||
old != self.cursor
|
||||
}
|
||||
|
||||
pub fn arrow(&mut self, opt: impl Into<Opt>) -> bool {
|
||||
let opt = opt.into() as Opt;
|
||||
if opt.step > 0 { self.next(opt.step as usize) } else { self.prev(opt.step.unsigned_abs()) }
|
||||
}
|
||||
}
|
||||
29
yazi-core/src/select/commands/close.rs
Normal file
29
yazi-core/src/select/commands/close.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use anyhow::anyhow;
|
||||
use yazi_config::keymap::Exec;
|
||||
|
||||
use crate::select::Select;
|
||||
|
||||
pub struct Opt {
|
||||
submit: bool,
|
||||
}
|
||||
|
||||
impl From<&Exec> for Opt {
|
||||
fn from(e: &Exec) -> Self { Self { submit: e.named.contains_key("submit") } }
|
||||
}
|
||||
impl From<bool> for Opt {
|
||||
fn from(submit: bool) -> Self { Self { submit } }
|
||||
}
|
||||
|
||||
impl Select {
|
||||
pub fn close(&mut self, opt: impl Into<Opt>) -> bool {
|
||||
let opt = opt.into() as Opt;
|
||||
if let Some(cb) = self.callback.take() {
|
||||
_ = cb.send(if opt.submit { Ok(self.cursor) } else { Err(anyhow!("canceled")) });
|
||||
}
|
||||
|
||||
self.cursor = 0;
|
||||
self.offset = 0;
|
||||
self.visible = false;
|
||||
true
|
||||
}
|
||||
}
|
||||
2
yazi-core/src/select/commands/mod.rs
Normal file
2
yazi-core/src/select/commands/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
mod arrow;
|
||||
mod close;
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod commands;
|
||||
mod option;
|
||||
mod select;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use anyhow::Result;
|
||||
use tokio::sync::oneshot::Sender;
|
||||
|
||||
use super::SelectOpt;
|
||||
|
|
@ -7,12 +7,12 @@ use crate::Position;
|
|||
#[derive(Default)]
|
||||
pub struct Select {
|
||||
title: String,
|
||||
items: Vec<String>,
|
||||
pub(super) items: Vec<String>,
|
||||
pub position: Position,
|
||||
|
||||
offset: usize,
|
||||
cursor: usize,
|
||||
callback: Option<Sender<Result<usize>>>,
|
||||
pub(super) offset: usize,
|
||||
pub(super) cursor: usize,
|
||||
pub(super) callback: Option<Sender<Result<usize>>>,
|
||||
|
||||
pub visible: bool,
|
||||
}
|
||||
|
|
@ -29,45 +29,6 @@ impl Select {
|
|||
self.visible = true;
|
||||
}
|
||||
|
||||
pub fn close(&mut self, submit: bool) -> bool {
|
||||
if let Some(cb) = self.callback.take() {
|
||||
_ = cb.send(if submit { Ok(self.cursor) } else { Err(anyhow!("canceled")) });
|
||||
}
|
||||
|
||||
self.cursor = 0;
|
||||
self.offset = 0;
|
||||
self.visible = false;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn next(&mut self, step: usize) -> bool {
|
||||
let len = self.items.len();
|
||||
if len == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let old = self.cursor;
|
||||
self.cursor = (self.cursor + step).min(len - 1);
|
||||
|
||||
let limit = self.limit();
|
||||
if self.cursor >= len.min(self.offset + limit) {
|
||||
self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old);
|
||||
}
|
||||
|
||||
old != self.cursor
|
||||
}
|
||||
|
||||
pub fn prev(&mut self, step: usize) -> bool {
|
||||
let old = self.cursor;
|
||||
self.cursor = self.cursor.saturating_sub(step);
|
||||
|
||||
if self.cursor < self.offset {
|
||||
self.offset = self.offset.saturating_sub(old - self.cursor);
|
||||
}
|
||||
|
||||
old != self.cursor
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn window(&self) -> &[String] {
|
||||
let end = (self.offset + self.limit()).min(self.items.len());
|
||||
|
|
|
|||
|
|
@ -166,18 +166,18 @@ impl<'a> Executor<'a> {
|
|||
}
|
||||
|
||||
fn select(&mut self, exec: &Exec) -> bool {
|
||||
macro_rules! on {
|
||||
($name:ident) => {
|
||||
if exec.cmd == stringify!($name) {
|
||||
return self.cx.select.$name(exec);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
on!(close);
|
||||
on!(arrow);
|
||||
|
||||
match exec.cmd.as_str() {
|
||||
"close" => self.cx.select.close(exec.named.contains_key("submit")),
|
||||
|
||||
"arrow" => {
|
||||
let step: isize = exec.args.first().and_then(|s| s.parse().ok()).unwrap_or(0);
|
||||
if step > 0 {
|
||||
self.cx.select.next(step as usize)
|
||||
} else {
|
||||
self.cx.select.prev(step.unsigned_abs())
|
||||
}
|
||||
}
|
||||
|
||||
"help" => self.cx.help.toggle(KeymapLayer::Select),
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue