Re: Scripting Help

Joost Vunderink <[email protected]> Wed, 23 Jun 2010 18:39:00 +0200
Newsgroups gmane.network.irc.irssi.user
Message-ID <[email protected]>
Stealth wrote:

> It also seems that "window goto active" does the same as alt+a and
> will go to the first active window. Is there anyway to get a usable
> window ID/reference that can be used as a reference for switching to
> that window? This will be needed for future features of this script,
> so might as well figure this out now :)

I once wrote a script to keep track of your window history; it allows
you to go back to the previous window you visited. What I do in that
script is basically:

my $win = Irssi::window_find_refnum($number);
$win->set_active();

I've attached the script; maybe you can steal some more stuff from it.

Cheers,
Joost.
windowhistory.pl (text/x-perl, 7 KB)
# windowhistory.pl

use strict;
use Irssi;
use Irssi::Irc;
use Irssi::TextUI;

use vars qw(%IRSSI $VERSION @history %goto_properties);

$VERSION = "0.2";

%IRSSI = (
    authors     => "Joost 'Garion' Vunderink",
    contact     => '[email protected]',
    name        => "window history",
    description => "Keeps track of the windows you have visited",
    license     => "GPLv2",
    url         => "http://www.garion.org/irssi/",
    changed     => "",
);

sub cmd_whis {
    my ($args, $server, $item) = @_;

    if ($args =~ m/^(help)|(show)|(reset)|(goto)/i ) {
        Irssi::command_runsub ('whis', $args, $server, $item);
        return;
    }

    print "Illegal command. Use help or show.";
}

sub _get_range {
    my ($history, $index) = @_;

    my $max = Irssi::settings_get_int('whis_max_print') - 1;
    my $begin = 0;
    my $end   = $max || scalar @history;

    # The end of the range cannot lie beyond the total number of items
    # in the history hash.
    if ($end >= scalar @$history) {
        return ($begin, scalar @$history);
    }

    if (!$index) {
        return ($begin, $end);
    }

    # We are currently at an index. Only print the history items
    # near that index.
    $begin = int($index - $max / 2);
    $end   = int($index + $max / 2);

    while ($begin < 0) {
        $begin++;
        $end++;
    }

    while ($end >= scalar @$history) {
        $begin--;
        $end--;
    }

    return ($begin, $end);
}

sub cmd_whis_show {
    my ($args, $server, $item) = @_;

    if (@history == 0) {
        print "No windows history.";
        return;
    }

    # Get the array indexes of the range to print.
    my ($begin, $end) = _get_range(\@history, $goto_properties{'index'});

    Irssi::printformat(MSGLEVEL_CRAP, 'whis_print_header',
        $end + 1 - $begin, scalar @history);

    for my $i ($begin .. $end) {
        if ($goto_properties{'index'} && $goto_properties{'index'} == $i + 1) {
           Irssi::printformat(MSGLEVEL_CRAP, 'whis_print_line_goto_index',
               $i + 1,
               $history[$i]->{'number'},
               $history[$i]->{'name'} || '[unnamed]',
               $history[$i]->{'tag'},
               $goto_properties{'start_window_num'},
           );
        } else {
           Irssi::printformat(MSGLEVEL_CRAP, 'whis_print_line',
               $i + 1,
               $history[$i]->{'number'},
               $history[$i]->{'name'} || '[unnamed]',
               $history[$i]->{'tag'},
           );
        }
    }
}

sub cmd_whis_reset {
    my ($args, $server, $item) = @_;

    @history = ();

    print "Window History cleared.";
}

