html/dr_who.pl
1 # TODO: people I care about first
2 # multiline
3 # away toggle is slow: why
4 # on terminal resize, window width returns old size. sleeping doesn't help
5 # does anyone know how to find space available to a statusbar instead of for the whole window?
6 # remember tickercount separately for each channel and don't reset it
7 # skip command to jump forward in the ticker
8 # only reset on dr_who setup changes, not everything else
9
10 # How to use:
11 # /script load dr_who
12 # /statusbar dr_who enable
13 # /statusbar dr_who add dr_who
14 # dr_who has to use the entire statusbar currently. Maybe this will change in the future
15
16 use strict;
17 use Irssi::TextUI;
18
19 use vars qw($VERSION %IRSSI);
20
21 $VERSION = '1.0';
22 %IRSSI = (
23 authors => 'Bitt Faulk',
24 contact => 'lxsfx3h02@sneakemail.com',
25 name => 'dr_who',
26 description => 'Put a nick list in a statusbar',
27 license => 'BSD',
28 url => 'http://beaglebros.com',
29 changed => '1-17-2005'
30 );
31
32 my ($dr_who_line, $timeout);
33 my $tickercount = 0;
34 my $direction = 1;
35
36 # Stolen from autoop.pl: http://xkr47.outerspace.dyndns.org/configs/irssi/autoop.pl
37 sub get_cur_channel() {
38 my $server_o = Irssi::active_server();
39 my $window_o = Irssi::active_win();
40 my @items = $window_o->items();
41 my $item_o;
42 foreach $item_o (@items) {
43 next unless($item_o->is_active());
44
45 my $channel = $item_o->{name};
46 my $channel_o = $server_o->channel_find($channel);
47
48 return $channel_o if($channel_o);
49 }
50
51 return ();
52 }
53
54 sub dr_who_refresh {
55 my $channel = get_cur_channel();
56 my %channicks;
57 my $nick;
58 my $text_count = 0;
59 my @nicks;
60 my $continue = 0;
61 my $displaytype = Irssi::settings_get_str('dr_who_longdisplay');
62 my $atend;
63 my $buffer;
64
65 if ( $channel ) {
66 my $window_width = Irssi::active_win()->{width};
67 foreach $nick (get_cur_channel()->nicks()) {
68 $channicks{$nick->{nick}} = $nick;
69 }
70 $dr_who_line = "{sb ";
71 $text_count += 4; #for bracket/space borders
72 $atend = scalar(keys %channicks);
73 foreach $nick (sort {uc($a) cmp uc($b)} keys %channicks) {
74 my ( $new_nick, $new_nick_width );
75
76 $atend--;
77 if ( $channicks{$nick}->{gone} ) {
78 $new_nick .= "{nohilight ";
79 } else {
80 $new_nick .= "{hilight ";
81 }
82 if ( Irssi::settings_get_bool('dr_who_nickflags') ) {
83 if ( $channicks{$nick}->{serverop} ) {
84 $new_nick .= "*";
85 $new_nick_width += 1;
86 }
87 if ( $channicks{$nick}->{op} ) {
88 $new_nick .= "@";
89 $new_nick_width += 1;
90 } elsif ( $channicks{$nick}->{voice} ) {
91 $new_nick .= "+";
92 $new_nick_width += 1;
93 }
94 }
95 $new_nick .= "$nick}";
96 $new_nick_width += length($nick);
97 if ( $displaytype eq "ticker" ) {
98 if ( $tickercount > 0 ) {
99 $buffer = 6;
100 } else {
101 $buffer = 0;
102 }
103 if ( (($text_count+$new_nick_width+$#nicks+1) > $window_width+$tickercount-$buffer) ) { # already written nicks and other text, plus new nick, plus spaces to separate them all (+1 because $#nicks is the last index, not the number in the array)
104 $continue = 1;
105 if ( (($window_width+$tickercount) - ($text_count+$#nicks+1)) > 5 ) { # there's at least six characters left available
106 my $extra = ($text_count+$new_nick_width+$#nicks+1) - ($window_width+$tickercount); # How far over?
107 $new_nick = substr($new_nick, 0, length($new_nick) - ($extra + 7));
108 $new_nick .= "}";
109 $new_nick_width -= ($extra + 7);
110 $text_count += $new_nick_width;
111 push(@nicks, { nick => $new_nick, len => $new_nick_width });
112 } else {
113 my $extra = ($text_count+$#nicks) - ($window_width+$tickercount) + 6; # How far over?
114 while ( $extra > 0 ) {
115 if ( $extra >= $nicks[$#nicks]{len} ) {
116 $extra -= $nicks[$#nicks]{len};
117 $text_count -= $nicks[$#nicks]{len};
118 pop(@nicks);
119 $nicks[$#nicks]{nick} .= " ";
120 } else {
121 $nicks[$#nicks]{nick} = substr($nicks[$#nicks]{nick}, 0, (length($nicks[$#nicks]{nick}) - $extra - 1));
122 $nicks[$#nicks]{nick} .= "}";
123 $nicks[$#nicks]{len} -= $extra;
124 $text_count -= $extra;
125 $extra = 0;
126 }
127 }
128 }
129 last;
130 } else {
131 if ( $tickercount > 0 ) {
132 $continue = 1;
133 }
134 push(@nicks, { nick => $new_nick, len => $new_nick_width });
135 $text_count += $new_nick_width;
136 if ( ($atend == 0) && ($tickercount > 0) ) {
137 $direction = -1;
138 }
139 }
140 } else {
141 if ( ($text_count+$new_nick_width+$#nicks+1) > $window_width ) { # length of already-written nicks and other text, plus length of the current nick, plus spaces to put between them all (the 1 is because $#nicks is the last index, not the number of items in the array)
142 $continue = 1;
143 if ( ($window_width - ($text_count+$#nicks+1)) > 2 ) {
144 my $extra = (($text_count+$#nicks+1)+$new_nick_width)-$window_width;
145 $new_nick = substr($new_nick, 0, length($new_nick) - ($extra + 4));
146 $new_nick .= "}";
147 push(@nicks, { nick => $new_nick, len => $new_nick_width });
148 } else {
149 my $extra = ($text_count+$#nicks) - $window_width + 3;
150 while ( $extra > 0 ) {
151 if ( $extra >= $nicks[$#nicks]{len} ) {
152 $extra -= $nicks[$#nicks]{len};
153 pop(@nicks);
154 $nicks[$#nicks]{nick} .= " ";
155 } else {
156 $nicks[$#nicks]{nick} = substr($nicks[$#nicks]{nick}, 0, (length($nicks[$#nicks]{nick}) - $extra - 1));
157 $nicks[$#nicks]{nick} .= "}";
158 $extra = 0;
159 }
160 }
161 }
162 last;
163 } else {
164 push(@nicks, { nick => $new_nick, len => $new_nick_width });
165 $text_count += $new_nick_width;
166 }
167 }
168 }
169 if ($continue && ($displaytype eq "ticker")) {
170 $dr_who_line .= "<--";
171 my $i = $tickercount;
172 my $tempspace;
173 foreach my $nickhash ( @nicks ) {
174 if ( $i > 0 ) {
175 if ( $$nickhash{len} == $i ) {
176 $i -= $$nickhash{len};
177 $dr_who_line .= " ";
178 } elsif ( $$nickhash{len} < $i ) {
179 $i -= $$nickhash{len} + 1;
180 } else {
181 $$nickhash{nick} =~ s/ (.*)}$//;
182 my $cut = $1;
183 $cut = substr($cut, $i);
184 $dr_who_line .= "$$nickhash{nick} $cut} ";
185 $i = 0;
186 }
187 } else {
188 $dr_who_line .= $$nickhash{nick} . " ";
189 }
190 }
191 $tickercount += $direction;
192 if ( $tickercount == 0 ) {
193 $direction = 1;
194 }
195 #if ( $tickercount < 0 ) {
196 #$tickercount = 0;
197 #$direction = 1;
198 #} elsif ( $atend == 0 ) {
199 #$atend = 0;
200 #$tickercount = -1;
201 #}
202 Irssi::timeout_remove($timeout);
203 $timeout = Irssi::timeout_add_once(Irssi::settings_get_int('dr_who_tickerspeed'), 'dr_who_refresh', undef);
204 } else {
205 $tickercount = 0;
206 $direction = 1;
207 foreach my $nickhash ( @nicks ) {
208 $dr_who_line .= $$nickhash{nick} . " ";
209 }
210 }
211 chop($dr_who_line);
212 $dr_who_line .= "-->" if ($continue);
213 $dr_who_line .= "}";
214 } else {
215 $dr_who_line = "";
216 }
217
218 Irssi::statusbar_items_redraw('dr_who');
219 }
220
221 sub dr_who_reset {
222 $tickercount = 0;
223 $direction = 1;
224 if (Irssi::settings_get_int('dr_who_tickerspeed') < 10 ) {
225 Irssi::print("dr_who: tickerspeed must be at least 10 milliseconds");
226 Irssi::settings_set_int('dr_who_tickerspeed', 10);
227 }
228 dr_who_refresh();
229 }
230
231 sub dr_who {
232 my ($item, $get_size_only) = @_;
233 $item->default_handler($get_size_only, $dr_who_line, undef, 1);
234 }
235
236 sub dr_who_start {
237 Irssi::statusbar_item_register('dr_who', undef, 'dr_who');
238 Irssi::command_bind('dr_who_refresh', 'dr_who_refresh');
239 Irssi::settings_add_bool('dr_who', 'dr_who_nickflags', 1);
240 Irssi::settings_add_str('dr_who', 'dr_who_longdisplay', 'static');
241 Irssi::settings_add_int('dr_who', 'dr_who_tickerspeed', 500);
242 &dr_who_refresh();
243 Irssi::signal_add('window changed', 'dr_who_reset');
244 Irssi::signal_add('nicklist new', 'dr_who_refresh');
245 Irssi::signal_add('nicklist remove', 'dr_who_refresh');
246 Irssi::signal_add('nicklist changed', 'dr_who_refresh');
247 Irssi::signal_add('channel joined', 'dr_who_refresh');
248 Irssi::signal_add('nick mode changed', 'dr_who_refresh');
249 Irssi::signal_add('user mode changed', 'dr_who_refresh');
250 Irssi::signal_add('away mode changed', 'dr_who_refresh');
251 Irssi::signal_add('terminal resized', 'dr_who_reset');
252 Irssi::signal_add('setup changed', 'dr_who_reset');
253 }
254
255 &dr_who_start();
256
257 # vim: set shiftwidth=2 tabstop=2: