diff --git a/crates/shrs_line/src/vi.rs b/crates/shrs_line/src/vi.rs index 5d3bd5d2..e1382995 100644 --- a/crates/shrs_line/src/vi.rs +++ b/crates/shrs_line/src/vi.rs @@ -3,7 +3,7 @@ use arboard::Clipboard; use shrs_utils::cursor_buffer::{CursorBuffer, Location, Result}; use shrs_vi::{Action, Motion}; -use crate::line::LineMode; +use crate::{completion::CompletionCtx, line::LineMode}; /// Extension trait to [CursorBuffer] that enables the execution of vi motions pub trait ViCursorBuffer { @@ -14,13 +14,29 @@ pub trait ViCursorBuffer { impl ViCursorBuffer for CursorBuffer { fn motion_to_loc(&self, motion: Motion) -> Result { match motion { - Motion::Find(c) => { + Motion::Find { ch, back, to } => { // if current char is character we are looking for go to next one let offset = match self.char_at(Location::Cursor()) { - Some(cur_char) if cur_char == c => Location::After(), + Some(cur_char) if cur_char == ch => Location::After(), _ => Location::Cursor(), }; - Ok(Location::FindChar(self, offset, c).unwrap_or_default()) + + let mut loc = if back { + Location::FindCharBack(self, offset, ch).unwrap_or_default() + } else { + Location::FindChar(self, offset, ch).unwrap_or_default() + }; + + if to && loc != Location::Cursor() { + loc = loc + + if back { + Location::After() + } else { + Location::Before() + }; + } + + Ok(loc) }, Motion::Left => Ok(Location::Before()), Motion::Right => Ok(Location::After()), @@ -110,7 +126,7 @@ impl ViCursorBuffer for CursorBuffer { | Motion::Word | Motion::WordPunc | Motion::BackWord - | Motion::Find(_) => { + | Motion::Find { .. } => { self.move_cursor(self.motion_to_loc(motion)?)?; }, _ => (), @@ -126,7 +142,7 @@ impl ViCursorBuffer for CursorBuffer { | Motion::Word | Motion::WordPunc | Motion::BackWord - | Motion::Find(_) => { + | Motion::Find { .. } => { self.delete(Location::Cursor(), self.motion_to_loc(motion)?)?; }, _ => (), diff --git a/crates/shrs_vi/src/ast.rs b/crates/shrs_vi/src/ast.rs index 9e7120f5..e199f013 100644 --- a/crates/shrs_vi/src/ast.rs +++ b/crates/shrs_vi/src/ast.rs @@ -18,7 +18,14 @@ pub enum Motion { End, /// Select entire line (for Move action this behaves same as End) All, - Find(char), + /// Search forward/backward for/to character + /// + /// Encapsulates `f`, `F`, `t`, and `T` + Find { + ch: char, + back: bool, + to: bool, + }, } #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/crates/shrs_vi/src/grammar.lalrpop b/crates/shrs_vi/src/grammar.lalrpop index 2aae1f25..3bef1723 100644 --- a/crates/shrs_vi/src/grammar.lalrpop +++ b/crates/shrs_vi/src/grammar.lalrpop @@ -21,7 +21,10 @@ pub Motion: Motion = { "$" => Motion::End, "^" => Motion::Start, "0" => Motion::Start, // currently implementing 0 as same as ^ - "f" => Motion::Find(c.chars().next().unwrap()), + "f" => Motion::Find { ch: c.chars().next().unwrap(), back: false, to: false }, + "F" => Motion::Find { ch: c.chars().next().unwrap(), back: true, to: false }, + "t" => Motion::Find { ch: c.chars().next().unwrap(), back: false, to: true}, + "T" => Motion::Find { ch: c.chars().next().unwrap(), back: true, to: true }, }; pub Action: Action = {