From bd443f482aff46d496be438da444108d7c84f49c Mon Sep 17 00:00:00 2001 From: "TechnoHouse (deephbz)" <13776377+deephbz@users.noreply.github.com> Date: Tue, 31 Dec 2024 11:45:43 +0800 Subject: [PATCH] Buf fix for cut-related commands: 's', 'd', 'c' and 'x': they should behave consistently with Vim: - 'x' should cut selection like d under visual mode but it only cut one char under cursor right now - 'c' cut selection correctly but it does not enter insert mode - get_selection bug fix: Vi mode should be inclusive: include the last char --- src/core_editor/editor.rs | 4 ++-- src/edit_mode/vi/command.rs | 19 ++++++++++++++++--- src/edit_mode/vi/mod.rs | 3 +-- src/edit_mode/vi/parser.rs | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/core_editor/editor.rs b/src/core_editor/editor.rs index 227606eb..a457e599 100644 --- a/src/core_editor/editor.rs +++ b/src/core_editor/editor.rs @@ -565,9 +565,9 @@ impl Editor { pub fn get_selection(&self) -> Option<(usize, usize)> { self.selection_anchor.map(|selection_anchor| { if self.insertion_point() > selection_anchor { - (selection_anchor, self.insertion_point()) + (selection_anchor, self.insertion_point() + 1) } else { - (self.insertion_point(), selection_anchor) + (self.insertion_point(), selection_anchor + 1) } }) } diff --git a/src/edit_mode/vi/command.rs b/src/edit_mode/vi/command.rs index f00b549b..28aeb461 100644 --- a/src/edit_mode/vi/command.rs +++ b/src/edit_mode/vi/command.rs @@ -1,4 +1,4 @@ -use super::{motion::Motion, motion::ViCharSearch, parser::ReedlineOption}; +use super::{motion::Motion, motion::ViCharSearch, parser::ReedlineOption, ViMode}; use crate::{EditCommand, ReedlineEvent, Vi}; use std::iter::Peekable; @@ -166,11 +166,24 @@ impl Command { select: false, })], Self::RewriteCurrentLine => vec![ReedlineOption::Edit(EditCommand::CutCurrentLine)], - Self::DeleteChar => vec![ReedlineOption::Edit(EditCommand::CutChar)], + Self::DeleteChar => { + if vi_state.mode == ViMode::Visual { + vec![ReedlineOption::Edit(EditCommand::CutSelection)] + } else { + vec![ReedlineOption::Edit(EditCommand::CutChar)] + } + } Self::ReplaceChar(c) => { vec![ReedlineOption::Edit(EditCommand::ReplaceChar(*c))] } - Self::SubstituteCharWithInsert => vec![ReedlineOption::Edit(EditCommand::CutChar)], + Self::SubstituteCharWithInsert => { + let result = if vi_state.mode == ViMode::Visual { + vec![ReedlineOption::Edit(EditCommand::CutSelection)] + } else { + vec![ReedlineOption::Edit(EditCommand::CutChar)] + }; + result + } Self::HistorySearch => vec![ReedlineOption::Event(ReedlineEvent::SearchHistory)], Self::Switchcase => vec![ReedlineOption::Edit(EditCommand::SwitchcaseChar)], // Whenever a motion is required to finish the command we must be in visual mode diff --git a/src/edit_mode/vi/mod.rs b/src/edit_mode/vi/mod.rs index 81fa5b04..b2621aa6 100644 --- a/src/edit_mode/vi/mod.rs +++ b/src/edit_mode/vi/mod.rs @@ -89,11 +89,10 @@ impl EditMode for Vi { self.cache.clear(); ReedlineEvent::None } else if res.is_complete(self.mode) { + let event = res.to_reedline_event(self); if let Some(mode) = res.changes_mode() { self.mode = mode; } - - let event = res.to_reedline_event(self); self.cache.clear(); event } else { diff --git a/src/edit_mode/vi/parser.rs b/src/edit_mode/vi/parser.rs index aebc7c8f..9a9c79ba 100644 --- a/src/edit_mode/vi/parser.rs +++ b/src/edit_mode/vi/parser.rs @@ -108,7 +108,8 @@ impl ParsedViSequence { | (Some(Command::RewriteCurrentLine), ParseResult::Incomplete) | (Some(Command::SubstituteCharWithInsert), ParseResult::Incomplete) | (Some(Command::HistorySearch), ParseResult::Incomplete) - | (Some(Command::Change), ParseResult::Valid(_)) => Some(ViMode::Insert), + | (Some(Command::Change), ParseResult::Valid(_)) + | (Some(Command::Change), ParseResult::Incomplete) => Some(ViMode::Insert), (Some(Command::ChangeInside(char)), ParseResult::Incomplete) if is_valid_change_inside_left(char) || is_valid_change_inside_right(char) => {