diff options
| author | Ailin Nemui | 2016-08-16 15:48:00 +0200 |
|---|---|---|
| committer | Ailin Nemui | 2016-08-16 15:48:00 +0200 |
| commit | 95fb0b8e4e44f3f7aee5e48496a6a21e887619e8 (patch) | |
| tree | e44a80c340c855b1d85254729c5ae880ad8e6e08 /scripts | |
| parent | 542987a4b18ab278a2e658783d3ec0190f8b4b9b (diff) | |
| download | scripts.irssi.org-95fb0b8e4e44f3f7aee5e48496a6a21e887619e8.tar.bz2 | |
add anames help, settings docs in comments, and get_max_column_count
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/anames.pl | 232 |
1 files changed, 185 insertions, 47 deletions
diff --git a/scripts/anames.pl b/scripts/anames.pl index e365a2a..385ffe6 100644 --- a/scripts/anames.pl +++ b/scripts/anames.pl @@ -1,7 +1,25 @@ # anames.pl -# Irssi script that adds an /anames command, a clone of /names, with away nicks -# grayed out. + +# Commands +# ======== +# /anames +# * a clone of /names, with away nicks greyed out. + +# Options +# ======= +# /format endofanames +# * equivalent of /format endofnames, the final summary line of /anames command # +# /format names_awaynick +# * colour for the nicks that are away, example: %w$0 +# +# /set anames_force_sync <ON|OFF> +# * whether to use -sync by default (request fresh /who list) +# if you do not turn this on you will have to manually refresh the +# away list using /who #channel, /anames -sync or you can turn it +# off if you are running the autowho script to automatically update +# the who list periodically + # Thanks to Dirm and Chris62vw for the Perl help and coekie for writing the # evil code to sort the nicklist by the alphabet and rank in nicklist.pl # @@ -36,13 +54,13 @@ # 0.9 - Initial test release use strict; +use warnings; use Irssi 20140918; -use POSIX; -use List::Util 'max'; +use List::Util qw(min max); use vars qw($VERSION %IRSSI); -$VERSION = '1.6'; # f200e871df81c77 +$VERSION = '1.6'; # 6eb152135b1bc6d %IRSSI = ( authors => 'Matt "f0rked" Sparks, Miklos Vajna', contact => 'ms+irssi@quadpoint.org', @@ -50,14 +68,12 @@ $VERSION = '1.6'; # f200e871df81c77 description => 'a /names display with away nicks coloured', license => 'GPLv2', url => 'http://quadpoint.org', - changed => '2010-07-12', ); -# How often to do a /who of all channels (in seconds) -#my $who_timer = 300; my $tmp_server; my $tmp_chan; +my $tmp_count; Irssi::theme_register([ @@ -66,30 +82,60 @@ Irssi::theme_register([ ]); -local $@; -eval { require Text::CharWidth; }; -unless ($@) { +sub cmd_help { + my ($args) = @_; + if ($args =~ /^anames *$/i) { + print CLIENTCRAP <<HELP +%9Syntax:%9 + +ANAMES [-sync | -cached] [-count] [-<server tag>] [<channel>] + +%9Parameters:%9 + + -sync: Synchronise the away state of the channel. + -cached: Do not synchronise the away state, use cached info. + -count: Displays the amount of users away in the channel. + + If no arguments are given, the users in the active channel will be + displayed. + +%9Description:%9 + + Display the users who are in channel and grey out those who are away. + +%9See also:%9 NAMES, WHO, WHOIS +HELP + + } +} + + +{ + local $@; + eval { require Text::CharWidth; }; + unless ($@) { *screen_length = sub { Text::CharWidth::mbswidth($_[0]) }; -} else { + } else { *screen_length = sub { length($_[0]); } + } } sub object_printformat_module { - my ($object, $level, $module, $format, @args) = @_; - { - local *CORE::GLOBAL::caller = sub { $module }; - $object->printformat($level, $format, @args); - } + my ($object, $level, $module, $format, @args) = @_; + { + local *CORE::GLOBAL::caller = sub { $module }; + $object->printformat($level, $format, @args); + } } sub core_printformat_module { - my ($level, $module, $format, @args) = @_; - { - local *CORE::GLOBAL::caller = sub { $module }; - Irssi::printformat($level, $format, @args); - } + my ($level, $module, $format, @args) = @_; + { + local *CORE::GLOBAL::caller = sub { $module }; + Irssi::printformat($level, $format, @args); + } } @@ -99,14 +145,34 @@ sub cmd_anames my $channel = $item; $tmp_server = $server->{"tag"}; $tmp_chan = $channel->{"name"}; + $tmp_count = undef; - if ($args ne "") { - my @args = split ' ', $args; + my ($force_sync, $force_cache); + my @args = split ' ', $args; + while (@args && $args[0] =~ /^-/) { + if (lc $args[0] eq '-sync') { + $force_sync = 1; shift @args; + } + elsif (lc $args[0] eq '-cached') { + $force_cache = 1; shift @args; + } + elsif (lc $args[0] eq '-count') { + $tmp_count = 1; shift @args; + } + else { + last; + } + } + if (@args) { if ($args[0] =~ /-(.*)/) { $tmp_server = $1; $server = Irssi::server_find_tag($tmp_server); shift @args; } + unless (@args) { + core_printformat_module(MSGLEVEL_CLIENTERROR, 'fe-common/core', 'not_enough_params'); + return; + } $tmp_chan = $args[0]; } @@ -116,13 +182,21 @@ sub cmd_anames } # set up redirection - $server->redirect_event("who", 1, $tmp_chan, 0, undef, + my $sync = Irssi::settings_get_bool('anames_force_sync'); + my $irc = $server->isa('Irssi::Irc::Server'); + if ($irc && ($force_sync || ($sync && !$force_cache))) { + $server->redirect_event("who", 1, $tmp_chan, 0, "", { "event 352" => "silent event who", "event 315" => "redir who_reply_end", }); - $server->command("who $tmp_chan"); + $server->command("who $tmp_chan"); + } elsif ($force_sync) { + print CLIENTERROR "anames -sync is not supported for the chat protocol of the target server"; + } else { + print_anames(); + } } @@ -195,13 +269,69 @@ sub print_anames } my $total = @nicks; - object_printformat_module($channel, MSGLEVEL_CLIENTCRAP, 'fe-common/core', 'names', $chan); - columnize_nicks($channel,@nicks); + unless ($tmp_count) { + object_printformat_module($channel, MSGLEVEL_CLIENTCRAP, 'fe-common/core', 'names', $chan); + columnize_nicks($channel, @nicks); + } $channel->printformat(MSGLEVEL_CLIENTNOTICE, 'endofanames', $chan, $total, $ops, $halfops, $voices, $normal, $away); } } +# src/core/misc.c +sub get_max_column_count { + my $max_width = pop(@_) - 1; + my @item_info = @_; + + my $items_count = @item_info; + if ($items_count == 0) { + return; + } + + my $min_len = max 1, min map { $_->[-1] } @item_info; + my $max_columns = max 1, int($max_width/$min_len); + + my (@columns, @columns_width, @columns_rows); + + for my $n (1 .. $max_columns - 1) { + $columns_rows[$n] = $items_count <= $n+1 ? 1 : + ($items_count+$n)/($n+1); + } + + # for each possible column count, save the column widths and + # find the biggest column count that fits to screen. + my $item_pos = 0; + my $max_len = max 1, map { $_->[-1] } @item_info; + for my $tmp (@item_info) { + my $len = $tmp->[-1]; + + for my $n (1 .. $max_columns - 1) { + no warnings 'uninitialized'; + if ($columns_width[$n] > $max_width) { + next; # too wide + } + + my $col = $item_pos/$columns_rows[$n]; + if ($columns[$n][$col] < $len) { + $columns_width[$n] += $len - $columns[$n][$col]; + $columns[$n][$col] = $len; + } + } + + $item_pos++; + } + + for my $n (reverse 1 .. $max_columns - 1) { + no warnings 'uninitialized'; + if ($columns_width[$n] <= $max_width && + $columns[$n][$n] > 0) { + return $n + 1; + } + } + + return 1; +} + { my %strip_table = ( # fe-common::core::formats.c:format_expand_styles @@ -211,10 +341,10 @@ sub print_anames (map { $_ => $_ } (split //, '{}%')), ); sub ir_strip_codes { # strip %codes - my $o = shift; - $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; - $o + my $o = shift; + $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; + $o } } @@ -227,35 +357,40 @@ sub columnize_nicks my $total = @nicks; # determine max columns - # FIXME: this could be more intelligent (i.e., read window size) my $cols = Irssi::settings_get_int("names_max_columns"); - if ($cols == 0) { - my $width = $channel->window->{width}; - my $ts_format = Irssi::settings_get_str('timestamp_format'); - my $render_str = Irssi::current_theme->format_expand( - Irssi::current_theme->get_format('fe-common/core', 'timestamp')); - (my $ts_escaped = $ts_format) =~ s/([%\$])/$1$1/g; - $render_str =~ s/(?|\$(.)(?!\w)|\$\{(\w+)\})/$1 eq 'Z' ? $ts_escaped : $1/ge; - $render_str = ir_strip_codes($render_str); - $width -= screen_length($render_str); - $cols = max(1, int( $width / max(1, map { 1+ $_->[-1] } @nicks) )); + my $width = $channel->window->{width}; + { + my $ts_format = Irssi::settings_get_str('timestamp_format'); + my $render_str = Irssi::current_theme->format_expand( + Irssi::current_theme->get_format('fe-common/core', 'timestamp')); + (my $ts_escaped = $ts_format) =~ s/([%\$])/$1$1/g; + $render_str =~ s/(?|\$(.)(?!\w)|\$\{(\w+)\})/$1 eq 'Z' ? $ts_escaped : $1/ge; + $render_str = ir_strip_codes($render_str); + $width -= screen_length($render_str); + } + $width = max 10, $width; + my $max_cols = get_max_column_count(@nicks, $width - 1); + return unless $max_cols; + if ($cols < 1) { + $cols = $max_cols; } + $cols = min $max_cols, $cols; # determine number of rows - my $rows = round(ceil($total / $cols)); + my $rows = int($total / $cols) + !!($total % $cols); # array of rows my @r; for (my $i = 0; $i < $cols; $i++) { # peek at next $rows items, determine max length - my $max_length = max map { $_->[-1] } @nicks[0 .. $rows - 1]; + my $max_length = max map { $_->[-1] } grep { defined } @nicks[0 .. $rows - 1]; # fill rows for (my $j = 0; $j < $rows; $j++) { my $n = shift @nicks; # single nick if ($n->[-1]) { $r[$j] .= $channel->window->format_get_text('fe-common/core', $channel->{server}, $channel->{visible_name}, - $n->[2], $n->[0], $n->[1] . fill_spaces($n->[-1],$max_length) ); + $n->[2], $n->[0], $n->[1] . fill_spaces($n->[-1], $max_length) ); } } } @@ -285,7 +420,7 @@ sub round sub who_reply_end { print_anames(); - Irssi::signal_emit('chanquery who end', @_); +# Irssi::signal_emit('chanquery who end', @_); $tmp_chan = ""; } @@ -297,4 +432,7 @@ Irssi::Irc::Server::redirect_register("who", 0, 0, Irssi::signal_register({'chanquery who end' => [qw[iobject string]]}); Irssi::signal_add("redir who_reply", 'who_reply'); Irssi::signal_add("redir who_reply_end", 'who_reply_end'); +Irssi::settings_add_bool("anames", "anames_force_sync", 0); Irssi::command_bind("anames", 'cmd_anames'); +Irssi::command_set_options("anames", "sync cached count"); +Irssi::command_bind_last('help' => 'cmd_help'); |