sub cmd_whis_goto {
    my ($args, $server, $item) = @_;

    # If we are starting a goto session, we will remember which window
    # number we started in.
    if (not defined $goto_properties{'index'}) {
        $goto_properties{'start_window_num'} = Irssi::active_win()->{'refnum'};
    }

    if (lc $args eq 'previous') {
        $args = $goto_properties{'index'} + 1;
        if ($args > scalar @history) {
            print "You have reached The End.";
            return;
        }
    }

    if (lc $args eq 'next') {
        $args = $goto_properties{'index'} - 1;
        if ($args < 1) {
            # We go back to the start_window which was defined when we started
            # this goto session.
            my $win = Irssi::window_find_refnum(
                $goto_properties{'start_window_num'}
            );
            %goto_properties = ();
            $goto_properties{'used_goto'} = 1;
            $win->set_active();
            return;
        }
    }

    if ($args =~ /\D/) {
        print "Use /whis goto <number>";
        return;
    }

    if ($args > @history) {
        print "There are only " . @history . " history items.";
        return;
    }

    my $info = $history[$args - 1];

    my $win = Irssi::window_find_refnum($info->{'number'});

    if (!$win) {
        print "Could not find window number " . $info->{'number'} .
            " to jump to.";
        return;
    }

    $goto_properties{'index'} = $args;

    # If we use goto to change to a new window, make sure the history
    # list is not modified.
    $goto_properties{'used_goto'} = 1;

    $win->set_active();
}

sub event_window_changed {
    my ($new_window, $old_window) = @_;

    return unless $old_window;

    # If we use goto to change to a new window, make sure the history
    # list is not modified.
    if ($goto_properties{'used_goto'}) {
        $goto_properties{'used_goto'} = 0;
        return;
    }

    # We did not use a goto. If there was a goto index present, delete it.
    $goto_properties{'index'} = undef;

    my $info = {
        number => $old_window->{'refnum'},
        tag    => $old_window->{'active_server'}->{'tag'},
        name   => $old_window->{'active'}->{'name'}
    };

    unshift @history, $info;

    # Clean up the history array by removing entries of too long ago.
    my $max = Irssi::settings_get_int('whis_history_size');
    pop @history while scalar @history > $max;
}

sub event_window_created {
    # probably not necessary
}

sub event_window_destroyed {
    my ($window) = @_;

    my $winnum_destroyed = $window->{'refnum'};

    print "Destroyed: " . $winnum_destroyed;

    my @tmp_history;

    for my $info (@history) {
        if ($info->{'number'} > $winnum_destroyed) {
            print "--ing " . $info->{'number'} . " " . $info->{'name'};
            $info->{'number'}--;
            push @tmp_history, $info;
        } elsif ($info->{'number'} == $winnum_destroyed) {
            print "Removing equal";
        } else {
            push @tmp_history, $info;
        }
    }

    @history = @tmp_history;
}


{
    # Mick's almost global variable
    my $refnum_process_signal = 0;

sub event_window_refnum_changed {
    my ($new_window, $old_window_num) = @_;
    my $new_window_num = $new_window->{'refnum'};

    if (!$refnum_process_signal) {
        $refnum_process_signal = 1;
        return;
    }

    $refnum_process_signal = 0;

    my @tmp_history;

    for my $info (@history) {
        if ($info->{'number'} == $old_window_num) {
            $info->{'number'} = $new_window_num;
        } elsif ($info->{'number'} == $new_window_num) {
            $info->{'number'} = $old_window_num;
        }

        push @tmp_history, $info;
    }

    @history = @tmp_history;
}

}

Irssi::command_bind('whis',        'cmd_whis');
Irssi::command_bind('whis help',   'cmd_whis_help');
Irssi::command_bind('whis show',   'cmd_whis_show');
Irssi::command_bind('whis reset',  'cmd_whis_reset');
Irssi::command_bind('whis goto',   'cmd_whis_goto');

Irssi::settings_add_int('whis',    'whis_history_size', 50);
Irssi::settings_add_int('whis',    'whis_max_print', 10);

Irssi::signal_add('window changed', 'event_window_changed');
Irssi::signal_add('window destroyed', 'event_window_destroyed');
Irssi::signal_add('window refnum changed', 'event_window_refnum_changed');

Irssi::theme_register([
    'whis_print_line',
    '   %G$0%n $1 $2 ($3)',

    'whis_print_line_goto_index',
    '%Y->%n %G$0%n $1 $2 ($3) [%C$4%n]',

    'whis_print_header',
    'Showing $0 items of $1 total items',
]);