aboutsummaryrefslogtreecommitdiffstats
path: root/vim-mode/vim_mode.pl
diff options
context:
space:
mode:
Diffstat (limited to 'vim-mode/vim_mode.pl')
-rw-r--r--vim-mode/vim_mode.pl181
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");
+}