]> git.madduck.net Git - code/irssi/scripts-bc-bd.git/blob - chanact.pl

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

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