yazi/yazi-core/src/input/commands/move_.rs
2024-09-21 20:12:35 +08:00

55 lines
1.3 KiB
Rust

use unicode_width::UnicodeWidthStr;
use yazi_shared::{event::{Cmd, Data}, render};
use crate::input::{Input, op::InputOp, snap::InputSnap};
pub struct Opt {
step: isize,
in_operating: bool,
}
impl From<Cmd> for Opt {
fn from(c: Cmd) -> Self {
Self {
step: c.first().and_then(Data::as_isize).unwrap_or(0),
in_operating: c.bool("in-operating"),
}
}
}
impl From<isize> for Opt {
fn from(step: isize) -> Self { Self { step, in_operating: false } }
}
impl Input {
pub fn move_(&mut self, opt: impl Into<Opt>) {
let opt = opt.into() as Opt;
let snap = self.snap();
if opt.in_operating && snap.op == InputOp::None {
return;
}
render!(self.handle_op(
if opt.step <= 0 {
snap.cursor.saturating_sub(opt.step.unsigned_abs())
} else {
snap.count().min(snap.cursor + opt.step as usize)
},
false,
));
let (limit, snap) = (self.limit(), self.snap_mut());
if snap.offset > snap.cursor {
snap.offset = snap.cursor;
} else if snap.value.is_empty() {
snap.offset = 0;
} else {
let delta = snap.mode.delta();
let s = snap.slice(snap.offset..snap.cursor + delta);
if s.width() >= limit {
let s = s.chars().rev().collect::<String>();
snap.offset = snap.cursor - InputSnap::find_window(&s, 0, limit).end.saturating_sub(delta);
}
}
}
}