All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
1 use Irssi 20020101.0001 ();
5 use vars qw($VERSION %IRSSI);
9 authors => 'BC-bd, Veli',
10 contact => 'bd@bc-bd.org, veli@piipiip.net',
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'
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
21 # for irssi 0.8.2 by bd@bc-bd.org
23 # inspired by chanlist.pl by 'cumol@hammerhart.de'
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 # chanact_filter_windowlist
34 # Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22
35 # Ivo Timmermans <ivo@o2w.nl> win->{hilight} patch
41 # copy the script to ~/.irssi/scripts/
45 # /script load chanact
46 # /statusbar window add -after act chanact
48 # If you want the item to appear on another position read the help
50 # To remove the [Act: 1,2,3] item type:
52 # /statusbar window remove act
54 # To see all chanact options type:
58 # After these steps you have your new statusbar item and you can start giving
59 # aliases to your windows. Go to the window you want to give the alias to
62 # /window_alias <alias char>
64 # You can also remove the aliases with:
66 # /window_unalias <alias char>
68 # or in aliased window:
72 # To see a list of your windows use:
80 # /set chanact_chop_status <ON|OFF>
81 # * ON : shorten (Status) to S
84 # /set chanact_show_mode <ON|OFF>
85 # * ON : show channel modes
86 # * OFF : don't show channel modes
88 # /set chanact_sort_by_activity <ON|OFF>
89 # * ON : sorts the list by last activity
90 # * OFF : sorts the list by window number
92 # /set chanact_display <string>
93 # * string : Format String for one Channel. The following $'s are expanded:
95 # $N : Number of the Window
96 # $M : Mode in that channel
97 # $H : Start highlightning
98 # $S : Stop highlightning
101 # /set chanact_display $H$N:$M.$S$C
103 # will give you on #irssi.de if you have voice
107 # with '3:+.' highlighted and the channel name printed in regular color
109 # /set chanact_display_alias <string>
110 # as 'chanact_display' but is used if the window has an alias and
111 # 'chanact_show_alias' is set to on.
113 # /set chanact_show_names <ON|OFF>
114 # * ON : show the channelnames after the number/alias
115 # * OFF : don't show the names
117 # /set chanact_abbreviate_names <int>
118 # * 0 : don't abbreviate
119 # * <int> : strip channel name prefix character and leave only
120 # that many characters of the proper name
122 # /set chanact_show_alias <ON|OFF>
123 # * ON : show the aliase instead of the refnum
124 # * OFF : shot the refnum
126 # /set chanact_header <str>
127 # * <str> : Characters to be displayed at the start of the item.
128 # Defaults to: "Act: "
130 # /set chanact_separator <str>
131 # * <str> : Charater to use between the channel entries
133 # /set chanact_autorenumber <ON|OFF>
134 # * ON : Move the window automatically to first available slot
135 # starting from "chanact_renumber_start" when assigning
136 # an alias to window. Also moves the window back to a
137 # first available slot from refnum 1 when the window
139 # * OFF : Don't move the windows automatically
141 # /set chanact_renumber_start <int>
142 # * <int> : Move the window to first available slot after this
143 # num when "chanact_autorenumber" is ON.
145 # /set chanact_remove_hash <ON|OFF>
146 # * ON : Remove &#+!= from channel names
147 # * OFF : Don't touch channel names
149 # /set chanact_remove_prefix <string>
150 # * <string> : Regular expression used to remove from the
151 # beginning of the channel name.
153 # To shorten a lot of debian channels:
155 # /set chanact_remove_prefix deb(ian.(devel-)?)?
157 # /set chanact_filter <int>
158 # * 0 : show all channels
159 # * 1 : hide channels without activity
160 # * 2 : hide channels with only join/part/etc messages
161 # * 3 : hide channels with text messages
162 # * 4 : hide all channels (now why would you want to do that)
164 # /set chanact_filter_windowlist <string>
165 # * <string> : space-separated list of windows for which to use
166 # chanact_filter_windowlist_level instead of
168 # Alternatively, an entry can be postfixed with
169 # a colon (':') and the level to use for that
171 # The special string @QUERIES matches all queries.
173 # /set chanact_filter_windowlist_level <int>
174 # like chanact_filter for windows in chanact_filter_windowlist, which do not
175 # have a specific value. Defaults to chanact_filter<4 ? 4 : 2, making
176 # chanact_filter_windowlist a list of windows never to show if
177 # chanact_filter<4, and a list of windows to show when there is reasonable
178 # activity if all channels would be hidden.
184 # If you have trouble with wrong colored entries your 'default.theme' might
185 # be too old. Try on a shell:
187 # $ mv ~/.irssi/default.theme /tmp/
197 0 => "{%n ", # NOTHING
198 1 => "{sb_act_text ", # TEXT
199 2 => "{sb_act_msg ", # MSG
200 3 => "{sb_act_hilight ", # HILIGHT
203 my ($actString,$needRemake);
206 my ($string, %format) = @_;
208 $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
212 # method will get called every time the statusbar item will be displayed
213 # but we dont need to recreate the item every time so we first
214 # check if something has changed and only then we recreate the string
215 # this might just save some cycles
216 # FIXME implement $get_size_only check, and user $item->{min|max-size}
218 my ($item, $get_size_only) = @_;
224 $item->default_handler($get_size_only, $actString, undef, 1);
227 sub get_filterlevel {
229 my $kwregexp = '(?:' . join('|', map quotemeta, @_) . ')';
230 my $defaultlevel = Irssi::settings_get_int('chanact_filter_windowlist_level');
231 foreach my $win (@$windows) {
232 return ($1 ? $1 : $defaultlevel) if $win =~ /^$kwregexp(?:\:(\d+))?$/;
239 # this is the real creation method
241 my ($afternumber,$finish,$hilight,$mode,$number,$display,@windows);
242 my $separator = Irssi::settings_get_str('chanact_separator');
243 my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');
244 my $remove_prefix = Irssi::settings_get_str('chanact_remove_prefix');
245 my $remove_hash = Irssi::settings_get_bool('chanact_remove_hash');
246 my @windowlist = split ' ', Irssi::settings_get_str('chanact_filter_windowlist');
248 if (Irssi::settings_get_bool('chanact_sort_by_activity')) {
249 @windows = sort { ($b->{last_line} <=> $a->{last_line}) }
252 @windows = sort { ($a->{refnum}) <=> ($b->{refnum}) }
257 foreach my $win (@windows) {
259 # since irssi is single threaded this shouldn't happen
262 my $active = $win->{active};
263 !ref($active) && next;
265 my $name = $win->get_active_name;
266 my $type = $active->{type};
268 ## determine the filter_level to use to determine whether the
269 ## activity on the current window is worth the bother
271 my @matchlist; push @matchlist, $name;
272 # if this is a query, also try to match @QUERIES
273 push @matchlist, '@QUERIES' if ($type eq 'QUERY');
274 # get_filterlevel matches all items in @matchlist against the
275 # @windowlist and returns the applicable filterlevel
276 my $filter_level = get_filterlevel(\@windowlist, @matchlist);
277 # if we don't have a match (undef), then use the
278 # chanact_filter value
279 $filter_level = Irssi::settings_get_int('chanact_filter') unless $filter_level;
281 # now, skip windows with data of level lower than the
283 next if ($win->{data_level} < $filter_level);
285 # alright, the activity is important, let's show the window
286 my $level = $win->{data_level};
288 # (status) is an awfull long name, so make it short to 'S'
289 # some people don't like it, so make it configurable
290 if (Irssi::settings_get_bool('chanact_chop_status')
291 && $name eq "(status)") {
295 # check if we should show the mode
297 if ($type eq "CHANNEL") {
298 my $server = $win->{active_server};
299 !ref($server) && next;
301 my $channel = $server->channel_find($name);
302 !ref($channel) && next;
304 my $nick = $channel->nick_find($server->{nick});
309 } elsif ($nick->{voice}) {
311 } elsif ($nick->{halfop}) {
316 # in case we have a specific hilightcolor use it
317 if ($win->{hilight_color}) {
318 $hilight = "{sb_act_hilight_color $win->{hilight_color} ";
320 $hilight = $show{$win->{data_level}};
323 if ($remove_prefix) {
324 $name =~ s/^([&#+!=]?)$remove_prefix/$1/;
327 if ($name =~ /^[&#+!=]/) {
328 $name = substr($name, 1, $abbrev + 1);
330 $name = substr($name, 0, $abbrev);
334 $name =~ s/^[&#+!=]//;
337 if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&
338 $win->{name} =~ /^([a-zA-Z+]):(.+)$/) {
340 $display = Irssi::settings_get_str('chanact_display_alias');
342 $number = $win->{refnum};
343 $display = Irssi::settings_get_str('chanact_display');
346 $actString .= expand($display,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
349 # assemble the final string
350 if ($actString ne "") {
351 # Remove the last separator
352 $actString =~ s/$separator$//;
354 if (Irssi::settings_get_int('chanact_filter')) {
355 $actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
357 $actString = "{sb ".$actString."}";
361 # no remake needed any longer
365 # method called because of some events. here we dont remake the item but just
366 # remember that we have to remake it the next time we are called
367 sub chanactHasChanged()
369 # if needRemake is already set, no need to trigger a redraw as we will
370 # be redrawing the item anyway.
371 return if $needRemake;
375 Irssi::statusbar_items_redraw('chanact');
378 # function by veli@piipiip.net
380 sub cmd_window_unalias {
381 my ($data, $server, $witem) = @_;
382 my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
384 unless ($data =~ /^[a-zA-Z]$/ ||
385 Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
386 Irssi::print("Usage: /window_unalias <char>");
387 Irssi::print("or /window_alias in window that has an alias.");
391 if ($data eq '') { $data = Irssi::active_win()->{name}; }
393 if (my $oldwin = Irssi::window_find_name($data)) {
394 $oldwin->set_name(undef);
395 Irssi::print("Removed alias with the key '$data'.");
397 if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
398 $oldwin->{refnum} >= $rn_start) {
399 my $old_refnum = $oldwin->{refnum};
401 # Find the first available slot and move the window
403 while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
404 $oldwin->set_refnum($newnum);
406 Irssi::print("and moved it to from $old_refnum to $newnum");
411 # function by veli@piipiip.net
413 sub cmd_window_alias {
414 my ($data, $server, $witem) = @_;
415 my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
417 unless ($data =~ /^[a-zA-Z+]$/) {
418 Irssi::print("Usage: /window_alias <char>");
422 cmd_window_unalias($data, $server, $witem);
424 my $window = $witem->window();
425 my $winnum = $window->{refnum};
427 if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
428 $window->{refnum} < $rn_start) {
429 my $old_refnum = $window->{refnum};
433 # Find the first available slot and move the window
434 while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
435 $window->set_refnum($winnum);
437 Irssi::print("Moved the window from $old_refnum to $winnum");
440 my $winname = $witem->{name};
441 my $winserver = $window->{active_server}->{tag};
442 my $winhandle = "$winserver/$winname";
443 $window->set_name("$data:$winhandle");
444 $server->command("/bind meta-$data change_window $data:$winhandle");
445 Irssi::print("Window $winhandle is now accessible with meta-$data");
448 # function by veli@piipiip.net
449 # Makes the aliases if names have already been set
450 sub cmd_rebuild_aliases {
451 foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
452 if ($_->{name} =~ /^[a-zA-Z]$/) {
453 cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
458 # function by veli@piipiip.net
459 # Change the binding if the window refnum changes.
461 my ($window, $oldref) = @_;
462 my $server = Irssi::active_server();
464 if ($window->{name} =~ /^[a-zA-Z]$/) {
465 $server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
471 # Window alias command
472 Irssi::command_bind('window_alias','cmd_window_alias');
473 Irssi::command_bind('window_unalias','cmd_window_unalias');
474 # Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');
477 Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
478 Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
479 Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
480 Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
481 Irssi::settings_add_str('chanact', 'chanact_separator', " ");
482 Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
483 Irssi::settings_add_bool('chanact', 'chanact_remove_hash', 0);
484 Irssi::settings_add_str('chanact', 'chanact_remove_prefix', "");
485 Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
486 Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
487 Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);
488 Irssi::settings_add_bool('chanact', 'chanact_sort_by_activity', 1);
489 Irssi::settings_add_int('chanact', 'chanact_filter', 0);
490 Irssi::settings_add_str('chanact', 'chanact_filter_windowlist', "");
491 Irssi::settings_add_int('chanact', 'chanact_filter_windowlist_level',
492 Irssi::settings_get_int('chanact_filter') < 4 ? 4 : 2);
494 # register the statusbar item
495 Irssi::statusbar_item_register('chanact', '$0', 'chanact');
496 # according to cras we shall not call this
497 # Irssi::statusbars_recreate_items();
499 # register all that nifty callbacks on special events
500 Irssi::signal_add_last('setup changed', 'chanactHasChanged');
501 Irssi::signal_add_last('window changed', 'chanactHasChanged');
502 Irssi::signal_add_last('window item changed', 'chanactHasChanged');
503 Irssi::signal_add_last('window hilight', 'chanactHasChanged');
504 Irssi::signal_add_last('window item hilight', 'chanactHasChanged');
505 Irssi::signal_add("window created", "chanactHasChanged");
506 Irssi::signal_add("window destroyed", "chanactHasChanged");
507 Irssi::signal_add("window name changed", "chanactHasChanged");
508 Irssi::signal_add("window activity", "chanactHasChanged");
509 Irssi::signal_add("print text", "chanactHasChanged");
510 Irssi::signal_add('nick mode changed', 'chanactHasChanged');
512 Irssi::signal_add_last('window refnum changed', 'refnum_changed');
520 # - added chanact_filter_windowlist, which is a space-separated list of
521 # windows for which to use chanact_filter_windowlist_level instead of
522 # chanact_filter. Each window can also have a specific level
523 # specified. You can use @QUERIES to match all queries
524 # (madduck@madduck.net).
527 # - fixed irssi crash when using Irssi::print from within remake()
528 # - added option to filter out some data levels, based on a patch by
529 # Juergen Jung <juergen@Winterkaelte.de>, see
530 # https://bc-bd.org/trac/irssi/ticket/15
531 # + retired chanact_show_all in favour of chanact_filter
534 # - changes by stefan voelkel
535 # + sort channels by activity, see
536 # https://bc-bd.org/trac/irssi/ticket/5, based on a patch by jan
538 # + fixed chrash on /exec -interactive, see
539 # https://bc-bd.org/trac/irssi/ticket/7
541 # - changes by Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22
542 # + updated documentation in script's comments
544 # - changes by Ivo Timmermans <ivo@o2w.nl>
545 # + honor actcolor /hilight setting if present
548 # - made aliases case-sensitive and include network in channel names by madduck
551 # - integrated remove patch by Christoph Berg <myon@debian.org>
554 # - fixed a bug (#1) reported by Wouter Coekaert
557 # - some speedups from David Leadbeater <dgl@dgl.cx>
561 # - added help for chanact_display_alias
564 # - added '+' to the available chars of aliase's
565 # - added chanact_display_alias to allow different display modes if the window
569 # - removed unused chanact_show_name settings (thx to Qerub)
570 # - fixed $mode display
571 # - guarded reference operations to (hopefully) fix errors on server disconnect
577 # - changed chanact_show_mode to chanact_display. reversed changes from
578 # Qerub through that, but kept funcionality.
579 # - removed chanact_color_all since it is no longer needed
583 # + added chanact_show_mode to show the mode just before the channel name
584 # + added chanact_chop_status to be able to control the (status) chopping
585 # [bd] minor implementation changes
586 # - moved Changelog to the end of the file since it is getting pretty big
589 # - changed back to old version numbering sheme
590 # - added '=' to Qrczak's chanact_abbreviate_names stuff :)
591 # - added chanact_header
594 # - changes by Qrczak
595 # + added setting 'chanact_abbreviate_names'
596 # + windows are sorted by refnum; I didn't understand the old
597 # logic and it broke sorting for numbers above 9
601 # + fixed channel sort [veli]
602 # + removed few typos and added some documentation [veli]
605 # - merge with window_alias.pl
606 # + added /window_alias from window_alias.pl by veli@piipiip.net
607 # + added setting 'chanact_show_alias'
608 # + added setting 'chanact_show_names'
609 # + changed setting 'chanact_show_mode' to int
610 # + added setting 'chanact_separator' [veli]
611 # + added setting 'chanact_autorenumber' [veli]
612 # + added setting 'chanact_renumber_start' [veli]
613 # + added /window_unalias [veli]
614 # + moved setting to their own group 'chanact' [veli]
617 # - merge with chanlist.pl
618 # + added setting 'chanact_show_mode'
619 # + added setting 'chanact_show_all'
622 # - added 'Act' to the item
623 # - added setting 'chanact_color_all'
624 # - finally found format for statusbar hilight