Simplify the code

This commit is contained in:
sxyazi 2023-11-14 01:55:43 +08:00
parent 0bdb52fd1b
commit 342e0bbf46
No known key found for this signature in database
3 changed files with 53 additions and 50 deletions

View file

@ -8,9 +8,6 @@ pub struct Opt;
impl From<&Exec> for Opt { impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self } fn from(_: &Exec) -> Self { Self }
} }
impl From<()> for Opt {
fn from(_: ()) -> Self { Self }
}
impl Input { impl Input {
pub fn backward(&mut self, _: impl Into<Opt>) -> bool { pub fn backward(&mut self, _: impl Into<Opt>) -> bool {

View file

@ -10,9 +10,6 @@ pub struct Opt {
impl From<&Exec> for Opt { impl From<&Exec> for Opt {
fn from(e: &Exec) -> Self { Self { end_of_word: e.named.contains_key("end-of-word") } } fn from(e: &Exec) -> Self { Self { end_of_word: e.named.contains_key("end-of-word") } }
} }
impl From<bool> for Opt {
fn from(end_of_word: bool) -> Self { Self { end_of_word } }
}
impl Input { impl Input {
pub fn forward(&mut self, opt: impl Into<Opt>) -> bool { pub fn forward(&mut self, opt: impl Into<Opt>) -> bool {

View file

@ -59,37 +59,39 @@ 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(input: impl Iterator<Item = char> + Clone) -> usize { fn find_word_boundary(input: impl Iterator<Item = char> + Clone) -> usize {
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()
} }
fn count_characters(mut input: std::iter::Peekable<impl Iterator<Item = char>>) -> usize { fn count_characters(mut input: impl Iterator<Item = char>) -> usize {
// Determine the current character class. // Determine the current character class.
let prev = input.peek().cloned(); let first = match input.next() {
let Some(prev) = prev else { Some(c) => CharKind::new(c),
return 0; None => return 0,
}; };
// Move until we see a different character class or the end of the iterator. // Move until we see a different character class or the end of the iterator.
input.take_while(|c| CharKind::new(*c) == CharKind::new(prev)).count() input.take_while(|c| CharKind::new(*c) == first).count() + 1
} }
let spaces_count = count_spaces(input.clone()); let spaces = count_spaces(input.clone());
let character_count = count_characters(input.skip(spaces_count).peekable()); spaces + count_characters(input.skip(spaces))
spaces_count + character_count
} }
fn delete_range(&mut self, range: impl RangeBounds<usize>) { fn delete_range(&mut self, range: impl RangeBounds<usize>) -> bool {
let snap = self.snap_mut(); let snap = self.snap_mut();
snap.cursor = match range.start_bound() { snap.cursor = match range.start_bound() {
std::ops::Bound::Included(i) => *i, std::ops::Bound::Included(i) => *i,
std::ops::Bound::Excluded(i) => i + 1, std::ops::Bound::Excluded(i) => i + 1,
std::ops::Bound::Unbounded => 0, std::ops::Bound::Unbounded => 0,
}; };
snap.value.drain(range); if snap.value.drain(range).next().is_some() {
self.flush_value(); self.flush_value();
return true;
}
false
} }
pub fn type_(&mut self, key: &Key) -> bool { pub fn type_(&mut self, key: &Key) -> bool {
@ -102,17 +104,26 @@ impl Input {
return self.type_str(c.encode_utf8(&mut bits)); return self.type_str(c.encode_utf8(&mut bits));
} }
use KeyCode::{Backspace, Char as C, Delete}; use KeyCode::{Backspace, Char as C};
match key { match key {
Key { code: Backspace, shift: false, ctrl: false, alt: false } => self.backspace(), // Move to the start of the line
// Handle Emacs-style keybindings.
Key { code: C('a'), shift: false, ctrl: true, alt: false } => self.move_(isize::MIN), Key { code: C('a'), shift: false, ctrl: true, alt: false } => self.move_(isize::MIN),
// Move to the end of the line
Key { code: C('e'), shift: false, ctrl: true, alt: false } => self.move_(isize::MAX), Key { code: C('e'), shift: false, ctrl: true, alt: false } => self.move_(isize::MAX),
// Move back a character
Key { code: C('b'), shift: false, ctrl: true, alt: false } => self.move_(-1), Key { code: C('b'), shift: false, ctrl: true, alt: false } => self.move_(-1),
// Move forward a character
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),
// Delete the character before the cursor
Key { code: Backspace, shift: false, ctrl: false, alt: false } => self.backspace(),
Key { code: C('h'), shift: false, ctrl: true, alt: false } => self.backspace(), Key { code: C('h'), shift: false, ctrl: true, alt: false } => self.backspace(),
// Delete the character under the cursor
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(),
// Move back to the start of the current or previous word
Key { code: C('b'), shift: false, ctrl: false, alt: true } => { Key { code: C('b'), shift: false, ctrl: false, alt: true } => {
let snap = self.snap(); let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len()); let idx = snap.idx(snap.cursor).unwrap_or(snap.len());
@ -120,61 +131,46 @@ impl Input {
let step = Self::find_word_boundary(snap.value[..idx].chars().rev()); let step = Self::find_word_boundary(snap.value[..idx].chars().rev());
self.move_(-(step as isize)) self.move_(-(step as isize))
} }
// Move forward to the end of the next word
Key { code: C('f'), shift: false, ctrl: false, alt: true } => { Key { code: C('f'), shift: false, ctrl: false, alt: true } => {
let snap = self.snap(); let snap = self.snap();
let idx = snap.idx(snap.cursor).unwrap_or(snap.len()); let step = Self::find_word_boundary(snap.value.chars().skip(snap.cursor));
let step = Self::find_word_boundary(snap.value[idx..].chars());
self.move_(step as isize) self.move_(step as isize)
} }
// Kill backwards to the start of the line
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());
self.delete_range(..end); self.delete_range(..end)
true
} }
Key { code: C('k'), shift: false, ctrl: true, alt: false } // Kill forwards to the end of the line
| Key { code: Delete, shift: false, ctrl: false, alt: false } => { Key { code: C('k'), shift: false, ctrl: true, alt: false } => {
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());
self.delete_range(start..); self.delete_range(start..)
true
} }
// Kill backwards to the start of the current word
Key { code: C('w'), shift: false, ctrl: true, alt: false } Key { code: C('w'), shift: false, ctrl: true, alt: false }
| 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()); let start = end - Self::find_word_boundary(snap.value[..end].chars().rev());
self.delete_range(start..end); self.delete_range(start..end)
true
} }
// Kill forwards to the end of the current word
Key { code: C('d'), shift: false, ctrl: false, alt: true } => { Key { code: C('d'), shift: false, ctrl: false, alt: true } => {
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`.
let end = start + Self::find_word_boundary(snap.value[start..].chars()); let end = start + Self::find_word_boundary(snap.value[start..].chars());
self.delete_range(start..end); self.delete_range(start..end)
true
} }
_ => false, _ => false,
} }
} }
pub fn forward_delete(&mut self) -> bool {
let snap = self.snaps.current_mut();
// Return false when there is no character on the right to delete.
// Note that the cursor can be at index `snap.value.len()` when in
// edit mode, but it should be strictly less for forward deletion.
if snap.cursor >= snap.value.len() {
return false;
} else {
snap.value.remove(snap.idx(snap.cursor).unwrap());
}
self.move_(0);
self.flush_value();
true
}
pub fn type_str(&mut self, s: &str) -> bool { pub fn type_str(&mut self, s: &str) -> bool {
let snap = self.snaps.current_mut(); let snap = self.snaps.current_mut();
if snap.cursor < 1 { if snap.cursor < 1 {
@ -201,6 +197,19 @@ impl Input {
true true
} }
pub fn forward_delete(&mut self) -> bool {
let snap = self.snaps.current_mut();
if snap.cursor >= snap.value.len() {
return false;
} else {
snap.value.remove(snap.idx(snap.cursor).unwrap());
}
self.move_(0);
self.flush_value();
true
}
pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool { pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool {
let old = self.snap().clone(); let old = self.snap().clone();
let snap = self.snaps.current_mut(); let snap = self.snaps.current_mut();