🔥
This commit is contained in:
43
irssi/scripts/awaybar.pl
Executable file
43
irssi/scripts/awaybar.pl
Executable file
@@ -0,0 +1,43 @@
|
||||
# awaybar.pl -- initially built for Irssi 0.8.9
|
||||
# thanks to mood.pl for practically allowing me
|
||||
# to copy the approach..
|
||||
use strict;
|
||||
use Irssi;
|
||||
use Irssi::TextUI;
|
||||
use vars qw($VERSION %IRSSI);
|
||||
|
||||
$VERSION = "0.1.1";
|
||||
%IRSSI = (
|
||||
authors => 'Simon Shine',
|
||||
contact => 'http://shine.eu.org/',
|
||||
name => 'awaybar',
|
||||
description => 'Provides a menubar item with away message',
|
||||
license => 'Public domain',
|
||||
);
|
||||
|
||||
Irssi::statusbar_item_register('awaybar', 0, 'awaybar');
|
||||
Irssi::signal_add('away mode changed', 'awaybar_redraw');
|
||||
|
||||
sub awaybar {
|
||||
my ($item, $get_size_only) = @_;
|
||||
my $away_reason = !Irssi::active_server() ? undef : Irssi::active_server()->{away_reason};
|
||||
|
||||
if (defined $away_reason && length $away_reason) {
|
||||
my %r = ('\{' => '(',
|
||||
'\}' => ')',
|
||||
'%' => '%%',);
|
||||
$away_reason =~ s/$_/$r{$_}/g for (keys %r);
|
||||
|
||||
#my $format = $theme->format_expand("{sb_awaybar Olet AWAY. Syy: $away_reason}");
|
||||
my $format = "{sb_awaybar $away_reason}.";
|
||||
|
||||
$item->{min_size} = $item->{max_size} = length($away_reason);
|
||||
$item->default_handler($get_size_only, $format, 0, 1);
|
||||
} else {
|
||||
$item->{min_size} = $item->{max_size} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub awaybar_redraw {
|
||||
Irssi::statusbar_items_redraw('awaybar');
|
||||
}
|
||||
2478
irssi/scripts/awl.pl
Executable file
2478
irssi/scripts/awl.pl
Executable file
File diff suppressed because it is too large
Load Diff
145
irssi/scripts/nickcolor.pl
Executable file
145
irssi/scripts/nickcolor.pl
Executable file
@@ -0,0 +1,145 @@
|
||||
use strict;
|
||||
use Irssi 20020101.0250 ();
|
||||
use vars qw($VERSION %IRSSI);
|
||||
$VERSION = "2";
|
||||
%IRSSI = (
|
||||
authors => "Timo Sirainen, Ian Peters, David Leadbeater",
|
||||
contact => "tss\@iki.fi",
|
||||
name => "Nick Color",
|
||||
description => "assign a different color for each nick",
|
||||
license => "Public Domain",
|
||||
url => "http://irssi.org/",
|
||||
changed => "Sun 15 Jun 19:10:44 BST 2014",
|
||||
);
|
||||
|
||||
# Settings:
|
||||
# nickcolor_colors: List of color codes to use.
|
||||
# e.g. /set nickcolor_colors 2 3 4 5 6 7 9 10 11 12 13
|
||||
# (avoid 8, as used for hilights in the default theme).
|
||||
|
||||
my %saved_colors;
|
||||
my %session_colors = {};
|
||||
|
||||
sub load_colors {
|
||||
open my $color_fh, "<", "$ENV{HOME}/.irssi/saved_colors";
|
||||
while (<$color_fh>) {
|
||||
chomp;
|
||||
my($nick, $color) = split ":";
|
||||
$saved_colors{$nick} = $color;
|
||||
}
|
||||
}
|
||||
|
||||
sub save_colors {
|
||||
open COLORS, ">", "$ENV{HOME}/.irssi/saved_colors";
|
||||
|
||||
foreach my $nick (keys %saved_colors) {
|
||||
print COLORS "$nick:$saved_colors{$nick}\n";
|
||||
}
|
||||
|
||||
close COLORS;
|
||||
}
|
||||
|
||||
# If someone we've colored (either through the saved colors, or the hash
|
||||
# function) changes their nick, we'd like to keep the same color associated
|
||||
# with them (but only in the session_colors, ie a temporary mapping).
|
||||
|
||||
sub sig_nick {
|
||||
my ($server, $newnick, $nick, $address) = @_;
|
||||
my $color;
|
||||
|
||||
$newnick = substr ($newnick, 1) if ($newnick =~ /^:/);
|
||||
|
||||
if ($color = $saved_colors{$nick}) {
|
||||
$session_colors{$newnick} = $color;
|
||||
} elsif ($color = $session_colors{$nick}) {
|
||||
$session_colors{$newnick} = $color;
|
||||
}
|
||||
}
|
||||
|
||||
# This gave reasonable distribution values when run across
|
||||
# /usr/share/dict/words
|
||||
|
||||
sub simple_hash {
|
||||
my ($string) = @_;
|
||||
chomp $string;
|
||||
my @chars = split //, $string;
|
||||
my $counter;
|
||||
|
||||
foreach my $char (@chars) {
|
||||
$counter += ord $char;
|
||||
}
|
||||
|
||||
my @colors = split / /, Irssi::settings_get_str('nickcolor_colors');
|
||||
$counter = $colors[$counter % @colors];
|
||||
|
||||
return $counter;
|
||||
}
|
||||
|
||||
sub sig_public {
|
||||
my ($server, $msg, $nick, $address, $target) = @_;
|
||||
|
||||
# Has the user assigned this nick a color?
|
||||
my $color = $saved_colors{$nick};
|
||||
|
||||
# Have -we- already assigned this nick a color?
|
||||
if (!$color) {
|
||||
$color = $session_colors{$nick};
|
||||
}
|
||||
|
||||
# Let's assign this nick a color
|
||||
if (!$color) {
|
||||
$color = simple_hash $nick;
|
||||
$session_colors{$nick} = $color;
|
||||
}
|
||||
|
||||
$color = sprintf "\003%02d", $color;
|
||||
$server->command('/^format pubmsg {pubmsgnick $2 {pubnick '.chr(3).$color.'$[-10]0}}$1');
|
||||
}
|
||||
|
||||
sub cmd_color {
|
||||
my ($data, $server, $witem) = @_;
|
||||
my ($op, $nick, $color) = split " ", $data;
|
||||
|
||||
$op = lc $op;
|
||||
|
||||
if (!$op) {
|
||||
Irssi::print ("No operation given (save/set/clear/list/preview)");
|
||||
} elsif ($op eq "save") {
|
||||
save_colors;
|
||||
} elsif ($op eq "set") {
|
||||
if (!$nick) {
|
||||
Irssi::print ("Nick not given");
|
||||
} elsif (!$color) {
|
||||
Irssi::print ("Color not given");
|
||||
} elsif ($color < 2 || $color > 14) {
|
||||
Irssi::print ("Color must be between 2 and 14 inclusive");
|
||||
} else {
|
||||
$saved_colors{$nick} = $color;
|
||||
}
|
||||
} elsif ($op eq "clear") {
|
||||
if (!$nick) {
|
||||
Irssi::print ("Nick not given");
|
||||
} else {
|
||||
delete ($saved_colors{$nick});
|
||||
}
|
||||
} elsif ($op eq "list") {
|
||||
Irssi::print ("\nSaved Colors:");
|
||||
foreach my $nick (keys %saved_colors) {
|
||||
Irssi::print (chr (3) . "$saved_colors{$nick}$nick" .
|
||||
chr (3) . "1 ($saved_colors{$nick})");
|
||||
}
|
||||
} elsif ($op eq "preview") {
|
||||
Irssi::print ("\nAvailable colors:");
|
||||
foreach my $i (2..14) {
|
||||
Irssi::print (chr (3) . "$i" . "Color #$i");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
load_colors;
|
||||
|
||||
Irssi::settings_add_str('misc', 'nickcolor_colors', '2 3 4 5 6 7 9 10 11 12 13');
|
||||
Irssi::command_bind('color', 'cmd_color');
|
||||
|
||||
Irssi::signal_add('message public', 'sig_public');
|
||||
Irssi::signal_add('event nick', 'sig_nick');
|
||||
805
irssi/scripts/nicklist.pl
Executable file
805
irssi/scripts/nicklist.pl
Executable file
@@ -0,0 +1,805 @@
|
||||
# This script adds a nicklist to the right of irssi
|
||||
# for documentation: see http://wouter.coekaerts.be/site/irssi/nicklist
|
||||
|
||||
# Copyright (C) 2002-2007 Wouter Coekaerts <coekie@irssi.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
use Irssi;
|
||||
use strict;
|
||||
use IO::Handle; # for (auto)flush
|
||||
use Fcntl; # for sysopen
|
||||
use vars qw($VERSION %IRSSI);
|
||||
$VERSION = '0.4.6+';
|
||||
%IRSSI = (
|
||||
authors => 'Wouter Coekaerts',
|
||||
contact => 'coekie@irssi.org',
|
||||
name => 'nicklist',
|
||||
description => 'draws a nicklist to another terminal, or at the right of your irssi in the same terminal',
|
||||
license => 'GPLv2+',
|
||||
url => 'http://wouter.coekaerts.be/irssi',
|
||||
changed => '05/05/2007'
|
||||
);
|
||||
|
||||
sub cmd_help {
|
||||
print ( <<EOF
|
||||
Commands:
|
||||
NICKLIST HELP
|
||||
NICKLIST SCROLL <nr of lines>
|
||||
NICKLIST SCREEN
|
||||
NICKLIST FIFO
|
||||
NICKLIST OFF
|
||||
NICKLIST UPDATE
|
||||
|
||||
For help see: http://wouter.coekaerts.be/site/irssi/nicklist
|
||||
|
||||
in short:
|
||||
|
||||
1. FIFO MODE
|
||||
- in irssi: /NICKLIST FIFO (only the first time, to create the fifo)
|
||||
- in a shell, in a window where you want the nicklist: cat ~/.irssi/nicklistfifo
|
||||
- back in irssi:
|
||||
/SET nicklist_heigth <height of nicklist>
|
||||
/SET nicklist_width <width of nicklist>
|
||||
/NICKLIST FIFO
|
||||
|
||||
2. SCREEN MODE
|
||||
- start irssi inside screen ("screen irssi")
|
||||
- /NICKLIST SCREEN
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
my $prev_lines = 0; # number of lines in previous written nicklist
|
||||
my $scroll_pos = 0; # scrolling position
|
||||
my $cursor_line; # line the cursor is currently on
|
||||
my ($OFF, $SCREEN, $FIFO) = (0,1,2); # modes
|
||||
my $mode = $OFF; # current mode
|
||||
my $need_redraw = 0; # nicklist needs redrawing
|
||||
my $screen_resizing = 0; # terminal is being resized
|
||||
my $active_channel; # (REC)
|
||||
|
||||
my @nicklist=(); # array of hashes, containing the internal nicklist of the active channel
|
||||
# nick => realnick
|
||||
# modeflag => '@', '%', '+', or other mode char
|
||||
# modepos => number representing the position in which to sort nicks with that mode
|
||||
# status => (not used yet...)
|
||||
#my ($STATUS_NORMAL, $STATUS_JOINING, $STATUS_PARTING, $STATUS_QUITING, $STATUS_KICKED, $STATUS_SPLIT) = (0,1,2,3,4,5);
|
||||
# text => text to be printed
|
||||
# cmp => text used to compare (sort) nicks
|
||||
|
||||
|
||||
# 'cached' settings
|
||||
my ($screen_prefix, $irssi_width, %prefix_mode, @prefix_status, $height, $nicklist_width, $check_friends, @prefix_friends);
|
||||
|
||||
sub read_settings {
|
||||
($screen_prefix = Irssi::settings_get_str('nicklist_screen_prefix')) =~ s/\\e/\033/g;
|
||||
|
||||
($prefix_mode{'@'} = Irssi::settings_get_str('nicklist_prefix_mode_op')) =~ s/\\e/\033/g;
|
||||
($prefix_mode{'%'} = Irssi::settings_get_str('nicklist_prefix_mode_halfop')) =~ s/\\e/\033/g;
|
||||
($prefix_mode{'+'} = Irssi::settings_get_str('nicklist_prefix_mode_voice')) =~ s/\\e/\033/g;
|
||||
($prefix_mode{' '} = Irssi::settings_get_str('nicklist_prefix_mode_normal')) =~ s/\\e/\033/g;
|
||||
|
||||
(my $prefix_mode_other = Irssi::settings_get_str('nicklist_prefix_mode_other')) =~ s/\\e/\033/g;
|
||||
foreach my $p (split (/ /, $prefix_mode_other)) {
|
||||
next if $p eq '';
|
||||
if ($p !~ /(.)=(.*)/) {
|
||||
Irssi::print("Could not parse nicklist_prefix_mode_other part '$p'. Expected space separated list of <mode character>=<prefix>");
|
||||
last;
|
||||
} else {
|
||||
$prefix_mode{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
(my $prefix_friends = Irssi::settings_get_str('nicklist_prefix_friends')) =~ s/\\e/\033/g;
|
||||
foreach my $p (split (/ /, $prefix_friends)) {
|
||||
next if $p eq '';
|
||||
if ($p !~ /(.+?)=(.*)/) {
|
||||
Irssi::print("Could not parse nicklist_prefix_friends part '$p'. Expected space separated list of <flags>=<prefix>");
|
||||
last;
|
||||
} else {
|
||||
push @prefix_friends, {'flags' => $1, 'prefix' => $2};
|
||||
}
|
||||
}
|
||||
|
||||
$check_friends = ($prefix_friends ne '');
|
||||
|
||||
if ($mode != $SCREEN) {
|
||||
$height = Irssi::settings_get_int('nicklist_height');
|
||||
}
|
||||
my $new_nicklist_width = Irssi::settings_get_int('nicklist_width');
|
||||
if ($new_nicklist_width != $nicklist_width && $mode == $SCREEN) {
|
||||
sig_terminal_resized();
|
||||
}
|
||||
$nicklist_width = $new_nicklist_width;
|
||||
}
|
||||
|
||||
sub update {
|
||||
read_settings();
|
||||
make_nicklist();
|
||||
}
|
||||
|
||||
##################
|
||||
##### OUTPUT #####
|
||||
##################
|
||||
|
||||
### off ###
|
||||
|
||||
sub cmd_off {
|
||||
if ($mode == $SCREEN) {
|
||||
screen_stop();
|
||||
} elsif ($mode == $FIFO) {
|
||||
fifo_stop();
|
||||
}
|
||||
}
|
||||
|
||||
### fifo ###
|
||||
|
||||
sub cmd_fifo_start {
|
||||
read_settings();
|
||||
my $path = Irssi::settings_get_str('nicklist_fifo_path');
|
||||
unless (-p $path) { # not a pipe
|
||||
if (-e _) { # but a something else
|
||||
die "$0: $path exists and is not a pipe, please remove it\n";
|
||||
} else {
|
||||
require POSIX;
|
||||
POSIX::mkfifo($path, 0666) or die "can\'t mkfifo $path: $!";
|
||||
Irssi::print("Fifo created. Start reading it (\"cat $path\") and try again.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!sysopen(FIFO, $path, O_WRONLY | O_NONBLOCK)) { # or die "can't write $path: $!";
|
||||
Irssi::print("Couldn\'t write to the fifo ($!). Please start reading the fifo (\"cat $path\") and try again.");
|
||||
return;
|
||||
}
|
||||
FIFO->autoflush(1);
|
||||
print FIFO "\033[2J\033[1;1H"; # erase screen & jump to 0,0
|
||||
$cursor_line = 0;
|
||||
if ($mode == $SCREEN) {
|
||||
screen_stop();
|
||||
}
|
||||
$mode = $FIFO;
|
||||
make_nicklist();
|
||||
}
|
||||
|
||||
sub fifo_stop {
|
||||
close FIFO;
|
||||
$mode = $OFF;
|
||||
Irssi::print("Fifo closed.");
|
||||
}
|
||||
|
||||
### screen ###
|
||||
|
||||
sub cmd_screen_start {
|
||||
if (!defined($ENV{'STY'})) {
|
||||
Irssi::print 'screen not detected, screen mode only works inside screen';
|
||||
return;
|
||||
}
|
||||
read_settings();
|
||||
if ($mode == $SCREEN) {return;}
|
||||
if ($mode == $FIFO) {
|
||||
fifo_stop();
|
||||
}
|
||||
$mode = $SCREEN;
|
||||
Irssi::signal_add_last('gui print text finished', \&sig_gui_print_text_finished);
|
||||
Irssi::signal_add_last('gui page scrolled', \&sig_page_scrolled);
|
||||
Irssi::signal_add('terminal resized', \&sig_terminal_resized);
|
||||
screen_size();
|
||||
make_nicklist();
|
||||
}
|
||||
|
||||
sub screen_stop {
|
||||
$mode = $OFF;
|
||||
Irssi::signal_remove('gui print text finished', \&sig_gui_print_text_finished);
|
||||
Irssi::signal_remove('gui page scrolled', \&sig_page_scrolled);
|
||||
Irssi::signal_remove('terminal resized', \&sig_terminal_resized);
|
||||
system 'screen -x '.$ENV{'STY'}.' -X fit';
|
||||
}
|
||||
|
||||
sub screen_size {
|
||||
if ($mode != $SCREEN) {
|
||||
return;
|
||||
}
|
||||
$screen_resizing = 1;
|
||||
# fit screen
|
||||
system 'screen -x '.$ENV{'STY'}.' -X fit';
|
||||
# we wait a second to make sure the fit command was processed
|
||||
Irssi::timeout_add_once(1000, \&screen_size_real, []);
|
||||
}
|
||||
|
||||
sub screen_size_real {
|
||||
# get size (from perldoc -q size)
|
||||
my ($winsize, $row, $col, $xpixel, $ypixel);
|
||||
eval 'use Term::ReadKey; ($col, $row, $xpixel, $ypixel) = GetTerminalSize';
|
||||
# require Term::ReadKey 'GetTerminalSize';
|
||||
# ($col, $row, $xpixel, $ypixel) = Term::ReadKey::GetTerminalSize;
|
||||
#};
|
||||
if ($@) { # no Term::ReadKey, try the ugly way
|
||||
eval {
|
||||
require 'sys/ioctl.ph';
|
||||
# without this reloading doesn't work. workaround for some unknown bug
|
||||
do 'asm/ioctls.ph';
|
||||
};
|
||||
|
||||
# ugly way not working, let's try something uglier, the dg-hack(tm) (constant for linux only?)
|
||||
if($@) { no strict 'refs'; *TIOCGWINSZ = sub { return 0x5413 } }
|
||||
|
||||
unless (defined &TIOCGWINSZ) {
|
||||
die "Term::ReadKey not found, and ioctl 'workaround' failed. Install the Term::ReadKey perl module to use screen mode.\n";
|
||||
}
|
||||
open(TTY, "+</dev/tty") or die "No tty: $!";
|
||||
unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
|
||||
die "Term::ReadKey not found, and ioctl 'workaround' failed ($!). Install the Term::ReadKey perl module to use screen mode.\n";
|
||||
}
|
||||
close(TTY);
|
||||
($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
|
||||
}
|
||||
|
||||
# set screen width
|
||||
$irssi_width = $col-$nicklist_width-1;
|
||||
$height = $row-1;
|
||||
|
||||
system 'screen -x '.$ENV{'STY'}.' -X width -w ' . $irssi_width;
|
||||
# wait another second for the resizing, and then redraw.
|
||||
Irssi::timeout_add_once(1000,sub {$screen_resizing = 0; redraw()}, []);
|
||||
}
|
||||
|
||||
sub sig_terminal_resized {
|
||||
if ($screen_resizing) {
|
||||
return;
|
||||
}
|
||||
$screen_resizing = 1;
|
||||
Irssi::timeout_add_once(1000,\&screen_size,[]);
|
||||
}
|
||||
|
||||
|
||||
### both ###
|
||||
|
||||
sub nicklist_write_start {
|
||||
if ($mode == $SCREEN) {
|
||||
print STDERR "\033P\033[s\033\\"; # save cursor
|
||||
}
|
||||
}
|
||||
|
||||
sub nicklist_write_end {
|
||||
if ($mode == $SCREEN) {
|
||||
print STDERR "\033P\033[u\033\\"; # restore cursor
|
||||
}
|
||||
}
|
||||
|
||||
sub nicklist_write_line {
|
||||
my ($line, $data) = @_;
|
||||
if ($mode == $SCREEN) {
|
||||
print STDERR "\033P\033[" . ($line+1) . ';'. ($irssi_width+1) .'H'. $screen_prefix . $data . "\033\\";
|
||||
} elsif ($mode == $FIFO) {
|
||||
$data = "\033[m$data"; # reset color
|
||||
if ($line == $cursor_line+1) {
|
||||
$data = "\n$data"; # next line
|
||||
} elsif ($line == $cursor_line) {
|
||||
$data = "\033[1G".$data; # back to beginning of line
|
||||
} else {
|
||||
$data = "\033[".($line+1).";0H".$data; # jump
|
||||
}
|
||||
$cursor_line=$line;
|
||||
print(FIFO $data) or fifo_stop();
|
||||
}
|
||||
}
|
||||
|
||||
sub calc_prefix_friends {
|
||||
my ($nick) = @_;
|
||||
|
||||
return '' unless $check_friends
|
||||
&& $nick->{'host'}
|
||||
&& is_friend($active_channel->{'server'}->{'chatnet'}, $active_channel->{'name'}, $nick->{'nick'}, $nick->{'host'});
|
||||
|
||||
my $flags = get_flags($active_channel->{'server'}->{'chatnet'}, $active_channel->{'name'}, $nick->{'nick'}, $nick->{'host'});
|
||||
|
||||
my $prefix;
|
||||
foreach my $prefix_friend (@prefix_friends) {
|
||||
if ($prefix_friend->{'flags'} eq 'noflag') {
|
||||
if ($flags eq '') {
|
||||
$prefix = $prefix_friend->{'prefix'};
|
||||
last;
|
||||
}
|
||||
} elsif (check_modes($flags, $prefix_friend->{'flags'})) {
|
||||
$prefix = $prefix_friend->{'prefix'};
|
||||
}
|
||||
}
|
||||
|
||||
return $prefix ? $prefix : '';
|
||||
}
|
||||
|
||||
# recalc the text of the nicklist item
|
||||
sub calc_text {
|
||||
my ($nick) = @_;
|
||||
my $tmp = $nicklist_width-3;
|
||||
(my $text = $nick->{'nick'}) =~ s/^(.{$tmp})..+$/$1\033[34m~/; # strip nick if too long
|
||||
|
||||
my $prefix_mode = $prefix_mode{$nick->{'modeflag'}};
|
||||
if (! defined($prefix_mode) ) {
|
||||
$prefix_mode = $nick->{'modeflag'};
|
||||
}
|
||||
|
||||
my $prefix_friends = calc_prefix_friends($nick);
|
||||
|
||||
$nick->{'text'} =
|
||||
$prefix_mode .
|
||||
$prefix_friends .
|
||||
$text .
|
||||
(' ' x ($nicklist_width-length($nick->{'nick'})-1)) .
|
||||
"\033[m"; # reset
|
||||
$nick->{'cmp'} = $nick->{'modepos'}.lc($nick->{'nick'});
|
||||
}
|
||||
|
||||
# redraw the given nick (nr) if it is visible
|
||||
sub redraw_nick_nr {
|
||||
my ($nr) = @_;
|
||||
my $line = $nr - $scroll_pos;
|
||||
if ($line >= 0 && $line < $height) {
|
||||
nicklist_write_line($line, $nicklist[$nr]->{'text'});
|
||||
}
|
||||
}
|
||||
|
||||
# nick was inserted, redraw area if necessary
|
||||
sub draw_insert_nick_nr {
|
||||
my ($nr) = @_;
|
||||
my $line = $nr - $scroll_pos;
|
||||
if ($line < 0) { # nick is inserted above visible area
|
||||
$scroll_pos++; # 'scroll' down :)
|
||||
} elsif ($line < $height) { # line is visible
|
||||
if ($mode == $SCREEN) {
|
||||
need_redraw();
|
||||
} elsif ($mode == $FIFO) {
|
||||
my $data = "\033[m\033[L". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
|
||||
if ($line == $cursor_line) {
|
||||
$data = "\033[1G".$data; # back to beginning of line
|
||||
} else {
|
||||
$data = "\033[".($line+1).";1H".$data; # jump
|
||||
}
|
||||
$cursor_line=$line;
|
||||
print(FIFO $data) or fifo_stop();
|
||||
if ($prev_lines < $height) {
|
||||
$prev_lines++; # the nicklist has one line more
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_remove_nick_nr {
|
||||
my ($nr) = @_;
|
||||
my $line = $nr - $scroll_pos;
|
||||
if ($line < 0) { # nick removed above visible area
|
||||
$scroll_pos--; # 'scroll' up :)
|
||||
} elsif ($line < $height) { # line is visible
|
||||
if ($mode == $SCREEN) {
|
||||
need_redraw();
|
||||
} elsif ($mode == $FIFO) {
|
||||
#my $data = "\033[m\033[L[i$line]". $nicklist[$nr]->{'text'}; # reset color & insert line & write nick
|
||||
my $data = "\033[M"; # delete line
|
||||
if ($line != $cursor_line) {
|
||||
$data = "\033[".($line+1)."d".$data; # jump
|
||||
}
|
||||
$cursor_line=$line;
|
||||
print(FIFO $data) or fifo_stop();
|
||||
if (@nicklist-$scroll_pos >= $height) {
|
||||
redraw_nick_nr($scroll_pos+$height-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# redraw the whole nicklist
|
||||
sub redraw {
|
||||
$need_redraw = 0;
|
||||
#make_nicklist();
|
||||
nicklist_write_start();
|
||||
my $line = 0;
|
||||
### draw nicklist ###
|
||||
for (my $i=$scroll_pos;$line < $height && $i < @nicklist; $i++) {
|
||||
nicklist_write_line($line++, $nicklist[$i]->{'text'});
|
||||
}
|
||||
|
||||
### clean up other lines ###
|
||||
my $real_lines = $line;
|
||||
while($line < $prev_lines) {
|
||||
nicklist_write_line($line++,' ' x $nicklist_width);
|
||||
}
|
||||
$prev_lines = $real_lines;
|
||||
nicklist_write_end();
|
||||
}
|
||||
|
||||
# redraw (with little delay to avoid redrawing to much)
|
||||
sub need_redraw {
|
||||
if(!$need_redraw) {
|
||||
$need_redraw = 1;
|
||||
Irssi::timeout_add_once(10,\&redraw,[]);
|
||||
}
|
||||
}
|
||||
|
||||
sub sig_page_scrolled {
|
||||
$prev_lines = $height; # we'll need to redraw everything if he scrolled up
|
||||
need_redraw;
|
||||
}
|
||||
|
||||
# redraw (with delay) if the window is visible (only in screen mode)
|
||||
sub sig_gui_print_text_finished {
|
||||
if ($need_redraw) { # there's already a redraw 'queued'
|
||||
return;
|
||||
}
|
||||
my $window = @_[0];
|
||||
if ($window->{'refnum'} == Irssi::active_win->{'refnum'} || Irssi::settings_get_str('nicklist_screen_split_windows') eq '*') {
|
||||
need_redraw;
|
||||
return;
|
||||
}
|
||||
foreach my $win (split(/[ ,]/, Irssi::settings_get_str('nicklist_screen_split_windows'))) {
|
||||
if ($window->{'refnum'} == $win || $window->{'name'} eq $win) {
|
||||
need_redraw;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
###################
|
||||
##### FRIENDS #####
|
||||
###################
|
||||
|
||||
# checks if $has_modes is in $need_modes, copied from trigger.pl
|
||||
sub check_modes {
|
||||
my ($has_modes, $need_modes) = @_;
|
||||
my $matches;
|
||||
my $switch = 1; # if a '-' if found, will be 0 (meaning the modes should not be set)
|
||||
foreach my $need_mode (split /&/,$need_modes) {
|
||||
$matches = 0;
|
||||
foreach my $char (split //,$need_mode) {
|
||||
if ($char eq '-') {
|
||||
$switch = 0;
|
||||
} elsif ($char eq '+') {
|
||||
$switch = 1;
|
||||
} elsif ((index($has_modes,$char) != -1) == $switch) {
|
||||
$matches = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (!$matches) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# get someones flags from people.pl or friends(_shasta).pl, copied from trigger.pl
|
||||
sub get_flags {
|
||||
my ($chatnet, $channel, $nick, $address) = @_;
|
||||
my $flags;
|
||||
no strict 'refs';
|
||||
if (defined %{ 'Irssi::Script::people::' }) {
|
||||
if (defined ($channel)) {
|
||||
$flags = (&{ 'Irssi::Script::people::find_local_flags' }($chatnet,$channel,$nick,$address));
|
||||
} else {
|
||||
$flags = (&{ 'Irssi::Script::people::find_global_flags' }($chatnet,$nick,$address));
|
||||
}
|
||||
$flags = join('',keys(%{$flags}));
|
||||
} else {
|
||||
my $shasta;
|
||||
if (defined %{ 'Irssi::Script::friends_shasta::' }) {
|
||||
$shasta = 'friends_shasta';
|
||||
} elsif (defined &{ 'Irssi::Script::friends::get_idx' }) {
|
||||
$shasta = 'friends';
|
||||
}
|
||||
if (!$shasta) {
|
||||
return undef;
|
||||
}
|
||||
my $idx = (&{ 'Irssi::Script::'.$shasta.'::get_idx' }($nick,$address));
|
||||
if ($idx == -1) {
|
||||
return '';
|
||||
}
|
||||
$flags = (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,undef));
|
||||
if ($channel) {
|
||||
$flags .= (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,$channel));
|
||||
}
|
||||
}
|
||||
return $flags;
|
||||
}
|
||||
|
||||
sub is_friend {
|
||||
my ($chatnet, $channel, $nick, $address) = @_;
|
||||
no strict 'refs';
|
||||
if (defined %{ 'Irssi::Script::people::' }) {
|
||||
return (() != &{'Irssi::Script::people::find_users'}($chatnet, $nick, $address));
|
||||
my $flags;
|
||||
if (defined ($channel)) {
|
||||
$flags = (&{ 'Irssi::Script::people::find_local_flags' }($chatnet,$channel,$nick,$address));
|
||||
} else {
|
||||
$flags = (&{ 'Irssi::Script::people::find_global_flags' }($chatnet,$nick,$address));
|
||||
}
|
||||
return ($flags ne ''); # TODO: test this
|
||||
} else {
|
||||
my $shasta;
|
||||
if (defined %{ 'Irssi::Script::friends_shasta::' }) {
|
||||
$shasta = 'friends_shasta';
|
||||
} elsif (defined &{ 'Irssi::Script::friends::get_idx' }) {
|
||||
$shasta = 'friends';
|
||||
}
|
||||
if (!$shasta) {
|
||||
return undef;
|
||||
}
|
||||
my $idx = (&{ 'Irssi::Script::'.$shasta.'::get_idx' }($nick,$address));
|
||||
return ($idx != -1);
|
||||
}
|
||||
}
|
||||
|
||||
####################
|
||||
##### NICKLIST #####
|
||||
####################
|
||||
|
||||
# returns the position of the given nick(as string) in the (internal) nicklist
|
||||
sub find_nick {
|
||||
my ($nick) = @_;
|
||||
for (my $i=0;$i < @nicklist; $i++) {
|
||||
if ($nicklist[$i]->{'nick'} eq $nick) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
# find position where nick should be inserted into the list
|
||||
sub find_insert_pos {
|
||||
my ($cmp)= @_;
|
||||
for (my $i=0;$i < @nicklist; $i++) {
|
||||
if ($nicklist[$i]->{'cmp'} gt $cmp) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
return scalar(@nicklist); #last
|
||||
}
|
||||
|
||||
# make the (internal) nicklist (@nicklist)
|
||||
sub make_nicklist {
|
||||
@nicklist = ();
|
||||
$scroll_pos = 0;
|
||||
|
||||
### get & check channel ###
|
||||
my $channel = Irssi::active_win->{active};
|
||||
|
||||
if (!$channel || (ref($channel) ne 'Irssi::Irc::Channel' && ref($channel) ne 'Irssi::Silc::Channel') || $channel->{'type'} ne 'CHANNEL' || ($channel->{chat_type} ne 'SILC' && !$channel->{'names_got'}) ) {
|
||||
$active_channel = undef;
|
||||
# no nicklist
|
||||
} else {
|
||||
$active_channel = $channel;
|
||||
### make nicklist ###
|
||||
foreach my $nick ($channel->nicks()) {
|
||||
my $thisnick = {'nick' => $nick->{'nick'}};
|
||||
recalc_nick($thisnick, $nick);
|
||||
push @nicklist, $thisnick;
|
||||
}
|
||||
@nicklist = sort {$a->{'cmp'} cmp $b->{'cmp'}} @nicklist;
|
||||
}
|
||||
need_redraw();
|
||||
}
|
||||
|
||||
# insert nick(as hash) into nicklist
|
||||
# pre: cmp has to be calculated
|
||||
sub insert_nick {
|
||||
my ($nick) = @_;
|
||||
my $nr = find_insert_pos($nick->{'cmp'});
|
||||
splice @nicklist, $nr, 0, $nick;
|
||||
draw_insert_nick_nr($nr);
|
||||
}
|
||||
|
||||
# remove nick(as nr) from nicklist
|
||||
sub remove_nick {
|
||||
my ($nr) = @_;
|
||||
splice @nicklist, $nr, 1;
|
||||
draw_remove_nick_nr($nr);
|
||||
}
|
||||
|
||||
# update the mode and cmp of a nick, based on a nickrec from irssi
|
||||
sub recalc_nick {
|
||||
my ($nick, $nickrec) = @_;
|
||||
if (! $nickrec) {
|
||||
$nickrec = $active_channel->nick_find($nick->{'nick'});
|
||||
}
|
||||
|
||||
my $nickflags = $active_channel->{'server'}->get_nick_flags() . ' ';
|
||||
|
||||
my $flag = (
|
||||
$nickrec->{'op'} ? '@' :
|
||||
$nickrec->{'halfop'} ? '%' :
|
||||
$nickrec->{'voice'} ? '+' :
|
||||
' '
|
||||
);
|
||||
|
||||
if ($nickrec->{'other'} && index($nickflags, $nick->{'other'}) < index($nickflags, $flag)) {
|
||||
$flag = chr($nickrec->{'other'});
|
||||
}
|
||||
|
||||
$nick->{'modepos'} = index($nickflags, $flag);
|
||||
$nick->{'modeflag'} = $flag;
|
||||
|
||||
$nick->{'host'} = $nickrec->{'host'};
|
||||
calc_text($nick);
|
||||
}
|
||||
|
||||
###################
|
||||
##### ACTIONS #####
|
||||
###################
|
||||
|
||||
# scroll the nicklist, arg = number of lines to scroll, positive = down, negative = up
|
||||
sub cmd_scroll {
|
||||
if (!$active_channel) { # not a channel active
|
||||
return;
|
||||
}
|
||||
my @nicks=Irssi::active_win->{active}->nicks;
|
||||
my $nick_count = scalar(@nicks)+0;
|
||||
my $channel = Irssi::active_win->{active};
|
||||
if (!$channel || $channel->{type} ne 'CHANNEL' || !$channel->{names_got} || $nick_count <= Irssi::settings_get_int('nicklist_height')) {
|
||||
return;
|
||||
}
|
||||
$scroll_pos += @_[0];
|
||||
|
||||
if ($scroll_pos > $nick_count - $height) {
|
||||
$scroll_pos = $nick_count - $height;
|
||||
}
|
||||
if ($scroll_pos <= 0) {
|
||||
$scroll_pos = 0;
|
||||
}
|
||||
need_redraw();
|
||||
}
|
||||
|
||||
sub is_active_channel {
|
||||
my ($server,$channel) = @_; # (channel as string)
|
||||
return ($server && $server->{'tag'} eq $active_channel->{'server'}->{'tag'} && $server->channel_find($channel) && $active_channel && $server->channel_find($channel)->{'name'} eq $active_channel->{'name'});
|
||||
}
|
||||
|
||||
sub sig_channel_wholist { # this is actualy a little late, when the names are received would be better
|
||||
my ($channel) = @_;
|
||||
if (Irssi::active_win->{'active'} && Irssi::active_win->{'active'}->{'name'} eq $channel->{'name'}) { # the channel joined is active
|
||||
make_nicklist
|
||||
}
|
||||
}
|
||||
|
||||
sub sig_join {
|
||||
my ($server,$channel,$nick,$address) = @_;
|
||||
if (!is_active_channel($server,$channel)) {
|
||||
return;
|
||||
}
|
||||
my $newnick = {'nick' => $nick};
|
||||
recalc_nick($newnick);
|
||||
insert_nick($newnick);
|
||||
}
|
||||
|
||||
sub sig_kick {
|
||||
my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
|
||||
if (!is_active_channel($server,$channel)) {
|
||||
return;
|
||||
}
|
||||
my $nr = find_nick($nick);
|
||||
if ($nr == -1) {
|
||||
Irssi::print("nicklist warning: $nick was kicked from $channel, but not found in nicklist");
|
||||
} else {
|
||||
remove_nick($nr);
|
||||
}
|
||||
}
|
||||
|
||||
sub sig_part {
|
||||
my ($server,$channel,$nick,$address, $reason) = @_;
|
||||
if (!is_active_channel($server,$channel)) {
|
||||
return;
|
||||
}
|
||||
my $nr = find_nick($nick);
|
||||
if ($nr == -1) {
|
||||
Irssi::print("nicklist warning: $nick has parted $channel, but was not found in nicklist");
|
||||
} else {
|
||||
remove_nick($nr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub sig_quit {
|
||||
my ($server,$nick,$address, $reason) = @_;
|
||||
if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
|
||||
return;
|
||||
}
|
||||
my $nr = find_nick($nick);
|
||||
if ($nr != -1) {
|
||||
remove_nick($nr);
|
||||
}
|
||||
}
|
||||
|
||||
sub sig_nick {
|
||||
my ($server, $newnick, $oldnick, $address) = @_;
|
||||
if ($server->{'tag'} ne $active_channel->{'server'}->{'tag'}) {
|
||||
return;
|
||||
}
|
||||
my $nr = find_nick($oldnick);
|
||||
if ($nr != -1) { # if nick was found (nickchange is in current channel)
|
||||
my $nick = $nicklist[$nr];
|
||||
remove_nick($nr);
|
||||
$nick->{'nick'} = $newnick;
|
||||
calc_text($nick);
|
||||
insert_nick($nick);
|
||||
}
|
||||
}
|
||||
|
||||
sub sig_mode {
|
||||
my ($channel, $nick, $setby, $mode, $type) = @_; # (nick and channel as rec)
|
||||
if ($channel->{'server'}->{'tag'} ne $active_channel->{'server'}->{'tag'} || $channel->{'name'} ne $active_channel->{'name'}) {
|
||||
return;
|
||||
}
|
||||
my $nr = find_nick($nick->{'nick'});
|
||||
if ($nr == -1) {
|
||||
Irssi::print("nicklist warning: $nick->{'nick'} had mode set on $channel->{'name'}, but was not found in nicklist");
|
||||
} else {
|
||||
my $nicklist_item = $nicklist[$nr];
|
||||
remove_nick($nr);
|
||||
recalc_nick($nicklist_item, $nick);
|
||||
insert_nick($nicklist_item);
|
||||
}
|
||||
}
|
||||
|
||||
##### command binds #####
|
||||
Irssi::command_bind 'nicklist' => sub {
|
||||
my ( $data, $server, $item ) = @_;
|
||||
$data =~ s/\s+$//g;
|
||||
Irssi::command_runsub ('nicklist', $data, $server, $item ) ;
|
||||
};
|
||||
Irssi::signal_add_first 'default command nicklist' => sub {
|
||||
# gets triggered if called with unknown subcommand
|
||||
cmd_help();
|
||||
};
|
||||
Irssi::command_bind('nicklist update',\&update);
|
||||
Irssi::command_bind('nicklist help',\&cmd_help);
|
||||
Irssi::command_bind('nicklist scroll',\&cmd_scroll);
|
||||
Irssi::command_bind('nicklist fifo',\&cmd_fifo_start);
|
||||
Irssi::command_bind('nicklist screen',\&cmd_screen_start);
|
||||
Irssi::command_bind('nicklist screensize',\&screen_size);
|
||||
Irssi::command_bind('nicklist off',\&cmd_off);
|
||||
|
||||
##### signals #####
|
||||
Irssi::signal_add_last('window item changed', \&make_nicklist);
|
||||
Irssi::signal_add_last('window changed', \&make_nicklist);
|
||||
Irssi::signal_add_last('channel wholist', \&sig_channel_wholist);
|
||||
Irssi::signal_add_first('message join', \&sig_join); # first, to be before ignores
|
||||
Irssi::signal_add_first('message part', \&sig_part);
|
||||
Irssi::signal_add_first('message kick', \&sig_kick);
|
||||
Irssi::signal_add_first('message quit', \&sig_quit);
|
||||
Irssi::signal_add_first('message nick', \&sig_nick);
|
||||
Irssi::signal_add_first('message own_nick', \&sig_nick);
|
||||
Irssi::signal_add_first('nick mode changed', \&sig_mode);
|
||||
|
||||
Irssi::signal_add('setup changed', \&read_settings);
|
||||
|
||||
##### settings #####
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_screen_prefix', '\e[m ');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_op', '\e[32m@\e[39m');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_halfop', '\e[34m%\e[39m');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_voice', '\e[33m+\e[39m');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_normal', ' ');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_mode_other', '&=\e[31m&\e[39m ~=\e[35m~\e[39m');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_prefix_friends', 'o=\e[32m v=\e[33m noflag=\e[1m');
|
||||
|
||||
Irssi::settings_add_int('nicklist', 'nicklist_width',11);
|
||||
Irssi::settings_add_int('nicklist', 'nicklist_height',24);
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_fifo_path', Irssi::get_irssi_dir . '/nicklistfifo');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_screen_split_windows', '');
|
||||
Irssi::settings_add_str('nicklist', 'nicklist_automode', '');
|
||||
|
||||
read_settings();
|
||||
if (uc(Irssi::settings_get_str('nicklist_automode')) eq 'SCREEN') {
|
||||
cmd_screen_start();
|
||||
} elsif (uc(Irssi::settings_get_str('nicklist_automode')) eq 'FIFO') {
|
||||
cmd_fifo_start();
|
||||
}
|
||||
425
irssi/scripts/tmux-nicklist-portable.pl
Normal file
425
irssi/scripts/tmux-nicklist-portable.pl
Normal file
@@ -0,0 +1,425 @@
|
||||
# based on the nicklist.pl script
|
||||
################################################################################
|
||||
# tmux_nicklist.pl
|
||||
# This script integrates tmux and irssi to display a list of nicks in a
|
||||
# vertical right pane with 20% width. Right now theres no configuration
|
||||
# or setup, simply initialize the script with irssi and by default you
|
||||
# will get the nicklist for every channel(customize by altering
|
||||
# the regex in /set nicklist_channel_re)
|
||||
#
|
||||
# /set nicklist_channel_re <regex>
|
||||
# * only show on channels matching this regular expression
|
||||
#
|
||||
# /set nicklist_max_users <num>
|
||||
# * only show when the channel has so many users or less (0 = always)
|
||||
#
|
||||
# /set nicklist_smallest_main <num>
|
||||
# * only show when main window is larger than this (0 = always)
|
||||
#
|
||||
# /set nicklist_pane_width <num>
|
||||
# * width of the nicklist pane
|
||||
#
|
||||
# /set nicklist_color <ON|OFF>
|
||||
# * colourise the nicks in the nicklist (required nickcolor script
|
||||
# with get_nick_color2 and debug_ansicolour functions)
|
||||
#
|
||||
# /set nicklist_gone_sort <ON|OFF>
|
||||
# * sort away people below
|
||||
#
|
||||
# It supports mouse scrolling and the following keys:
|
||||
# k/up arrow: up one line
|
||||
# j/down arrow: down one line
|
||||
# pageup: up 20 lines
|
||||
# pagedown: down 20 lines
|
||||
# gg: go to top
|
||||
# G: go to bottom
|
||||
#
|
||||
# For better integration, unrecognized sequences will be sent to irssi and
|
||||
# its pane will be focused.
|
||||
#
|
||||
# to toggle the nicklist if it is in the way you can make a key binding:
|
||||
# /bind meta-Z /script exec Irssi::Script::tmux_nicklist_portable::toggle_nicklist
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Handle;
|
||||
use IO::Select;
|
||||
use POSIX;
|
||||
use File::Temp qw/ :mktemp /;
|
||||
use File::Basename;
|
||||
our $VERSION = '0.1.6'; # aea329934f6a48c
|
||||
our %IRSSI = (
|
||||
authors => 'Thiago de Arruda',
|
||||
contact => 'tpadilha84@gmail.com',
|
||||
name => 'tmux-nicklist',
|
||||
description => 'displays a list of nicks in a separate tmux pane',
|
||||
license => 'WTFPL',
|
||||
);
|
||||
|
||||
# "other" prefixes by danielg4 <daniel@gimpelevich.san-francisco.ca.us>
|
||||
|
||||
{ package Irssi::Nick }
|
||||
|
||||
if ($#ARGV == -1) {
|
||||
require Irssi;
|
||||
|
||||
my $enabled = 0;
|
||||
my $nicklist_toggle = 1;
|
||||
my $script_path = __FILE__;
|
||||
my $tmpdir;
|
||||
my $fifo_path;
|
||||
my $fifo;
|
||||
my $just_launched;
|
||||
my $resize_timer;
|
||||
|
||||
sub enable_nicklist {
|
||||
return if ($enabled);
|
||||
$tmpdir = mkdtemp Irssi::get_irssi_dir()."/nicklist-XXXXXXXX";
|
||||
$fifo_path = "$tmpdir/fifo";
|
||||
POSIX::mkfifo($fifo_path, 0600) or die "can't mkfifo $fifo_path: $!";
|
||||
my $cmd = "perl $script_path $fifo_path $ENV{TMUX_PANE}";
|
||||
my $width = Irssi::settings_get_int('nicklist_pane_width');
|
||||
system('tmux', 'split-window', '-dh', '-l', $width, '-t', $ENV{TMUX_PANE}, $cmd);
|
||||
open_fifo();
|
||||
Irssi::timeout_remove($just_launched) if defined $just_launched;
|
||||
$just_launched = Irssi::timeout_add_once(300, sub { $just_launched = undef; }, '');
|
||||
}
|
||||
|
||||
sub open_fifo {
|
||||
# The next system call will block until the other pane has opened the pipe
|
||||
# for reading, so synchronization is not an issue here.
|
||||
open $fifo, ">", $fifo_path or do {
|
||||
if ($! == 4) {
|
||||
Irssi::timeout_add_once(300, \&open_fifo, '');
|
||||
$enabled = -1 unless $enabled;
|
||||
return;
|
||||
}
|
||||
die "can't open $fifo_path: $!";
|
||||
};
|
||||
$fifo->autoflush(1);
|
||||
if ($enabled < -1) {
|
||||
$enabled = 1;
|
||||
disable_nicklist();
|
||||
} elsif ($enabled == -1) {
|
||||
$enabled = 1;
|
||||
reset_nicklist("enabled");
|
||||
} else {
|
||||
$enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub disable_nicklist {
|
||||
return unless ($enabled);
|
||||
if ($enabled > 0) {
|
||||
print $fifo "EXIT\n";
|
||||
close $fifo;
|
||||
$fifo = undef;
|
||||
unlink $fifo_path;
|
||||
rmdir $tmpdir;
|
||||
}
|
||||
$enabled--;
|
||||
}
|
||||
|
||||
sub reset_nicklist {
|
||||
my $event = shift;
|
||||
my $active = Irssi::active_win();
|
||||
my $channel = $active->{active};
|
||||
return disable_nicklist unless $channel && ref $channel;
|
||||
if ($event =~ /^nick/) {
|
||||
# check if that nick event is for the current channel/nicklist
|
||||
my ($event_channel) = @_;
|
||||
return unless $channel->{_irssi} == $event_channel->{_irssi};
|
||||
}
|
||||
my ($colourer, $ansifier);
|
||||
if (Irssi::settings_get_bool('nicklist_color')) {
|
||||
for my $script (sort map { my $z = $_; $z =~ s/::$//; $z } grep { /^nickcolor|nm/ } keys %Irssi::Script::) {
|
||||
if ($colourer = "Irssi::Script::$script"->can('get_nick_color2')) {
|
||||
$ansifier = "Irssi::Script::$script"->can('debug_ansicolour');
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
my $channel_pattern = Irssi::settings_get_str('nicklist_channel_re');
|
||||
{ local $@;
|
||||
$channel_pattern = eval { qr/$channel_pattern/ };
|
||||
$channel_pattern = qr/(?!)/ if $@;
|
||||
}
|
||||
my $smallest_main = Irssi::settings_get_int('nicklist_smallest_main');
|
||||
if (!$nicklist_toggle
|
||||
|| !$channel || !ref($channel)
|
||||
|| !$channel->isa('Irssi::Channel')
|
||||
|| !$channel->{'names_got'}
|
||||
|| $channel->{'name'} !~ $channel_pattern
|
||||
|| ($smallest_main && $channel->window->{width} < $smallest_main)) {
|
||||
disable_nicklist;
|
||||
} else {
|
||||
my %colour;
|
||||
my @nicks = $channel->nicks();
|
||||
my $max_nicks = Irssi::settings_get_int('nicklist_max_users');
|
||||
if ($max_nicks && @nicks > $max_nicks) {
|
||||
disable_nicklist;
|
||||
} else {
|
||||
enable_nicklist;
|
||||
return unless $enabled > 0;
|
||||
foreach my $nick (sort { $a->{_irssi} <=> $b->{_irssi} } @nicks) {
|
||||
$colour{$nick->{nick}} = ($ansifier && $colourer) ? $ansifier->($colourer->($active->{active}{server}{tag}, $channel->{name}, $nick->{nick}, 0)) : '';
|
||||
}
|
||||
print($fifo "BEGIN\n");
|
||||
my $gone_sort = Irssi::settings_get_bool('nicklist_gone_sort');
|
||||
my $prefer_real;
|
||||
if (exists $Irssi::Script::{'realnames::'}) {
|
||||
my $code = "Irssi::Script::realnames"->can('use_realnames');
|
||||
$prefer_real = $code && $code->($channel);
|
||||
}
|
||||
my $_real = sub {
|
||||
my $nick = shift;
|
||||
$prefer_real && length $nick->{'realname'} ? $nick->{'realname'} : $nick->{'nick'}
|
||||
};
|
||||
foreach my $nick (sort {($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':$a->{'other'}>32?'0':'4').($gone_sort?($a->{'gone'}?1:0):'').lc($_real->($a))
|
||||
cmp ($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':$b->{'other'}>32?'0':'4').($gone_sort?($b->{'gone'}?1:0):'').lc($_real->($b))} @nicks) {
|
||||
my $colour = $colour{$nick->{nick}} || "\e[39m";
|
||||
$colour = "\e[37m" if $nick->{'gone'};
|
||||
print($fifo "NICK");
|
||||
if ($nick->{'op'}) {
|
||||
print($fifo "\e[32m\@$colour".$_real->($nick)."\e[39m");
|
||||
} elsif ($nick->{'halfop'}) {
|
||||
print($fifo "\e[34m%$colour".$_real->($nick)."\e[39m");
|
||||
} elsif ($nick->{'voice'}) {
|
||||
print($fifo "\e[33m+$colour".$_real->($nick)."\e[39m");
|
||||
} elsif ($nick->{'other'}>32) {
|
||||
print($fifo "\e[31m".(chr $nick->{'other'})."$colour".$_real->($nick)."\e[39m");
|
||||
} else {
|
||||
print($fifo " $colour".$_real->($nick)."\e[39m");
|
||||
}
|
||||
print($fifo "\n");
|
||||
}
|
||||
print($fifo "END\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub toggle_nicklist {
|
||||
if ($enabled) {
|
||||
$nicklist_toggle = undef
|
||||
} else {
|
||||
$nicklist_toggle = 1;
|
||||
}
|
||||
reset_nicklist("toggle");
|
||||
}
|
||||
|
||||
sub switch_channel {
|
||||
print $fifo "SWITCH_CHANNEL\n" if $fifo;
|
||||
&reset_nicklist;
|
||||
}
|
||||
|
||||
sub resized_timed {
|
||||
Irssi::timeout_remove($resize_timer) if defined $resize_timer;
|
||||
return if defined $just_launched;
|
||||
$resize_timer = Irssi::timeout_add_once(1100, \&resized, '');
|
||||
#resized();
|
||||
}
|
||||
sub resized {
|
||||
$resize_timer = undef;
|
||||
return if defined $just_launched;
|
||||
return unless $enabled >= 0;
|
||||
disable_nicklist;
|
||||
Irssi::timeout_add_once(200, sub{reset_nicklist("terminal resized")}, '');
|
||||
}
|
||||
sub UNLOAD {
|
||||
disable_nicklist;
|
||||
}
|
||||
|
||||
Irssi::settings_add_str('tmux_nicklist', 'nicklist_channel_re', '.*');
|
||||
Irssi::settings_add_int('tmux_nicklist', 'nicklist_max_users', 0);
|
||||
Irssi::settings_add_int('tmux_nicklist', 'nicklist_smallest_main', 0);
|
||||
Irssi::settings_add_int('tmux_nicklist', 'nicklist_pane_width', 13);
|
||||
Irssi::settings_add_bool('tmux_nicklist', 'nicklist_color', 1);
|
||||
Irssi::settings_add_bool('tmux_nicklist', 'nicklist_gone_sort', 0);
|
||||
Irssi::signal_add_last('window item changed', sub{switch_channel("window item changed",@_)});
|
||||
Irssi::signal_add_last('window changed', sub{switch_channel("window changed",@_)});
|
||||
Irssi::signal_add_last('channel joined', sub{switch_channel("channel joined",@_)});
|
||||
Irssi::signal_add('nicklist new', sub{reset_nicklist("nicklist new",@_)});
|
||||
Irssi::signal_add('nicklist remove', sub{reset_nicklist("nicklist remove",@_)});
|
||||
Irssi::signal_add('nicklist changed', sub{reset_nicklist("nicklist changed",@_)});
|
||||
Irssi::signal_add_first('nick mode changed', sub{reset_nicklist("nick mode changed",@_)});
|
||||
Irssi::signal_add('gui exit', \&disable_nicklist);
|
||||
Irssi::signal_add_last('terminal resized', \&resized_timed);
|
||||
|
||||
} else {
|
||||
my $fifo_path = $ARGV[0];
|
||||
my $irssi_pane = $ARGV[1];
|
||||
# array to store the current channel nicknames
|
||||
my @nicknames = ();
|
||||
|
||||
# helper functions for manipulating the terminal
|
||||
# escape sequences taken from
|
||||
# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
|
||||
sub enable_mouse { print "\e[?1000h"; }
|
||||
# recognized sequences
|
||||
my $MOUSE_SCROLL_DOWN="\e[Ma";
|
||||
my $MOUSE_SCROLL_UP="\e[M`";
|
||||
my $ARROW_DOWN="\e[B";
|
||||
my $ARROW_UP="\e[A";
|
||||
my $UP="k";
|
||||
my $DOWN="j";
|
||||
my $PAGE_DOWN="\e[6~";
|
||||
my $PAGE_UP="\e[5~";
|
||||
my $GO_TOP="gg";
|
||||
my $GO_BOTTOM="G";
|
||||
|
||||
my $current_line = 0;
|
||||
my $sequence = '';
|
||||
my ($rows, $cols);
|
||||
|
||||
sub term_size {
|
||||
split ' ', `stty size`;
|
||||
}
|
||||
|
||||
sub redraw {
|
||||
my $last_nick_idx = @nicknames;
|
||||
my $last_idx = $current_line + $rows;
|
||||
# normalize last visible index
|
||||
if ($last_idx > ($last_nick_idx)) {
|
||||
$last_idx = $last_nick_idx;
|
||||
}
|
||||
# redraw visible nicks
|
||||
for my $i (reverse 1..$rows) {
|
||||
print "\e[$i;1H\e[K";
|
||||
my $idx = $current_line + $i - 1;
|
||||
if ($idx < $last_idx) {
|
||||
my $z = 0; my $col = $cols;
|
||||
for (split /(\e\[(?:\d|;|:|\?|\s)*.)/, $nicknames[$idx]) {
|
||||
if ($z ^= 1) {
|
||||
print +(substr $_, 0, $col) if $col > 0;
|
||||
$col -= length;
|
||||
} else {
|
||||
print
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub move_down {
|
||||
$sequence = '';
|
||||
my $count = int $_[0];
|
||||
my $nickcount = $#nicknames;
|
||||
return if ($nickcount <= $rows);
|
||||
if ($count == -1) {
|
||||
$current_line = $nickcount - $rows - 1;
|
||||
redraw;
|
||||
return;
|
||||
}
|
||||
my $visible = $nickcount - $current_line - $count;
|
||||
if ($visible > $rows) {
|
||||
$current_line += $count;
|
||||
redraw;
|
||||
} elsif (($visible + $count) > $rows) {
|
||||
# scroll the maximum we can
|
||||
$current_line = $nickcount - $rows - 1;
|
||||
redraw;
|
||||
}
|
||||
}
|
||||
|
||||
sub move_up {
|
||||
$sequence = '';
|
||||
my $count = int $_[0];
|
||||
if ($count == -1) {
|
||||
$current_line = 0;
|
||||
redraw;
|
||||
return;
|
||||
}
|
||||
return if ($current_line == 0);
|
||||
$count = 1 if $count == 0;
|
||||
$current_line -= $count;
|
||||
$current_line = 0 if $current_line < 0;
|
||||
redraw;
|
||||
}
|
||||
|
||||
$SIG{INT} = 'IGNORE';
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
# setup terminal so we can listen for individual key presses without echo
|
||||
`stty -icanon -echo`;
|
||||
|
||||
# open named pipe and setup the 'select' wrapper object for listening on both
|
||||
# fds(fifo and sdtin)
|
||||
open my $fifo, "<", $fifo_path or die "can't open $fifo_path: $!";
|
||||
my $select = IO::Select->new();
|
||||
my @ready;
|
||||
$select->add($fifo);
|
||||
$select->add(\*STDIN);
|
||||
|
||||
enable_mouse;
|
||||
system('tput', 'smcup');
|
||||
print "\e[?7l"; #system('tput', 'rmam');
|
||||
system('tput', 'civis');
|
||||
MAIN: {
|
||||
while (@ready = $select->can_read) {
|
||||
foreach my $fd (@ready) {
|
||||
($rows, $cols) = term_size;
|
||||
if ($fd == $fifo) {
|
||||
while (<$fifo>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /^BEGIN/) {
|
||||
@nicknames = ();
|
||||
} elsif ($line =~ /^SWITCH_CHANNEL/) {
|
||||
$current_line = 0;
|
||||
} elsif ($line =~ /^NICK(.+)$/) {
|
||||
push @nicknames, $1;
|
||||
} elsif ($line =~ /^END$/) {
|
||||
redraw;
|
||||
last;
|
||||
} elsif ($line =~ /^EXIT$/) {
|
||||
last MAIN;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my $key = '';
|
||||
sysread(STDIN, $key, 1);
|
||||
$sequence .= $key;
|
||||
if ($MOUSE_SCROLL_DOWN =~ /^\Q$sequence\E/) {
|
||||
if ($MOUSE_SCROLL_DOWN eq $sequence) {
|
||||
move_down 3;
|
||||
# mouse scroll has two more bytes that I dont use here
|
||||
# so consume them now to avoid sending unwanted bytes to
|
||||
# irssi
|
||||
sysread(STDIN, $key, 2);
|
||||
}
|
||||
} elsif ($MOUSE_SCROLL_UP =~ /^\Q$sequence\E/) {
|
||||
if ($MOUSE_SCROLL_UP eq $sequence) {
|
||||
move_up 3;
|
||||
sysread(STDIN, $key, 2);
|
||||
}
|
||||
} elsif ($ARROW_DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down 1 if ($ARROW_DOWN eq $sequence);
|
||||
} elsif ($ARROW_UP =~ /^\Q$sequence\E/) {
|
||||
move_up 1 if ($ARROW_UP eq $sequence);
|
||||
} elsif ($DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down 1 if ($DOWN eq $sequence);
|
||||
} elsif ($UP =~ /^\Q$sequence\E/) {
|
||||
move_up 1 if ($UP eq $sequence);
|
||||
} elsif ($PAGE_DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down $rows/2 if ($PAGE_DOWN eq $sequence);
|
||||
} elsif ($PAGE_UP =~ /^\Q$sequence\E/) {
|
||||
move_up $rows/2 if ($PAGE_UP eq $sequence);
|
||||
} elsif ($GO_BOTTOM =~ /^\Q$sequence\E/) {
|
||||
move_down -1 if ($GO_BOTTOM eq $sequence);
|
||||
} elsif ($GO_TOP =~ /^\Q$sequence\E/) {
|
||||
move_up -1 if ($GO_TOP eq $sequence);
|
||||
} else {
|
||||
# Unrecognized sequences will be send to irssi and its pane
|
||||
# will be focused
|
||||
system('tmux', 'send-keys', '-t', $irssi_pane, $sequence);
|
||||
system('tmux', 'select-pane', '-t', $irssi_pane);
|
||||
$sequence = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close $fifo;
|
||||
|
||||
}
|
||||
304
irssi/scripts/tmux-nicklist.pl
Normal file
304
irssi/scripts/tmux-nicklist.pl
Normal file
@@ -0,0 +1,304 @@
|
||||
# based on the nicklist.pl script
|
||||
################################################################################
|
||||
# tmux_nicklist.pl
|
||||
# This script integrates tmux and irssi to display a list of nicks in a
|
||||
# vertical right pane with 20% width. Right now theres no configuration
|
||||
# or setup, simply initialize the script with irssi and by default you
|
||||
# will get the nicklist for every channel(customize by altering
|
||||
# the regex in '$channel_pattern'.
|
||||
#
|
||||
# It supports mouse scrolling and the following keys:
|
||||
# k/up arrow: up one line
|
||||
# j/down arrow: down one line
|
||||
# pageup: up 20 lines
|
||||
# pagedown: down 20 lines
|
||||
# gg: go to top
|
||||
# G: go to bottom
|
||||
#
|
||||
# For better integration, unrecognized sequences will be sent to irssi and
|
||||
# its pane will be focused.
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use IO::Handle;
|
||||
use IO::Select;
|
||||
use POSIX;
|
||||
use File::Temp qw/ :mktemp /;
|
||||
use File::Basename;
|
||||
use vars qw($VERSION %IRSSI);
|
||||
$VERSION = '0.0.0';
|
||||
%IRSSI = (
|
||||
authors => 'Thiago de Arruda',
|
||||
contact => 'tpadilha84@gmail.com',
|
||||
name => 'tmux-nicklist',
|
||||
description => 'displays a list of nicks in a separate tmux pane',
|
||||
license => 'WTFPL',
|
||||
);
|
||||
|
||||
if ($#ARGV == -1) {
|
||||
require Irssi;
|
||||
|
||||
my $enabled = 0;
|
||||
my $script_path = __FILE__;
|
||||
my $tmpdir;
|
||||
my $fifo_path;
|
||||
# my $channel_pattern = '^&bitlbee$';
|
||||
my $channel_pattern = '^.+$';
|
||||
|
||||
sub enable_nicklist {
|
||||
return if ($enabled);
|
||||
$tmpdir = mkdtemp "/tmp/nicklist-XXXXXXXX";
|
||||
$fifo_path = "$tmpdir/fifo";
|
||||
POSIX::mkfifo($fifo_path, 0600) or die "can\'t mkfifo $fifo_path: $!";
|
||||
my $cmd = "perl $script_path $fifo_path $ENV{'TMUX_PANE'}";
|
||||
system('tmux', 'split-window', '-dh', '-p', '20', $cmd);
|
||||
# The next system call will block until the other pane has opened the pipe
|
||||
# for reading, so synchronization is not an issue here.
|
||||
open (FIFO, "> $fifo_path") or die "can't open $fifo_path: $!";
|
||||
FIFO->autoflush(1);
|
||||
$enabled = 1;
|
||||
}
|
||||
|
||||
sub disable_nicklist {
|
||||
return unless ($enabled);
|
||||
print(FIFO "EXIT\n");
|
||||
close FIFO;
|
||||
unlink $fifo_path;
|
||||
rmdir $tmpdir;
|
||||
$enabled = 0;
|
||||
}
|
||||
|
||||
sub reset_nicklist {
|
||||
my $active = Irssi::active_win();
|
||||
my $channel = $active->{active};
|
||||
|
||||
if ((!$channel ||
|
||||
(ref($channel) ne 'Irssi::Irc::Channel' && ref($channel) ne
|
||||
'Irssi::Silc::Channel') || $channel->{'type'} ne 'CHANNEL' ||
|
||||
($channel->{chat_type} ne 'SILC' && !$channel->{'names_got'})) ||
|
||||
($channel->{'name'} !~ /$channel_pattern/ )) {
|
||||
disable_nicklist;
|
||||
} else {
|
||||
enable_nicklist;
|
||||
print(FIFO "BEGIN\n");
|
||||
foreach my $nick (sort {(($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':'4').lc($a->{'nick'}))
|
||||
cmp (($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':'4').lc($b->{'nick'}))} $channel->nicks()) {
|
||||
print(FIFO "NICK");
|
||||
if ($nick->{'op'}) {
|
||||
print(FIFO "\e[32m\@$nick->{'nick'}\e[39m");
|
||||
} elsif ($nick->{'halfop'}) {
|
||||
print(FIFO "\e[34m%$nick->{'nick'}\e[39m");
|
||||
} elsif ($nick->{'voice'}) {
|
||||
print(FIFO "\e[33m+$nick->{'nick'}\e[39m");
|
||||
} else {
|
||||
print(FIFO " $nick->{'nick'}");
|
||||
}
|
||||
print(FIFO "\n");
|
||||
}
|
||||
print(FIFO "END\n");
|
||||
}
|
||||
}
|
||||
|
||||
sub switch_channel {
|
||||
print(FIFO "SWITCH_CHANNEL\n");
|
||||
reset_nicklist;
|
||||
}
|
||||
|
||||
Irssi::signal_add_last('window item changed', \&switch_channel);
|
||||
Irssi::signal_add_last('window changed', \&switch_channel);
|
||||
Irssi::signal_add_last('channel wholist', \&reset_nicklist);
|
||||
# first, to be before ignores
|
||||
Irssi::signal_add_first('message join', \&reset_nicklist);
|
||||
Irssi::signal_add_first('message part', \&reset_nicklist);
|
||||
Irssi::signal_add_first('message kick', \&reset_nicklist);
|
||||
Irssi::signal_add_first('message quit', \&reset_nicklist);
|
||||
Irssi::signal_add_first('message nick', \&reset_nicklist);
|
||||
Irssi::signal_add_first('message own_nick', \&reset_nicklist);
|
||||
Irssi::signal_add_first('nick mode changed', \&reset_nicklist);
|
||||
Irssi::signal_add('gui exit', \&disable_nicklist);
|
||||
|
||||
} else {
|
||||
require 'sys/ioctl.ph';
|
||||
# open STDERR, '>', "$ENV{'HOME'}/.nickbar-errors.log";
|
||||
my $fifo_path = $ARGV[0];
|
||||
my $irssi_pane = $ARGV[1];
|
||||
# array to store the current channel nicknames
|
||||
my @nicknames = ();
|
||||
|
||||
# helper functions for manipulating the terminal
|
||||
# escape sequences taken from
|
||||
# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
|
||||
sub clear_screen { print "\e[2J"; }
|
||||
sub save_cursor { print "\e[s"; }
|
||||
sub restore_cursor { print "\e[u"; }
|
||||
sub enable_mouse { print "\e[?1000h"; }
|
||||
# recognized sequences
|
||||
my $MOUSE_SCROLL_DOWN="\e[Ma";
|
||||
my $MOUSE_SCROLL_UP="\e[M`";
|
||||
my $ARROW_DOWN="\e[B";
|
||||
my $ARROW_UP="\e[A";
|
||||
my $UP="k";
|
||||
my $DOWN="j";
|
||||
my $PAGE_DOWN="\e[6~";
|
||||
my $PAGE_UP="\e[5~";
|
||||
my $GO_TOP="gg";
|
||||
my $GO_BOTTOM="G";
|
||||
|
||||
my $current_line = 0;
|
||||
my $sequence = '';
|
||||
|
||||
sub term_row_count {
|
||||
# from http://stackoverflow.com/questions/4286158/how-do-i-get-width-and-height-of-my-terminal-with-ioctl
|
||||
my $terminal_size;
|
||||
ioctl(STDOUT, TIOCGWINSZ() , $terminal_size);
|
||||
my ($rows, $cols, $xpix, $ypix) = unpack 'S4', $terminal_size;
|
||||
return $rows;
|
||||
}
|
||||
|
||||
sub redraw {
|
||||
my $rows = term_row_count;
|
||||
my $last_nick_idx = $#nicknames;
|
||||
my $last_idx = $current_line + $rows;
|
||||
# normalize last visible index
|
||||
if ($last_idx > ($last_nick_idx)) {
|
||||
$last_idx = $last_nick_idx;
|
||||
}
|
||||
# redraw visible nicks
|
||||
restore_cursor;
|
||||
clear_screen;
|
||||
for (my $idx = $current_line; $idx <= $last_idx; $idx++) {
|
||||
print "$nicknames[$idx]\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub move_down {
|
||||
$sequence = '';
|
||||
my $count = $_[0];
|
||||
my $nickcount = $#nicknames;
|
||||
my $rows = term_row_count;
|
||||
return if ($nickcount <= $rows);
|
||||
if ($count == -1) {
|
||||
$current_line = $nickcount - $rows - 1;
|
||||
redraw;
|
||||
return;
|
||||
}
|
||||
my $visible = $nickcount - $current_line - $count;
|
||||
if ($visible > $rows) {
|
||||
$current_line += $count;
|
||||
redraw;
|
||||
} elsif (($visible + $count) > $rows) {
|
||||
# scroll the maximum we can
|
||||
$current_line = $nickcount - $rows - 1;
|
||||
redraw;
|
||||
}
|
||||
}
|
||||
|
||||
sub move_up {
|
||||
$sequence = '';
|
||||
my $count = $_[0];
|
||||
if ($count == -1) {
|
||||
$current_line = 0;
|
||||
redraw;
|
||||
return;
|
||||
}
|
||||
return if ($current_line == 0);
|
||||
if (($current_line - $count) >= 0) {
|
||||
$current_line -= $count;
|
||||
redraw;
|
||||
}
|
||||
}
|
||||
|
||||
$SIG{INT} = 'IGNORE';
|
||||
|
||||
# setup terminal so we can listen for individual key presses without echo
|
||||
my ($term, $oterm, $echo, $noecho, $fd_stdin);
|
||||
$fd_stdin = fileno(STDIN);
|
||||
$term = POSIX::Termios->new();
|
||||
$term->getattr($fd_stdin);
|
||||
$oterm = $term->getlflag();
|
||||
$echo = ECHO | ECHOK | ICANON;
|
||||
$noecho = $oterm & ~$echo;
|
||||
$term->setlflag($noecho);
|
||||
$term->setcc(VTIME, 1);
|
||||
$term->setattr($fd_stdin, TCSANOW);
|
||||
|
||||
# open named pipe and setup the 'select' wrapper object for listening on both
|
||||
# fds(fifo and sdtin)
|
||||
open (FIFO, "< $fifo_path") or die "can't open $fifo_path: $!";
|
||||
my $fifo = \*FIFO;
|
||||
my $stdin = \*STDIN;
|
||||
my $select = IO::Select->new();
|
||||
my @ready;
|
||||
$select->add($fifo);
|
||||
$select->add($stdin);
|
||||
|
||||
save_cursor;
|
||||
enable_mouse;
|
||||
system('tput', 'civis');
|
||||
MAIN: {
|
||||
while (@ready = $select->can_read) {
|
||||
foreach my $fd (@ready) {
|
||||
if ($fd == $fifo) {
|
||||
while (<$fifo>) {
|
||||
my $line = $_;
|
||||
if ($line =~ /^BEGIN/) {
|
||||
@nicknames = ();
|
||||
} elsif ($line =~ /^SWITCH_CHANNEL/) {
|
||||
$current_line = 0;
|
||||
} elsif ($line =~ /^NICK(.+)$/) {
|
||||
push @nicknames, $1;
|
||||
} elsif ($line =~ /^END$/) {
|
||||
redraw;
|
||||
last;
|
||||
} elsif ($line =~ /^EXIT$/) {
|
||||
last MAIN;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my $key = '';
|
||||
sysread(STDIN, $key, 1);
|
||||
$sequence .= $key;
|
||||
if ($MOUSE_SCROLL_DOWN =~ /^\Q$sequence\E/) {
|
||||
if ($MOUSE_SCROLL_DOWN eq $sequence) {
|
||||
move_down 3;
|
||||
# mouse scroll has two more bytes that I dont use here
|
||||
# so consume them now to avoid sending unwanted bytes to
|
||||
# irssi
|
||||
sysread(STDIN, $key, 2);
|
||||
}
|
||||
} elsif ($MOUSE_SCROLL_UP =~ /^\Q$sequence\E/) {
|
||||
if ($MOUSE_SCROLL_UP eq $sequence) {
|
||||
move_up 3;
|
||||
sysread(STDIN, $key, 2);
|
||||
}
|
||||
} elsif ($ARROW_DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down 1 if ($ARROW_DOWN eq $sequence);
|
||||
} elsif ($ARROW_UP =~ /^\Q$sequence\E/) {
|
||||
move_up 1 if ($ARROW_UP eq $sequence);
|
||||
} elsif ($DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down 1 if ($DOWN eq $sequence);
|
||||
} elsif ($UP =~ /^\Q$sequence\E/) {
|
||||
move_up 1 if ($UP eq $sequence);
|
||||
} elsif ($PAGE_DOWN =~ /^\Q$sequence\E/) {
|
||||
move_down 20 if ($PAGE_DOWN eq $sequence);
|
||||
} elsif ($PAGE_UP =~ /^\Q$sequence\E/) {
|
||||
move_up 20 if ($PAGE_UP eq $sequence);
|
||||
} elsif ($GO_BOTTOM =~ /^\Q$sequence\E/) {
|
||||
move_down -1 if ($GO_BOTTOM eq $sequence);
|
||||
} elsif ($GO_TOP =~ /^\Q$sequence\E/) {
|
||||
move_up -1 if ($GO_TOP eq $sequence);
|
||||
} else {
|
||||
# Unrecognized sequences will be send to irssi and its pane
|
||||
# will be focused
|
||||
system('tmux', 'send-keys', '-l', '-t', $irssi_pane, $sequence);
|
||||
system('tmux', 'select-pane', '-t', $irssi_pane);
|
||||
$sequence = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close FIFO;
|
||||
|
||||
}
|
||||
189
irssi/scripts/trackbar.pl
Executable file
189
irssi/scripts/trackbar.pl
Executable file
@@ -0,0 +1,189 @@
|
||||
# trackbar.pl
|
||||
#
|
||||
# This little script will do just one thing: it will draw a line each time you
|
||||
# switch away from a window. This way, you always know just upto where you've
|
||||
# been reading that window :) It also removes the previous drawn line, so you
|
||||
# don't see double lines.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# The script works right out of the box, but if you want you can change
|
||||
# the working by /set'ing the following variables:
|
||||
#
|
||||
# trackbar_string The characters to repeat to draw the bar
|
||||
# trackbar_style The style for the bar, %r is red for example
|
||||
# See formats.txt that came with irssi
|
||||
#
|
||||
# /mark is a command that will redraw the line at the bottom. However! This
|
||||
# requires irssi version after 20021228. otherwise you'll get the error
|
||||
# redraw: unknown command, and your screen is all goofed up :)
|
||||
#
|
||||
# /upgrade & buf.pl notice: This version tries to remove the trackbars before
|
||||
# the upgrade is done, so buf.pl does not restore them, as they are not removeable
|
||||
# afterwards by trackbar. Unfortiounatly, to make this work, trackbar and buf.pl
|
||||
# need to be loaded in a specific order. Please experiment to see which order works
|
||||
# for you (strangely, it differs from configuration to configuration, something I will
|
||||
# try to fix in a next version)
|
||||
#
|
||||
# Authors:
|
||||
# - Main maintainer & author: Peter 'kinlo' Leurs
|
||||
# - Many thanks to Timo 'cras' Sirainen for placing me on my way
|
||||
# - on-upgrade-remove-line patch by Uwe Dudenhoeffer
|
||||
#
|
||||
# Version history:
|
||||
# 1.4: - Changed our's by my's so the irssi script header is valid
|
||||
# - Removed utf-8 support. In theory, the script should work w/o any
|
||||
# problems for utf-8, just set trackbar_string to a valid utf-8 character
|
||||
# and everything *should* work. However, this script is being plagued by
|
||||
# irssi internal bugs. The function Irssi::settings_get_str does NOT handle
|
||||
# unicode strings properly, hence you will notice problems when setting the bar
|
||||
# to a unicode char. For changing your bar to utf-8 symbols, read the line sub.
|
||||
# 1.3: - Upgrade now removes the trackbars.
|
||||
# - Some code cleanups, other defaults
|
||||
# - /mark sets the line to the bottom
|
||||
# 1.2: - Support for utf-8
|
||||
# - How the bar looks can now be configured with trackbar_string
|
||||
# and trackbar_style
|
||||
# 1.1: - Fixed bug when closing window
|
||||
# 1.0: - Initial release
|
||||
#
|
||||
#
|
||||
# Call for help!
|
||||
#
|
||||
# There is a trackbar version 2.0 that properly handles resizes and immediate config change
|
||||
# activation. However, there is/are some bug(s) in irssi's main buffer/window code that causes
|
||||
# irssi to 'forget' lines, which is ofcourse completly unaccepteable. I haven't found the time
|
||||
# nor do I know the irssi's internals enough to find and fix this bug, if you want to help, please
|
||||
# contact me, I'll give you a copy of the 2.0 version that will immediatly show you the problems.
|
||||
#
|
||||
# Known bugs:
|
||||
# - if you /clear a window, it will be uncleared when returning to the window
|
||||
# - UTF-8 characters in the trackbar_string doesnt work. This is an irssi bug.
|
||||
# - if you resize your irssi (in xterm or so) the bar is not resized
|
||||
# - changing the trackbar style is only visible after returning to a window
|
||||
# however, changing style/resize takes in effect after you left the window.
|
||||
#
|
||||
# Whishlist/todo:
|
||||
# - instead of drawing a line, just invert timestamp or something,
|
||||
# to save a line (but I don't think this is possible with current irssi)
|
||||
# - some pageup keybinding possibility, to scroll up upto the trackbar
|
||||
# - <@coekie> kinlo: if i switch to another window, in another split window, i
|
||||
# want the trackbar to go down in the previouswindow in that splitwindow :)
|
||||
# - < bob_2> anyway to clear the line once the window is read?
|
||||
# - < elho> kinlo: wishlist item: a string that gets prepended to the repeating pattern
|
||||
# - < elho> an option to still have the timestamp in front of the bar
|
||||
# - < elho> oh and an option to not draw it in the status window :P
|
||||
#
|
||||
# BTW: when you have feature requests, mailing a patch that works is the fastest way
|
||||
# to get it added :p
|
||||
|
||||
use strict;
|
||||
use 5.6.1;
|
||||
use Irssi;
|
||||
use Irssi::TextUI;
|
||||
|
||||
my $VERSION = "1.4";
|
||||
|
||||
my %IRSSI = (
|
||||
authors => "Peter 'kinlo' Leurs",
|
||||
contact => "peter\@pfoe.be",
|
||||
name => "trackbar",
|
||||
description => "Shows a bar where you've last read a window",
|
||||
license => "GPLv2",
|
||||
url => "http://www.pfoe.be/~peter/trackbar/",
|
||||
changed => "Thu Feb 20 16:18:08 2003",
|
||||
);
|
||||
|
||||
my %config;
|
||||
|
||||
Irssi::settings_add_str('trackbar', 'trackbar_string' => '_');
|
||||
$config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
|
||||
|
||||
Irssi::settings_add_str('trackbar', 'trackbar_style' => '%K');
|
||||
$config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
|
||||
|
||||
Irssi::signal_add(
|
||||
'setup changed' => sub {
|
||||
$config{'trackbar_string'} = Irssi::settings_get_str('trackbar_string');
|
||||
$config{'trackbar_style'} = Irssi::settings_get_str('trackbar_style');
|
||||
if ($config{'trackbar_style'} =~ /(?<!%)[^%]|%%|%$/) {
|
||||
Irssi::print(
|
||||
"trackbar: %RWarning!%n 'trackbar_style' seems to contain "
|
||||
. "printable characters. Only use format codes (read "
|
||||
. "formats.txt).", MSGLEVEL_CLIENTERROR);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Irssi::signal_add(
|
||||
'window changed' => sub {
|
||||
my (undef, $oldwindow) = @_;
|
||||
|
||||
if ($oldwindow) {
|
||||
my $line = $oldwindow->view()->get_bookmark('trackbar');
|
||||
$oldwindow->view()->remove_line($line) if defined $line;
|
||||
$oldwindow->print(line($oldwindow->{'width'}), MSGLEVEL_NEVER);
|
||||
$oldwindow->view()->set_bookmark_bottom('trackbar');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
sub line {
|
||||
my $width = shift;
|
||||
my $string = $config{'trackbar_string'};
|
||||
$string = '-' unless defined $string;
|
||||
|
||||
# There is a bug in irssi's utf-8 handling on config file settings, as you
|
||||
# can reproduce/see yourself by the following code sniplet:
|
||||
#
|
||||
# my $quake = pack 'U*', 8364; # EUR symbol
|
||||
# Irssi::settings_add_str 'temp', 'temp_foo' => $quake;
|
||||
# Irssi::print length $quake;
|
||||
# # prints 1
|
||||
# Irssi::print length Irssi::settings_get_str 'temp_foo';
|
||||
# # prints 3
|
||||
#
|
||||
#
|
||||
# Trackbar used to have a workaround, but on recent versions of perl/irssi
|
||||
# it does no longer work. Therefore, if you want your trackbar to contain
|
||||
# unicode characters, uncomment the line below for a nice full line, or set
|
||||
# the string to whatever char you want.
|
||||
|
||||
# $string = pack('U*', 0x2500);
|
||||
|
||||
|
||||
my $length = length $string;
|
||||
|
||||
if ($length == 0) {
|
||||
$string = '-';
|
||||
$length = 1;
|
||||
}
|
||||
|
||||
my $times = $width / $length;
|
||||
$times = int(1 + $times) if $times != int($times);
|
||||
$string =~ s/%/%%/g;
|
||||
return $config{'trackbar_style'} . substr($string x $times, 0, $width);
|
||||
}
|
||||
|
||||
# Remove trackbars on upgrade - but this doesn't really work if the scripts are not loaded in the correct order... watch out!
|
||||
|
||||
Irssi::signal_add_first( 'session save' => sub {
|
||||
for my $window (Irssi::windows) {
|
||||
next unless defined $window;
|
||||
my $line = $window->view()->get_bookmark('trackbar');
|
||||
$window->view()->remove_line($line) if defined $line;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
sub cmd_mark {
|
||||
my $window = Irssi::active_win();
|
||||
# return unless defined $window;
|
||||
my $line = $window->view()->get_bookmark('trackbar');
|
||||
$window->view()->remove_line($line) if defined $line;
|
||||
$window->print(line($window->{'width'}), MSGLEVEL_NEVER);
|
||||
$window->view()->set_bookmark_bottom('trackbar');
|
||||
Irssi::command("redraw");
|
||||
}
|
||||
|
||||
Irssi::command_bind('mark', 'cmd_mark');
|
||||
500
irssi/scripts/trackbar22.pl
Normal file
500
irssi/scripts/trackbar22.pl
Normal file
@@ -0,0 +1,500 @@
|
||||
# trackbar.pl
|
||||
#
|
||||
# This little script will do just one thing: it will draw a line each time you
|
||||
# switch away from a window. This way, you always know just upto where you've
|
||||
# been reading that window :) It also removes the previous drawn line, so you
|
||||
# don't see double lines.
|
||||
#
|
||||
# redraw trackbar only works on irssi 0.8.17 or higher.
|
||||
#
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# The script works right out of the box, but if you want you can change
|
||||
# the working by /set'ing the following variables:
|
||||
#
|
||||
# Setting: trackbar_style
|
||||
# Description: This setting will be the color of your trackbar line.
|
||||
# By default the value will be '%K', only Irssi color
|
||||
# formats are allowed. If you don't know the color formats
|
||||
# by heart, you can take a look at the formats documentation.
|
||||
# You will find the proper docs on http://www.irssi.org/docs.
|
||||
#
|
||||
# Setting: trackbar_string
|
||||
# Description: This is the string that your line will display. This can
|
||||
# be multiple characters or just one. For example: '~-~-'
|
||||
# The default setting is '-'.
|
||||
#
|
||||
# Setting: trackbar_use_status_window
|
||||
# Description: If this setting is set to OFF, Irssi won't print a trackbar
|
||||
# in the statuswindow
|
||||
#
|
||||
# Setting: trackbar_ignore_windows
|
||||
# Description: A list of windows where no trackbar should be printed
|
||||
#
|
||||
# Setting: trackbar_print_timestamp
|
||||
# Description: If this setting is set to ON, Irssi will print the formatted
|
||||
# timestamp in front of the trackbar.
|
||||
#
|
||||
# Setting: trackbar_require_seen
|
||||
# Description: Only clear the trackbar if it has been scrolled to.
|
||||
#
|
||||
# /mark is a command that will redraw the line at the bottom.
|
||||
#
|
||||
# Command: /trackbar, /trackbar goto
|
||||
# Description: Jump to where the trackbar is, to pick up reading
|
||||
#
|
||||
# Command: /trackbar keep
|
||||
# Description: Keep this window's trackbar where it is the next time
|
||||
# you switch windows (then this flag is cleared again)
|
||||
#
|
||||
# Command: /mark, /trackbar mark
|
||||
# Description: Remove the old trackbar and mark the bottom of this
|
||||
# window with a new trackbar
|
||||
#
|
||||
# Command: /trackbar markvisible
|
||||
# Description: Like mark for all visible windows
|
||||
#
|
||||
# Command: /trackbar markall
|
||||
# Description: Like mark for all windows
|
||||
#
|
||||
# Command: /trackbar remove
|
||||
# Description: Remove this window's trackbar
|
||||
#
|
||||
# Command: /trackbar removeall
|
||||
# Description: Remove all windows' trackbars
|
||||
#
|
||||
# Command: /trackbar redraw
|
||||
# Description: Force redraw of trackbars
|
||||
#
|
||||
|
||||
|
||||
# For bugreports and other improvements contact one of the authors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this script; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Irssi;
|
||||
use Irssi::TextUI;
|
||||
use Encode;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
use vars qw($VERSION %IRSSI);
|
||||
|
||||
$VERSION = "2.2"; # cb3189a33c8e5f9
|
||||
|
||||
%IRSSI = (
|
||||
authors => 'Peter Leurs and Geert Hauwaerts',
|
||||
contact => 'peter@pfoe.be',
|
||||
patchers => 'Johan Kiviniemi (UTF-8), Uwe Dudenhoeffer (on-upgrade-remove-line)',
|
||||
name => 'trackbar',
|
||||
description => 'Shows a bar where you have last read a window.',
|
||||
license => 'GNU General Public License',
|
||||
url => 'http://www.pfoe.be/~peter/trackbar/',
|
||||
changed => 'Fri Jan 23 23:59:11 2004',
|
||||
commands => 'trackbar',
|
||||
);
|
||||
|
||||
## Comments and remarks.
|
||||
#
|
||||
# This script uses settings.
|
||||
# Use /SET to change the value or /TOGGLE to switch it on or off.
|
||||
#
|
||||
#
|
||||
# Tip: The command 'trackbar' is very usefull if you bind that to a key,
|
||||
# so you can easily jump to the trackbar. Please see 'help bind' for
|
||||
# more information about keybindings in Irssi.
|
||||
#
|
||||
# Command: /BIND meta2-P key F1
|
||||
# /BIND F1 command trackbar
|
||||
#
|
||||
##
|
||||
|
||||
## Bugfixes and new items in this rewrite.
|
||||
#
|
||||
# * Remove all the trackbars before upgrading.
|
||||
# * New setting trackbar_use_status_window to control the statuswindow trackbar.
|
||||
# * New setting trackbar_print_timestamp to print a timestamp or not.
|
||||
# * New command 'trackbar' to scroll up to the trackbar.
|
||||
# * When resizing your terminal, Irssi will update all the trackbars to the new size.
|
||||
# * When changing trackbar settings, change all the trackbars to the new settings.
|
||||
# * New command 'trackbar mark' to draw a new trackbar (The old '/mark').
|
||||
# * New command 'trackbar markall' to draw a new trackbar in each window.
|
||||
# * New command 'trackbar remove' to remove the trackbar from the current window.
|
||||
# * New command 'trackbar removeall' to remove all the trackbars.
|
||||
# * Don't draw a trackbar in empty windows.
|
||||
# * Added a version check to prevent Irssi redraw errors.
|
||||
# * Fixed a bookmark NULL versus 0 bug.
|
||||
# * Fixed a remove-line bug in Uwe Dudenhoeffer his patch.
|
||||
# * New command 'help trackbar' to display the trackbar commands.
|
||||
# * Fixed an Irssi startup bug, now processing each auto-created window.
|
||||
#
|
||||
##
|
||||
|
||||
## Known bugs and the todolist.
|
||||
#
|
||||
# Todo: * Instead of drawing a line, invert the line.
|
||||
#
|
||||
##
|
||||
|
||||
sub cmd_help {
|
||||
my ($args) = @_;
|
||||
if ($args =~ /^trackbar *$/i) {
|
||||
print CLIENTCRAP <<HELP
|
||||
%9Syntax:%9
|
||||
|
||||
TRACKBAR
|
||||
TRACKBAR GOTO
|
||||
TRACKBAR KEEP
|
||||
TRACKBAR MARK
|
||||
TRACKBAR MARKVISIBLE
|
||||
TRACKBAR MARKALL
|
||||
TRACKBAR REMOVE
|
||||
TRACKBAR REMOVEALL
|
||||
TRACKBAR REDRAW
|
||||
|
||||
%9Parameters:%9
|
||||
|
||||
GOTO: Jump to where the trackbar is, to pick up reading
|
||||
KEEP: Keep this window's trackbar where it is the next time
|
||||
you switch windows (then this flag is cleared again)
|
||||
MARK: Remove the old trackbar and mark the bottom of this
|
||||
window with a new trackbar
|
||||
MARKVISIBLE: Like mark for all visible windows
|
||||
MARKALL: Like mark for all windows
|
||||
REMOVE: Remove this window's trackbar
|
||||
REMOVEALL: Remove all windows' trackbars
|
||||
REDRAW: Force redraw of trackbars
|
||||
|
||||
%9Description:%9
|
||||
|
||||
Manage a trackbar. Without arguments, it will scroll up to the trackbar.
|
||||
|
||||
%9Examples:%9
|
||||
|
||||
/TRACKBAR MARK
|
||||
/TRACKBAR REMOVE
|
||||
HELP
|
||||
}
|
||||
}
|
||||
|
||||
Irssi::theme_register([
|
||||
'trackbar_loaded', '%R>>%n %_Scriptinfo:%_ Loaded $0 version $1 by $2.',
|
||||
'trackbar_wrong_version', '%R>>%n %_Trackbar:%_ Please upgrade your client to 0.8.17 or above if you would like to use this feature of trackbar.',
|
||||
'trackbar_all_removed', '%R>>%n %_Trackbar:%_ All the trackbars have been removed.',
|
||||
'trackbar_not_found', '%R>>%n %_Trackbar:%_ No trackbar found in this window.',
|
||||
]);
|
||||
|
||||
my $old_irssi = Irssi::version < 20140701;
|
||||
sub check_version {
|
||||
if ($old_irssi) {
|
||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_wrong_version');
|
||||
return;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub is_utf8 {
|
||||
lc Irssi::settings_get_str('term_charset') eq 'utf-8'
|
||||
}
|
||||
|
||||
my (%config, %keep_trackbar, %unseen_trackbar);
|
||||
|
||||
sub remove_one_trackbar {
|
||||
my $win = shift;
|
||||
my $view = shift || $win->view;
|
||||
my $line = $view->get_bookmark('trackbar');
|
||||
if (defined $line) {
|
||||
my $bottom = $view->{bottom};
|
||||
$view->remove_line($line);
|
||||
$win->command('^scrollback end') if $bottom && !$win->view->{bottom};
|
||||
$view->redraw;
|
||||
}
|
||||
}
|
||||
|
||||
sub add_one_trackbar {
|
||||
my $win = shift;
|
||||
my $view = shift || $win->view;
|
||||
$win->print(line($win->{width}), MSGLEVEL_NEVER);
|
||||
$view->set_bookmark_bottom('trackbar');
|
||||
$unseen_trackbar{ $win->{_irssi} } = 1;
|
||||
$view->redraw;
|
||||
}
|
||||
|
||||
sub update_one_trackbar {
|
||||
my $win = shift;
|
||||
my $view = shift || $win->view;
|
||||
my $force = shift;
|
||||
my $ignored = win_ignored($win, $view);
|
||||
remove_one_trackbar($win, $view)
|
||||
if $force || !defined $force || !$ignored;
|
||||
add_one_trackbar($win, $view)
|
||||
if $force || !$ignored;
|
||||
}
|
||||
|
||||
sub win_ignored {
|
||||
my $win = shift;
|
||||
my $view = shift || $win->view;
|
||||
return 1 unless $view->{buffer}{lines_count};
|
||||
return 1 if $win->{name} eq '(status)' && !$config{use_status_window};
|
||||
return 1 if grep { $win->{name} eq $_ || $win->{refnum} eq $_
|
||||
|| $win->get_active_name eq $_ } @{ $config{ignore_windows} };
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub sig_window_changed {
|
||||
my ($newwindow, $oldwindow) = @_;
|
||||
return unless $oldwindow;
|
||||
trackbar_update_seen($newwindow);
|
||||
return if delete $keep_trackbar{ $oldwindow->{_irssi} };
|
||||
trackbar_update_seen($oldwindow);
|
||||
return if $config{require_seen} && $unseen_trackbar{ $oldwindow->{_irssi } };
|
||||
update_one_trackbar($oldwindow, undef, 0);
|
||||
}
|
||||
|
||||
sub trackbar_update_seen {
|
||||
my $win = shift;
|
||||
return unless $win;
|
||||
my $view = $win->view;
|
||||
my $line = $view->get_bookmark('trackbar');
|
||||
unless ($line) {
|
||||
delete $unseen_trackbar{ $win->{_irssi} };
|
||||
return;
|
||||
}
|
||||
my $startline = $view->{startline};
|
||||
return unless $startline;
|
||||
|
||||
if ($startline->{info}{time} < $line->{info}{time}
|
||||
|| $startline->{_irssi} == $line->{_irssi}) {
|
||||
delete $unseen_trackbar{ $win->{_irssi} };
|
||||
}
|
||||
}
|
||||
|
||||
sub screen_length;
|
||||
{ local $@;
|
||||
eval { require Text::CharWidth; };
|
||||
unless ($@) {
|
||||
*screen_length = sub { Text::CharWidth::mbswidth($_[0]) };
|
||||
}
|
||||
else {
|
||||
*screen_length = sub {
|
||||
my $temp = shift;
|
||||
if (is_utf8()) {
|
||||
Encode::_utf8_on($temp);
|
||||
}
|
||||
length($temp)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
{ my %strip_table = (
|
||||
(map { $_ => '' } (split //, '04261537' . 'kbgcrmyw' . 'KBGCRMYW' . 'U9_8I:|FnN>#[' . 'pP')),
|
||||
(map { $_ => $_ } (split //, '{}%')),
|
||||
);
|
||||
sub c_length {
|
||||
my $o = Irssi::strip_codes($_[0]);
|
||||
$o =~ s/(%(%|Z.{6}|z.{6}|X..|x..|.))/exists $strip_table{$2} ? $strip_table{$2} :
|
||||
$2 =~ m{x(?:0[a-f]|[1-6][0-9a-z]|7[a-x])|z[0-9a-f]{6}}i ? '' : $1/gex;
|
||||
screen_length($o)
|
||||
}
|
||||
}
|
||||
|
||||
sub line {
|
||||
my ($width, $time) = @_;
|
||||
my $string = $config{string};
|
||||
$string = ' ' unless length $string;
|
||||
$time ||= time;
|
||||
|
||||
Encode::_utf8_on($string);
|
||||
my $length = c_length($string);
|
||||
|
||||
my $format = '';
|
||||
if ($config{print_timestamp}) {
|
||||
$format = $config{timestamp_str};
|
||||
$format =~ y/%/\01/;
|
||||
$format =~ s/\01\01/%/g;
|
||||
$format = strftime($format, localtime $time);
|
||||
$format =~ y/\01/%/;
|
||||
}
|
||||
|
||||
my $times = $width / $length;
|
||||
$times += 1 if $times != int $times;
|
||||
$format .= $config{style};
|
||||
$width -= c_length($format);
|
||||
$string x= $times;
|
||||
chop $string while length $string && c_length($string) > $width;
|
||||
return $format . $string;
|
||||
}
|
||||
|
||||
sub remove_all_trackbars {
|
||||
for my $window (Irssi::windows) {
|
||||
next unless ref $window;
|
||||
remove_one_trackbar($window);
|
||||
}
|
||||
}
|
||||
|
||||
sub UNLOAD {
|
||||
remove_all_trackbars();
|
||||
}
|
||||
|
||||
sub redraw_trackbars {
|
||||
return unless check_version();
|
||||
for my $win (Irssi::windows) {
|
||||
next unless ref $win;
|
||||
my $view = $win->view;
|
||||
my $line = $view->get_bookmark('trackbar');
|
||||
next unless $line;
|
||||
my $bottom = $view->{bottom};
|
||||
$win->print_after($line, MSGLEVEL_NEVER, line($win->{width}, $line->{info}{time}),
|
||||
$line->{info}{time});
|
||||
$view->set_bookmark('trackbar', $win->last_line_insert);
|
||||
$view->redraw;
|
||||
$view->remove_line($line);
|
||||
$win->command('^scrollback end') if $bottom && !$win->view->{bottom};
|
||||
$view->redraw;
|
||||
}
|
||||
}
|
||||
|
||||
sub goto_trackbar {
|
||||
my $win = Irssi::active_win;
|
||||
my $line = $win->view->get_bookmark('trackbar');
|
||||
|
||||
if ($line) {
|
||||
$win->command("scrollback goto ". strftime("%d %H:%M:%S", localtime($line->{info}{time})));
|
||||
} else {
|
||||
$win->printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_not_found');
|
||||
}
|
||||
}
|
||||
|
||||
sub cmd_mark {
|
||||
update_one_trackbar(Irssi::active_win, undef, 1);
|
||||
}
|
||||
|
||||
sub cmd_markall {
|
||||
for my $window (Irssi::windows) {
|
||||
next unless ref $window;
|
||||
update_one_trackbar($window);
|
||||
}
|
||||
}
|
||||
|
||||
sub signal_stop {
|
||||
Irssi::signal_stop;
|
||||
}
|
||||
|
||||
sub cmd_markvisible {
|
||||
my @wins = Irssi::windows;
|
||||
my $awin =
|
||||
my $bwin = Irssi::active_win;
|
||||
my $awin_counter = 0;
|
||||
Irssi::signal_add_priority('window changed' => 'signal_stop', -99);
|
||||
do {
|
||||
Irssi::active_win->command('window up');
|
||||
$awin = Irssi::active_win;
|
||||
update_one_trackbar($awin);
|
||||
++$awin_counter;
|
||||
} until ($awin->{refnum} == $bwin->{refnum} || $awin_counter >= @wins);
|
||||
Irssi::signal_remove('window changed' => 'signal_stop');
|
||||
}
|
||||
|
||||
sub cmd_trackbar_remove_one {
|
||||
remove_one_trackbar(Irssi::active_win);
|
||||
}
|
||||
|
||||
sub cmd_remove_all_trackbars {
|
||||
remove_all_trackbars();
|
||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_all_removed');
|
||||
}
|
||||
|
||||
sub cmd_keep_once {
|
||||
$keep_trackbar{ Irssi::active_win->{_irssi} } = 1;
|
||||
}
|
||||
|
||||
sub trackbar_runsub {
|
||||
my ($data, $server, $item) = @_;
|
||||
$data =~ s/\s+$//g;
|
||||
|
||||
if ($data) {
|
||||
Irssi::command_runsub('trackbar', $data, $server, $item);
|
||||
} else {
|
||||
goto_trackbar();
|
||||
}
|
||||
}
|
||||
|
||||
sub update_config {
|
||||
my $was_status_window = $config{use_status_window};
|
||||
$config{style} = Irssi::settings_get_str('trackbar_style');
|
||||
$config{string} = Irssi::settings_get_str('trackbar_string');
|
||||
$config{require_seen} = Irssi::settings_get_bool('trackbar_require_seen');
|
||||
$config{ignore_windows} = [ split /[,\s]+/, Irssi::settings_get_str('trackbar_ignore_windows') ];
|
||||
$config{use_status_window} = Irssi::settings_get_bool('trackbar_use_status_window');
|
||||
$config{print_timestamp} = Irssi::settings_get_bool('trackbar_print_timestamp');
|
||||
if (defined $was_status_window && $was_status_window != $config{use_status_window}) {
|
||||
if (my $swin = Irssi::window_find_name('(status)')) {
|
||||
if ($config{use_status_window}) {
|
||||
update_one_trackbar($swin);
|
||||
}
|
||||
else {
|
||||
remove_one_trackbar($swin);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($config{print_timestamp}) {
|
||||
my $ts_format = Irssi::settings_get_str('timestamp_format');
|
||||
my $ts_theme = Irssi::current_theme->get_format('fe-common/core', 'timestamp');
|
||||
my $render_str = Irssi::current_theme->format_expand($ts_theme);
|
||||
(my $ts_escaped = $ts_format) =~ s/([%\$])/$1$1/g;
|
||||
$render_str =~ s/(?|\$(.)(?!\w)|\$\{(\w+)\})/$1 eq 'Z' ? $ts_escaped : $1/ge;
|
||||
$config{timestamp_str} = $render_str;
|
||||
}
|
||||
redraw_trackbars() unless $old_irssi;
|
||||
}
|
||||
|
||||
Irssi::settings_add_str('trackbar', 'trackbar_string', is_utf8() ? "\x{2500}" : '-');
|
||||
Irssi::settings_add_str('trackbar', 'trackbar_style', '%K');
|
||||
Irssi::settings_add_str('trackbar', 'trackbar_ignore_windows', '');
|
||||
Irssi::settings_add_bool('trackbar', 'trackbar_use_status_window', 1);
|
||||
Irssi::settings_add_bool('trackbar', 'trackbar_print_timestamp', 0);
|
||||
Irssi::settings_add_bool('trackbar', 'trackbar_require_seen', 0);
|
||||
|
||||
update_config();
|
||||
|
||||
Irssi::signal_add_last( 'mainwindow resized' => 'redraw_trackbars')
|
||||
unless $old_irssi;
|
||||
|
||||
Irssi::signal_register({'gui page scrolled' => [qw/Irssi::UI::Window/]});
|
||||
Irssi::signal_add_last('gui page scrolled' => 'trackbar_update_seen');
|
||||
|
||||
Irssi::signal_add('setup changed' => 'update_config');
|
||||
Irssi::signal_add_priority('session save' => 'remove_all_trackbars', Irssi::SIGNAL_PRIORITY_HIGH-1);
|
||||
|
||||
Irssi::signal_add('window changed' => 'sig_window_changed');
|
||||
|
||||
Irssi::command_bind('trackbar goto' => 'goto_trackbar');
|
||||
Irssi::command_bind('trackbar keep' => 'cmd_keep_once');
|
||||
Irssi::command_bind('trackbar mark' => 'cmd_mark');
|
||||
Irssi::command_bind('trackbar markvisible' => 'cmd_markvisible');
|
||||
Irssi::command_bind('trackbar markall' => 'cmd_markall');
|
||||
Irssi::command_bind('trackbar remove' => 'cmd_trackbar_remove_one');
|
||||
Irssi::command_bind('trackbar removeall' => 'cmd_remove_all_trackbars');
|
||||
Irssi::command_bind('trackbar redraw' => 'redraw_trackbars');
|
||||
Irssi::command_bind('trackbar' => 'trackbar_runsub');
|
||||
Irssi::command_bind('mark' => 'cmd_mark');
|
||||
Irssi::command_bind_last('help' => 'cmd_help');
|
||||
|
||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_loaded', $IRSSI{name}, $VERSION, $IRSSI{authors});
|
||||
171
irssi/scripts/usercount.pl
Executable file
171
irssi/scripts/usercount.pl
Executable file
@@ -0,0 +1,171 @@
|
||||
use Irssi 20020101.0250 ();
|
||||
$VERSION = "1.16";
|
||||
%IRSSI = (
|
||||
authors => 'David Leadbeater, Timo Sirainen, Georg Lukas',
|
||||
contact => 'dgl@dgl.cx, tss@iki.fi, georg@boerde.de',
|
||||
name => 'usercount',
|
||||
description => 'Adds a usercount for a channel as a statusbar item',
|
||||
license => 'GNU GPLv2 or later',
|
||||
url => 'http://irssi.dgl.yi.org/',
|
||||
);
|
||||
|
||||
# Once you have loaded this script run the following command:
|
||||
# /statusbar window add usercount
|
||||
# You can also add -alignment left|right option
|
||||
|
||||
# /set usercount_show_zero on or off to show users when 0 users of that type
|
||||
# /set usercount_show_ircops (default off)
|
||||
# /set usercount_show_halfops (default on)
|
||||
|
||||
# you can customize the look of this item from theme file:
|
||||
# sb_usercount = "{sb %_$0%_ nicks ($1-)}";
|
||||
# sb_uc_ircops = "%_*%_$*";
|
||||
# sb_uc_ops = "%_@%_$*";
|
||||
# sb_uc_halfops = "%_%%%_$*";
|
||||
# sb_uc_voices = "%_+%_$*";
|
||||
# sb_uc_normal = "$*";
|
||||
# sb_uc_space = " ";
|
||||
|
||||
|
||||
use strict;
|
||||
use Irssi::TextUI;
|
||||
|
||||
my ($ircops, $ops, $halfops, $voices, $normal, $total);
|
||||
my ($timeout_tag, $recalc);
|
||||
|
||||
# Called to make the status bar item
|
||||
sub usercount {
|
||||
my ($item, $get_size_only) = @_;
|
||||
my $wi = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
|
||||
|
||||
if(!ref $wi || $wi->{type} ne "CHANNEL") { # only works on channels
|
||||
return unless ref $item;
|
||||
$item->{min_size} = $item->{max_size} = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($recalc) {
|
||||
$recalc = 0;
|
||||
calc_users($wi);
|
||||
}
|
||||
|
||||
my $theme = Irssi::current_theme();
|
||||
my $format = $theme->format_expand("{sb_usercount}");
|
||||
if ($format) {
|
||||
# use theme-specific look
|
||||
my $ircopstr = $theme->format_expand("{sb_uc_ircops $ircops}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
my $opstr = $theme->format_expand("{sb_uc_ops $ops}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
my $halfopstr = $theme->format_expand("{sb_uc_halfops $halfops}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
my $voicestr = $theme->format_expand("{sb_uc_voices $voices}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
my $normalstr = $theme->format_expand("{sb_uc_normal $normal}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
my $space = $theme->format_expand('{sb_uc_space}',
|
||||
Irssi::EXPAND_FLAG_IGNORE_EMPTY);
|
||||
$space = " " unless $space;
|
||||
|
||||
my $str = "";
|
||||
$str .= $ircopstr.$space if defined $ircops;
|
||||
$str .= $opstr.$space if defined $ops;
|
||||
$str .= $halfopstr.$space if defined $halfops;
|
||||
$str .= $voicestr.$space if defined $voices;
|
||||
$str .= $normalstr.$space if defined $normal;
|
||||
$str =~ s/\Q$space\E$//;
|
||||
|
||||
$format = $theme->format_expand("{sb_usercount $total $str}",
|
||||
Irssi::EXPAND_FLAG_IGNORE_REPLACES);
|
||||
} else {
|
||||
# use the default look
|
||||
$format = "{sb \%_$total\%_ nicks \%c(\%n";
|
||||
$format .= '*'.$ircops.' ' if (defined $ircops);
|
||||
$format .= '@'.$ops.' ' if (defined $ops);
|
||||
$format .= '%%'.$halfops.' ' if (defined $halfops);
|
||||
$format .= "+$voices " if (defined $voices);
|
||||
$format .= "$normal " if (defined $normal);
|
||||
$format =~ s/ $//;
|
||||
$format .= "\%c)}";
|
||||
}
|
||||
|
||||
$item->default_handler($get_size_only, $format, undef, 1);
|
||||
}
|
||||
|
||||
sub calc_users() {
|
||||
my $channel = shift;
|
||||
my $server = $channel->{server};
|
||||
|
||||
$ircops = $ops = $halfops = $voices = $normal = 0;
|
||||
for ($channel->nicks()) {
|
||||
if ($_->{serverop}) {
|
||||
$ircops++;
|
||||
}
|
||||
|
||||
if ($_->{op}) {
|
||||
$ops++;
|
||||
} elsif ($_->{halfop}) {
|
||||
$halfops++;
|
||||
} elsif ($_->{voice}) {
|
||||
$voices++;
|
||||
} else {
|
||||
$normal++;
|
||||
}
|
||||
}
|
||||
|
||||
$total = $ops+$halfops+$voices+$normal;
|
||||
if (!Irssi::settings_get_bool('usercount_show_zero')) {
|
||||
$ircops = undef if ($ircops == 0);
|
||||
$ops = undef if ($ops == 0);
|
||||
$halfops = undef if ($halfops == 0);
|
||||
$voices = undef if ($voices == 0);
|
||||
$normal = undef if ($normal == 0);
|
||||
}
|
||||
$halfops = undef unless Irssi::settings_get_bool('usercount_show_halfops');
|
||||
$ircops = undef unless Irssi::settings_get_bool('usercount_show_ircops');
|
||||
}
|
||||
|
||||
sub refresh {
|
||||
if ($timeout_tag > 0) {
|
||||
Irssi::timeout_remove($timeout_tag);
|
||||
$timeout_tag = 0;
|
||||
}
|
||||
Irssi::statusbar_items_redraw('usercount');
|
||||
}
|
||||
|
||||
sub refresh_check {
|
||||
my $channel = shift;
|
||||
my $wi = ref Irssi::active_win() ? Irssi::active_win()->{active} : 0;
|
||||
|
||||
return unless ref $wi && ref $channel;
|
||||
return if $wi->{name} ne $channel->{name};
|
||||
return if $wi->{server}->{tag} ne $channel->{server}->{tag};
|
||||
|
||||
# don't refresh immediately, or we'll end up refreshing
|
||||
# a lot around netsplits
|
||||
$recalc = 1;
|
||||
Irssi::timeout_remove($timeout_tag) if ($timeout_tag > 0);
|
||||
$timeout_tag = Irssi::timeout_add(500, 'refresh', undef);
|
||||
}
|
||||
|
||||
sub refresh_recalc {
|
||||
$recalc = 1;
|
||||
refresh();
|
||||
}
|
||||
|
||||
$recalc = 1;
|
||||
$timeout_tag = 0;
|
||||
|
||||
Irssi::settings_add_bool('usercount', 'usercount_show_zero', 1);
|
||||
Irssi::settings_add_bool('usercount', 'usercount_show_ircops', 0);
|
||||
Irssi::settings_add_bool('usercount', 'usercount_show_halfops', 1);
|
||||
|
||||
Irssi::statusbar_item_register('usercount', undef, 'usercount');
|
||||
Irssi::statusbars_recreate_items();
|
||||
|
||||
Irssi::signal_add_last('nicklist new', 'refresh_check');
|
||||
Irssi::signal_add_last('nicklist remove', 'refresh_check');
|
||||
Irssi::signal_add_last('nick mode changed', 'refresh_check');
|
||||
Irssi::signal_add_last('setup changed', 'refresh_recalc');
|
||||
Irssi::signal_add_last('window changed', 'refresh_recalc');
|
||||
Irssi::signal_add_last('window item changed', 'refresh_recalc');
|
||||
Reference in New Issue
Block a user