aboutsummaryrefslogtreecommitdiffstats
path: root/vim-mode/vim_mode.pl
diff options
context:
space:
mode:
authorSimon Ruderich <simon@ruderich.org>2010-10-02 14:08:44 +0000
committerSimon Ruderich <simon@ruderich.org>2010-10-02 14:08:44 +0000
commit3aade79d22d3ba9bb09f220245bffd52c57ea784 (patch)
tree15ecd72f237f727059909264d00c7c415613e658 /vim-mode/vim_mode.pl
parentvim_mode: Add :bd. (diff)
downloadirssi-scripts-3aade79d22d3ba9bb09f220245bffd52c57ea784.tar.gz
irssi-scripts-3aade79d22d3ba9bb09f220245bffd52c57ea784.zip
vim_mode: Add text-object aW.
Diffstat (limited to 'vim-mode/vim_mode.pl')
-rw-r--r--vim-mode/vim_mode.pl93
1 files changed, 89 insertions, 4 deletions
diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl
index d013f11..2adcdc9 100644
--- a/vim-mode/vim_mode.pl
+++ b/vim-mode/vim_mode.pl
@@ -17,6 +17,7 @@
# * Cursor motion: h l 0 ^ $ <space> f t F T
# * History motion: j k
# * Cursor word motion: w b ge e W gE B E
+# * Word objects (only the following work yet): aW
# * Yank and paste: y p P
# * Change and delete: c d
# * Delete at cursor: x X
@@ -788,8 +789,86 @@ sub cmd_movement_i_ {
sub cmd_movement_a_ {
my ($count, $pos, $repeat, $char) = @_;
- _warn("a_ not implemented yet");
- return;
+ my $cur_pos;
+ my $input = _input();
+
+ # aw and aW
+ if ($char eq 'w' or $char eq 'W') {
+ if ($char eq 'w') {
+
+ } elsif ($char eq 'W') {
+ while ($count-- > 0 and length($input) > $pos) {
+ if (substr($input, $pos, 1) =~ /\s/) {
+ # Any whitespace before the WORD must be removed.
+ if (not defined $cur_pos) {
+ $cur_pos = _find_regex_before($input, '\S', $pos, 0);
+ if ($cur_pos < 0) {
+ $cur_pos = 0;
+ } else {
+ $cur_pos++;
+ }
+ }
+ # Move before the WORD.
+ if (substr($input, $pos + 1) =~ /^\s+/) {
+ $pos += $+[0];
+ }
+ # And delete it.
+ if (substr($input, $pos + 1) =~ /\s/) {
+ $pos += $-[0] + 1;
+ } else {
+ $pos = length($input);
+ }
+
+ } else {
+ # Start at the beginning of this WORD.
+ if (not defined $cur_pos and $pos > 0 and
+ substr($input, $pos - 1, 1) !~ /\s/) {
+ $cur_pos = _find_regex_before($input, '\s', $pos - 1, 0);
+ if ($cur_pos < 0) {
+ $cur_pos = 0;
+ } else {
+ $cur_pos++;
+ }
+ }
+ # Delete to the end of the word.
+ if (substr($input, $pos + 1) =~ /^\S*\s+\S/) {
+ $pos += $+[0];
+ } else {
+ $pos = length($input);
+ # If we are at the end of the line, whitespace before
+ # the WORD is also deleted.
+ my $new_pos = _find_regex_before($input, '\s+', $pos, 1);
+ if (not defined $cur_pos or $cur_pos > $new_pos + 1) {
+ $cur_pos = $new_pos + 1;
+ }
+ }
+ }
+ }
+ _input_pos($pos);
+ }
+ }
+
+ return $cur_pos;
+}
+# Find regex as close as possible before the current position. If $end is true
+# the end of the match is returned, otherwise the beginning.
+sub _find_regex_before {
+ my ($input, $regex, $pos, $end) = @_;
+
+ $input = reverse $input;
+ $pos = length($input) - $pos - 1;
+ $pos = 0 if $pos < 0;
+
+ if (substr($input, $pos) =~ /$regex/) {
+ if (!$end) {
+ $pos += $-[0];
+ } else {
+ $pos += $+[0];
+ }
+ return length($input) - $pos - 1;
+ } else {
+ return -1;
+ }
}
sub cmd_movement_0 {
@@ -1575,8 +1654,14 @@ sub handle_command_cmd {
# problems with e.g. f when the search string doesn't exist).
if ($operator and $cur_pos != $new_pos) {
print "Processing operator: ", $operator if DEBUG;
- $operators->{$operator}->{func}->($cur_pos, $new_pos, $char,
- $repeat);
+ # If text-objects are used the real move character must be
+ # passed to the operator.
+ my $tmp_char = $char;
+ if ($char eq 'i_' or $char eq 'a_') {
+ $tmp_char = substr $movement, 1;
+ }
+ $operators->{$operator}->{func}->($cur_pos, $new_pos,
+ $tmp_char, $repeat);
}
# Store command, necessary for .