From e9b966e96494d5be7aa9cd13159668ee1351713d Mon Sep 17 00:00:00 2001 From: Matei Stroia Date: Thu, 28 May 2026 21:42:10 +0300 Subject: [PATCH] fix(vi): enter visual mode through command --- src/core_editor/editor.rs | 5 +++++ src/edit_mode/vi/command.rs | 9 +++++++++ src/edit_mode/vi/mod.rs | 5 ----- src/edit_mode/vi/parser.rs | 3 +++ src/enums.rs | 10 +++++++--- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/core_editor/editor.rs b/src/core_editor/editor.rs index 0d7673ba..a5fa4fa0 100644 --- a/src/core_editor/editor.rs +++ b/src/core_editor/editor.rs @@ -138,6 +138,7 @@ impl Editor { self.move_left_until_char(*c, true, true, *select) } EditCommand::SelectAll => self.select_all(), + EditCommand::SelectChar => self.select_char(), EditCommand::CutSelection => self.cut_selection_to_cut_buffer(), EditCommand::CopySelection => self.copy_selection_to_cut_buffer(), EditCommand::Paste => self.paste_cut_buffer(), @@ -642,6 +643,10 @@ impl Editor { self.line_buffer.move_to_end(); } + fn select_char(&mut self) { + self.update_selection_anchor(true); + } + #[cfg(feature = "system_clipboard")] fn cut_selection_to_system(&mut self) { if let Some((start, end)) = self.get_selection() { diff --git a/src/edit_mode/vi/command.rs b/src/edit_mode/vi/command.rs index 18999e5c..cf9789ba 100644 --- a/src/edit_mode/vi/command.rs +++ b/src/edit_mode/vi/command.rs @@ -78,6 +78,13 @@ where let _ = input.next(); Some(Command::EnterViAppend) } + Some('v') => { + let _ = input.next(); + match mode { + ViMode::Normal => Some(Command::EnterViVisual), + _ => None, + } + } Some('u') => { let _ = input.next(); Some(Command::Undo) @@ -185,6 +192,7 @@ pub enum Command { PasteBefore, EnterViAppend, EnterViInsert, + EnterViVisual, Undo, ChangeToLineEnd, DeleteToEnd, @@ -228,6 +236,7 @@ impl Command { Self::EnterViAppend => vec![ReedlineOption::Edit(EditCommand::MoveRight { select: false, })], + Self::EnterViVisual => vec![ReedlineOption::Edit(EditCommand::SelectChar)], Self::NewlineAbove => vec![ReedlineOption::Edit(EditCommand::InsertNewlineAbove)], Self::NewlineBelow => vec![ReedlineOption::Edit(EditCommand::InsertNewlineBelow)], Self::PasteAfter => vec![ReedlineOption::Edit(EditCommand::PasteCutBufferAfter)], diff --git a/src/edit_mode/vi/mod.rs b/src/edit_mode/vi/mod.rs index 721e45d9..d9118185 100644 --- a/src/edit_mode/vi/mod.rs +++ b/src/edit_mode/vi/mod.rs @@ -78,11 +78,6 @@ impl EditMode for Vi { Event::Key(KeyEvent { code, modifiers, .. }) => match (self.mode, modifiers, code) { - (ViMode::Normal, KeyModifiers::NONE, KeyCode::Char('v')) => { - self.cache.clear(); - self.mode = ViMode::Visual; - ReedlineEvent::Multiple(vec![ReedlineEvent::Esc, ReedlineEvent::Repaint]) - } (ViMode::Normal | ViMode::Visual, modifier, KeyCode::Char(c)) => { let c = c.to_ascii_lowercase(); diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index da0839cd..3eb5595a 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -115,6 +115,9 @@ impl ParsedViSequence { (Some(Command::Delete), ParseResult::Incomplete) if mode == ViMode::Visual => { Some(ViMode::Normal) } + (Some(Command::EnterViVisual), ParseResult::Incomplete) if mode == ViMode::Normal => { + Some(ViMode::Visual) + } (Some(Command::ChangeInsidePair { .. }), _) => Some(ViMode::Insert), (Some(Command::ChangeTextObject { .. }), _) => Some(ViMode::Insert), (Some(Command::Delete), ParseResult::Incomplete) diff --git a/src/enums.rs b/src/enums.rs index 160c9e25..eb1869f6 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -384,6 +384,9 @@ pub enum EditCommand { /// Select whole input buffer SelectAll, + /// Select grapheme under cursor, + SelectChar, + /// Cut selection to local buffer CutSelection, @@ -536,9 +539,10 @@ impl EditCommand { | EditCommand::MoveLeftBefore { select, .. } => { EditType::MoveCursor { select: *select } } - EditCommand::SwapCursorAndAnchor => EditType::MoveCursor { select: true }, - - EditCommand::SelectAll => EditType::MoveCursor { select: true }, + // Selection + EditCommand::SwapCursorAndAnchor | EditCommand::SelectAll | EditCommand::SelectChar => { + EditType::MoveCursor { select: true } + } // Text edits EditCommand::InsertChar(_) | EditCommand::Backspace