From 38f9d6cd9bee0940367500ae0223b2320edf80c2 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Fri, 8 Oct 2010 22:27:33 +0200 Subject: vim_mode: :map supports in {rhs}. --- vim-mode/vim_mode.pl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 5d6dfe1..07968d4 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -82,14 +82,15 @@ # # {lhs} is the key combination to be mapped, {rhs} the target. The <> notation # is used (e.g. is Ctrl-F), case is ignored. Supported <> keys: -# -, , , , . Mapping ex-mode and irssi commands -# is supported. Only default mappings can be used in {rhs}. +# -, , , , , . Mapping ex-mode and irssi +# commands is supported. Only default mappings can be used in {rhs}. # Examples: # :map w W # to remap w to work like W # :map gb :bnext # to map gb to call :bnext # :map gB :bprev # :map /clear # map Ctrl-L to irssi command /clear # :map /window goto 1 +# :map - disable , it does nothing now # # # The following irssi settings are available: @@ -243,6 +244,8 @@ sub C_INSERT () { 4 } sub C_EX () { 5 } # irssi commands sub C_IRSSI () { 6 } +# does nothing +sub C_NOP () { 7 } # word and non-word regex, keep in sync with setup_changed()! my $word = qr/[\w_]/o; @@ -1598,6 +1601,12 @@ sub ex_map { func => substr($rhs, 1), type => C_IRSSI, }; + # does nothing + } elsif (lc $rhs eq '') { + $command = { char => '', + func => undef, + type => C_NOP, + }; # command-mode command } else { $rhs = _parse_mapping($2); @@ -2044,6 +2053,10 @@ sub handle_command_cmd { print "Processing irssi-command: $map->{char} ($cmd->{char})" if DEBUG; Irssi::command($cmd->{func}); return 1; # call _stop(); + # does nothing. + } elsif ($cmd->{type} == C_NOP) { + print "Processing : $map->{char}" if DEBUG; + return 1; # call _stop(); } # text-objects (i a) are simulated with $movement -- cgit v1.2.3 From e369746edd750d429fc1c98f798350f811709dc7 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Fri, 8 Oct 2010 22:33:05 +0200 Subject: vim_mode: Update documentation. --- vim-mode/vim_mode.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 07968d4..3a2bdec 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -67,7 +67,7 @@ # :bp[rev] - switch to previous window # * Close window: :bd[elete] # * Display windows: :ls :buffers -# * Display registers: :reg[isters] :di[splay] {args} +# * Display registers: :reg[isters] {args} :di[splay] {args} # * Display undolist: :undol[ist] (mostly used for debugging) # * Source files :so[urce] - only sources vim_moderc at the moment, # {file} not supported @@ -85,10 +85,10 @@ # -, , , , , . Mapping ex-mode and irssi # commands is supported. Only default mappings can be used in {rhs}. # Examples: -# :map w W # to remap w to work like W -# :map gb :bnext # to map gb to call :bnext +# :map w W - to remap w to work like W +# :map gb :bnext - to map gb to call :bnext # :map gB :bprev -# :map /clear # map Ctrl-L to irssi command /clear +# :map /clear - map Ctrl-L to irssi command /clear # :map /window goto 1 # :map - disable , it does nothing now # -- cgit v1.2.3 From d2263ffcb0d32517a60c3093e87702179cff5a9d Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Fri, 8 Oct 2010 22:58:22 +0200 Subject: vim_mode: Add :mkv[imrc]. --- vim-mode/vim_mode.pl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 3a2bdec..f18fb09 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -73,6 +73,7 @@ # {file} not supported # * Mappings: :map - display custom mappings # :map {lhs} {rhs} - add mapping +# * Save mappings: :mkv[imrc] - like in Vim, but [file] not supported # * Substitute: :s/// - i and g are supported as flags, only /// can be # used as separator, uses Perl regex instead of # Vim regex @@ -383,6 +384,8 @@ my $commands_ex map => { char => ':map', func => \&ex_map, type => C_EX }, source => { char => ':source', func => \&ex_source, type => C_EX }, so => { char => ':so', func => \&ex_source, type => C_EX }, + mkvimrc => { char => ':mkvimrc', func => \&ex_mkvimrc, type => C_EX }, + mkv => { char => ':mkv', func => \&ex_mkvimrc, type => C_EX }, }; # MAPPINGS @@ -1700,6 +1703,29 @@ sub ex_source { } } +sub ex_mkvimrc { + # :mkv[imrc], [file] not supported + + my $vim_moderc = Irssi::get_irssi_dir(). '/vim_moderc'; + if (-f $vim_moderc) { + return _warn_ex('mkvimrc', "$vim_moderc already exists"); + } + + open my $file, '>', $vim_moderc or return; + + # copied from ex_map() + foreach my $key (sort keys %$maps) { + my $map = $maps->{$key}; + my $cmd = $map->{cmd}; + if (defined $cmd) { + next if $map->{char} eq $cmd->{char}; # skip default mappings + print $file "$map->{char} $cmd->{char}\n"; + } + } + + close $file; +} + sub _warn_ex { my ($command, $description) = @_; my $message = "Error in ex-mode command $command"; -- cgit v1.2.3 From ff5fb6c40953421e40f4118473547096474f35de Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 01:17:49 +0200 Subject: vim_mode: Fix :map with ex-commands. Broken in d736f605126e368124b3ff8ed4db5b28f83b650f. --- vim-mode/vim_mode.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index f18fb09..065411e 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -2072,7 +2072,7 @@ sub handle_command_cmd { # ex-mode command doesn't need any additional arguments. if ($cmd->{type} == C_EX) { print "Processing ex-command: $map->{char} ($cmd->{char})" if DEBUG; - $cmd->{func}->($cmd->{char}); + $cmd->{func}->(substr $cmd->{char}, 1); return 1; # call _stop() # As can irssi commands. } elsif ($cmd->{type} == C_IRSSI) { -- cgit v1.2.3 From 3389ded1e95cb545ac83f5c8194ef4c0dbd43429 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 01:20:03 +0200 Subject: vim_mode: Fix :mkv[imrc]. --- vim-mode/vim_mode.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 065411e..6f219dc 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -1719,7 +1719,7 @@ sub ex_mkvimrc { my $cmd = $map->{cmd}; if (defined $cmd) { next if $map->{char} eq $cmd->{char}; # skip default mappings - print $file "$map->{char} $cmd->{char}\n"; + print $file "map $map->{char} $cmd->{char}\n"; } } -- cgit v1.2.3 From da1f8fac4198a8fa88f9e5e61e1fd1283b914b50 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 01:29:08 +0200 Subject: vim_moderc: Add [!] to :mkv[imrc]. --- vim-mode/vim_mode.pl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 6f219dc..575d697 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -73,7 +73,7 @@ # {file} not supported # * Mappings: :map - display custom mappings # :map {lhs} {rhs} - add mapping -# * Save mappings: :mkv[imrc] - like in Vim, but [file] not supported +# * Save mappings: :mkv[imrc][!] - like in Vim, but [file] not supported # * Substitute: :s/// - i and g are supported as flags, only /// can be # used as separator, uses Perl regex instead of # Vim regex @@ -1704,10 +1704,12 @@ sub ex_source { } sub ex_mkvimrc { - # :mkv[imrc], [file] not supported + my ($arg_str) = @_; + + # :mkv[imrc][!], [file] not supported my $vim_moderc = Irssi::get_irssi_dir(). '/vim_moderc'; - if (-f $vim_moderc) { + if (-f $vim_moderc and $arg_str !~ /^mkv(?:imrc)?!$/) { return _warn_ex('mkvimrc', "$vim_moderc already exists"); } -- cgit v1.2.3 From a676f809891739c143f52c52c72e28ef296ccc15 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 01:57:10 +0200 Subject: vim_mode: Fix vim_mode.pl crash with invalid regex in :b. --- vim-mode/vim_mode.pl | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 575d697..4eacf55 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -1520,10 +1520,16 @@ sub ex_buffer { Irssi::command('window last'); # Go to best regex matching window. } else { - my $matches = _matching_windows($buffer); - if (scalar @$matches > 0) { - $window = @$matches[0]->{window}; - $item = @$matches[0]->{item}; + eval { + my $matches = _matching_windows($buffer); + if (scalar @$matches > 0) { + $window = @$matches[0]->{window}; + $item = @$matches[0]->{item}; + } + }; + # Catch errors in /$buffer/ regex. + if ($@) { + _warn($@); } } @@ -1831,8 +1837,14 @@ sub b_windows_cb { my $buffer = $1; if ($buffer !~ /^[0-9]$/ and $buffer ne '#') { # Display matching windows. - my $matches = _matching_windows($buffer); - $windows = join ',', map { $_->{text} } @$matches; + eval { + my $matches = _matching_windows($buffer); + $windows = join ',', map { $_->{text} } @$matches; + }; + # Catch errors in /$buffer/ regex. + if ($@) { + _warn($@); + } } } -- cgit v1.2.3 From 2fc2e4fb9822362c9a94e3222ca5e4d10813faf3 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 02:27:17 +0200 Subject: vim_mode: Remove unnecessary sub cmd_space(), use cmd_l(). --- vim-mode/vim_mode.pl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 4eacf55..9cc1ae4 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -269,7 +269,7 @@ my $commands # arrow like movement h => { char => 'h', func => \&cmd_h, type => C_NORMAL }, l => { char => 'l', func => \&cmd_l, type => C_NORMAL }, - ' ' => { char => '', func => \&cmd_space, type => C_NORMAL }, + ' ' => { char => '', func => \&cmd_l, type => C_NORMAL }, # history movement j => { char => 'j', func => \&cmd_j, type => C_NORMAL }, k => { char => 'k', func => \&cmd_k, type => C_NORMAL }, @@ -627,10 +627,6 @@ sub cmd_l { $pos = _fix_input_pos($pos, $length); return (undef, $pos); } -sub cmd_space { - my ($count, $pos, $repeat) = @_; - return cmd_l($count, $pos); -} # later history (down) sub cmd_j { -- cgit v1.2.3 From 9acb5260382391d327a85566e1addcf1dcea5af8 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 15:33:24 +0200 Subject: vim_mode: Prevent invalid operator/command combinations. --- vim-mode/vim_mode.pl | 85 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 31 deletions(-) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 9cc1ae4..ad75ede 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -271,11 +271,14 @@ my $commands l => { char => 'l', func => \&cmd_l, type => C_NORMAL }, ' ' => { char => '', func => \&cmd_l, type => C_NORMAL }, # history movement - j => { char => 'j', func => \&cmd_j, type => C_NORMAL }, - k => { char => 'k', func => \&cmd_k, type => C_NORMAL }, - gg => { char => 'gg', func => \&cmd_gg, type => C_NORMAL }, + j => { char => 'j', func => \&cmd_j, type => C_NORMAL, + no_operator => 1 }, + k => { char => 'k', func => \&cmd_k, type => C_NORMAL, + no_operator => 1 }, + gg => { char => 'gg', func => \&cmd_gg, type => C_NORMAL, + no_operator => 1 }, G => { char => 'G', func => \&cmd_G, type => C_NORMAL, - needs_count => 1 }, + needs_count => 1, no_operator => 1 }, # char movement, take an additional parameter and use $movement f => { char => 'f', func => \&cmd_f, type => C_NEEDSKEY, selection_needs_move_right => 1 }, @@ -307,58 +310,71 @@ my $commands '$' => { char => '$', func => \&cmd_dollar, type => C_NORMAL }, # delete chars x => { char => 'x', func => \&cmd_x, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, X => { char => 'X', func => \&cmd_X, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, + # C_NORMAL is correct, operator c takes care of insert mode s => { char => 's', func => \&cmd_s, type => C_NORMAL, - repeatable => 1 }, # operator c takes care of insert mode + repeatable => 1, no_operator => 1 }, + # C_NORMAL is correct, operator c takes care of insert mode S => { char => 'S', func => \&cmd_S, type => C_NORMAL, - repeatable => 1 }, # operator c takes care of insert mode + repeatable => 1, no_operator => 1 }, # insert mode i => { char => 'i', func => \&cmd_i, type => C_INSERT, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, I => { char => 'I', func => \&cmd_I, type => C_INSERT, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, a => { char => 'a', func => \&cmd_a, type => C_INSERT, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, A => { char => 'A', func => \&cmd_A, type => C_INSERT, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, # replace r => { char => 'r', func => \&cmd_r, type => C_NEEDSKEY, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, # paste p => { char => 'p', func => \&cmd_p, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, P => { char => 'P', func => \&cmd_P, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, # to end of line C => { char => 'C', func => \&cmd_C, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, D => { char => 'D', func => \&cmd_D, type => C_NORMAL, - repeatable => 1 }, + repeatable => 1, no_operator => 1 }, # scrolling - "\x05" => { char => '', func => \&cmd_ctrl_d, type => C_NORMAL }, + "\x05" => { char => '', func => \&cmd_ctrl_d, type => C_NORMAL, + no_operator => 1 }, "\x04" => { char => '', func => \&cmd_ctrl_d, type => C_NORMAL, - needs_count => 1 }, - "\x19" => { char => '', func => \&cmd_ctrl_u, type => C_NORMAL }, + needs_count => 1, no_operator => 1 }, + "\x19" => { char => '', func => \&cmd_ctrl_u, type => C_NORMAL, + no_operator => 1 }, "\x15" => { char => '', func => \&cmd_ctrl_u, type => C_NORMAL, - needs_count => 1 }, - "\x06" => { char => '', func => \&cmd_ctrl_f, type => C_NORMAL }, - "\x02" => { char => '', func => \&cmd_ctrl_b, type => C_NORMAL }, + needs_count => 1, no_operator => 1 }, + "\x06" => { char => '', func => \&cmd_ctrl_f, type => C_NORMAL, + no_operator => 1 }, + "\x02" => { char => '', func => \&cmd_ctrl_b, type => C_NORMAL, + no_operator => 1 }, # window switching - "\x17j" => { char => 'j', func => \&cmd_ctrl_wj, type => C_NORMAL }, - "\x17k" => { char => 'k', func => \&cmd_ctrl_wk, type => C_NORMAL }, - "\x1e" => { char => '', func => \&cmd_ctrl_6, type => C_NORMAL }, + "\x17j" => { char => 'j', func => \&cmd_ctrl_wj, type => C_NORMAL, + no_operator => 1 }, + "\x17k" => { char => 'k', func => \&cmd_ctrl_wk, type => C_NORMAL, + no_operator => 1 }, + "\x1e" => { char => '', func => \&cmd_ctrl_6, type => C_NORMAL, + no_operator => 1 }, # misc '~' => { char => '~', func => \&cmd_tilde, type => C_NORMAL, - repeatable => 1 }, - '"' => { char => '"', func => \&cmd_register, type => C_NEEDSKEY }, - '.' => { char => '.', type => C_NORMAL, repeatable => 1 }, + repeatable => 1, no_operator => 1 }, + '"' => { char => '"', func => \&cmd_register, type => C_NEEDSKEY, + no_operator => 1 }, + '.' => { char => '.', type => C_NORMAL, repeatable => 1, + no_operator => 1 }, ':' => { char => ':', type => C_NORMAL }, "\n" => { char => '', type => C_NORMAL }, # return # undo - 'u' => { char => 'u', func => \&cmd_undo, type => C_NORMAL }, - "\x12" => { char => '', func => \&cmd_redo, type => C_NORMAL }, + 'u' => { char => 'u', func => \&cmd_undo, type => C_NORMAL, + no_operator => 1 }, + "\x12" => { char => '', func => \&cmd_redo, type => C_NORMAL, + no_operator => 1 }, }; # All available commands in Ex-Mode. @@ -2174,6 +2190,13 @@ sub handle_command_cmd { } } + # Ignore invalid operator/command combinations. + if ($operator and $cmd->{no_operator}) { + print "Invalid operator/command: $operator->{char} $cmd->{char}" + if DEBUG; + $skip = 1; + } + if ($skip) { print "Skipping movement and operator." if DEBUG; } else { -- cgit v1.2.3 From dd2e9a766e4fc7de278681f4658ba42c8b74e2a5 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 9 Oct 2010 15:59:31 +0200 Subject: vim_mode: Add :unm[ap] {lhs}. --- vim-mode/vim_mode.pl | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'vim-mode/vim_mode.pl') diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index ad75ede..9d8e04b 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -73,6 +73,7 @@ # {file} not supported # * Mappings: :map - display custom mappings # :map {lhs} {rhs} - add mapping +# :unm[ap] {lhs} - remove custom mapping # * Save mappings: :mkv[imrc][!] - like in Vim, but [file] not supported # * Substitute: :s/// - i and g are supported as flags, only /// can be # used as separator, uses Perl regex instead of @@ -92,6 +93,7 @@ # :map /clear - map Ctrl-L to irssi command /clear # :map /window goto 1 # :map - disable , it does nothing now +# :unmap - restore default behavior of after disabling it # # # The following irssi settings are available: @@ -398,6 +400,8 @@ my $commands_ex undolist => { char => ':undolist', func => \&ex_undolist, type => C_EX }, undol => { char => ':undol', func => \&ex_undolist, type => C_EX }, map => { char => ':map', func => \&ex_map, type => C_EX }, + unmap => { char => ':unmap', func => \&ex_unmap, type => C_EX }, + unm => { char => ':unm', func => \&ex_unmap, type => C_EX }, source => { char => ':source', func => \&ex_source, type => C_EX }, so => { char => ':so', func => \&ex_source, type => C_EX }, mkvimrc => { char => ':mkvimrc', func => \&ex_mkvimrc, type => C_EX }, @@ -1657,6 +1661,25 @@ sub ex_map { _warn_ex('map'); } } +sub ex_unmap { + my ($arg_str) = @_; + + # :unm[ap] {lhs} + if ($arg_str !~ /^unm(?:ap)? (\S+)$/) { + return _warn_ex('unmap'); + } + + my $lhs = _parse_mapping($1); + if (not defined $lhs) { + return _warn_ex('unmap', 'invalid {lhs}'); + # Prevent unmapping of unknown or default mappings. + } elsif (not exists $maps->{$lhs} or not defined $maps->{$lhs}->{cmd} or + ($commands->{$lhs} and $maps->{$lhs}->{cmd} == $commands->{$lhs})) { + return _warn_ex('unmap', "$1 not found"); + } + + delete_map($lhs); +} sub _parse_mapping { my ($string) = @_; @@ -2485,6 +2508,45 @@ sub add_map { $maps->{$keys}->{char} = _parse_mapping_reverse($keys); $maps->{$keys}->{cmd} = $command; } +sub delete_map { + my ($keys) = @_; + + # Abort for non-existent mappings or placeholder mappings. + return if not exists $maps->{$keys} or not defined $maps->{$keys}->{cmd}; + + my @add = (); + + # If no maps need the current key, then remove it and all other + # unnecessary keys in the "tree". + if (keys %{$maps->{$keys}->{maps}} == 0) { + my $tmp = $keys; + while (length $tmp > 1) { + my $map = substr $tmp, -1, 1, ''; + delete $maps->{$tmp}->{maps}->{$tmp . $map}; + if (not $maps->{$tmp}->{cmd} and keys %{$maps->{$tmp}->{maps}} == 0) { + push @add, $tmp; + delete $maps->{$tmp}; + } else { + last; + } + } + } + + if (keys %{$maps->{$keys}->{maps}} > 0) { + $maps->{$keys}->{cmd} = undef; + } else { + delete $maps->{$keys}; + } + push @add, $keys; + + # Restore default keybindings in case we :unmaped a or a remapped + # key. + foreach my $key (@add) { + if (exists $commands->{$key}) { + add_map($key, $commands->{$key}); + } + } +} sub _commit_line { -- cgit v1.2.3