From 7f90231e08c7d3c9ddfc11cbdf946bfcafc7b449 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sun, 26 Sep 2010 01:58:35 +0200 Subject: vim_mode: Fix f,t,F,T. They are not operators! Instead they are movements which take an additional argument. --- vim-mode/vim_mode.pl | 78 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 25 deletions(-) (limited to 'vim-mode') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index d970e9e..4e7bc72 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -75,6 +75,9 @@ my $numeric_prefix = undef; # vi operators like d, c, .. my $operator = undef; +# vi movements, only used when a movement needs more than one key (like f t). +my $movement = undef; + # what Vi mode we're in. We start in insert mode. my $mode = M_INS; @@ -102,11 +105,6 @@ my $operators = { 'c' => { func => \&cmd_operator_c }, 'd' => { func => \&cmd_operator_d }, - # char movement, works like an operator - 'f' => { func => \&cmd_movement_f }, - 't' => { func => \&cmd_movement_t }, - 'F' => { func => \&cmd_movement_F }, - 'T' => { func => \&cmd_movement_T }, }; # vi-moves like w,b; they move the cursor and may get combined with an @@ -119,6 +117,11 @@ my $movements 'l' => { func => \&cmd_movement_l }, #'j' => { func => \&cmd_movement_j }, #'k' => { func => \&cmd_movement_k }, + # char movement, take an additional parameter and use $movement + 'f' => { func => \&cmd_movement_f }, + 't' => { func => \&cmd_movement_t }, + 'F' => { func => \&cmd_movement_F }, + 'T' => { func => \&cmd_movement_T }, # word movement 'w' => { func => \&cmd_movement_w }, 'b' => { func => \&cmd_movement_b }, @@ -134,25 +137,39 @@ my $movements 'A' => { func => \&cmd_movement_A }, }; +# special movements which take an additional key +my $movements_multiple = + { + 'f' => undef, + 't' => undef, + 'F' => undef, + 'T' => undef, + }; + sub cmd_operator_c { - my ($old_pos, $new_pos) = @_; + my ($old_pos, $new_pos, $move) = @_; - cmd_operator_d($old_pos, $new_pos); + cmd_operator_d($old_pos, $new_pos, $move); _update_mode(M_INS); } sub cmd_operator_d { - my ($old_pos, $new_pos) = @_; + my ($old_pos, $new_pos, $move) = @_; my $length = $new_pos - $old_pos; # We need a positive length and $old_pos must be smaller. if ($length < 0) { - my $tmp = $old_pos; $old_pos = $new_pos; - $new_pos = $tmp; $length *= -1; } + # w and x are the only movements which move one character after the + # deletion area (which is what we need), all other commands need one + # character more for correct deletion. + if ($move ne 'w' and $move ne 'x') { + $length += 1; + } + # Remove the selected string from the input. my $input = _input(); substr $input, $old_pos, $length, ''; @@ -288,7 +305,7 @@ sub cmd_movement_dollar { sub cmd_movement_x { my ($count, $pos) = @_; - cmd_operator_d($pos, $pos + $count); + cmd_operator_d($pos, $pos + $count, 'x'); } sub cmd_movement_i { @@ -456,21 +473,23 @@ sub handle_command { } else { my $char = chr($key); - if ($char =~ m/[1-9]/ || ($numeric_prefix && $char =~ m/[0-9]/)) { + + # We need to treat $movements_multiple specially as they need another + # argument. + if ($movement) { + $movement .= $char; + } + + if (!$movement && ($char =~ m/[1-9]/ || + ($numeric_prefix && $char =~ m/[0-9]/))) { print "Processing numeric prefix: $char" if DEBUG; handle_numeric_prefix($char); - # Special case for f,t,F,T as they take an additional argument - } elsif ($operator and - ($operator eq 'f' or $operator eq 't' or - $operator eq 'F' or $operator eq 'T')) { - $numeric_prefix = 1 if not $numeric_prefix; - $operators->{$operator}->{func} - ->($numeric_prefix, _input_pos(), $char); - $operator = undef; - $numeric_prefix = undef; + } elsif (!$movement && exists $movements_multiple->{$char}) { + print "Processing movement: $char" if DEBUG; + $movement = $char; - } elsif (exists $operators->{$char}) { + } elsif (!$movement && exists $operators->{$char}) { print "Processing operator: $char" if DEBUG; # Abort operator if we already have one pending. @@ -481,24 +500,33 @@ sub handle_command { $operator = $char; } - } elsif (exists $movements->{$char}) { + } elsif ($movement || exists $movements->{$char}) { print "Processing movement command: $char" if DEBUG; $numeric_prefix = 1 if not $numeric_prefix; # Execute the movement (multiple times). my $cur_pos = _input_pos(); - $movements->{$char}->{func}->($numeric_prefix, $cur_pos); + if (not $movement) { + $movements->{$char}->{func}->($numeric_prefix, $cur_pos); + } else { + # Use the real movement command (like t or f) for operator + # below. + $char = substr $movement, 0, 1; + $movements->{$char}->{func} + ->($numeric_prefix, $cur_pos, substr $movement, 1); + } my $new_pos = _input_pos(); # If we have an operator pending then run it on the handled text. if ($operator) { print "Processing operator: ", $operator if DEBUG; - $operators->{$operator}->{func}->($cur_pos, $new_pos); + $operators->{$operator}->{func}->($cur_pos, $new_pos, $char); $operator = undef; } $numeric_prefix = undef; + $movement = undef; # Start Ex mode. } elsif ($char eq ':') { -- cgit v1.2.3