/var/www/www.irssi.org-old/scripts/html/chanact.pl


   1 use Irssi 20020101.0001 ();
   2 use strict;
   3 use Irssi::TextUI;
   4 
   5 use vars qw($VERSION %IRSSI);
   6 
   7 $VERSION = "0.5.10";
   8 %IRSSI = (
   9     authors     => 'BC-bd, Veli',
  10     contact     => 'bd@bc-bd.org, veli@piipiip.net',
  11     name        => 'chanact',
  12     description => 'Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias). Lets you give alias characters to windows so that you can select those with meta-<char>',
  13     license     => 'GNU GPLv2 or later',
  14     url         => 'https://bc-bd.org/svn/repos/irssi/chanact'
  15 );
  16 
  17 # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).
  18 # Lets you give alias characters to windows so that you can select those with
  19 # meta-<char>.
  20 #
  21 # for irssi 0.8.2 by bd@bc-bd.org
  22 #
  23 # inspired by chanlist.pl by 'cumol@hammerhart.de'
  24 #
  25 #########
  26 # Contributors
  27 #########
  28 #
  29 # veli@piipiip.net   /window_alias code
  30 # qrczak@knm.org.pl  chanact_abbreviate_names
  31 # qerub@home.se      Extra chanact_show_mode and chanact_chop_status
  32 # madduck@madduck.net Better channel aliasing (case-sensitive, cross-network)
  33 # Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22
  34 # Ivo Timmermans <ivo@o2w.nl>	win->{hilight} patch
  35 # 
  36 #########
  37 # USAGE
  38 ###
  39 # 
  40 # copy the script to ~/.irssi/scripts/
  41 #
  42 # In irssi:
  43 #
  44 #		/script load chanact
  45 #		/statusbar window add -after act chanact
  46 #
  47 # If you want the item to appear on another position read the help
  48 # for /statusbar.
  49 # To remove the [Act: 1,2,3] item type:
  50 #
  51 #		/statusbar window remove act
  52 #
  53 # To see all chanact options type:
  54 #
  55 # 	/ set chanact_
  56 #
  57 # After these steps you have your new statusbar item and you can start giving
  58 # aliases to your windows. Go to the window you want to give the alias to
  59 # and say:
  60 #
  61 #		/window_alias <alias char>
  62 #
  63 # You can also remove the aliases with:
  64 #
  65 #		/window_unalias <alias char>
  66 #
  67 # or in aliased window:
  68 #
  69 #		/window_unalias
  70 #
  71 # To see a list of your windows use:
  72 #
  73 #		/window list
  74 #
  75 #########
  76 # OPTIONS
  77 #########
  78 #
  79 # /set chanact_chop_status <ON|OFF>
  80 #               * ON  : shorten (Status) to S
  81 #               * OFF : don't do it
  82 #
  83 # /set chanact_show_mode <ON|OFF>
  84 #               * ON  : show channel modes
  85 #               * OFF : don't show channel modes
  86 #
  87 # /set chanact_sort_by_activity <ON|OFF>
  88 #               * ON  : sorts the list by last activity
  89 #               * OFF : sorts the list by window number
  90 #
  91 # /set chanact_display <string>
  92 #		* string : Format String for one Channel. The following $'s are expanded:
  93 #		    $C : Channel
  94 #		    $N : Number of the Window
  95 #		    $M : Mode in that channel
  96 #		    $H : Start highlightning
  97 #		    $S : Stop highlightning
  98 #		* example:
  99 #		
 100 #		      /set chanact_display $H$N:$M.$S$C
 101 #		      
 102 #		    will give you on #irssi.de if you have voice
 103 #		    
 104 #		      [3:+.#irssi.de]
 105 #
 106 #		    with '3:+.' highlighted and the channel name printed in regular color
 107 #
 108 # /set chanact_display_alias <string>
 109 #   as 'chanact_display' but is used if the window has an alias and
 110 #   'chanact_show_alias' is set to on.
 111 # 
 112 # /set chanact_show_names <ON|OFF>
 113 #		* ON  : show the channelnames after the number/alias
 114 #		* OFF : don't show the names
 115 #
 116 # /set chanact_abbreviate_names <int>
 117 #               * 0     : don't abbreviate
 118 #               * <int> : strip channel name prefix character and leave only
 119 #                         that many characters of the proper name
 120 #
 121 # /set chanact_show_alias <ON|OFF>
 122 #		* ON  : show the aliase instead of the refnum
 123 #		* OFF : shot the refnum
 124 #
 125 # /set chanact_header <str>
 126 # 	* <str> : Characters to be displayed at the start of the item.
 127 # 	          Defaults to: "Act: "
 128 #
 129 # /set chanact_separator <str>
 130 #		* <str> : Charater to use between the channel entries
 131 #
 132 # /set chanact_autorenumber <ON|OFF>
 133 #		* ON  : Move the window automatically to first available slot
 134 #		        starting from "chanact_renumber_start" when assigning 
 135 #		        an alias to window. Also moves the window back to a
 136 #		        first available slot from refnum 1 when the window
 137 #		        loses it's alias.
 138 #		* OFF : Don't move the windows automatically
 139 #
 140 # /set chanact_renumber_start <int>
 141 # 		* <int> : Move the window to first available slot after this
 142 # 		          num when "chanact_autorenumber" is ON.
 143 #
 144 # /set chanact_remove_hash <ON|OFF>
 145 # 		* ON  : Remove &#+!= from channel names
 146 # 		* OFF : Don't touch channel names
 147 #
 148 # /set chanact_remove_prefix <string>
 149 # 		* <string> : Regular expression used to remove from the
 150 # 		             beginning of the channel name.
 151 # 		* example  :
 152 # 		    To shorten a lot of debian channels:
 153 # 		    
 154 # 			/set chanact_remove_prefix deb(ian.(devel-)?)?
 155 #
 156 # /set chanact_filter <int>
 157 # 		* 0 : show all channels
 158 # 		* 1 : hide channels without activity
 159 # 		* 2 : hide channels with only join/part/etc messages
 160 # 		* 3 : hide channels with text messages
 161 # 		* 4 : hide all channels (now why would you want to do that)
 162 #
 163 #########
 164 # HINTS
 165 #########
 166 #
 167 # If you have trouble with wrong colored entries your 'default.theme' might
 168 # be too old. Try on a shell:
 169 #
 170 # 	$ mv ~/.irssi/default.theme /tmp/
 171 #
 172 # And in irssi:
 173 #	/reload
 174 #	/save
 175 #
 176 ###
 177 #################
 178 
 179 my %show = (
 180 	0 => "{%n ",			# NOTHING
 181 	1 => "{sb_act_text ",		# TEXT
 182 	2 => "{sb_act_msg ",		# MSG
 183 	3 => "{sb_act_hilight ",	# HILIGHT
 184 );
 185 
 186 my ($actString,$needRemake);
 187 
 188 sub expand {
 189   my ($string, %format) = @_;
 190   my ($exp, $repl);
 191   $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
 192   return $string;
 193 }
 194 
 195 # method will get called every time the statusbar item will be displayed
 196 # but we dont need to recreate the item every time so we first
 197 # check if something has changed and only then we recreate the string
 198 # this might just save some cycles
 199 # FIXME implement $get_size_only check, and user $item->{min|max-size}
 200 sub chanact {
 201 	my ($item, $get_size_only) = @_;
 202 
 203 	if ($needRemake) {
 204 		remake();
 205 	}
 206 	
 207 	$item->default_handler($get_size_only, $actString, undef, 1);
 208 }
 209 
 210 # this is the real creation method
 211 sub remake() {
 212 	my ($afternumber,$finish,$hilight,$mode,$number,$display,@windows);
 213 	my $separator = Irssi::settings_get_str('chanact_separator'); 
 214 	my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');
 215 	my $remove_prefix = Irssi::settings_get_str('chanact_remove_prefix');
 216 	my $remove_hash = Irssi::settings_get_bool('chanact_remove_hash');
 217 
 218  	if (Irssi::settings_get_bool('chanact_sort_by_activity')) {
 219 		@windows = sort { ($b->{last_line} <=> $a->{last_line}) }
 220 			Irssi::windows;
 221 	} else {
 222 		@windows = sort { ($a->{refnum}) <=> ($b->{refnum}) }
 223 			Irssi::windows;
 224 	}
 225 
 226 	$actString = "";
 227 	foreach my $win (@windows) {
 228 	
 229 		# since irssi is single threaded this shouldn't happen
 230 		!ref($win) && next;
 231 
 232 		my $active = $win->{active};
 233 		!ref($active) && next;
 234 
 235 		my $name = $win->get_active_name;
 236 
 237 		# (status) is an awfull long name, so make it short to 'S'
 238 		# some people don't like it, so make it configurable
 239 		if (Irssi::settings_get_bool('chanact_chop_status')
 240 		    && $name eq "(status)") {
 241 			$name = "S";
 242 		}
 243 	
 244 		# check if we should show the mode
 245 		$mode = "";
 246 		if ($active->{type} eq "CHANNEL") {
 247 			my $server = $win->{active_server};
 248 			!ref($server) && next;
 249 
 250 			my $channel = $server->channel_find($name);
 251 			!ref($channel) && next;
 252 
 253 			my $nick = $channel->nick_find($server->{nick});
 254 			!ref($nick) && next;
 255 			
 256 			if ($nick->{op}) {
 257 				$mode = "@";
 258 			} elsif ($nick->{voice}) {
 259 				$mode = "+";
 260 			} elsif ($nick->{halfop}) {
 261 				$mode = "%";
 262 			}
 263 		}
 264 
 265 		next if (Irssi::settings_get_int('chanact_filter') > $win->{data_level});
 266 
 267 		# in case we have a specific hilightcolor use it
 268 		if ($win->{hilight_color}) {
 269 			$hilight = "{sb_act_hilight_color $win->{hilight_color} ";
 270 		} else {
 271 			$hilight = $show{$win->{data_level}};
 272 		}
 273 
 274 		if ($remove_prefix) {
 275 			$name =~ s/^([&#+!=]?)$remove_prefix/$1/;
 276 		}
 277 		if ($abbrev) {
 278 			if ($name =~ /^[&#+!=]/) {
 279 				$name = substr($name, 1, $abbrev + 1);
 280 			} else {
 281 				$name = substr($name, 0, $abbrev);
 282 			}
 283 		}
 284 		if ($remove_hash) {
 285 			$name =~ s/^[&#+!=]//;
 286 		}
 287 
 288 		if (Irssi::settings_get_bool('chanact_show_alias') == 1 && 
 289 				$win->{name} =~ /^([a-zA-Z+]):(.+)$/) {
 290 			$number = "$1";
 291 			$display = Irssi::settings_get_str('chanact_display_alias'); 
 292 		} else {
 293 			$number = $win->{refnum};
 294 			$display = Irssi::settings_get_str('chanact_display'); 
 295 		}
 296 
 297 		$actString .= expand($display,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
 298 	}
 299 
 300 	# assemble the final string
 301 	if ($actString ne "") {
 302 		# Remove the last separator
 303 		$actString =~ s/$separator$//;
 304 		
 305 		if (Irssi::settings_get_int('chanact_filter')) {
 306 			$actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
 307 		} else {
 308 			$actString = "{sb ".$actString."}";
 309 		}
 310 	}
 311 
 312 	# no remake needed any longer
 313 	$needRemake = 0;
 314 }
 315 
 316 # method called because of some events. here we dont remake the item but just
 317 # remember that we have to remake it the next time we are called
 318 sub chanactHasChanged()
 319 {
 320 	# if needRemake is already set, no need to trigger a redraw as we will
 321 	# be redrawing the item anyway.
 322 	return if $needRemake;
 323 
 324 	$needRemake = 1;
 325 
 326 	Irssi::statusbar_items_redraw('chanact');
 327 }
 328 
 329 # function by veli@piipiip.net
 330 # Remove alias
 331 sub cmd_window_unalias {
 332 	my ($data, $server, $witem) = @_;
 333 	my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
 334 	
 335 	unless ($data =~ /^[a-zA-Z]$/ || 
 336 			Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
 337 		Irssi::print("Usage: /window_unalias <char>");
 338 		Irssi::print("or /window_alias in window that has an alias.");
 339 		return;
 340 	}
 341 	
 342 	if ($data eq '') { $data = Irssi::active_win()->{name}; }
 343 
 344 	if (my $oldwin = Irssi::window_find_name($data)) {
 345 		$oldwin->set_name(undef);
 346 		Irssi::print("Removed alias with the key '$data'.");
 347 		
 348 		if (Irssi::settings_get_bool('chanact_autorenumber') == 1 && 
 349 				$oldwin->{refnum} >= $rn_start) {
 350 			my $old_refnum = $oldwin->{refnum};
 351 			
 352 			# Find the first available slot and move the window
 353 			my $newnum = 1;
 354 			while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
 355 			$oldwin->set_refnum($newnum);
 356 			
 357 			Irssi::print("and moved it to from $old_refnum to $newnum");
 358 		}
 359 	}
 360 }
 361 
 362 # function by veli@piipiip.net
 363 # Make an alias
 364 sub cmd_window_alias {
 365 	my ($data, $server, $witem) = @_;
 366 	my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
 367 
 368 	unless ($data =~ /^[a-zA-Z+]$/) {
 369 		Irssi::print("Usage: /window_alias <char>");
 370 		return;
 371 	}
 372 
 373 	cmd_window_unalias($data, $server, $witem);
 374 	
 375 	my $window = $witem->window();
 376 	my $winnum = $window->{refnum};
 377 	
 378 	if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
 379 			$window->{refnum} < $rn_start) {
 380 		my $old_refnum = $window->{refnum};
 381 
 382 		$winnum = $rn_start;
 383  
 384 		# Find the first available slot and move the window
 385 		while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
 386 		$window->set_refnum($winnum);
 387 		
 388 		Irssi::print("Moved the window from $old_refnum to $winnum");
 389 	}
 390 	
 391 	my $winname = $witem->{name};
 392 	my $winserver = $window->{active_server}->{tag};
 393 	my $winhandle = "$winserver/$winname";
 394 	$window->set_name("$data:$winhandle");
 395 	$server->command("/bind meta-$data change_window $data:$winhandle");
 396 	Irssi::print("Window $winhandle is now accessible with meta-$data");
 397 }
 398 
 399 # function by veli@piipiip.net
 400 # Makes the aliases if names have already been set
 401 sub cmd_rebuild_aliases {
 402 	foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
 403 		if ($_->{name} =~ /^[a-zA-Z]$/) {
 404 			cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
 405 		}
 406 	}
 407 }
 408 
 409 # function by veli@piipiip.net
 410 # Change the binding if the window refnum changes.
 411 sub refnum_changed {
 412 	my ($window, $oldref) = @_;
 413 	my $server = Irssi::active_server();
 414 
 415 	if ($window->{name} =~ /^[a-zA-Z]$/) {
 416 		$server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
 417 	}
 418 }
 419 
 420 $needRemake = 1;
 421 
 422 # Window alias command
 423 Irssi::command_bind('window_alias','cmd_window_alias');
 424 Irssi::command_bind('window_unalias','cmd_window_unalias');
 425 # Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');
 426 
 427 # our config item
 428 Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
 429 Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
 430 Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
 431 Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
 432 Irssi::settings_add_str('chanact', 'chanact_separator', " ");
 433 Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
 434 Irssi::settings_add_bool('chanact', 'chanact_remove_hash', 0);
 435 Irssi::settings_add_str('chanact', 'chanact_remove_prefix', "");
 436 Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
 437 Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
 438 Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);
 439 Irssi::settings_add_bool('chanact', 'chanact_sort_by_activity', 1);
 440 Irssi::settings_add_int('chanact', 'chanact_filter', 0);
 441 
 442 # register the statusbar item
 443 Irssi::statusbar_item_register('chanact', '$0', 'chanact');
 444 # according to cras we shall not call this
 445 # Irssi::statusbars_recreate_items();
 446 
 447 # register all that nifty callbacks on special events
 448 Irssi::signal_add_last('setup changed', 'chanactHasChanged');
 449 Irssi::signal_add_last('window changed', 'chanactHasChanged');
 450 Irssi::signal_add_last('window item changed', 'chanactHasChanged');
 451 Irssi::signal_add_last('window hilight', 'chanactHasChanged');
 452 Irssi::signal_add_last('window item hilight', 'chanactHasChanged');
 453 Irssi::signal_add("window created", "chanactHasChanged");
 454 Irssi::signal_add("window destroyed", "chanactHasChanged");
 455 Irssi::signal_add("window name changed", "chanactHasChanged");
 456 Irssi::signal_add("window activity", "chanactHasChanged");
 457 Irssi::signal_add("print text", "chanactHasChanged");
 458 Irssi::signal_add('nick mode changed', 'chanactHasChanged');
 459 
 460 Irssi::signal_add_last('window refnum changed', 'refnum_changed');
 461 
 462 ###############
 463 ###
 464 #
 465 # Changelog
 466 # 
 467 # 0.5.10
 468 # 	- fixed irssi crash when using Irssi::print from within remake()
 469 #       - added option to filter out some data levels, based on a patch by
 470 #         Juergen Jung <juergen@Winterkaelte.de>, see
 471 #         https://bc-bd.org/trac/irssi/ticket/15
 472 #         	+ retired chanact_show_all in favour of chanact_filter
 473 #
 474 # 0.5.9
 475 # 	- changes by stefan voelkel
 476 # 		+ sort channels by activity, see
 477 # 		  https://bc-bd.org/trac/irssi/ticket/5, based on a patch by jan
 478 # 		  krueger
 479 # 		+ fixed chrash on /exec -interactive, see
 480 # 		https://bc-bd.org/trac/irssi/ticket/7
 481 #
 482 # 	- changes by Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22
 483 # 		+ updated documentation in script's comments
 484 #
 485 # 	- changes by Ivo Timmermans <ivo@o2w.nl>
 486 # 		+ honor actcolor /hilight setting if present
 487 #
 488 # 0.5.8
 489 # - made aliases case-sensitive and include network in channel names by madduck
 490 #
 491 # 0.5.7
 492 # - integrated remove patch by Christoph Berg <myon@debian.org>
 493 #
 494 # 0.5.6
 495 # - fixed a bug (#1) reported by Wouter Coekaert
 496 # 
 497 # 0.5.5
 498 # - some speedups from David Leadbeater <dgl@dgl.cx>
 499 # 
 500 #
 501 # 0.5.4
 502 # - added help for chanact_display_alias
 503 #
 504 # 0.5.3
 505 # - added '+' to the available chars of aliase's
 506 # - added chanact_display_alias to allow different display modes if the window
 507 #   has an alias
 508 #
 509 # 0.5.2
 510 # - removed unused chanact_show_name settings (thx to Qerub)
 511 # - fixed $mode display
 512 # - guarded reference operations to (hopefully) fix errors on server disconnect
 513 # 
 514 # 0.5.1
 515 # - small typo fixed
 516 #
 517 # 0.5.0
 518 # - changed chanact_show_mode to chanact_display. reversed changes from
 519 #   Qerub through that, but kept funcionality.
 520 # - removed chanact_color_all since it is no longer needed
 521 # 
 522 # 0.4.3
 523 # - changes by Qerub
 524 #   + added chanact_show_mode to show the mode just before the channel name
 525 #   + added chanact_chop_status to be able to control the (status) chopping
 526 #     [bd] minor implementation changes
 527 # - moved Changelog to the end of the file since it is getting pretty big
 528 #
 529 # 0.4.2
 530 # - changed back to old version numbering sheme
 531 # - added '=' to Qrczak's chanact_abbreviate_names stuff :)
 532 # - added chanact_header
 533 #
 534 # 0.41q
 535 #	- changes by Qrczak
 536 #		+ added setting 'chanact_abbreviate_names'
 537 #		+ windows are sorted by refnum; I didn't understand the old
 538 #		  logic and it broke sorting for numbers above 9
 539 #
 540 # 0.41
 541 #	- minor updates
 542 #		+ fixed channel sort [veli]
 543 #		+ removed few typos and added some documentation [veli]
 544 #
 545 # 0.4
 546 #	- merge with window_alias.pl
 547 #		+ added /window_alias from window_alias.pl by veli@piipiip.net
 548 #		+ added setting 'chanact_show_alias'
 549 #		+ added setting 'chanact_show_names'
 550 #		+ changed setting 'chanact_show_mode' to int
 551 #		+ added setting 'chanact_separator' [veli]
 552 #		+ added setting 'chanact_autorenumber' [veli]
 553 #		+ added setting 'chanact_renumber_start' [veli]
 554 #		+ added /window_unalias [veli]
 555 #		+ moved setting to their own group 'chanact' [veli]
 556 #
 557 # 0.3
 558 #	- merge with chanlist.pl
 559 #		+ added setting 'chanact_show_mode'
 560 #		+ added setting 'chanact_show_all'
 561 #
 562 # 0.2
 563 #	- added 'Act' to the item
 564 #		- added setting 'chanact_color_all'
 565 #		- finally found format for statusbar hilight
 566 #
 567 # 0.1
 568 #	- Initial Release
 569 #
 570 ###
 571 ################