]>
git.sthu.org Git - shutils.git/blob - dotfiles/irssi/scripts/nm.pl
4 use vars
qw($VERSION %IRSSI);
9 contact=> 'bd@bc-bd.org',
11 description=> 'right aligned nicks depending on longest nick',
13 url=> 'http://bc-bd.org/blog/irssi/',
16 # $Id: 9cb009e8b7e6f5ce60294334faf88715ef01413e $
18 # for irssi 0.8.4 by bd@bc-bd.org
20 # right aligned nicks depending on longest nick
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
39 # for help on available commands
46 /set neat_colorize <ON|OFF>
48 * OFF : do not colorize nicks
50 /set neat_colors <string>
51 Use these colors when colorizing nicks, eg:
55 See the file formats.txt on an explanation of what colors are
58 /set neat_left_actions <ON|OFF>
59 * ON : print nicks left-aligned on actions
60 * OFF : print nicks right-aligned on actions
62 /set neat_left_messages <ON|OFF>
63 * ON : print nicks left-aligned on messages
64 * OFF : print nicks right-aligned on messages
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
70 /set neat_maxlength <number>
71 * number : Maximum length of Nicks to display. Longer nicks are truncated.
72 * 0 : Do not truncate nicks.
74 /set neat_melength <number>
75 * number : number of spaces to substract from /me padding
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_:
82 /set neat_ignorechars [_]
84 /set neat_allow_shrinking <ON|OFF>
85 * ON : shrink padding when longest nick disappears
86 * OFF : do not shrink, only allow growing
98 # - fix losing of saved color when changing nick shares more than one channel
102 # - fix longest nick calculation for nicks shorter than the current longest
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
112 # - fixed crash when calling /neatcolor without parameters
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
124 # - now also aligning own messages in queries
127 # - fxed off by one error in nick_to_color, patch by jrib, see
128 # https://bc-bd.org/trac/irssi/ticket/24
131 # - added support for alignment in queries, see
132 # https://bc-bd.org/trac/irssi/ticket/21
135 # - integrated left alignment patch from Eric Wald <eswald@gmail.com>, see
136 # https://bc-bd.org/trac/irssi/ticket/18
139 # - /me padding, see https://bc-bd.org/trac/irssi/ticket/17
142 # - integrate nick coloring support
145 # - moved neat_maxlength check to reformat() (thx to Jerome De Greef <jdegreef@brutele.be>)
148 # - by adrianel <adrinael@nuclearzone.org>
149 # * reformat after setup reload
150 # * maximum length of nicks
153 # - got lost somewhere
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
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
182 my ($longestNick, %saved_colors, @colors, $alignment, $sign, %commands);
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')? '': '-';
191 if ($max && $max < $longestNick) {
195 my $me = $longestNick - Irssi::settings_get_int('neat_melength');
196 $me = 0 if ($me < 0);
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');
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');
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');
225 Irssi::command('^format own_msg_private_query {ownprivmsgnick {ownprivnick $['.$length.']2}}$1');
226 Irssi::command('^format msg_private_query {privmsgnick $['.$length.']0}$2');
229 sub findLongestNick {
232 # get own nick length
234 my $len = length($_->{nick});
236 $longestNick = $len if ($len > $longestNick);
239 # find longest other nick
240 foreach (Irssi::channels()) {
241 foreach ($_->nicks()) {
242 my $len = length($_->{nick});
244 $longestNick = $len if ($len > $longestNick);
251 # a new nick was created
254 my ($channel, $nick) = @_;
256 my $len = length($nick->{nick});
258 if ($len > $longestNick) {
263 return if (exists($saved_colors{$nick->{nick}}));
265 $saved_colors{$nick->{nick}} = "%".nick_to_color($nick->{nick});
271 my ($channel, $nick, $old_nick) = @_;
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});
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};
282 my $new = length($nick->{nick});
284 # in case the new nick is longer than the old one, simply remember this
285 # as the new longest nick and reformat.
287 # if the new nick is as long as the known longest nick nothing has to be
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) {
294 } elsif ($new == $longestNick) {
297 return unless Irssi::settings_get_bool('neat_allow_shrinking');
306 my ($channel, $nick) = @_;
308 my $thisLen = length($nick->{nick});
310 # we only need to recalculate if this was the longest nick and we are
312 if ($thisLen == $longestNick && Irssi::settings_get_bool('neat_allow_shrinking')) {
317 # we do not remove a known color for a gone nick, as they may return
320 # based on simple_hash from nickcolor.pl
321 sub nick_to_color($) {
325 my $ignore = Irssi::settings_get_str("neat_ignorechars");
326 $string =~ s/$ignore//g;
329 foreach my $char (split(//, $string)) {
330 $counter += ord $char;
333 return $colors[$counter % ($#colors + 1)];
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');
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');
347 my ($server, $msg, $nick, $address, $target) = @_;
349 &$alignment($saved_colors{$nick});
353 @colors = split(//, Irssi::settings_get_str('neat_colors'));
355 # check left or right alignment
356 if (Irssi::settings_get_bool('neat_right_mode') == 0) {
357 $alignment = \&color_left;
359 $alignment = \&color_right;
362 # check if we switched coloring on or off
363 my $new = Irssi::settings_get_bool('neat_colorize');
364 if ($new != $colorize) {
366 Irssi::signal_add('message public', 'sig_public');
368 if ($colorize >= 0) {
369 Irssi::signal_remove('message public', 'sig_public');
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}}));
385 $saved_colors{$_->{nick}} = "%".nick_to_color($_->{nick});
390 # load colors from file
392 open(FID, "<".$ENV{HOME}."/.irssi/saved_colors") || return;
396 my ($k, $v) = split(/:/);
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'");
405 $saved_colors{$k} = $v;
411 # save colors to file
413 open(FID, ">".$ENV{HOME}."/.irssi/saved_colors");
415 print FID $_.":".$saved_colors{$_}."\n" foreach (keys(%saved_colors));
420 # log a line to a window item
422 my ($witem, @text) = @_;
424 $witem->print("nm.pl: ".$_) foreach(@text);
427 # show available colors
428 sub cmd_neatcolor_colors($) {
429 my ($witem, undef, undef) = @_;
431 neat_log($witem, "Available colors: ".join("", map { "%".$_.$_ } @colors));
434 # display the configured color for a nick
435 sub cmd_neatcolor_get() {
436 my ($witem, $nick, undef) = @_;
438 if (!exists($saved_colors{$nick})) {
439 neat_log($witem, "Error: no such nick '$nick'");
443 neat_log($witem, "Color for ".$saved_colors{$nick}.$nick);
447 sub cmd_neatcolor_help() {
448 my ($witem, $cmd, undef) = @_;
451 if (!exists($commands{$cmd})) {
452 neat_log($witem, "Error: no such command '$cmd'");
456 if (!exists($commands{$cmd}{verbose})) {
457 neat_log($witem, "No additional help for '$cmd' available");
461 neat_log($witem, ( "", "Help for ".uc($cmd), "" ) );
462 neat_log($witem, @{$commands{$cmd}{verbose}});
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)));
471 foreach (sort(keys(%commands))) {
472 push(@verbose, $_) if exists($commands{$_}{verbose});
475 neat_log($witem, "Verbose help available for: '".join(", ", @verbose)."'");
478 # list configured nicks
479 sub cmd_neatcolor_list() {
480 my ($witem, undef, undef) = @_;
482 neat_log($witem, "Configured nicks: ".join(", ", map { $saved_colors{$_}.$_ } sort(keys(%saved_colors))));
485 # reset a nick to its default color
486 sub cmd_neatcolor_reset() {
487 my ($witem, $nick, undef) = @_;
489 if ($nick eq '--all') {
492 neat_log($witem, "Reset all colors");
496 if (!exists($saved_colors{$nick})) {
497 neat_log($witem, "Error: no such nick '$nick'");
501 $saved_colors{$nick} = "%".nick_to_color($nick);
502 neat_log($witem, "Reset color for ".$saved_colors{$nick}.$nick);
505 # save configured colors to disk
506 sub cmd_neatcolor_save() {
507 my ($witem, undef, undef) = @_;
511 neat_log($witem, "color information saved");
514 # set a color for a nick
515 sub cmd_neatcolor_set() {
516 my ($witem, $nick, $color) = @_;
518 my @found = grep(/$color/, @colors);
520 neat_log($witem, "Error: trying to set unknown color '%$color$color%n'");
521 cmd_neatcolor_colors($witem);
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");
529 my @nicks = grep(/^$nick$/i, map { $_->{nick} } ($witem->nicks()));
532 neat_log($witem, "Warning: could not find nick '$nick' here");
534 if ($nicks[0] ne $nick) {
535 neat_log($witem, "Warning: using '$nicks[0]' instead of '$nick'");
541 $saved_colors{$nick} = "%".$color;
542 neat_log($witem, "Set color for $saved_colors{$nick}$nick");
547 text => "show available colors",
551 "displays all available colors",
553 "You can restrict/define the list of available colors ".
554 "with the help of the neat_colors setting"
556 func => \&cmd_neatcolor_colors,
559 text => "retrieve color for a nick",
563 "displays color used for <nick>"
565 func => \&cmd_neatcolor_get,
568 text => "print this help message",
569 func => \&cmd_neatcolor_help,
572 text => "list configured nick/color pairs",
573 func => \&cmd_neatcolor_list,
576 text => "reset color to default",
578 "RESET --all|<nick>",
580 "resets the color used for all nicks or for <nick> to ",
581 "its internal default",
583 func => \&cmd_neatcolor_reset,
586 text => "save color information to disk",
590 "saves color information to disk, so that it survives ".
593 "Color information will be automatically saved on /quit",
595 func => \&cmd_neatcolor_save,
598 text => "set a specific color for a nick",
600 "SET <nick> <color>",
602 "use <color> for <nick>",
604 "This command will perform a couple of sanity checks, ".
605 "when called from a CHANNEL/QUERY window",
608 " /neatcolor set bc-bd r",
610 "use /neatcolor COLORS to see available colors"
612 func => \&cmd_neatcolor_set,
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);
623 # make sure we have a valid witem to print text to
624 $witem = Irssi::active_win() unless ($witem);
626 if (!exists($commands{$cmd})) {
627 neat_log($witem, "Error: unknown command '$cmd'");
628 &{$commands{"help"}{"func"}}($witem) if (exists($commands{"help"}));
632 &{$commands{$cmd}{"func"}}($witem, $nick, $color);
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);
645 Irssi::command_bind('neatcolor', 'cmd_neatcolor');
647 Irssi::signal_add('nicklist new', 'sig_newNick');
648 Irssi::signal_add('nicklist changed', 'sig_changeNick');
649 Irssi::signal_add('nicklist remove', 'sig_removeNick');
651 Irssi::signal_add('setup changed', 'sig_setup');
652 Irssi::signal_add_last('setup reread', 'sig_setup');
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');