|
9 | 9 | match input.peek() {
|
10 | 10 | Some('d') => {
|
11 | 11 | let _ = input.next();
|
12 |
| - Some(Command::Delete) |
| 12 | + if let Some('i') = input.peek() { |
| 13 | + let _ = input.next(); |
| 14 | + match input.next() { |
| 15 | + Some(c) |
| 16 | + if is_valid_change_inside_left(c) || is_valid_change_inside_right(c) => |
| 17 | + { |
| 18 | + Some(Command::DeleteInside(*c)) |
| 19 | + } |
| 20 | + _ => None, |
| 21 | + } |
| 22 | + } else { |
| 23 | + Some(Command::Delete) |
| 24 | + } |
13 | 25 | }
|
14 | 26 | Some('p') => {
|
15 | 27 | let _ = input.next();
|
|
33 | 45 | }
|
34 | 46 | Some('c') => {
|
35 | 47 | let _ = input.next();
|
36 |
| - Some(Command::Change) |
| 48 | + if let Some('i') = input.peek() { |
| 49 | + let _ = input.next(); |
| 50 | + match input.next() { |
| 51 | + Some(c) |
| 52 | + if is_valid_change_inside_left(c) || is_valid_change_inside_right(c) => |
| 53 | + { |
| 54 | + Some(Command::ChangeInside(*c)) |
| 55 | + } |
| 56 | + _ => None, |
| 57 | + } |
| 58 | + } else { |
| 59 | + Some(Command::Change) |
| 60 | + } |
37 | 61 | }
|
38 | 62 | Some('x') => {
|
39 | 63 | let _ = input.next();
|
@@ -107,6 +131,8 @@ pub enum Command {
|
107 | 131 | HistorySearch,
|
108 | 132 | Switchcase,
|
109 | 133 | RepeatLastAction,
|
| 134 | + ChangeInside(char), |
| 135 | + DeleteInside(char), |
110 | 136 | }
|
111 | 137 |
|
112 | 138 | impl Command {
|
@@ -150,10 +176,44 @@ impl Command {
|
150 | 176 | // Whenever a motion is required to finish the command we must be in visual mode
|
151 | 177 | Self::Delete | Self::Change => vec![ReedlineOption::Edit(EditCommand::CutSelection)],
|
152 | 178 | Self::Incomplete => vec![ReedlineOption::Incomplete],
|
153 |
| - Command::RepeatLastAction => match &vi_state.previous { |
| 179 | + Self::RepeatLastAction => match &vi_state.previous { |
154 | 180 | Some(event) => vec![ReedlineOption::Event(event.clone())],
|
155 | 181 | None => vec![],
|
156 | 182 | },
|
| 183 | + Self::ChangeInside(left) if is_valid_change_inside_left(left) => { |
| 184 | + let right = bracket_for(left); |
| 185 | + vec![ |
| 186 | + ReedlineOption::Edit(EditCommand::CutLeftBefore(*left)), |
| 187 | + ReedlineOption::Edit(EditCommand::CutRightBefore(right)), |
| 188 | + ] |
| 189 | + } |
| 190 | + Self::ChangeInside(right) if is_valid_change_inside_right(right) => { |
| 191 | + let left = bracket_for(right); |
| 192 | + vec![ |
| 193 | + ReedlineOption::Edit(EditCommand::CutLeftBefore(left)), |
| 194 | + ReedlineOption::Edit(EditCommand::CutRightBefore(*right)), |
| 195 | + ] |
| 196 | + } |
| 197 | + Self::ChangeInside(_) => { |
| 198 | + vec![] |
| 199 | + } |
| 200 | + Self::DeleteInside(left) if is_valid_change_inside_left(left) => { |
| 201 | + let right = bracket_for(left); |
| 202 | + vec![ |
| 203 | + ReedlineOption::Edit(EditCommand::CutLeftBefore(*left)), |
| 204 | + ReedlineOption::Edit(EditCommand::CutRightBefore(right)), |
| 205 | + ] |
| 206 | + } |
| 207 | + Self::DeleteInside(right) if is_valid_change_inside_right(right) => { |
| 208 | + let left = bracket_for(right); |
| 209 | + vec![ |
| 210 | + ReedlineOption::Edit(EditCommand::CutLeftBefore(left)), |
| 211 | + ReedlineOption::Edit(EditCommand::CutRightBefore(*right)), |
| 212 | + ] |
| 213 | + } |
| 214 | + Self::DeleteInside(_) => { |
| 215 | + vec![] |
| 216 | + } |
157 | 217 | }
|
158 | 218 | }
|
159 | 219 |
|
@@ -276,3 +336,25 @@ impl Command {
|
276 | 336 | }
|
277 | 337 | }
|
278 | 338 | }
|
| 339 | + |
| 340 | +fn bracket_for(c: &char) -> char { |
| 341 | + match *c { |
| 342 | + '(' => ')', |
| 343 | + '[' => ']', |
| 344 | + '{' => '}', |
| 345 | + '<' => '>', |
| 346 | + ')' => '(', |
| 347 | + ']' => '[', |
| 348 | + '}' => '{', |
| 349 | + '>' => '<', |
| 350 | + _ => *c, |
| 351 | + } |
| 352 | +} |
| 353 | + |
| 354 | +pub(crate) fn is_valid_change_inside_left(c: &char) -> bool { |
| 355 | + matches!(c, '(' | '[' | '{' | '"' | '\'' | '`' | '<') |
| 356 | +} |
| 357 | + |
| 358 | +pub(crate) fn is_valid_change_inside_right(c: &char) -> bool { |
| 359 | + matches!(c, ')' | ']' | '}' | '"' | '\'' | '`' | '>') |
| 360 | +} |
0 commit comments