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: