enames.pl


   1 use strict;
   2 use Irssi;
   3 
   4 use vars qw($VERSION %IRSSI);
   5 $VERSION = '0.5';
   6 %IRSSI   = (
   7     authors     => 'Mathieu Doidy',
   8     contact     => 'mdoidy at roulaize dot net',
   9     name        => 'enames',
  10     description => 'extend the names command to display away people grayed',
  11     license     => 'GPLv2',
  12     url         => 'http://irssi.roulaize.net',
  13     changed     => '14/11/2003',
  14 );
  15 
  16 sub _status {
  17     my ($nick) = @_;
  18     my $status =
  19       $nick->{'op'} ? 4 : $nick->{'halfop'} ? 3 : $nick->{'voice'} ? 2 : 1;
  20     return $status;
  21 }
  22 
  23 sub _max {
  24     my $ret = 0;
  25     foreach (@_) {
  26         my $ln = length( $_->{'nick'} ) + 4;
  27         $ret = $ln if $ln > $ret;
  28     }
  29     return $ret;
  30 }
  31 
  32 sub _sum {
  33     my $ret = 0;
  34     foreach (@_) { $ret += $_; }
  35     return $ret;
  36 }
  37 
  38 sub _get_max_column_count {
  39     my ( $max_w, $max_c, $item_extra, $item_min_size, @items ) = @_;
  40     my $items_count = scalar(@items);
  41     my ( @cols, @cols_w, $cols_r, $n );
  42     my $len = int( $max_w / ( $item_extra + $item_min_size ) );
  43     $len = 1 if $len <= 0;
  44     $max_c = $len if ( $max_c <= 0 || $len < $max_c );
  45 
  46     foreach ( 0 .. ( $max_c - 1 ) ) {
  47         my $n = $max_c - $_;
  48         $cols_r =
  49           $items_count < $n + 1 ? 1 : int( ( $items_count + $n - 1 ) / ($n) );
  50 
  51         foreach my $m ( 1 .. $max_c ) {
  52             $cols_w[$m] = 0;
  53             next if $m > $n;
  54             $cols_w[$m] =
  55               _max( @items[ ( $m - 1 ) * $cols_r .. $m * $cols_r - 1 ] );
  56         }
  57 
  58         return ( $n, $cols_r, @cols_w )
  59           if ( _sum(@cols_w) < $max_w
  60             && ( $n - 1 ) * ($cols_r) <= $items_count );
  61     }
  62 }
  63 
  64 sub _columns_sort_list {
  65     my ( $rows, @list ) = @_;
  66 
  67     my @sorted;
  68 
  69     foreach my $row ( 0 .. ( $rows - 1 ) ) {
  70         my $i = $row;
  71         while ( $list[$i] ) {
  72             push @sorted, $list[$i];
  73             $i += $rows;
  74         }
  75     }
  76     return @sorted;
  77 }
  78 
  79 sub _display_sorted_nicks {
  80     my ( $chan, @nicks ) = @_;
  81     my $window = Irssi::window_find_closest( $chan, MSGLEVEL_CLIENTCRAP );
  82 
  83     my $theme = $window->{theme} || Irssi::current_theme;
  84     my $format = $theme->get_format( 'fe-common/core', 'names' );
  85 
  86     my ( $count, $count_ops, $count_halfops, $count_voices, $count_normal )=(0,0,0,0,0);
  87 
  88     Irssi::theme_register(
  89         [
  90             'names',
  91             '{names_users Users {names_channel $0}}',
  92             'endofnames', '{line_start}{hilight Irssi:} {channel $0}: Total of {hilight $1} nicks {comment {hilight $2} ops, {hilight $3} halfops, {hilight $4} voices, {hilight $5} normal}'
  93         ]
  94     );
  95 
  96     $window->printformat( MSGLEVEL_CLIENTCRAP, 'names', $chan );
  97 
  98     my $max_w       = $window->{'width'} - 10;
  99     my $names_max_w = Irssi::settings_get_int("names_max_width");
 100     $max_w = $names_max_w if ( $names_max_w > 0 && $names_max_w < $max_w );
 101     $max_w = 10 if $max_w <= 0;
 102 
 103     my ( $cols, $rows, @cols_w ) =
 104       _get_max_column_count( $max_w,
 105         Irssi::settings_get_int("names_max_columns"),
 106         4, 3, @nicks );
 107 
 108     my @cnicks = _columns_sort_list( $rows, @nicks );
 109 
 110     my $last_col_rows = $rows - ( $cols * $rows - ( scalar @nicks ) );
 111     $last_col_rows = $rows if !$last_col_rows;
 112 
 113     my ( $col, $str, $row ) = (1);
 114 
 115     foreach (@cnicks) {
 116         my $mode =
 117           $_->{'op'} ? '@'
 118           : $_->{'halfop'} ? '%'
 119           : $_->{'voice'}  ? '+'
 120           : ' ';
 121         $count++;
 122         $_->{'op'} ? $count_ops++ : $_->{'halfop'}
 123           ? $count_halfops++
 124           : $_->{'voice'} ? $count_voices++ : $count_normal++;
 125         my $away = $_->{'gone'} ? '%w' : '';
 126 
 127         $str .= "%g[%n%_$mode%_$away$_->{'nick'}"
 128           . " " x ( $cols_w[$col] - 4 - length( $_->{'nick'} ) ) . "%g]%g";
 129         if ( ++$col == $cols + 1 ) {
 130             $window->print( $str, MSGLEVEL_CLIENTCRAP );
 131             $col = 1;
 132             $str = '';
 133             $row++;
 134             $cols-- if $row == $last_col_rows;
 135         }
 136         else { $str .= ' '; }
 137     }
 138 
 139     $window->print( $str, MSGLEVEL_CLIENTCRAP ) if $str;
 140     $window->printformat( MSGLEVEL_CLIENTCRAP, 'endofnames', $chan, $count,
 141         $count_ops, $count_halfops, $count_voices, $count_normal );
 142 }
 143 
 144 sub sig_stop { Irssi::signal_stop() }
 145 
 146 sub enames {
 147     my ( $data, $server, $channel ) = @_;
 148     ## Irssi::signal_add_first( 'print text', 'sig_stop' );
 149     ## $channel->command("who");
 150     ## Irssi::signal_remove( 'print text', 'sig_stop' );
 151     my @nicks = sort {
 152         _status($b) <=> _status($a)
 153           || lc( $a->{'nick'} ) cmp lc( $b->{'nick'} )
 154     } $channel->nicks();
 155     _display_sorted_nicks( $channel->{'name'}, @nicks );
 156 }
 157 
 158 Irssi::command_bind( 'enames', 'enames' );