diff options
author | Christian Duerr <contact@christianduerr.com> | 2023-10-20 11:33:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-20 13:33:38 +0400 |
commit | 845a5d8a8d47c233c4ed8177ecbb20b05b22118b (patch) | |
tree | 057f4c5974f60defa0c6f79060ef26e59398b1f1 /alacritty/src/event.rs | |
parent | 7ceb638ff80eca99ac63df5fd8cbb2f703d4637a (diff) | |
download | r-alacritty-845a5d8a8d47c233c4ed8177ecbb20b05b22118b.tar.gz r-alacritty-845a5d8a8d47c233c4ed8177ecbb20b05b22118b.tar.bz2 r-alacritty-845a5d8a8d47c233c4ed8177ecbb20b05b22118b.zip |
Add inline vi mode search
This patch adds inline search to vi mode using `f`/`F` and `t`/`T` as
default bindings. The behavior matches that of vim.
Fixes #7203.
Diffstat (limited to 'alacritty/src/event.rs')
-rw-r--r-- | alacritty/src/event.rs | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 1b7e280c..7bb3a83e 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -29,7 +29,7 @@ use winit::window::WindowId; use alacritty_terminal::config::LOG_TARGET_CONFIG; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; use alacritty_terminal::event_loop::Notifier; -use alacritty_terminal::grid::{Dimensions, Scroll}; +use alacritty_terminal::grid::{BidirectionalIterator, Dimensions, Scroll}; use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side}; use alacritty_terminal::selection::{Selection, SelectionType}; use alacritty_terminal::term::search::{Match, RegexSearch}; @@ -178,6 +178,27 @@ impl Default for SearchState { } } +/// Vi inline search state. +pub struct InlineSearchState { + /// Whether inline search is currently waiting for search character input. + pub char_pending: bool, + pub character: Option<char>, + + direction: Direction, + stop_short: bool, +} + +impl Default for InlineSearchState { + fn default() -> Self { + Self { + direction: Direction::Right, + char_pending: Default::default(), + stop_short: Default::default(), + character: Default::default(), + } + } +} + pub struct ActionContext<'a, N, T> { pub notifier: &'a mut N, pub terminal: &'a mut Term<T>, @@ -193,6 +214,7 @@ pub struct ActionContext<'a, N, T> { pub event_proxy: &'a EventLoopProxy<Event>, pub scheduler: &'a mut Scheduler, pub search_state: &'a mut SearchState, + pub inline_search_state: &'a mut InlineSearchState, pub font_size: &'a mut Size, pub dirty: &'a mut bool, pub occluded: &'a mut bool, @@ -839,6 +861,30 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon *self.dirty = true; } + /// Get vi inline search state. + fn inline_search_state(&mut self) -> &mut InlineSearchState { + self.inline_search_state + } + + /// Start vi mode inline search. + fn start_inline_search(&mut self, direction: Direction, stop_short: bool) { + self.inline_search_state.stop_short = stop_short; + self.inline_search_state.direction = direction; + self.inline_search_state.char_pending = true; + } + + /// Jump to the next matching character in the line. + fn inline_search_next(&mut self) { + let direction = self.inline_search_state.direction; + self.inline_search(direction); + } + + /// Jump to the next matching character in the line. + fn inline_search_previous(&mut self) { + let direction = self.inline_search_state.direction.opposite(); + self.inline_search(direction); + } + fn message(&self) -> Option<&Message> { self.message_buffer.message() } @@ -1032,6 +1078,41 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.scheduler.schedule(event, blinking_timeout_interval, false, timer_id); } + + /// Perferm vi mode inline search in the specified direction. + fn inline_search(&mut self, direction: Direction) { + let c = match self.inline_search_state.character { + Some(c) => c, + None => return, + }; + let mut buf = [0; 4]; + let search_character = c.encode_utf8(&mut buf); + + // Find next match in this line. + let vi_point = self.terminal.vi_mode_cursor.point; + let point = match direction { + Direction::Right => self.terminal.inline_search_right(vi_point, search_character), + Direction::Left => self.terminal.inline_search_left(vi_point, search_character), + }; + + // Jump to point if there's a match. + if let Ok(mut point) = point { + if self.inline_search_state.stop_short { + let grid = self.terminal.grid(); + point = match direction { + Direction::Right => { + grid.iter_from(point).prev().map_or(point, |cell| cell.point) + }, + Direction::Left => { + grid.iter_from(point).next().map_or(point, |cell| cell.point) + }, + }; + } + + self.terminal.vi_goto_point(point); + self.mark_dirty(); + } + } } /// Identified purpose of the touch input. |