From 31603ee5759187fddc75c0372313b65d19709147 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] fix: align cut-related commands behavior with Vim standards --- src/core_editor/editor.rs | 5 +++-- src/edit_mode/vi/command.rs | 18 +++++++++++++++--- 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..5caa00b3 100644 --- a/src/core_editor/editor.rs +++ b/src/core_editor/editor.rs @@ -564,10 +564,11 @@ impl Editor { /// The range is guaranteed to be ascending. pub fn get_selection(&self) -> Option<(usize, usize)> { self.selection_anchor.map(|selection_anchor| { + let buffer_len = self.line_buffer.len(); if self.insertion_point() > selection_anchor { - (selection_anchor, self.insertion_point()) + (selection_anchor, (self.insertion_point() + 1).min(buffer_len)) } else { - (self.insertion_point(), selection_anchor) + (self.insertion_point(), (selection_anchor + 1).min(buffer_len)) } }) } diff --git a/src/edit_mode/vi/command.rs b/src/edit_mode/vi/command.rs index f00b549b..6bbddcd9 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,23 @@ 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 => { + if vi_state.mode == ViMode::Visual { + vec![ReedlineOption::Edit(EditCommand::CutSelection)] + } else { + vec![ReedlineOption::Edit(EditCommand::CutChar)] + } + } 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) => {