diff options
-rw-r--r-- | vim-mode/vim_mode.pl | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index d441afc..4fa4120 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -80,6 +80,12 @@ my $movement = undef; # what Vi mode we're in. We start in insert mode. my $mode = M_INS; +# vi registers, at the moment only the default yank register (") is used +my $registers + = { + '"' => '' + }; + # index into the history list (for j,k) my $history_index = undef; @@ -106,6 +112,7 @@ my $operators = { 'c' => { func => \&cmd_operator_c }, 'd' => { func => \&cmd_operator_d }, + 'y' => { func => \&cmd_operator_y }, }; # vi-moves like w,b; they move the cursor and may get combined with an @@ -137,6 +144,9 @@ my $movements 'I' => { func => \&cmd_movement_I }, 'a' => { func => \&cmd_movement_a }, 'A' => { func => \&cmd_movement_A }, + # paste + 'p' => { func => \&cmd_movement_p }, + 'P' => { func => \&cmd_movement_P }, }; # special movements which take an additional key @@ -154,10 +164,35 @@ sub cmd_operator_c { cmd_operator_d($old_pos, $new_pos, $move); _update_mode(M_INS); } - sub cmd_operator_d { my ($old_pos, $new_pos, $move) = @_; + my ($pos, $length) = _get_pos_and_length($old_pos, $new_pos, $move); + + # Remove the selected string from the input. + my $input = _input(); + substr $input, $pos, $length, ''; + _input($input); + + # Move the cursor at the right position. + _input_pos($pos); +} +sub cmd_operator_y { + my ($old_pos, $new_pos, $move) = @_; + + my ($pos, $length) = _get_pos_and_length($old_pos, $new_pos, $move); + + # Extract the selected string and put it in the " register. + my $input = _input(); + my $string = substr $input, $pos, $length; + $registers->{'"'} = $string; + print "Yanked: $string" if DEBUG; + + _input_pos($old_pos); +} +sub _get_pos_and_length { + 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) { @@ -172,15 +207,10 @@ sub cmd_operator_d { $length += 1; } - # Remove the selected string from the input. - my $input = _input(); - substr $input, $old_pos, $length, ''; - _input($input); - - # Move the cursor at the right position. - _input_pos($old_pos); + return ($old_pos, $length); } + # later history (down) sub cmd_movement_j { my ($count, $pos) = @_; @@ -368,6 +398,28 @@ sub cmd_movement_A { _update_mode(M_INS); } +sub cmd_movement_p { + my ($count, $pos) = @_; + _paste_at_position($count, $pos + 1); +} +sub cmd_movement_P { + my ($count, $pos) = @_; + _paste_at_position($count, $pos); +} +sub _paste_at_position { + my ($count, $pos) = @_; + + return if not $registers->{'"'}; + + my $string = $registers->{'"'} x $count; + + my $input = _input(); + substr($input, $pos, 0) = $string; + _input($input); + + _input_pos($pos - 1 + length $string); +} + sub cmd_ex_command { my $arg_str = join '', @ex_buf; if ($arg_str =~ m|s/(.+)/(.*)/([ig]*)|) { |