Fix Input width

This commit is contained in:
sxyazi 2023-11-17 09:33:20 +08:00
parent 16473af4e6
commit fe00017d5d
No known key found for this signature in database
5 changed files with 47 additions and 39 deletions

View file

@ -30,7 +30,7 @@ impl Input {
} }
} }
} }
self.snaps.tag(); self.snaps.tag(self.limit());
true true
} }
} }

View file

@ -38,7 +38,7 @@ impl Input {
false, false,
); );
let snap = self.snap_mut(); let (limit, snap) = (self.limit(), self.snap_mut());
if snap.offset > snap.cursor { if snap.offset > snap.cursor {
snap.offset = snap.cursor; snap.offset = snap.cursor;
} else if snap.value.is_empty() { } else if snap.value.is_empty() {
@ -46,9 +46,9 @@ impl Input {
} else { } else {
let delta = snap.mode.delta(); let delta = snap.mode.delta();
let s = snap.slice(snap.offset..snap.cursor + delta); let s = snap.slice(snap.offset..snap.cursor + delta);
if s.width() >= /*TODO: hardcode*/ 50 - 2 { if s.width() >= limit {
let s = s.chars().rev().collect::<String>(); let s = s.chars().rev().collect::<String>();
snap.offset = snap.cursor - InputSnap::find_window(&s, 0).end.saturating_sub(delta); snap.offset = snap.cursor - InputSnap::find_window(&s, 0, limit).end.saturating_sub(delta);
} }
} }

View file

@ -2,7 +2,7 @@ use std::ops::Range;
use tokio::sync::mpsc::UnboundedSender; use tokio::sync::mpsc::UnboundedSender;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use yazi_config::popup::{InputOpt, Position}; use yazi_config::{popup::{InputOpt, Position}, INPUT};
use yazi_shared::InputError; use yazi_shared::InputError;
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps}; use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
@ -29,9 +29,7 @@ pub struct Input {
impl Input { impl Input {
pub fn show(&mut self, opt: InputOpt, tx: UnboundedSender<Result<String, InputError>>) { pub fn show(&mut self, opt: InputOpt, tx: UnboundedSender<Result<String, InputError>>) {
self.close(false); self.close(false);
self.snaps.reset(opt.value);
self.visible = true; self.visible = true;
self.title = opt.title; self.title = opt.title;
self.position = opt.position; self.position = opt.position;
@ -42,6 +40,14 @@ impl Input {
// Shell // Shell
self.highlight = opt.highlight; self.highlight = opt.highlight;
// Reset snaps
self.snaps.reset(opt.value, self.limit());
}
#[inline]
pub(super) fn limit(&self) -> usize {
self.position.offset.width.saturating_sub(INPUT.border()) as usize
} }
pub fn type_str(&mut self, s: &str) -> bool { pub fn type_str(&mut self, s: &str) -> bool {
@ -93,7 +99,7 @@ impl Input {
return false; return false;
} }
if !matches!(old.op, InputOp::None | InputOp::Select(_)) { if !matches!(old.op, InputOp::None | InputOp::Select(_)) {
self.snaps.tag().then(|| self.flush_value()); self.snaps.tag(self.limit()).then(|| self.flush_value());
} }
true true
} }
@ -116,7 +122,7 @@ impl Input {
impl Input { impl Input {
#[inline] #[inline]
pub fn value(&self) -> &str { self.snap().slice(self.snap().window()) } pub fn value(&self) -> &str { self.snap().slice(self.snap().window(self.limit())) }
#[inline] #[inline]
pub fn mode(&self) -> InputMode { self.snap().mode } pub fn mode(&self) -> InputMode { self.snap().mode }
@ -134,7 +140,7 @@ impl Input {
let (start, end) = let (start, end) =
if start < snap.cursor { (start, snap.cursor) } else { (snap.cursor + 1, start + 1) }; if start < snap.cursor { (start, snap.cursor) } else { (snap.cursor + 1, start + 1) };
let win = snap.window(); let win = snap.window(self.limit());
let Range { start, end } = start.max(win.start)..end.min(win.end); let Range { start, end } = start.max(win.start)..end.min(win.end);
let s = snap.slice(snap.offset..start).width() as u16; let s = snap.slice(snap.offset..start).width() as u16;

View file

@ -16,7 +16,7 @@ pub(super) struct InputSnap {
} }
impl InputSnap { impl InputSnap {
pub(super) fn new(value: String) -> Self { pub(super) fn new(value: String, limit: usize) -> Self {
let mut snap = Self { let mut snap = Self {
value, value,
@ -26,15 +26,15 @@ impl InputSnap {
offset: usize::MAX, offset: usize::MAX,
cursor: usize::MAX, cursor: usize::MAX,
}; };
snap.reset(); snap.reset(limit);
snap snap
} }
#[inline] #[inline]
pub(super) fn reset(&mut self) { pub(super) fn reset(&mut self, limit: usize) {
self.cursor = self.cursor.min(self.value.chars().count().saturating_sub(self.mode.delta())); self.cursor = self.cursor.min(self.value.chars().count().saturating_sub(self.mode.delta()));
self.offset = self.offset =
self.offset.min(self.cursor.saturating_sub(Self::find_window(&self.rev(), 0).end)); self.offset.min(self.cursor.saturating_sub(Self::find_window(&self.rev(), 0, limit).end));
} }
} }
@ -65,10 +65,12 @@ impl InputSnap {
pub(super) fn rev(&self) -> String { self.value.chars().rev().collect::<String>() } pub(super) fn rev(&self) -> String { self.value.chars().rev().collect::<String>() }
#[inline] #[inline]
pub(super) fn window(&self) -> Range<usize> { Self::find_window(&self.value, self.offset) } pub(super) fn window(&self, limit: usize) -> Range<usize> {
Self::find_window(&self.value, self.offset, limit)
}
#[inline] #[inline]
pub(super) fn find_window(s: &str, offset: usize) -> Range<usize> { pub(super) fn find_window(s: &str, offset: usize, limit: usize) -> Range<usize> {
let mut width = 0; let mut width = 0;
let v = s let v = s
.chars() .chars()
@ -76,7 +78,7 @@ impl InputSnap {
.skip(offset) .skip(offset)
.map_while(|(i, c)| { .map_while(|(i, c)| {
width += c.width().unwrap_or(0); width += c.width().unwrap_or(0);
if width < /*TODO: hardcode*/ 50 - 2 { Some(i) } else { None } if width < limit { Some(i) } else { None }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -11,13 +11,33 @@ pub(super) struct InputSnaps {
impl InputSnaps { impl InputSnaps {
#[inline] #[inline]
pub(super) fn reset(&mut self, value: String) { pub(super) fn reset(&mut self, value: String, limit: usize) {
self.idx = 0; self.idx = 0;
self.versions.clear(); self.versions.clear();
self.versions.push(InputSnap::new(value)); self.versions.push(InputSnap::new(value, limit));
self.current = self.versions[0].clone(); self.current = self.versions[0].clone();
} }
pub(super) fn tag(&mut self, limit: usize) -> bool {
// Sync *current* cursor position to the *last* version:
// Save offset/cursor/ect. of the *current* as the last version,
// while keeping the *last* value unchanged.
let value = mem::take(&mut self.versions[self.idx].value);
self.versions[self.idx] = self.current.clone();
self.versions[self.idx].value = value;
self.versions[self.idx].reset(limit);
// If the *current* value is the same as the *last* version
if self.versions[self.idx].value == self.current.value {
return false;
}
self.versions.truncate(self.idx + 1);
self.versions.push(self.current().clone());
self.idx += 1;
true
}
pub(super) fn undo(&mut self) -> bool { pub(super) fn undo(&mut self) -> bool {
if self.idx == 0 { if self.idx == 0 {
return false; return false;
@ -37,26 +57,6 @@ impl InputSnaps {
self.current = self.versions[self.idx].clone(); self.current = self.versions[self.idx].clone();
true true
} }
pub(super) fn tag(&mut self) -> bool {
// Sync *current* cursor position to the *last* version:
// Save offset/cursor/ect. of the *current* as the last version,
// while keeping the *last* value unchanged.
let value = mem::take(&mut self.versions[self.idx].value);
self.versions[self.idx] = self.current.clone();
self.versions[self.idx].value = value;
self.versions[self.idx].reset();
// If the *current* value is the same as the *last* version
if self.versions[self.idx].value == self.current.value {
return false;
}
self.versions.truncate(self.idx + 1);
self.versions.push(self.current().clone());
self.idx += 1;
true
}
} }
impl InputSnaps { impl InputSnaps {