html/nm.pl


   1 use Irssi;
   2 use strict;
   3 
   4 use vars qw($VERSION %IRSSI);
   5 
   6 $VERSION="0.3.10";
   7 %IRSSI = (
   8 	authors=> 'BC-bd',
   9 	contact=> 'bd@bc-bd.org',
  10 	name=> 'nm',
  11 	description=> 'right aligned nicks depending on longest nick',
  12 	license=> 'GPL v2',
  13 	url=> 'http://bc-bd.org/blog/irssi/',
  14 );
  15 
  16 # $Id: 9cb009e8b7e6f5ce60294334faf88715ef01413e $
  17 # nm.pl
  18 # for irssi 0.8.4 by bd@bc-bd.org
  19 #
  20 # right aligned nicks depending on longest nick
  21 #
  22 # inspired by neatmsg.pl from kodgehopper <kodgehopper@netscape.net
  23 # formats taken from www.irssi.de
  24 # thanks to adrianel <adrinael@nuclearzone.org> for some hints
  25 # thanks to Eric Wald <eswald@gmail.com> for the left alignment patch
  26 # inspired by nickcolor.pl by Timo Sirainen and Ian Peters
  27 # thanks to And1 <and1@meinungsverstaerker.de> for a small patch
  28 # thanks to berber@tzi.de for the save/load patch
  29 # thanks to Dennis Heimbert <dennis.heimbert@gmail.com> for a bug report/patch
  30 #
  31 #########
  32 # USAGE
  33 ###
  34 # 
  35 # use
  36 # 
  37 # 	/neatcolor help
  38 #
  39 # for help on available commands
  40 #
  41 #########
  42 # OPTIONS
  43 #########
  44 
  45 my $help = "
  46 /set neat_colorize <ON|OFF>
  47         * ON  : colorize nicks
  48         * OFF : do not colorize nicks
  49 
  50 /set neat_colors <string>
  51         Use these colors when colorizing nicks, eg:
  52 
  53                 /set neat_colors yYrR
  54 
  55         See the file formats.txt on an explanation of what colors are
  56         available.
  57 
  58 /set neat_left_actions <ON|OFF>
  59         * ON  : print nicks left-aligned on actions
  60         * OFF : print nicks right-aligned on actions
  61 
  62 /set neat_left_messages <ON|OFF>
  63         * ON  : print nicks left-aligned on messages
  64         * OFF : print nicks right-aligned on messages
  65 
  66 /set neat_right_mode <ON|OFF>
  67         * ON  : print the mode of the nick e.g @%+ after the nick
  68         * OFF : print it left of the nick 
  69 
  70 /set neat_maxlength <number>
  71         * number : Maximum length of Nicks to display. Longer nicks are truncated.
  72         * 0      : Do not truncate nicks.
  73 
  74 /set neat_melength <number>
  75         * number : number of spaces to substract from /me padding
  76 
  77 /set neat_ignorechars <str>
  78         * str : regular expression used to filter out unwanted characters in
  79                         nicks. this can be used to assign the same color for similar
  80                         nicks, e.g. foo and foo_:
  81 
  82                                 /set neat_ignorechars [_]
  83 
  84 /set neat_allow_shrinking <ON|OFF>
  85         * ON  : shrink padding when longest nick disappears
  86         * OFF : do not shrink, only allow growing
  87   
  88 ";
  89 
  90 #
  91 ###
  92 ################
  93 ###
  94 #
  95 # Changelog
  96 #
  97 # Version 0.3.10
  98 #  - fix losing of saved color when changing nick shares more than one channel
  99 #    with you
 100 #
 101 # Version 0.3.9
 102 #  - fix longest nick calculation for nicks shorter than the current longest
 103 #    nick
 104 #  - updated url
 105 #
 106 # Version 0.3.8
 107 #  - fixed error in the nickchange tracking code, reported by Kevin Ballard
 108 #  - added --all switch to reset command
 109 #  - skip broken lines in saved_colors
 110 #
 111 # Version 0.3.7
 112 #  - fixed crash when calling /neatcolor without parameters
 113 #  - fixed url
 114 #
 115 # Version 0.3.6
 116 #  - added option to ignore certain characters from color hash building, see
 117 #    https://bc-bd.org/trac/irssi/ticket/22
 118 #  - added option to save and specify colors for nicks, see
 119 #    https://bc-bd.org/trac/irssi/ticket/23
 120 #  - added option to disallow shrinking, see
 121 #    https://bc-bd.org/trac/irssi/ticket/12
 122 #
 123 # Version 0.3.5
 124 #  - now also aligning own messages in queries
 125 #
 126 # Version 0.3.4
 127 #  - fxed off by one error in nick_to_color, patch by jrib, see
 128 #  https://bc-bd.org/trac/irssi/ticket/24
 129 #
 130 # Version 0.3.3
 131 #  - added support for alignment in queries, see
 132 #    https://bc-bd.org/trac/irssi/ticket/21
 133 #
 134 # Version 0.3.2
 135 #  - integrated left alignment patch from Eric Wald <eswald@gmail.com>, see
 136 #    https://bc-bd.org/trac/irssi/ticket/18
 137 #
 138 # Version 0.3.1
 139 #  - /me padding, see https://bc-bd.org/trac/irssi/ticket/17
 140 #
 141 # Version 0.3.0
 142 #  - integrate nick coloring support
 143 #
 144 # Version 0.2.1
 145 #  - moved neat_maxlength check to reformat() (thx to Jerome De Greef <jdegreef@brutele.be>)
 146 #
 147 # Version 0.2.0
 148 #  - by adrianel <adrinael@nuclearzone.org>
 149 #     * reformat after setup reload
 150 #     * maximum length of nicks
 151 #
 152 # Version 0.1.0
 153 #  - got lost somewhere
 154 #
 155 # Version 0.0.2
 156 #  - ugly typo fixed
 157 #  
 158 # Version 0.0.1
 159 #  - initial release
 160 #
 161 ###
 162 ################
 163 ###
 164 #
 165 # BUGS
 166 #
 167 # Empty nicks, eg "<> message"
 168 # 	This seems to be triggered by some themes. As of now there is no known
 169 # 	fix other than changing themes, see
 170 # 	https://bc-bd.org/trac/irssi/ticket/19
 171 #
 172 # Well, it's a feature: due to the lacking support of extendable themes
 173 # from irssi it is not possible to just change some formats per window.
 174 # This means that right now all windows are aligned with the same nick
 175 # length, which can be somewhat annoying.
 176 # If irssi supports extendable themes, I will include per-server indenting
 177 # and a setting where you can specify servers you don't want to be indented
 178 #
 179 ###
 180 ################
 181 
 182 my ($longestNick, %saved_colors, @colors, $alignment, $sign, %commands);
 183 
 184 my $colorize = -1;
 185 
 186 sub reformat() {
 187 	my $max = Irssi::settings_get_int('neat_maxlength');
 188 	my $actsign = Irssi::settings_get_bool('neat_left_actions')? '': '-';
 189 	$sign = Irssi::settings_get_bool('neat_left_messages')? '': '-';
 190 
 191 	if ($max && $max < $longestNick) {
 192 		$longestNick = $max;
 193 	}
 194 
 195 	my $me = $longestNick - Irssi::settings_get_int('neat_melength');
 196 	$me = 0 if ($me < 0);
 197 
 198 	Irssi::command('^format own_action {ownaction $['.$actsign.$me.']0} $1');
 199 	Irssi::command('^format action_public {pubaction $['.$actsign.$me.']0}$1');
 200 	Irssi::command('^format action_private {pvtaction $['.$actsign.$me.']0}$1');
 201 	Irssi::command('^format action_private_query {pvtaction_query $['.$actsign.$me.']0} $2');
 202 
 203 	my $length = $sign . $longestNick;
 204 	if (Irssi::settings_get_bool('neat_right_mode') == 0) {
 205 		Irssi::command('^format own_msg {ownmsgnick $2 {ownnick $['.$length.']0}}$1');
 206 		Irssi::command('^format own_msg_channel {ownmsgnick $3 {ownnick $['.$length.']0}{msgchannel $1}}$2');
 207 		Irssi::command('^format pubmsg_me {pubmsgmenick $2 {menick $['.$length.']0}}$1');
 208 		Irssi::command('^format pubmsg_me_channel {pubmsgmenick $3 {menick $['.$length.']0}{msgchannel $1}}$2');
 209 		Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $3 $['.$length.']1%n}$2');
 210 		Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $4 $['.$length.']1{msgchannel $2}}$3');
 211 		Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick $['.$length.']0}}$1');
 212 		Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick $['.$length.']0}}$1');
 213 	} else {
 214 		Irssi::command('^format own_msg {ownmsgnick {ownnick $['.$length.']0$2}}$1');
 215 		Irssi::command('^format own_msg_channel {ownmsgnick {ownnick $['.$length.']0$3}{msgchannel $1}}$2');
 216 		Irssi::command('^format pubmsg_me {pubmsgmenick {menick $['.$length.']0}$2}$1');
 217 		Irssi::command('^format pubmsg_me_channel {pubmsgmenick {menick $['.$length.']0$3}{msgchannel $1}}$2');
 218 		Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $0 $['.$length.']1$3%n}$2');
 219 		Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $['.$length.']1$4{msgchannel $2}}$3');
 220 		Irssi::command('^format pubmsg {pubmsgnick {pubnick $['.$length.']0$2}}$1');
 221 		Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick $['.$length.']0$2}}$1');
 222 	}
 223 
 224 	# format queries
 225 	Irssi::command('^format own_msg_private_query {ownprivmsgnick {ownprivnick $['.$length.']2}}$1');
 226 	Irssi::command('^format msg_private_query {privmsgnick $['.$length.']0}$2');
 227 };
 228 
 229 sub findLongestNick {
 230 	$longestNick = 0;
 231 
 232 	# get own nick length
 233 	map {
 234 		my $len = length($_->{nick});
 235 
 236 		$longestNick = $len if ($len > $longestNick);
 237 	} Irssi::servers();
 238 
 239 	# find longest other nick
 240 	foreach (Irssi::channels()) {
 241 		foreach ($_->nicks()) {
 242 			my $len = length($_->{nick});
 243 
 244 			$longestNick = $len if ($len > $longestNick);
 245 		}
 246 	}
 247 
 248 	reformat();
 249 }
 250 
 251 # a new nick was created
 252 sub sig_newNick
 253 {
 254 	my ($channel, $nick) = @_;
 255 
 256 	my $len = length($nick->{nick});
 257 
 258 	if ($len > $longestNick) {
 259 		$longestNick = $len;
 260 		reformat();
 261 	}
 262 
 263 	return if (exists($saved_colors{$nick->{nick}}));
 264 
 265 	$saved_colors{$nick->{nick}} = "%".nick_to_color($nick->{nick});
 266 }
 267 
 268 # something changed
 269 sub sig_changeNick
 270 {
 271 	my ($channel, $nick, $old_nick) = @_;
 272 
 273 	# if no saved color exists, we already handled this nickchange. irssi
 274 	# generates one signal per channel the nick is in, so if you share more
 275 	# than one channel with this nick, you'd lose the coloring.
 276 	return unless exists($saved_colors{$old_nick});
 277 
 278 	# we need to update the saved colorors hash independent of nick lenght
 279 	$saved_colors{$nick->{nick}} = $saved_colors{$old_nick};
 280 	delete $saved_colors{$old_nick};
 281 
 282 	my $new = length($nick->{nick});
 283 
 284 	# in case the new nick is longer than the old one, simply remember this
 285 	# as the new longest nick and reformat.
 286 	#
 287 	# if the new nick is as long as the known longest nick nothing has to be
 288 	# done
 289 	#
 290 	# if the new nick is shorter than the current longest one and if the
 291 	# user allows us to shrink, find new longest nick and reformat.
 292 	if ($new > $longestNick) {
 293 		$longestNick = $new;
 294 	} elsif ($new == $longestNick) {
 295 		return;
 296 	} else {
 297 		return unless Irssi::settings_get_bool('neat_allow_shrinking');
 298 		findLongestNick();
 299 	}
 300 
 301 	reformat();
 302 }
 303 
 304 sub sig_removeNick
 305 {
 306 	my ($channel, $nick) = @_;
 307 
 308 	my $thisLen = length($nick->{nick});
 309 
 310 	# we only need to recalculate if this was the longest nick and we are
 311 	# allowed to shrink
 312 	if ($thisLen == $longestNick && Irssi::settings_get_bool('neat_allow_shrinking')) {
 313 		findLongestNick();
 314 		reformat();
 315 	}
 316 
 317 	# we do not remove a known color for a gone nick, as they may return
 318 }
 319 
 320 # based on simple_hash from nickcolor.pl
 321 sub nick_to_color($) {
 322 	my ($string) = @_;
 323 	chomp $string;
 324 
 325 	my $ignore = Irssi::settings_get_str("neat_ignorechars");
 326 	$string =~ s/$ignore//g;
 327 
 328 	my $counter;
 329 	foreach my $char (split(//, $string)) {
 330 		$counter += ord $char;
 331 	}
 332 
 333 	return $colors[$counter % ($#colors + 1)];
 334 }
 335 
 336 sub color_left($) {
 337 	Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1');
 338 	Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1');
 339 }
 340 
 341 sub color_right($) {
 342 	Irssi::command('^format pubmsg {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1');
 343 	Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1');
 344 }
 345 
 346 sub sig_public {
 347 	my ($server, $msg, $nick, $address, $target) = @_;
 348 
 349 	&$alignment($saved_colors{$nick});
 350 }
 351 
 352 sub sig_setup {
 353 	@colors = split(//, Irssi::settings_get_str('neat_colors'));
 354 
 355 	# check left or right alignment
 356 	if (Irssi::settings_get_bool('neat_right_mode') == 0) {
 357 		$alignment = \&color_left;
 358 	} else {
 359 		$alignment = \&color_right;
 360 	}
 361 	
 362 	# check if we switched coloring on or off
 363 	my $new = Irssi::settings_get_bool('neat_colorize');
 364 	if ($new != $colorize) {
 365 		if ($new) {
 366 			Irssi::signal_add('message public', 'sig_public');
 367 		} else {
 368 			if ($colorize >= 0) {
 369 				Irssi::signal_remove('message public', 'sig_public');
 370 			}
 371 		}
 372 	}
 373 	$colorize = $new;
 374 
 375 	reformat();
 376 	&$alignment('%w');
 377 }
 378 
 379 # make sure that every nick has an assigned color
 380 sub assert_colors() {
 381 	foreach (Irssi::channels()) {
 382 		foreach ($_->nicks()) {
 383 			next if (exists($saved_colors{$_->{nick}}));
 384 
 385 			$saved_colors{$_->{nick}} = "%".nick_to_color($_->{nick});
 386 		}
 387 	}
 388 }
 389 
 390 # load colors from file
 391 sub load_colors() {
 392 	open(FID, "<".$ENV{HOME}."/.irssi/saved_colors") || return;
 393 
 394 	while (<FID>) {
 395 		chomp;
 396 		my ($k, $v) = split(/:/);
 397 
 398 		# skip broken lines, those may have been introduced by nm.pl
 399 		# version 0.3.7 and earlier
 400 		if ($k eq '' || $v eq '') {
 401 			neat_log(Irssi::active_win(), "Warning, broken line in saved_colors file, skipping '$k:$v'");
 402 			next;
 403 		}
 404 
 405 		$saved_colors{$k} = $v;
 406 	}
 407 
 408 	close(FID);
 409 }
 410 
 411 # save colors to file
 412 sub save_colors() {
 413 	open(FID, ">".$ENV{HOME}."/.irssi/saved_colors");
 414 
 415 	print FID $_.":".$saved_colors{$_}."\n" foreach (keys(%saved_colors));
 416 
 417 	close(FID);
 418 }
 419 
 420 # log a line to a window item
 421 sub neat_log($@) {
 422 	my ($witem, @text) = @_;
 423 
 424 	$witem->print("nm.pl: ".$_) foreach(@text);
 425 }
 426 
 427 # show available colors
 428 sub cmd_neatcolor_colors($) {
 429 	my ($witem, undef, undef) = @_;
 430 
 431 	neat_log($witem, "Available colors: ".join("", map { "%".$_.$_ } @colors));
 432 }
 433 
 434 # display the configured color for a nick
 435 sub cmd_neatcolor_get() {
 436 	my ($witem, $nick, undef) = @_;
 437 
 438 	if (!exists($saved_colors{$nick})) {
 439 		neat_log($witem, "Error: no such nick '$nick'");
 440 		return;
 441 	}
 442 
 443 	neat_log($witem, "Color for ".$saved_colors{$nick}.$nick);
 444 }
 445 
 446 # display help
 447 sub cmd_neatcolor_help() {
 448 	my ($witem, $cmd, undef) = @_;
 449 
 450 	if ($cmd) {
 451 		if (!exists($commands{$cmd})) {
 452 			neat_log($witem, "Error: no such command '$cmd'");
 453 			return;
 454 		}
 455 
 456 		if (!exists($commands{$cmd}{verbose})) {
 457 			neat_log($witem, "No additional help for '$cmd' available");
 458 			return;
 459 		}
 460 
 461 		neat_log($witem, ( "", "Help for ".uc($cmd), "" ) );
 462 		neat_log($witem, @{$commands{$cmd}{verbose}});
 463 		return;
 464 	}
 465 
 466 	neat_log($witem, split(/\n/, $help));
 467 	neat_log($witem, "Available options for /neatcolor");
 468 	neat_log($witem, "    ".$_.": ".$commands{$_}{text}) foreach(sort(keys(%commands)));
 469 
 470 	my @verbose;
 471 	foreach (sort(keys(%commands))) {
 472 		push(@verbose, $_) if exists($commands{$_}{verbose});
 473 	}
 474 
 475 	neat_log($witem, "Verbose help available for: '".join(", ", @verbose)."'");
 476 }
 477 
 478 # list configured nicks
 479 sub cmd_neatcolor_list() {
 480 	my ($witem, undef, undef) = @_;
 481 
 482 	neat_log($witem, "Configured nicks: ".join(", ", map { $saved_colors{$_}.$_ } sort(keys(%saved_colors))));
 483 }
 484 
 485 # reset a nick to its default color
 486 sub cmd_neatcolor_reset() {
 487 	my ($witem, $nick, undef) = @_;
 488 
 489 	if ($nick eq '--all') {
 490 		%saved_colors = ();
 491 		assert_colors();
 492 		neat_log($witem, "Reset all colors");
 493 		return;
 494 	}
 495 
 496 	if (!exists($saved_colors{$nick})) {
 497 		neat_log($witem, "Error: no such nick '$nick'");
 498 		return;
 499 	}
 500 
 501 	$saved_colors{$nick} = "%".nick_to_color($nick);
 502 	neat_log($witem, "Reset color for ".$saved_colors{$nick}.$nick);
 503 }
 504 
 505 # save configured colors to disk
 506 sub cmd_neatcolor_save() {
 507 	my ($witem, undef, undef) = @_;
 508 
 509 	save_colors();
 510 
 511 	neat_log($witem, "color information saved");
 512 }
 513 
 514 # set a color for a nick
 515 sub cmd_neatcolor_set() {
 516 	my ($witem, $nick, $color) = @_;
 517 
 518 	my @found = grep(/$color/, @colors);
 519 	if ($#found) {
 520 		neat_log($witem, "Error: trying to set unknown color '%$color$color%n'");
 521 		cmd_neatcolor_colors($witem);
 522 		return;
 523 	}
 524 
 525 	if ($witem->{type} ne "CHANNEL" && $witem->{type} ne "QUERY") {
 526 		neat_log($witem, "Warning: not a Channel/Query, can not check nick!");
 527 		neat_log($witem, "Remember, nicks are case sensitive to nm.pl");
 528 	} else {
 529 		my @nicks = grep(/^$nick$/i, map { $_->{nick} } ($witem->nicks()));
 530 
 531 		if ($#nicks < 0) {
 532 			neat_log($witem, "Warning: could not find nick '$nick' here");
 533 		} else {
 534 			if ($nicks[0] ne $nick) {
 535 				neat_log($witem, "Warning: using '$nicks[0]' instead of '$nick'");
 536 				$nick = $nicks[0];
 537 			}
 538 		}
 539 	}
 540 
 541 	$saved_colors{$nick} = "%".$color;
 542 	neat_log($witem, "Set color for $saved_colors{$nick}$nick");
 543 }
 544 
 545 %commands = (
 546 	colors => {
 547 		text => "show available colors",
 548 		verbose => [
 549 			"COLORS",
 550 			"",
 551 			"displays all available colors",
 552 			"",
 553 			"You can restrict/define the list of available colors ".
 554 			"with the help of the neat_colors setting"
 555 		],
 556 		func => \&cmd_neatcolor_colors,
 557 	},
 558 	get => {
 559 		text => "retrieve color for a nick",
 560 		verbose => [
 561 			"GET <nick>",
 562 			"",
 563 			"displays color used for <nick>"
 564 		],
 565 		func => \&cmd_neatcolor_get,
 566 	},
 567 	help => {
 568 		text => "print this help message",
 569 		func => \&cmd_neatcolor_help,
 570 	},
 571 	list => {
 572 		text => "list configured nick/color pairs",
 573 		func => \&cmd_neatcolor_list,
 574 	},
 575 	reset => {
 576 		text => "reset color to default",
 577 		verbose => [
 578 			"RESET --all|<nick>",
 579 			"",
 580 			"resets the color used for all nicks or for <nick> to ",
 581 			"its internal default",
 582 		],
 583 		func => \&cmd_neatcolor_reset,
 584 	},
 585 	save => {
 586 		text => "save color information to disk",
 587 		verbose => [
 588 			"SAVE",
 589 			"",
 590 			"saves color information to disk, so that it survives ".
 591 			"an irssi restart.",
 592 			"",
 593 			"Color information will be automatically saved on /quit",
 594 		],
 595 		func => \&cmd_neatcolor_save,
 596 	},
 597 	set => {
 598 		text => "set a specific color for a nick",
 599 		verbose => [
 600 			"SET <nick> <color>",
 601 			"",
 602 			"use <color> for <nick>",
 603 			"",
 604 			"This command will perform a couple of sanity checks, ".
 605 			"when called from a CHANNEL/QUERY window",
 606 			"",
 607 			"EXAMPLE:",
 608 			"  /neatcolor set bc-bd r",
 609 			"",
 610 			"use /neatcolor COLORS to see available colors"
 611 		],
 612 		func => \&cmd_neatcolor_set,
 613 	},
 614 );
 615 
 616 # the main command callback that gets called for all neatcolor commands
 617 sub cmd_neatcolor() {
 618 	my ($data, $server, $witem) = @_;
 619 	my ($cmd, $nick, $color) = split (/ /, $data);
 620 
 621 	$cmd = lc($cmd);
 622 
 623 	# make sure we have a valid witem to print text to
 624 	$witem = Irssi::active_win() unless ($witem);
 625 
 626 	if (!exists($commands{$cmd})) {
 627 		neat_log($witem, "Error: unknown command '$cmd'");
 628 		&{$commands{"help"}{"func"}}($witem) if (exists($commands{"help"}));
 629 		return;
 630 	}
 631 
 632 	&{$commands{$cmd}{"func"}}($witem, $nick, $color);
 633 }
 634 
 635 Irssi::settings_add_bool('misc', 'neat_left_messages', 0);
 636 Irssi::settings_add_bool('misc', 'neat_left_actions', 0);
 637 Irssi::settings_add_bool('misc', 'neat_right_mode', 1);
 638 Irssi::settings_add_int('misc', 'neat_maxlength', 0);
 639 Irssi::settings_add_int('misc', 'neat_melength', 2);
 640 Irssi::settings_add_bool('misc', 'neat_colorize', 1);
 641 Irssi::settings_add_str('misc', 'neat_colors', 'rRgGyYbBmMcC');
 642 Irssi::settings_add_str('misc', 'neat_ignorechars', '');
 643 Irssi::settings_add_bool('misc', 'neat_allow_shrinking', 1);
 644 
 645 Irssi::command_bind('neatcolor', 'cmd_neatcolor');
 646 
 647 Irssi::signal_add('nicklist new', 'sig_newNick');
 648 Irssi::signal_add('nicklist changed', 'sig_changeNick');
 649 Irssi::signal_add('nicklist remove', 'sig_removeNick');
 650 
 651 Irssi::signal_add('setup changed', 'sig_setup');
 652 Irssi::signal_add_last('setup reread', 'sig_setup');
 653 
 654 findLongestNick();
 655 sig_setup;
 656 
 657 load_colors();
 658 assert_colors();
 659 
 660 # we need to add this signal _after_ the colors have been loaded, to make sure
 661 # no race condition exists wrt color saving
 662 Irssi::signal_add('gui exit', 'save_colors');