Skip to content

Commit

Permalink
Implemented VI mode change inside and delete inside functionality (#844)
Browse files Browse the repository at this point in the history
* Implemented change in and delete in functionality

* only allow certain chars for change in

* added <

* added clippy feedback

* added > mapping for <

* make change inside work with left or right brackets

* Don't switch to insert mode on an invalid ChangeInside character

* Fixed delete case, I was comparing right side twice
  • Loading branch information
ayax79 authored Oct 17, 2024
1 parent 4d8b8ce commit 5dd7e0e
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
88 changes: 85 additions & 3 deletions src/edit_mode/vi/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ where
match input.peek() {
Some('d') => {
let _ = input.next();
Some(Command::Delete)
if let Some('i') = input.peek() {
let _ = input.next();
match input.next() {
Some(c)
if is_valid_change_inside_left(c) || is_valid_change_inside_right(c) =>
{
Some(Command::DeleteInside(*c))
}
_ => None,
}
} else {
Some(Command::Delete)
}
}
Some('p') => {
let _ = input.next();
Expand All @@ -33,7 +45,19 @@ where
}
Some('c') => {
let _ = input.next();
Some(Command::Change)
if let Some('i') = input.peek() {
let _ = input.next();
match input.next() {
Some(c)
if is_valid_change_inside_left(c) || is_valid_change_inside_right(c) =>
{
Some(Command::ChangeInside(*c))
}
_ => None,
}
} else {
Some(Command::Change)
}
}
Some('x') => {
let _ = input.next();
Expand Down Expand Up @@ -107,6 +131,8 @@ pub enum Command {
HistorySearch,
Switchcase,
RepeatLastAction,
ChangeInside(char),
DeleteInside(char),
}

impl Command {
Expand Down Expand Up @@ -150,10 +176,44 @@ impl Command {
// Whenever a motion is required to finish the command we must be in visual mode
Self::Delete | Self::Change => vec![ReedlineOption::Edit(EditCommand::CutSelection)],
Self::Incomplete => vec![ReedlineOption::Incomplete],
Command::RepeatLastAction => match &vi_state.previous {
Self::RepeatLastAction => match &vi_state.previous {
Some(event) => vec![ReedlineOption::Event(event.clone())],
None => vec![],
},
Self::ChangeInside(left) if is_valid_change_inside_left(left) => {
let right = bracket_for(left);
vec![
ReedlineOption::Edit(EditCommand::CutLeftBefore(*left)),
ReedlineOption::Edit(EditCommand::CutRightBefore(right)),
]
}
Self::ChangeInside(right) if is_valid_change_inside_right(right) => {
let left = bracket_for(right);
vec![
ReedlineOption::Edit(EditCommand::CutLeftBefore(left)),
ReedlineOption::Edit(EditCommand::CutRightBefore(*right)),
]
}
Self::ChangeInside(_) => {
vec![]
}
Self::DeleteInside(left) if is_valid_change_inside_left(left) => {
let right = bracket_for(left);
vec![
ReedlineOption::Edit(EditCommand::CutLeftBefore(*left)),
ReedlineOption::Edit(EditCommand::CutRightBefore(right)),
]
}
Self::DeleteInside(right) if is_valid_change_inside_right(right) => {
let left = bracket_for(right);
vec![
ReedlineOption::Edit(EditCommand::CutLeftBefore(left)),
ReedlineOption::Edit(EditCommand::CutRightBefore(*right)),
]
}
Self::DeleteInside(_) => {
vec![]
}
}
}

Expand Down Expand Up @@ -276,3 +336,25 @@ impl Command {
}
}
}

fn bracket_for(c: &char) -> char {
match *c {
'(' => ')',
'[' => ']',
'{' => '}',
'<' => '>',
')' => '(',
']' => '[',
'}' => '{',
'>' => '<',
_ => *c,
}
}

pub(crate) fn is_valid_change_inside_left(c: &char) -> bool {
matches!(c, '(' | '[' | '{' | '"' | '\'' | '`' | '<')
}

pub(crate) fn is_valid_change_inside_right(c: &char) -> bool {
matches!(c, ')' | ']' | '}' | '"' | '\'' | '`' | '>')
}
9 changes: 8 additions & 1 deletion src/edit_mode/vi/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use super::command::{parse_command, Command};
use super::command::{
is_valid_change_inside_left, is_valid_change_inside_right, parse_command, Command,
};
use super::motion::{parse_motion, Motion};
use crate::{edit_mode::vi::ViMode, EditCommand, ReedlineEvent, Vi};
use std::iter::Peekable;
Expand Down Expand Up @@ -107,6 +109,11 @@ impl ParsedViSequence {
| (Some(Command::SubstituteCharWithInsert), ParseResult::Incomplete)
| (Some(Command::HistorySearch), ParseResult::Incomplete)
| (Some(Command::Change), ParseResult::Valid(_)) => Some(ViMode::Insert),
(Some(Command::ChangeInside(char)), ParseResult::Incomplete)
if is_valid_change_inside_left(char) || is_valid_change_inside_right(char) =>
{
Some(ViMode::Insert)
}
(Some(Command::Delete), ParseResult::Incomplete) => Some(ViMode::Normal),
_ => None,
}
Expand Down

0 comments on commit 5dd7e0e

Please sign in to comment.