diff options
Diffstat (limited to '')
-rw-r--r-- | vim-mode/vim_mode.pl | 219 |
1 files changed, 128 insertions, 91 deletions
diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl index 5f4a201..becf13b 100644 --- a/vim-mode/vim_mode.pl +++ b/vim-mode/vim_mode.pl @@ -969,18 +969,21 @@ my $should_ignore = 0; # buffer to keep track of the last N keystrokes, used for Esc detection and # insert mode mappings -my @input_buf; -my $input_buf_timer; -my $input_buf_enabled = 0; +my @escape_buf; +my $escape_buf_timer; +my $escape_buf_enabled = 0; + +# mode-related input buffers +# -------------------------- # insert mode repeat buffer, used to repeat (.) last insert -my @insert_buf; +my @insert_mode_buf; +my @cmd_mode_buf; +my @ex_mode_buf; -# Ex-mode input related vars -# -------------------------- +# Ex-mode related vars +# -------------------- -# ex mode buffer -my @ex_buf; # ex mode history storage. my @ex_history; my $ex_history_index = 0; @@ -1856,7 +1859,7 @@ sub cmd_A { # Add @insert_buf to _input() at the given position. sub _insert_buffer { my ($count, $pos) = @_; - return _insert_at_position(join('', @insert_buf), $count, $pos); + return _insert_at_position(join('', @insert_mode_buf), $count, $pos); } sub _insert_at_position { @@ -2079,7 +2082,7 @@ sub _fix_input_pos { ################################################################ sub cmd_ex_command { - my $arg_str = join '', @ex_buf; + my $arg_str = join '', @ex_mode_buf; if ($arg_str !~ /^(\d*)?([a-z]+)/) { return _warn("Invalid Ex-mode command!"); @@ -2523,7 +2526,7 @@ sub _parse_mapping_reverse { my ($string) = @_; if (not defined $string) { - _warn("Unable to reverse-map command: " . join('', @ex_buf)); + _warn("Unable to reverse-map command: " . join('', @ex_mode_buf)); return; } @@ -2897,7 +2900,7 @@ sub vim_buffer_windows_string { # A little code duplication of cmd_ex_command(), but \s+ instead of \s* so # :bd doesn't display buffers matching d. - my $arg_str = join '', @ex_buf; + my $arg_str = join '', @ex_mode_buf; if ($arg_str =~ m|^b(?:uffer)?\s+(.+)$|) { my $buffer = $1; if ($buffer !~ /^[0-9]$/ and $buffer ne '#') { @@ -3247,7 +3250,7 @@ sub _update_mode { if ($mode == M_INS) { $history_index = undef; $register = '"'; - @insert_buf = (); + @insert_mode_buf = (); # Reset every command mode related status as a fallback in case something # goes wrong. } elsif ($mode == M_CMD) { @@ -3259,7 +3262,7 @@ sub _update_mode { $pending_map = undef; # Also clear ex-mode buffer. - @ex_buf = (); + @ex_mode_buf = (); } Irssi::statusbar_items_redraw("vim_mode"); @@ -3366,7 +3369,7 @@ sub ex_history_fwd { _debug("Ex history line: $line"); - @ex_buf = split '', $line; + @ex_mode_buf = split '', $line; handle_command_ex(-1); } @@ -3383,7 +3386,7 @@ sub ex_history_back { $line = '' if not defined $line; _debug("Ex history line: $line"); - @ex_buf = split '', $line; + @ex_mode_buf = split '', $line; handle_command_ex(-1); } @@ -3414,7 +3417,7 @@ sub sig_gui_keypress { my $should_stop = process_input_key($key, $char); - _stop() if ($should_stop == SIG_STOP); + _stop() if (defined $should_stop and $should_stop == SIG_STOP); } @@ -3426,20 +3429,102 @@ sub sig_gui_keypress { sub process_input_key { my ($key, $char) = @_; + # no matter what mode we're in, we need to deal with escape (and escape + # sequences) specially. So do them first. + + # First, if ($key == KEY_ESC) { - print "Esc seen, starting buffer" if DEBUG; - $input_buf_enabled = 1; + _debug("Escape seen, beginning escape_buf collection"); + $escape_buf_enabled = 1; + + push @escape_buf, $key; # NOTE: this timeout might be too low on laggy systems, but # it comes at the cost of keystroke latency for things that # contain escape sequences (arrow keys, etc) my $esc_buf_timeout = $settings->{esc_buf_timeout}->{value}; - $input_buf_timer - = Irssi::timeout_add_once($esc_buf_timeout, - \&handle_input_buffer, undef); + $escape_buf_timer = + Irssi::timeout_add_once($esc_buf_timeout, + \&escape_buffer_timeout, undef); + + _debug("Buffer Timer tag: $escape_buf_timer"); + + } elsif ($escape_buf_enabled) { + attempt_escape_buffer_parse($key, $char); + # we can check at this point if we recognise the sequence, and cancel + # the timeout if we do. + } +} +sub attempt_escape_buffer_parse { + my ($key, $char) = @_; + + if ($char eq '[') { + _debug("Spotted CSI"); + } elsif ($char eq ']') { + _debug ("Spotted OSC"); + } else { + push @escape_buf, $key; + } +} + +sub escape_buffer_timeout { + + $escape_buf_timer = undef; + $escape_buf_enabled = 0; + + _debug("Escape buffer contains: ", join(", ", @escape_buf)); + + if (@escape_buf == 1 && $escape_buf[0] == KEY_ESC) { + + _debug("escape only, Enter Command Mode"); + _update_mode(M_CMD); + + } else { + # we have more than a single esc, implying an escape sequence + # (meta-* or esc-*) + + # currently, we only extract escape sequences if: + # a) we're in ex mode + # b) they're arrow keys (for history control) - print "Buffer Timer tag: $input_buf_timer" if DEBUG; + if ($mode == M_EX) { + # ex mode + my $key_str = join '', map { chr } @escape_buf; + if ($key_str =~ m/^\e\[([ABCD])/) { + my $arrow = $1; + _debug( "Arrow key: $arrow"); + if ($arrow eq 'A') { # up + ex_history_back(); + } elsif ($arrow eq 'B') { # down + ex_history_fwd(); + } else { + $arrow =~ s/C/right/; + $arrow =~ s/D/left/; + _debug("Arrow key $arrow not supported"); + } + } + } else { + # otherwise, we just forward them to irssi. + _emulate_keystrokes(@escape_buf); + } + + # Clear insert buffer, pressing "special" keys (like arrow keys) + # resets it. + @escape_buf = (); + } + + @escape_buf = (); + $escape_buf_enabled = 0; +} + + + + + +# work slowly incorporating stuff back in. + +=pod } elsif ($mode == M_INS) { @@ -3487,12 +3572,12 @@ sub process_input_key { # TODO: maybe allow it } elsif ($key == KEY_DEL or $key == KEY_BS) { - @insert_buf = (); + @insert_mode_buf = (); # All other entered characters need to be stored to allow repeat of # insert mode. Ignore delete and control characters. } elsif ($key > 31) { - push @insert_buf, chr($key); + push @insert_mode_buf, chr($key); } } @@ -3522,72 +3607,24 @@ sub process_input_key { return SIG_CONT; } +=cut # TODO: merge this with 'flush_input_buffer' below. -sub handle_input_buffer { - - #Irssi::timeout_remove($input_buf_timer); - $input_buf_timer = undef; - # see what we've collected. - print "Input buffer contains: ", join(", ", @input_buf) if DEBUG; - - if (@input_buf == 1 && $input_buf[0] == KEY_ESC) { - - print "Enter Command Mode" if DEBUG; - _update_mode(M_CMD); - - } else { - # we have more than a single esc, implying an escape sequence - # (meta-* or esc-*) - - # currently, we only extract escape sequences if: - # a) we're in ex mode - # b) they're arrow keys (for history control) - - if ($mode == M_EX) { - # ex mode - my $key_str = join '', map { chr } @input_buf; - if ($key_str =~ m/^\e\[([ABCD])/) { - my $arrow = $1; - _debug( "Arrow key: $arrow"); - if ($arrow eq 'A') { # up - ex_history_back(); - } elsif ($arrow eq 'B') { # down - ex_history_fwd(); - } else { - $arrow =~ s/C/right/; - $arrow =~ s/D/left/; - _debug("Arrow key $arrow not supported"); - } - } - } else { - # otherwise, we just forward them to irssi. - _emulate_keystrokes(@input_buf); - } - - # Clear insert buffer, pressing "special" keys (like arrow keys) - # resets it. - @insert_buf = (); - } - - @input_buf = (); - $input_buf_enabled = 0; -} sub flush_input_buffer { - Irssi::timeout_remove($input_buf_timer) if defined $input_buf_timer; - $input_buf_timer = undef; + Irssi::timeout_remove($escape_buf_timer) if defined $escape_buf_timer; + $escape_buf_timer = undef; # see what we've collected. - print "Input buffer flushed" if DEBUG; + _debug("Escape buffer flushed"); - # Add the characters to @insert_buf so they can be repeated. - push @insert_buf, map chr, @input_buf; + # Add the characters to @escape_buf so they can be repeated. + push @escape_buf, map chr, @escape_buf; - _emulate_keystrokes(@input_buf); + _emulate_keystrokes(@escape_buf); - @input_buf = (); - $input_buf_enabled = 0; + @escape_buf = (); + $escape_buf_enabled = 0; $imap = undef; } @@ -3908,9 +3945,9 @@ sub handle_command_ex { # BS key (8) or DEL key (127) - remove last character. if ($key == 8 || $key == 127) { print "Delete" if DEBUG; - if (@ex_buf > 0) { - pop @ex_buf; - _set_prompt(':' . join '', @ex_buf); + if (@ex_mode_buf > 0) { + pop @ex_mode_buf; + _set_prompt(':' . join '', @ex_mode_buf); # Backspacing over : exits ex-mode. } else { _update_mode(M_CMD); @@ -3924,12 +3961,12 @@ sub handle_command_ex { } elsif ($key == 9) { # TAB print "Tab pressed" if DEBUG; - print "Ex buf contains: " . join('', @ex_buf) if DEBUG; - @tab_candidates = _tab_complete(join('', @ex_buf), [keys %$commands_ex]); + print "Ex buf contains: " . join('', @ex_mode_buf) if DEBUG; + @tab_candidates = _tab_complete(join('', @ex_mode_buf), [keys %$commands_ex]); _debug("Candidates: " . join(", ", @tab_candidates)); if (@tab_candidates == 1) { - @ex_buf = ( split('', $tab_candidates[0]), ' '); - _set_prompt(':' . join '', @ex_buf); + @ex_mode_buf = ( split('', $tab_candidates[0]), ' '); + _set_prompt(':' . join '', @ex_mode_buf); } # Ignore control characters for now. } elsif ($key > 0 && $key < 32) { @@ -3939,9 +3976,9 @@ sub handle_command_ex { } else { if ($key != -1) { # check we're not called from an ex_history_* function - push @ex_buf, chr $key; + push @ex_mode_buf, chr $key; } - _set_prompt(':' . join '', @ex_buf); + _set_prompt(':' . join '', @ex_mode_buf); } Irssi::statusbar_items_redraw("vim_windows"); |