From a6fb8ee64b83ded59ec73af80c6c327ea902c0bb Mon Sep 17 00:00:00 2001 From: sxyazi Date: Fri, 25 Apr 2025 07:07:19 +0800 Subject: [PATCH] .. --- yazi-widgets/src/input/commands/move_.rs | 9 +++--- yazi-widgets/src/input/input.rs | 20 +++++-------- yazi-widgets/src/input/snap.rs | 37 +++++++++++++++++++----- yazi-widgets/src/input/snaps.rs | 8 ++--- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/yazi-widgets/src/input/commands/move_.rs b/yazi-widgets/src/input/commands/move_.rs index 17d00e64..0f48bf1a 100644 --- a/yazi-widgets/src/input/commands/move_.rs +++ b/yazi-widgets/src/input/commands/move_.rs @@ -1,6 +1,5 @@ use std::{num::ParseIntError, str::FromStr}; -use unicode_width::UnicodeWidthStr; use yazi_macro::render; use yazi_shared::event::{CmdCow, Data}; @@ -40,10 +39,10 @@ impl Input { snap.offset = 0; } else { let delta = snap.mode.delta(); - let s = snap.slice(snap.offset..snap.cursor + delta); - if s.width() >= limit { - let range = InputSnap::find_window(s.chars().rev(), 0, limit); - snap.offset = snap.cursor - range.end.saturating_sub(delta); + let range = snap.offset..snap.cursor + delta; + if snap.width(range.clone()) >= limit as u16 { + let it = snap.slice(range).chars().rev().map(|c| if snap.obscure { '•' } else { c }); + snap.offset = snap.cursor - InputSnap::find_window(it, 0, limit).end.saturating_sub(delta); } } } diff --git a/yazi-widgets/src/input/input.rs b/yazi-widgets/src/input/input.rs index b476563e..e6855852 100644 --- a/yazi-widgets/src/input/input.rs +++ b/yazi-widgets/src/input/input.rs @@ -1,7 +1,6 @@ -use std::ops::Range; +use std::{borrow::Cow, ops::Range}; use crossterm::cursor::SetCursorStyle; -use unicode_width::UnicodeWidthStr; use yazi_config::YAZI; use yazi_plugin::CLIPBOARD; @@ -12,14 +11,14 @@ pub type InputCallback = Box; #[derive(Default)] pub struct Input { pub snaps: InputSnaps, - pub limit: usize, + pub limit: usize, // FIXME pub obscure: bool, pub callback: Option, } impl Input { pub fn new(value: String, limit: usize, obscure: bool, callback: InputCallback) -> Self { - Self { snaps: InputSnaps::new(value, limit), limit, obscure, callback: Some(callback) } + Self { snaps: InputSnaps::new(value, obscure, limit), limit, obscure, callback: Some(callback) } } pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool { @@ -78,9 +77,9 @@ impl Input { #[inline] pub fn display(&self) -> Cow { if self.obscure { - "•".repeat(self.window(self.limit).len()).into() + "•".repeat(self.snap().window(self.limit).len()).into() } else { - self.snap().slice(self.window(self.limit)).into() + self.snap().slice(self.snap().window(self.limit)).into() } } @@ -88,10 +87,7 @@ impl Input { pub fn mode(&self) -> InputMode { self.snap().mode } #[inline] - pub fn cursor(&self) -> u16 { - let snap = self.snap(); - snap.slice(snap.offset..snap.cursor).width() as u16 - } + pub fn cursor(&self) -> u16 { self.snap().width(self.snap().offset..self.snap().cursor) } pub fn cursor_shape(&self) -> SetCursorStyle { use InputMode as M; @@ -117,8 +113,8 @@ impl Input { let win = snap.window(self.limit); let Range { start, end } = start.max(win.start)..end.min(win.end); - let s = snap.slice(snap.offset..start).width() as u16; - Some(s..s + snap.slice(start..end).width() as u16) + let s = snap.width(snap.offset..start); + Some(s..s + snap.width(start..end)) } #[inline] diff --git a/yazi-widgets/src/input/snap.rs b/yazi-widgets/src/input/snap.rs index c1ee4c2b..b3584cc0 100644 --- a/yazi-widgets/src/input/snap.rs +++ b/yazi-widgets/src/input/snap.rs @@ -1,6 +1,6 @@ use std::ops::Range; -use unicode_width::UnicodeWidthChar; +use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use super::{InputMode, InputOp}; @@ -10,20 +10,24 @@ pub struct InputSnap { pub op: InputOp, - pub mode: InputMode, + pub mode: InputMode, + pub obscure: bool, + pub offset: usize, pub cursor: usize, } impl InputSnap { - pub(super) fn new(value: String, limit: usize) -> Self { + pub(super) fn new(value: String, obscure: bool, limit: usize) -> Self { let mut snap = Self { value, op: Default::default(), mode: Default::default(), - offset: usize::MAX, + obscure, + + offset: 0, cursor: usize::MAX, }; snap.resize(limit); @@ -32,9 +36,19 @@ impl InputSnap { #[inline] pub(super) fn resize(&mut self, limit: usize) { - let range = Self::find_window(self.value.chars().rev(), 0, limit); + let count = self.count(); + let limit = if self.obscure { + count.min(limit) + } else { + Self::find_window(self.value.chars().rev(), 0, limit).end + }; + self.cursor = self.cursor.min(self.count().saturating_sub(self.mode.delta())); - self.offset = self.offset.min(self.cursor.saturating_sub(range.end)); + self.offset = if self.cursor < (self.offset + limit).min(count) { + count.saturating_sub(limit).min(self.offset) + } else { + count.saturating_sub(limit).min(self.cursor.saturating_sub(limit) + 1) + }; } } @@ -61,9 +75,18 @@ impl InputSnap { &self.value[s.unwrap()..e.unwrap()] } + #[inline] + pub(super) fn width(&self, range: Range) -> u16 { + if self.obscure { range.len() as u16 } else { self.slice(range).width() as u16 } + } + #[inline] pub(super) fn window(&self, limit: usize) -> Range { - Self::find_window(self.value.chars(), self.offset, limit) + Self::find_window( + self.value.chars().map(|c| if self.obscure { '•' } else { c }), + self.offset, + limit, + ) } pub(super) fn find_window(it: T, offset: usize, limit: usize) -> Range diff --git a/yazi-widgets/src/input/snaps.rs b/yazi-widgets/src/input/snaps.rs index 2d19078b..0bfbd539 100644 --- a/yazi-widgets/src/input/snaps.rs +++ b/yazi-widgets/src/input/snaps.rs @@ -13,15 +13,15 @@ impl Default for InputSnaps { fn default() -> Self { Self { idx: 0, - versions: vec![InputSnap::new(String::new(), 0)], - current: InputSnap::new(String::new(), 0), + versions: vec![InputSnap::new(String::new(), false, 0)], + current: InputSnap::new(String::new(), false, 0), } } } impl InputSnaps { - pub fn new(value: String, limit: usize) -> Self { - let current = InputSnap::new(value, limit); + pub fn new(value: String, obscure: bool, limit: usize) -> Self { + let current = InputSnap::new(value, obscure, limit); Self { idx: 0, versions: vec![current.clone()], current } }