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

semi-consistent use of tabs
[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         => 'http://bc-bd.org/blog/irssi/'
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                 # (status) is an awfull long name, so make it short to 'S'
238                 # some people don't like it, so make it configurable
239                 if (Irssi::settings_get_bool('chanact_chop_status')
240                         && $name eq "(status)") {
241                         $name = "S";
242                 }
243
244                 # check if we should show the mode
245                 $mode = "";
246                 if ($active->{type} eq "CHANNEL") {
247                         my $server = $win->{active_server};
248                         !ref($server) && next;
249
250                         my $channel = $server->channel_find($name);
251                         !ref($channel) && next;
252
253                         my $nick = $channel->nick_find($server->{nick});
254                         !ref($nick) && next;
255
256                         if ($nick->{op}) {
257                                 $mode = "@";
258                         } elsif ($nick->{voice}) {
259                                 $mode = "+";
260                         } elsif ($nick->{halfop}) {
261                                 $mode = "%";
262                         }
263                 }
264
265                 next if (Irssi::settings_get_int('chanact_filter') > $win->{data_level});
266
267                 # in case we have a specific hilightcolor use it
268                 if ($win->{hilight_color}) {
269                         $hilight = "{sb_act_hilight_color $win->{hilight_color} ";
270                 } else {
271                         $hilight = $show{$win->{data_level}};
272                 }
273
274                 if ($remove_prefix) {
275                         $name =~ s/^([&#+!=]?)$remove_prefix/$1/;
276                 }
277                 if ($abbrev) {
278                         if ($name =~ /^[&#+!=]/) {
279                                 $name = substr($name, 1, $abbrev + 1);
280                         } else {
281                                 $name = substr($name, 0, $abbrev);
282                         }
283                 }
284                 if ($remove_hash) {
285                         $name =~ s/^[&#+!=]//;
286                 }
287
288                 if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&
289                                 $win->{name} =~ /^([a-zA-Z+]):(.+)$/) {
290                         $number = "$1";
291                         $display = Irssi::settings_get_str('chanact_display_alias');
292                 } else {
293                         $number = $win->{refnum};
294                         $display = Irssi::settings_get_str('chanact_display');
295                 }
296
297                 $actString .= expand($display,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
298         }
299
300         # assemble the final string
301         if ($actString ne "") {
302                 # Remove the last separator
303                 $actString =~ s/$separator$//;
304
305                 if (Irssi::settings_get_int('chanact_filter')) {
306                         $actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
307                 } else {
308                         $actString = "{sb ".$actString."}";
309                 }
310         }
311
312         # no remake needed any longer
313         $needRemake = 0;
314 }
315
316 # method called because of some events. here we dont remake the item but just
317 # remember that we have to remake it the next time we are called
318 sub chanactHasChanged()
319 {
320         # if needRemake is already set, no need to trigger a redraw as we will
321         # be redrawing the item anyway.
322         return if $needRemake;
323
324         $needRemake = 1;
325
326         Irssi::statusbar_items_redraw('chanact');
327 }
328
329 # function by veli@piipiip.net
330 # Remove alias
331 sub cmd_window_unalias {
332         my ($data, $server, $witem) = @_;
333         my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
334
335         unless ($data =~ /^[a-zA-Z]$/ ||
336                         Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
337                 Irssi::print("Usage: /window_unalias <char>");
338                 Irssi::print("or /window_alias in window that has an alias.");
339                 return;
340         }
341
342         if ($data eq '') { $data = Irssi::active_win()->{name}; }
343
344         if (my $oldwin = Irssi::window_find_name($data)) {
345                 $oldwin->set_name(undef);
346                 Irssi::print("Removed alias with the key '$data'.");
347
348                 if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
349                                 $oldwin->{refnum} >= $rn_start) {
350                         my $old_refnum = $oldwin->{refnum};
351
352                         # Find the first available slot and move the window
353                         my $newnum = 1;
354                         while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
355                         $oldwin->set_refnum($newnum);
356
357                         Irssi::print("and moved it to from $old_refnum to $newnum");
358                 }
359         }
360 }
361
362 # function by veli@piipiip.net
363 # Make an alias
364 sub cmd_window_alias {
365         my ($data, $server, $witem) = @_;
366         my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
367
368         unless ($data =~ /^[a-zA-Z+]$/) {
369                 Irssi::print("Usage: /window_alias <char>");
370                 return;
371         }
372
373         cmd_window_unalias($data, $server, $witem);
374
375         my $window = $witem->window();
376         my $winnum = $window->{refnum};
377
378         if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
379                         $window->{refnum} < $rn_start) {
380                 my $old_refnum = $window->{refnum};
381
382                 $winnum = $rn_start;
383
384                 # Find the first available slot and move the window
385                 while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
386                 $window->set_refnum($winnum);
387
388                 Irssi::print("Moved the window from $old_refnum to $winnum");
389         }
390
391         my $winname = $witem->{name};
392         my $winserver = $window->{active_server}->{tag};
393         my $winhandle = "$winserver/$winname";
394         $window->set_name("$data:$winhandle");
395         $server->command("/bind meta-$data change_window $data:$winhandle");
396         Irssi::print("Window $winhandle is now accessible with meta-$data");
397 }
398
399 # function by veli@piipiip.net
400 # Makes the aliases if names have already been set
401 sub cmd_rebuild_aliases {
402         foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
403                 if ($_->{name} =~ /^[a-zA-Z]$/) {
404                         cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
405                 }
406         }
407 }
408
409 # function by veli@piipiip.net
410 # Change the binding if the window refnum changes.
411 sub refnum_changed {
412         my ($window, $oldref) = @_;
413         my $server = Irssi::active_server();
414
415         if ($window->{name} =~ /^[a-zA-Z]$/) {
416                 $server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
417         }
418 }
419
420 $needRemake = 1;
421
422 # Window alias command
423 Irssi::command_bind('window_alias','cmd_window_alias');
424 Irssi::command_bind('window_unalias','cmd_window_unalias');
425 # Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');
426
427 # our config item
428 Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
429 Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
430 Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
431 Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
432 Irssi::settings_add_str('chanact', 'chanact_separator', " ");
433 Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
434 Irssi::settings_add_bool('chanact', 'chanact_remove_hash', 0);
435 Irssi::settings_add_str('chanact', 'chanact_remove_prefix', "");
436 Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
437 Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
438 Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);
439 Irssi::settings_add_bool('chanact', 'chanact_sort_by_activity', 1);
440 Irssi::settings_add_int('chanact', 'chanact_filter', 0);
441
442 # register the statusbar item
443 Irssi::statusbar_item_register('chanact', '$0', 'chanact');
444 # according to cras we shall not call this
445 # Irssi::statusbars_recreate_items();
446
447 # register all that nifty callbacks on special events
448 Irssi::signal_add_last('setup changed', 'chanactHasChanged');
449 Irssi::signal_add_last('window changed', 'chanactHasChanged');
450 Irssi::signal_add_last('window item changed', 'chanactHasChanged');
451 Irssi::signal_add_last('window hilight', 'chanactHasChanged');
452 Irssi::signal_add_last('window item hilight', 'chanactHasChanged');
453 Irssi::signal_add("window created", "chanactHasChanged");
454 Irssi::signal_add("window destroyed", "chanactHasChanged");
455 Irssi::signal_add("window name changed", "chanactHasChanged");
456 Irssi::signal_add("window activity", "chanactHasChanged");
457 Irssi::signal_add("print text", "chanactHasChanged");
458 Irssi::signal_add('nick mode changed', 'chanactHasChanged');
459
460 Irssi::signal_add_last('window refnum changed', 'refnum_changed');
461
462 ###############
463 ###
464 #
465 # Changelog
466
467 # 0.5.10
468 #       - fixed irssi crash when using Irssi::print from within remake()
469 #       - added option to filter out some data levels, based on a patch by
470 #         Juergen Jung <juergen@Winterkaelte.de>, see
471 #         https://bc-bd.org/trac/irssi/ticket/15
472 #               + retired chanact_show_all in favour of chanact_filter
473 #
474 # 0.5.9
475 #       - changes by stefan voelkel
476 #               + sort channels by activity, see
477 #                 https://bc-bd.org/trac/irssi/ticket/5, based on a patch by jan
478 #                 krueger
479 #               + fixed chrash on /exec -interactive, see
480 #               https://bc-bd.org/trac/irssi/ticket/7
481 #
482 #       - changes by Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22
483 #               + updated documentation in script's comments
484 #
485 #       - changes by Ivo Timmermans <ivo@o2w.nl>
486 #               + honor actcolor /hilight setting if present
487 #
488 # 0.5.8
489 # - made aliases case-sensitive and include network in channel names by madduck
490 #
491 # 0.5.7
492 # - integrated remove patch by Christoph Berg <myon@debian.org>
493 #
494 # 0.5.6
495 # - fixed a bug (#1) reported by Wouter Coekaert
496 #
497 # 0.5.5
498 # - some speedups from David Leadbeater <dgl@dgl.cx>
499 #
500 #
501 # 0.5.4
502 # - added help for chanact_display_alias
503 #
504 # 0.5.3
505 # - added '+' to the available chars of aliase's
506 # - added chanact_display_alias to allow different display modes if the window
507 #   has an alias
508 #
509 # 0.5.2
510 # - removed unused chanact_show_name settings (thx to Qerub)
511 # - fixed $mode display
512 # - guarded reference operations to (hopefully) fix errors on server disconnect
513 #
514 # 0.5.1
515 # - small typo fixed
516 #
517 # 0.5.0
518 # - changed chanact_show_mode to chanact_display. reversed changes from
519 #   Qerub through that, but kept funcionality.
520 # - removed chanact_color_all since it is no longer needed
521 #
522 # 0.4.3
523 # - changes by Qerub
524 #   + added chanact_show_mode to show the mode just before the channel name
525 #   + added chanact_chop_status to be able to control the (status) chopping
526 #     [bd] minor implementation changes
527 # - moved Changelog to the end of the file since it is getting pretty big
528 #
529 # 0.4.2
530 # - changed back to old version numbering sheme
531 # - added '=' to Qrczak's chanact_abbreviate_names stuff :)
532 # - added chanact_header
533 #
534 # 0.41q
535 #       - changes by Qrczak
536 #               + added setting 'chanact_abbreviate_names'
537 #               + windows are sorted by refnum; I didn't understand the old
538 #                 logic and it broke sorting for numbers above 9
539 #
540 # 0.41
541 #       - minor updates
542 #               + fixed channel sort [veli]
543 #               + removed few typos and added some documentation [veli]
544 #
545 # 0.4
546 #       - merge with window_alias.pl
547 #               + added /window_alias from window_alias.pl by veli@piipiip.net
548 #               + added setting 'chanact_show_alias'
549 #               + added setting 'chanact_show_names'
550 #               + changed setting 'chanact_show_mode' to int
551 #               + added setting 'chanact_separator' [veli]
552 #               + added setting 'chanact_autorenumber' [veli]
553 #               + added setting 'chanact_renumber_start' [veli]
554 #               + added /window_unalias [veli]
555 #               + moved setting to their own group 'chanact' [veli]
556 #
557 # 0.3
558 #       - merge with chanlist.pl
559 #               + added setting 'chanact_show_mode'
560 #               + added setting 'chanact_show_all'
561 #
562 # 0.2
563 #       - added 'Act' to the item
564 #               - added setting 'chanact_color_all'
565 #               - finally found format for statusbar hilight
566 #
567 # 0.1
568 #       - Initial Release
569 #
570 ###
571 ################
572 #
573 # vim:noet