diff options
Diffstat (limited to 'vim-mode')
| -rw-r--r-- | vim-mode/vim_mode.pl | 181 | 
1 files changed, 181 insertions, 0 deletions
| diff --git a/vim-mode/vim_mode.pl b/vim-mode/vim_mode.pl new file mode 100644 index 0000000..47ae262 --- /dev/null +++ b/vim-mode/vim_mode.pl @@ -0,0 +1,181 @@ +use strict; +use warnings; + +use Irssi; +use Irssi::TextUI; # for sbar_items_redraw + +# /statusbar window add vim_mode to get the status. + +use vars qw($VERSION %IRSSI); +$VERSION = "1.0.1"; +%IRSSI = +  ( +   authors         => "shabble", +   contact         => 'shabble+irssi@metavore.org, shabble@#irssi/Freenode', +   name            => "vim_mode", +   description     => "Give Irssi Vim-like commands for editing the inputline", +   license         => "Public Domain", +   changed         => "20/9/2010" +  ); + +#sub DEBUG () { 1 } +sub DEBUG () { 0 } + +# circular buffer to keep track of the last N keystrokes. +my @key_buf; + +my $mode = 0; # 0 is insert, 1 is command. no Ex for now. + +my $commands +  = { +     'i' => { command => 'insert at cur', +              func => \&cmd_insert, +              params => {pos => sub { _input_pos() }}, +            }, + +     'I' => { command => 'insert at end', +              func => \&cmd_insert, +              params => {pos => sub { _input_len() }}, +            }, + +     'A' => { command => 'insert at start', +              func => \&cmd_insert, +              params => { pos => sub { 0 } }, +            }, + +     'h' => { command => 'move left', +              func => \&cmd_move, +              params => { 'dir' => 'left' }, +            }, +     'l' => { command => 'move right', +              func => \&cmd_move, +              params => { 'dir' => 'right' }, +            }, + +    }; + +sub cmd_jump_word { +    my ($params) = @_; +     +} + +sub cmd_insert { +    my ($params) = @_; +    my $pos = $params->{pos}->(); + +    _input_pos($pos); + +    $mode = 0; + +    _update_mode(); +    _stop(); +} + +sub cmd_move { +    my ($params) = @_; +    my $dir = $params->{dir}; +    my $current_pos = _input_pos(); + +    if ($dir eq 'left') { +        _input_pos($current_pos -1) if $current_pos; +    } elsif ($dir eq 'right') { +        my $current_len = _input_len(); +        _input_pos($current_pos +1) unless $current_pos == $current_len; +    } else { +        print "Unknown direction: $dir"; +    } + +    _stop(); +} + +sub vim_mode_cb { +    my ($sb_item, $get_size_only) = @_; +    my $mode_str = ''; +    if ($mode == 0) { +        $mode_str = 'Insert'; +    } else { +        $mode_str = '%_Command%_'; +    } +    $sb_item->default_handler($get_size_only, "{sb $mode_str}", '', 0); +} + + +sub got_key { +    my ($key) = @_; +    _key_buf_add($key); +    if ($mode == 0) { +        # we're in insert mode. +        if ($key == 27) { # esc + +            $mode = 1; +            _update_mode(); +            Irssi::signal_stop(); +            return; +        } + +        return; +    } else { +        # command mode +        handle_command($key); +    } +    print "Keys: ", join ', ', @key_buf; +} + + +sub handle_command { +    my ($key) = @_; +    my $char = chr($key); +    if (exists $commands->{$char}) { +        my $cmd = $commands->{$char}; +        print "Going to execute command: ", $cmd->{command}; +        $cmd->{func}->( $cmd->{params} ); +    } else { +        # some error handling. +    } +} + + + + +Irssi::signal_add_first 'gui key pressed' => \&got_key; +Irssi::statusbar_item_register ('vim_mode', 0, 'vim_mode_cb'); + +sub _key_buf_add { +    my ($key) = @_; +    push @key_buf, $key; +    if (@key_buf > 5) { +        shift @key_buf; +    } +} + +sub _input { +    my ($data) = @_; +    if (defined $data) { +        Irssi::gui_input_set($data); +    } else { +        $data = Irssi::parse_special('$L', 0, 0) +    } +    return $data; +} + +sub _input_len { +    return length (Irssi::parse_special('$L', 0, 0)); +} + +sub _input_pos { +    my ($pos) = @_; +    if (defined $pos) { +        Irssi::gui_input_set_pos($pos); +    } else { +        $pos = Irssi::gui_input_get_pos(); +    } +    return $pos; +} + +sub _stop() { +    Irssi::signal_stop(); +} + +sub _update_mode() { +    Irssi::statusbar_items_redraw("vim_mode"); +} | 
