separate vim and emacs logic (find_word_boundary)

This commit is contained in:
Francis Chua 2023-11-12 18:04:52 +00:00
parent c60ba82699
commit 0bdb52fd1b
3 changed files with 61 additions and 33 deletions

View file

@ -1,4 +1,5 @@
use yazi_config::keymap::Exec; use yazi_config::keymap::Exec;
use yazi_shared::CharKind;
use crate::input::Input; use crate::input::Input;
@ -14,9 +15,24 @@ impl From<()> for Opt {
impl Input { impl Input {
pub fn backward(&mut self, _: impl Into<Opt>) -> bool { pub fn backward(&mut self, _: impl Into<Opt>) -> bool {
let snap = self.snap(); let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len()); if snap.cursor == 0 {
return self.move_(0);
}
let step = Self::find_word_boundary(snap.value[..idx].chars().rev(), false, true); let idx = snap.idx(snap.cursor).unwrap_or(snap.len());
self.move_(-(step as isize)) let mut it = snap.value[..idx].chars().rev().enumerate();
let mut prev = CharKind::new(it.next().unwrap().1);
for (i, c) in it {
let c = CharKind::new(c);
if prev != CharKind::Space && prev != c {
return self.move_(-(i as isize));
}
prev = c;
}
if prev != CharKind::Space {
return self.move_(-(snap.len() as isize));
}
false
} }
} }

View file

@ -1,4 +1,5 @@
use yazi_config::keymap::Exec; use yazi_config::keymap::Exec;
use yazi_shared::CharKind;
use crate::input::{op::InputOp, Input}; use crate::input::{op::InputOp, Input};
@ -18,14 +19,27 @@ impl Input {
let opt = opt.into() as Opt; let opt = opt.into() as Opt;
let snap = self.snap(); let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len()); if snap.value.is_empty() {
return self.move_(0);
}
let step = Self::find_word_boundary( let mut it = snap.value.chars().skip(snap.cursor).enumerate();
snap.value[idx..].chars(), let mut prev = CharKind::new(it.next().unwrap().1);
// If not in vim mode or just moving (not deleting or yanking), use end_of_word. for (i, c) in it {
if let InputOp::None = snap.op { opt.end_of_word } else { false }, let c = CharKind::new(c);
opt.end_of_word, let b = if opt.end_of_word {
); prev != CharKind::Space && prev != c && i != 1
self.move_(step as isize) } else {
c != CharKind::Space && c != prev
};
if b && !matches!(snap.op, InputOp::None | InputOp::Select(_)) {
return self.move_(i as isize);
} else if b {
return self.move_(if opt.end_of_word { i - 1 } else { i } as isize);
}
prev = c;
}
self.move_(snap.len() as isize)
} }
} }

View file

@ -59,15 +59,7 @@ impl Input {
/// ///
/// Otherwise, returns how many characters to move to reach right *AFTER* the /// Otherwise, returns how many characters to move to reach right *AFTER* the
/// word boundary, or the end of the iterator. /// word boundary, or the end of the iterator.
pub(super) fn find_word_boundary( pub(super) fn find_word_boundary(input: impl Iterator<Item = char> + Clone) -> usize {
input: impl Iterator<Item = char> + Clone,
stop_before_boundary: bool,
skip_whitespace_first: bool,
) -> usize {
// If we want the *NEXT* end of word, then we want to skip the current
// character.
let input = input.skip(stop_before_boundary.into());
fn count_spaces(input: impl Iterator<Item = char>) -> usize { fn count_spaces(input: impl Iterator<Item = char>) -> usize {
// Move until we don't see any more whitespace. // Move until we don't see any more whitespace.
input.take_while(|c| CharKind::new(*c) == CharKind::Space).count() input.take_while(|c| CharKind::new(*c) == CharKind::Space).count()
@ -84,15 +76,9 @@ impl Input {
input.take_while(|c| CharKind::new(*c) == CharKind::new(prev)).count() input.take_while(|c| CharKind::new(*c) == CharKind::new(prev)).count()
} }
if skip_whitespace_first {
let spaces_count = count_spaces(input.clone()); let spaces_count = count_spaces(input.clone());
let character_count = count_characters(input.skip(spaces_count).peekable()); let character_count = count_characters(input.skip(spaces_count).peekable());
spaces_count + character_count spaces_count + character_count
} else {
let character_count = count_characters(input.clone().peekable());
let spaces_count = count_spaces(input.skip(character_count));
spaces_count + character_count
}
} }
fn delete_range(&mut self, range: impl RangeBounds<usize>) { fn delete_range(&mut self, range: impl RangeBounds<usize>) {
@ -127,8 +113,20 @@ impl Input {
Key { code: C('f'), shift: false, ctrl: true, alt: false } => self.move_(1), Key { code: C('f'), shift: false, ctrl: true, alt: false } => self.move_(1),
Key { code: C('h'), shift: false, ctrl: true, alt: false } => self.backspace(), Key { code: C('h'), shift: false, ctrl: true, alt: false } => self.backspace(),
Key { code: C('d'), shift: false, ctrl: true, alt: false } => self.forward_delete(), Key { code: C('d'), shift: false, ctrl: true, alt: false } => self.forward_delete(),
Key { code: C('b'), shift: false, ctrl: false, alt: true } => self.backward(()), Key { code: C('b'), shift: false, ctrl: false, alt: true } => {
Key { code: C('f'), shift: false, ctrl: false, alt: true } => self.forward(false), let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len());
let step = Self::find_word_boundary(snap.value[..idx].chars().rev());
self.move_(-(step as isize))
}
Key { code: C('f'), shift: false, ctrl: false, alt: true } => {
let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len());
let step = Self::find_word_boundary(snap.value[idx..].chars());
self.move_(step as isize)
}
Key { code: C('u'), shift: false, ctrl: true, alt: false } => { Key { code: C('u'), shift: false, ctrl: true, alt: false } => {
let snap = self.snap_mut(); let snap = self.snap_mut();
let end = snap.idx(snap.cursor).unwrap_or(snap.len()); let end = snap.idx(snap.cursor).unwrap_or(snap.len());
@ -146,7 +144,7 @@ impl Input {
| Key { code: Backspace, shift: false, ctrl: false, alt: true } => { | Key { code: Backspace, shift: false, ctrl: false, alt: true } => {
let snap = self.snap_mut(); let snap = self.snap_mut();
let end = snap.idx(snap.cursor).unwrap_or(snap.len()); let end = snap.idx(snap.cursor).unwrap_or(snap.len());
let start = end - Self::find_word_boundary(snap.value[..end].chars().rev(), false, false); let start = end - Self::find_word_boundary(snap.value[..end].chars().rev());
self.delete_range(start..end); self.delete_range(start..end);
true true
} }
@ -154,7 +152,7 @@ impl Input {
let snap = self.snap_mut(); let snap = self.snap_mut();
let start = snap.idx(snap.cursor).unwrap_or(snap.len()); let start = snap.idx(snap.cursor).unwrap_or(snap.len());
// Hitting this keybind `ab |cd `should give `|cd`. // Hitting this keybind `ab |cd `should give `|cd`.
let end = start + Self::find_word_boundary(snap.value[start..].chars(), false, false); let end = start + Self::find_word_boundary(snap.value[start..].chars());
self.delete_range(start..end); self.delete_range(start..end);
true true
} }