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' );