Mercurial > dotfiles.old
diff irssi/scripts/nm.pl @ 148:4e92ca6c779a
add irssi conf
author | zegervdv <zegervdv@me.com> |
---|---|
date | Sat, 18 Oct 2014 10:06:58 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/irssi/scripts/nm.pl Sat Oct 18 10:06:58 2014 +0200 @@ -0,0 +1,693 @@ +use Irssi; +use strict; + +use vars qw($VERSION %IRSSI); + +$VERSION="0.3.10"; +%IRSSI = ( + authors=> 'BC-bd', + contact=> '[email protected]', + name=> 'nm', + description=> 'right aligned nicks depending on longest nick', + license=> 'GPL v2', + url=> 'http://bc-bd.org/blog/irssi/', +); + +# $Id: 9cb009e8b7e6f5ce60294334faf88715ef01413e $ +# nm.pl +# for irssi 0.8.4 by [email protected] +# +# right aligned nicks depending on longest nick +# +# inspired by neatmsg.pl from kodgehopper <[email protected] +# formats taken from www.irssi.de +# thanks to adrianel <[email protected]> for some hints +# thanks to Eric Wald <[email protected]> for the left alignment patch +# inspired by nickcolor.pl by Timo Sirainen and Ian Peters +# thanks to And1 <[email protected]> for a small patch +# thanks to [email protected] for the save/load patch +# thanks to Dennis Heimbert <[email protected]> for a bug report/patch +# thanks to Roy Sigurd Karlsbakk <[email protected]> for an autosave patch +# +######### +# USAGE +### +# +# use +# +# /neatcolor help +# +# for help on available commands +# +######### +# OPTIONS +######### + +my $help = " +/set neat_colorize <ON|OFF> + * ON : colorize nicks + * OFF : do not colorize nicks + +/set neat_colors <string> + Use these colors when colorizing nicks, eg: + + /set neat_colors yYrR + + See the file formats.txt on an explanation of what colors are + available. + +/set neat_left_actions <ON|OFF> + * ON : print nicks left-aligned on actions + * OFF : print nicks right-aligned on actions + +/set neat_left_messages <ON|OFF> + * ON : print nicks left-aligned on messages + * OFF : print nicks right-aligned on messages + +/set neat_right_mode <ON|OFF> + * ON : print the mode of the nick e.g @%+ after the nick + * OFF : print it left of the nick + +/set neat_maxlength <number> + * number : Maximum length of Nicks to display. Longer nicks are truncated. + * 0 : Do not truncate nicks. + +/set neat_melength <number> + * number : number of spaces to substract from /me padding + +/set neat_ignorechars <str> + * str : regular expression used to filter out unwanted characters in + nicks. this can be used to assign the same color for similar + nicks, e.g. foo and foo_: + + /set neat_ignorechars [_] + +/set neat_allow_shrinking <ON|OFF> + * ON : shrink padding when longest nick disappears + * OFF : do not shrink, only allow growing + +/set neat_autosave <number> + * number : autosave after <number> seconds, defaults to 60. Set to 0 to + disable. +"; + +# +### +################ +### +# +# Changelog +# +# Version 0.3.11 +# - added autosave, idea from Roy Sigurd Karlsbakk +# +# Version 0.3.10 +# - fix losing of saved color when changing nick shares more than one channel +# with you +# +# Version 0.3.9 +# - fix longest nick calculation for nicks shorter than the current longest +# nick +# - updated url +# +# Version 0.3.8 +# - fixed error in the nickchange tracking code, reported by Kevin Ballard +# - added --all switch to reset command +# - skip broken lines in saved_colors +# +# Version 0.3.7 +# - fixed crash when calling /neatcolor without parameters +# - fixed url +# +# Version 0.3.6 +# - added option to ignore certain characters from color hash building, see +# https://bc-bd.org/trac/irssi/ticket/22 +# - added option to save and specify colors for nicks, see +# https://bc-bd.org/trac/irssi/ticket/23 +# - added option to disallow shrinking, see +# https://bc-bd.org/trac/irssi/ticket/12 +# +# Version 0.3.5 +# - now also aligning own messages in queries +# +# Version 0.3.4 +# - fxed off by one error in nick_to_color, patch by jrib, see +# https://bc-bd.org/trac/irssi/ticket/24 +# +# Version 0.3.3 +# - added support for alignment in queries, see +# https://bc-bd.org/trac/irssi/ticket/21 +# +# Version 0.3.2 +# - integrated left alignment patch from Eric Wald <[email protected]>, see +# https://bc-bd.org/trac/irssi/ticket/18 +# +# Version 0.3.1 +# - /me padding, see https://bc-bd.org/trac/irssi/ticket/17 +# +# Version 0.3.0 +# - integrate nick coloring support +# +# Version 0.2.1 +# - moved neat_maxlength check to reformat() (thx to Jerome De Greef <[email protected]>) +# +# Version 0.2.0 +# - by adrianel <[email protected]> +# * reformat after setup reload +# * maximum length of nicks +# +# Version 0.1.0 +# - got lost somewhere +# +# Version 0.0.2 +# - ugly typo fixed +# +# Version 0.0.1 +# - initial release +# +### +################ +### +# +# BUGS +# +# Empty nicks, eg "<> message" +# This seems to be triggered by some themes. As of now there is no known +# fix other than changing themes, see +# https://bc-bd.org/trac/irssi/ticket/19 +# +# Well, it's a feature: due to the lacking support of extendable themes +# from irssi it is not possible to just change some formats per window. +# This means that right now all windows are aligned with the same nick +# length, which can be somewhat annoying. +# If irssi supports extendable themes, I will include per-server indenting +# and a setting where you can specify servers you don't want to be indented +# +### +################ + +my ($longestNick, %saved_colors, @colors, $alignment, $sign, %commands,); +my ($pending_save); + +my $colorize = -1; + +sub reformat() { + my $max = Irssi::settings_get_int('neat_maxlength'); + my $actsign = Irssi::settings_get_bool('neat_left_actions')? '': '-'; + $sign = Irssi::settings_get_bool('neat_left_messages')? '': '-'; + + if ($max && $max < $longestNick) { + $longestNick = $max; + } + + my $me = $longestNick - Irssi::settings_get_int('neat_melength'); + $me = 0 if ($me < 0); + + Irssi::command('^format own_action {ownaction $['.$actsign.$me.']0} $1'); + Irssi::command('^format action_public {pubaction $['.$actsign.$me.']0}$1'); + Irssi::command('^format action_private {pvtaction $['.$actsign.$me.']0}$1'); + Irssi::command('^format action_private_query {pvtaction_query $['.$actsign.$me.']0} $2'); + + my $length = $sign . $longestNick; + if (Irssi::settings_get_bool('neat_right_mode') == 0) { + Irssi::command('^format own_msg {ownmsgnick $2 {ownnick $['.$length.']0}}$1'); + Irssi::command('^format own_msg_channel {ownmsgnick $3 {ownnick $['.$length.']0}{msgchannel $1}}$2'); + Irssi::command('^format pubmsg_me {pubmsgmenick $2 {menick $['.$length.']0}}$1'); + Irssi::command('^format pubmsg_me_channel {pubmsgmenick $3 {menick $['.$length.']0}{msgchannel $1}}$2'); + Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $3 $['.$length.']1%n}$2'); + Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $4 $['.$length.']1{msgchannel $2}}$3'); + Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick $['.$length.']0}}$1'); + Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick $['.$length.']0}}$1'); + } else { + Irssi::command('^format own_msg {ownmsgnick {ownnick $['.$length.']0$2}}$1'); + Irssi::command('^format own_msg_channel {ownmsgnick {ownnick $['.$length.']0$3}{msgchannel $1}}$2'); + Irssi::command('^format pubmsg_me {pubmsgmenick {menick $['.$length.']0}$2}$1'); + Irssi::command('^format pubmsg_me_channel {pubmsgmenick {menick $['.$length.']0$3}{msgchannel $1}}$2'); + Irssi::command('^format pubmsg_hilight {pubmsghinick $0 $0 $['.$length.']1$3%n}$2'); + Irssi::command('^format pubmsg_hilight_channel {pubmsghinick $0 $['.$length.']1$4{msgchannel $2}}$3'); + Irssi::command('^format pubmsg {pubmsgnick {pubnick $['.$length.']0$2}}$1'); + Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick $['.$length.']0$2}}$1'); + } + + # format queries + Irssi::command('^format own_msg_private_query {ownprivmsgnick {ownprivnick $['.$length.']2}}$1'); + Irssi::command('^format msg_private_query {privmsgnick $['.$length.']0}$2'); +}; + +sub findLongestNick { + $longestNick = 0; + + # get own nick length + map { + my $len = length($_->{nick}); + + $longestNick = $len if ($len > $longestNick); + } Irssi::servers(); + + # find longest other nick + foreach (Irssi::channels()) { + foreach ($_->nicks()) { + my $len = length($_->{nick}); + + $longestNick = $len if ($len > $longestNick); + } + } + + reformat(); +} + +sub delayed_save +{ + # skip if we have already a save pending. we don't reset the timeout + # here, else you could end up with changes never being automatically + # saved if they happen more often than <neat_autosave> seconds + return if $pending_save; + + return unless Irssi::settings_get_int('neat_autosave'); + + Irssi::timeout_add_once(Irssi::settings_get_int('neat_autosave') * 1000, + \&save_colors, undef); +} + +# a new nick was created +sub sig_newNick +{ + my ($channel, $nick) = @_; + + my $len = length($nick->{nick}); + + if ($len > $longestNick) { + $longestNick = $len; + reformat(); + } + + return if (exists($saved_colors{$nick->{nick}})); + + $saved_colors{$nick->{nick}} = "%".nick_to_color($nick->{nick}); + delayed_save(); +} + +# something changed +sub sig_changeNick +{ + my ($channel, $nick, $old_nick) = @_; + + # if no saved color exists, we already handled this nickchange. irssi + # generates one signal per channel the nick is in, so if you share more + # than one channel with this nick, you'd lose the coloring. + return unless exists($saved_colors{$old_nick}); + + # we need to update the saved colorors hash independent of nick lenght + $saved_colors{$nick->{nick}} = $saved_colors{$old_nick}; + delete $saved_colors{$old_nick}; + delayed_save(); + + my $new = length($nick->{nick}); + + # in case the new nick is longer than the old one, simply remember this + # as the new longest nick and reformat. + # + # if the new nick is as long as the known longest nick nothing has to be + # done + # + # if the new nick is shorter than the current longest one and if the + # user allows us to shrink, find new longest nick and reformat. + if ($new > $longestNick) { + $longestNick = $new; + } elsif ($new == $longestNick) { + return; + } else { + return unless Irssi::settings_get_bool('neat_allow_shrinking'); + findLongestNick(); + } + + reformat(); +} + +sub sig_removeNick +{ + my ($channel, $nick) = @_; + + my $thisLen = length($nick->{nick}); + + # we only need to recalculate if this was the longest nick and we are + # allowed to shrink + if ($thisLen == $longestNick && Irssi::settings_get_bool('neat_allow_shrinking')) { + findLongestNick(); + reformat(); + } + + # we do not remove a known color for a gone nick, as they may return +} + +# based on simple_hash from nickcolor.pl +sub nick_to_color($) { + my ($string) = @_; + chomp $string; + + my $ignore = Irssi::settings_get_str("neat_ignorechars"); + $string =~ s/$ignore//g; + + my $counter; + foreach my $char (split(//, $string)) { + $counter += ord $char; + } + + return $colors[$counter % ($#colors + 1)]; +} + +sub color_left($) { + Irssi::command('^format pubmsg {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1'); + Irssi::command('^format pubmsg_channel {pubmsgnick $2 {pubnick '.$_[0].'$['.$sign.$longestNick.']0}}$1'); +} + +sub color_right($) { + Irssi::command('^format pubmsg {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1'); + Irssi::command('^format pubmsg_channel {pubmsgnick {pubnick '.$_[0].'$['.$sign.$longestNick.']0}$2}$1'); +} + +sub sig_public { + my ($server, $msg, $nick, $address, $target) = @_; + + &$alignment($saved_colors{$nick}); +} + +sub sig_setup { + @colors = split(//, Irssi::settings_get_str('neat_colors')); + + # check left or right alignment + if (Irssi::settings_get_bool('neat_right_mode') == 0) { + $alignment = \&color_left; + } else { + $alignment = \&color_right; + } + + # check if we switched coloring on or off + my $new = Irssi::settings_get_bool('neat_colorize'); + if ($new != $colorize) { + if ($new) { + Irssi::signal_add('message public', 'sig_public'); + } else { + if ($colorize >= 0) { + Irssi::signal_remove('message public', 'sig_public'); + } + } + } + $colorize = $new; + + reformat(); + &$alignment('%w'); +} + +# make sure that every nick has an assigned color +sub assert_colors() { + foreach (Irssi::channels()) { + foreach ($_->nicks()) { + next if (exists($saved_colors{$_->{nick}})); + + $saved_colors{$_->{nick}} = "%".nick_to_color($_->{nick}); + delayed_save(); + } + } +} + +# load colors from file +sub load_colors() { + open(FID, "<".$ENV{HOME}."/.irssi/saved_colors") || return; + + while (<FID>) { + chomp; + my ($k, $v) = split(/:/); + + # skip broken lines, those may have been introduced by nm.pl + # version 0.3.7 and earlier + if ($k eq '' || $v eq '') { + neat_log(Irssi::active_win(), "Warning, broken line in saved_colors file, skipping '$k:$v'"); + next; + } + + $saved_colors{$k} = $v; + } + + close(FID); +} + +# save colors to file +sub save_colors() { + open(FID, ">".$ENV{HOME}."/.irssi/saved_colors"); + + print FID $_.":".$saved_colors{$_}."\n" foreach (keys(%saved_colors)); + + close(FID); + + # clear possible pending save. + Irssi::timeout_remove($pending_save) if $pending_save; + $pending_save = undef; +} + +# log a line to a window item +sub neat_log($@) { + my ($witem, @text) = @_; + + $witem->print("nm.pl: ".$_) foreach(@text); +} + +# show available colors +sub cmd_neatcolor_colors($) { + my ($witem, undef, undef) = @_; + + neat_log($witem, "Available colors: ".join("", map { "%".$_.$_ } @colors)); +} + +# display the configured color for a nick +sub cmd_neatcolor_get() { + my ($witem, $nick, undef) = @_; + + if (!exists($saved_colors{$nick})) { + neat_log($witem, "Error: no such nick '$nick'"); + return; + } + + neat_log($witem, "Color for ".$saved_colors{$nick}.$nick); +} + +# display help +sub cmd_neatcolor_help() { + my ($witem, $cmd, undef) = @_; + + if ($cmd) { + if (!exists($commands{$cmd})) { + neat_log($witem, "Error: no such command '$cmd'"); + return; + } + + if (!exists($commands{$cmd}{verbose})) { + neat_log($witem, "No additional help for '$cmd' available"); + return; + } + + neat_log($witem, ( "", "Help for ".uc($cmd), "" ) ); + neat_log($witem, @{$commands{$cmd}{verbose}}); + return; + } + + neat_log($witem, split(/\n/, $help)); + neat_log($witem, "Available options for /neatcolor"); + neat_log($witem, " ".$_.": ".$commands{$_}{text}) foreach(sort(keys(%commands))); + + my @verbose; + foreach (sort(keys(%commands))) { + push(@verbose, $_) if exists($commands{$_}{verbose}); + } + + neat_log($witem, "Verbose help available for: '".join(", ", @verbose)."'"); +} + +# list configured nicks +sub cmd_neatcolor_list() { + my ($witem, undef, undef) = @_; + + neat_log($witem, "Configured nicks: ".join(", ", map { $saved_colors{$_}.$_ } sort(keys(%saved_colors)))); +} + +# reset a nick to its default color +sub cmd_neatcolor_reset() { + my ($witem, $nick, undef) = @_; + + if ($nick eq '--all') { + %saved_colors = (); + assert_colors(); + neat_log($witem, "Reset all colors"); + return; + } + + if (!exists($saved_colors{$nick})) { + neat_log($witem, "Error: no such nick '$nick'"); + return; + } + + $saved_colors{$nick} = "%".nick_to_color($nick); + delayed_save(); + neat_log($witem, "Reset color for ".$saved_colors{$nick}.$nick); +} + +# save configured colors to disk +sub cmd_neatcolor_save() { + my ($witem, undef, undef) = @_; + + save_colors(); + + neat_log($witem, "color information saved"); +} + +# set a color for a nick +sub cmd_neatcolor_set() { + my ($witem, $nick, $color) = @_; + + my @found = grep(/$color/, @colors); + if ($#found) { + neat_log($witem, "Error: trying to set unknown color '%$color$color%n'"); + cmd_neatcolor_colors($witem); + return; + } + + if ($witem->{type} ne "CHANNEL" && $witem->{type} ne "QUERY") { + neat_log($witem, "Warning: not a Channel/Query, can not check nick!"); + neat_log($witem, "Remember, nicks are case sensitive to nm.pl"); + } else { + my @nicks = grep(/^$nick$/i, map { $_->{nick} } ($witem->nicks())); + + if ($#nicks < 0) { + neat_log($witem, "Warning: could not find nick '$nick' here"); + } else { + if ($nicks[0] ne $nick) { + neat_log($witem, "Warning: using '$nicks[0]' instead of '$nick'"); + $nick = $nicks[0]; + } + } + } + + $saved_colors{$nick} = "%".$color; + delayed_save(); + neat_log($witem, "Set color for $saved_colors{$nick}$nick"); +} + +%commands = ( + colors => { + text => "show available colors", + verbose => [ + "COLORS", + "", + "displays all available colors", + "", + "You can restrict/define the list of available colors ". + "with the help of the neat_colors setting" + ], + func => \&cmd_neatcolor_colors, + }, + get => { + text => "retrieve color for a nick", + verbose => [ + "GET <nick>", + "", + "displays color used for <nick>" + ], + func => \&cmd_neatcolor_get, + }, + help => { + text => "print this help message", + func => \&cmd_neatcolor_help, + }, + list => { + text => "list configured nick/color pairs", + func => \&cmd_neatcolor_list, + }, + reset => { + text => "reset color to default", + verbose => [ + "RESET --all|<nick>", + "", + "resets the color used for all nicks or for <nick> to ", + "its internal default", + ], + func => \&cmd_neatcolor_reset, + }, + save => { + text => "save color information to disk", + verbose => [ + "SAVE", + "", + "saves color information to disk, so that it survives ". + "an irssi restart.", + "", + "Color information will be automatically saved on /quit", + ], + func => \&cmd_neatcolor_save, + }, + set => { + text => "set a specific color for a nick", + verbose => [ + "SET <nick> <color>", + "", + "use <color> for <nick>", + "", + "This command will perform a couple of sanity checks, ". + "when called from a CHANNEL/QUERY window", + "", + "EXAMPLE:", + " /neatcolor set bc-bd r", + "", + "use /neatcolor COLORS to see available colors" + ], + func => \&cmd_neatcolor_set, + }, +); + +# the main command callback that gets called for all neatcolor commands +sub cmd_neatcolor() { + my ($data, $server, $witem) = @_; + my ($cmd, $nick, $color) = split (/ /, $data); + + $cmd = lc($cmd); + + # make sure we have a valid witem to print text to + $witem = Irssi::active_win() unless ($witem); + + if (!exists($commands{$cmd})) { + neat_log($witem, "Error: unknown command '$cmd'"); + &{$commands{"help"}{"func"}}($witem) if (exists($commands{"help"})); + return; + } + + &{$commands{$cmd}{"func"}}($witem, $nick, $color); +} + +Irssi::settings_add_bool('misc', 'neat_left_messages', 0); +Irssi::settings_add_bool('misc', 'neat_left_actions', 0); +Irssi::settings_add_bool('misc', 'neat_right_mode', 1); +Irssi::settings_add_int('misc', 'neat_maxlength', 0); +Irssi::settings_add_int('misc', 'neat_melength', 2); +Irssi::settings_add_bool('misc', 'neat_colorize', 1); +Irssi::settings_add_str('misc', 'neat_colors', 'rRgGyYbBmMcC'); +Irssi::settings_add_str('misc', 'neat_ignorechars', ''); +Irssi::settings_add_bool('misc', 'neat_allow_shrinking', 1); +Irssi::settings_add_int('misc', 'neat_autosave', 60); + +Irssi::command_bind('neatcolor', 'cmd_neatcolor'); + +Irssi::signal_add('nicklist new', 'sig_newNick'); +Irssi::signal_add('nicklist changed', 'sig_changeNick'); +Irssi::signal_add('nicklist remove', 'sig_removeNick'); + +Irssi::signal_add('setup changed', 'sig_setup'); +Irssi::signal_add_last('setup reread', 'sig_setup'); + +findLongestNick(); +sig_setup; + +load_colors(); +assert_colors(); + +# we need to add this signal _after_ the colors have been loaded, to make sure +# no race condition exists wrt color saving +Irssi::signal_add('gui exit', 'save_colors');