]> 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:

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