summaryrefslogtreecommitdiffstats
path: root/irssi/scripts/chanact.pl
blob: 4c192e1ce6eb1f3f4e2a275d2dab30d0f0845b79 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
use Irssi 20020101.0001 ();
use strict;
use Irssi::TextUI;

use vars qw($VERSION %IRSSI);

$VERSION = "0.5.5";
%IRSSI = (
    authors     => 'BC-bd, Veli',
    contact     => 'bd@bc-bd.org, veli@piipiip.net',
    name        => 'chanact',
    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>',
    license     => 'GNU GPLv2 or later',
    url         => 'http://bc-bd.org/software.php3#irssi'
);

# 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>.
#
# for irssi 0.8.2 by bd@bc-bd.org
#
# inspired by chanlist.pl by 'cumol@hammerhart.de'
#
#########
# Contributors
#########
#
# veli@piipiip.net   /window_alias code
# qrczak@knm.org.pl  chanact_abbreviate_names
# qerub@home.se      Extra chanact_show_mode and chanact_chop_status
# 
#########
# USAGE
###
# 
# copy the script to ~/.irssi/scripts/
#
# In irssi:
#
#		/script load chanact
#		/statusbar window add chanact -after act
#
# If you want the item to appear on another position read the help
# for /statusbar.
# To remove the [Act: 1,2,3] item type:
#
#		/statusbar window remove act
#
# To see all chanact options type:
#
# 	/ set chanact_
#
# After these steps you have your new statusbar item and you can start giving
# aliases to your windows. Go to the window you want to give the alias to
# and say:
#
#		/window_alias <alias char>
#
# You can also remove the aliases with:
#
#		/window_unalias <alias char>
#
# or in aliased window:
#
#		/window_unalias
#
# To see a list of your windows use:
#
#		/window list
#
#########
# OPTIONS
#########
#
# /set chanact_show_all <ON|OFF>
#		* ON  : show all windows
#		* OFF : show only those with activity
#
# /set chanact_display <string>
#		* string : Format String for one Channel. The following $'s are expanded:
#		    $C : Channel
#		    $N : Number of the Window
#		    $M : Mode in that channel
#		    $H : Start highlightning
#		    $S : Stop highlightning
#		* example:
#		
#		      /set chanact_display $H$N:$M.$S$C
#		      
#		    will give you on #irssi.de if you have voice
#		    
#		      [3:+.#irssi.de]
#
#		    with '3:+.' highlighted and the channel name printed in regular color
#
# /set chanact_display_alias <string>
#   as 'chanact_display' but is used if the window has an alias and
#   'chanact_show_alias' is set to on.
# 
# /set chanact_show_names <ON|OFF>
#		* ON  : show the channelnames after the number/alias
#		* OFF : don't show the names
#
# /set chanact_abbreviate_names <int>
#               * 0     : don't abbreviate
#               * <int> : strip channel name prefix character and leave only
#                         that many characters of the proper name
#
# /set chanact_show_alias <ON|OFF>
#		* ON  : show the aliase instead of the refnum
#		* OFF : shot the refnum
#
# /set chanact_separator <str>
# 	* <str> : Characters to be displayed at the start of the item.
# 	          Defaults to: "Act: "
#
# /set chanact_separator <str>
#		* <str> : Charater to use between the channel entries
#
# /set chanact_autorenumber <ON|OFF>
#		* ON  : Move the window automatically to first available slot
#		        starting from "chanact_renumber_start" when assigning 
#		        an alias to window. Also moves the window back to a
#		        first available slot from refnum 1 when the window
#		        loses it's alias.
#		* OFF : Don't move the windows automatically
#
# /set chanact_renumber_start <int>
# 		* <int> : Move the window to first available slot after this
# 		          num when "chanact_autorenumber" is ON.
# 		
# 
#########
# HINTS
#########
#
# If you have trouble with wrong colored entries your 'default.theme' might
# be too old. Try on a shell:
#
# 	$ mv ~/.irssi/default.theme /tmp/
#
# And in irssi:
#	/reload
#	/save
#
###
#################

my ($actString,$needRemake);

sub expand {
  my ($string, %format) = @_;
  my ($exp, $repl);
  $string =~ s/\$$exp/$repl/g while (($exp, $repl) = each(%format));
  return $string;
}

# method will get called every time the statusbar item will be displayed
# but we dont need to recreate the item every time so we first
# check if something has changed and only then we recreate the string
# this might just save some cycles
# FIXME implement $get_size_only check, and user $item->{min|max-size}
sub chanact {
	my ($item, $get_size_only) = @_;

	if ($needRemake) {
		remake();
	}
	
	$item->default_handler($get_size_only, $actString, undef, 1);
}

# this is the real creation method
sub remake() {
	my ($afternumber,$finish,$hilight,$mode,$number,$display);
	my $separator = Irssi::settings_get_str('chanact_separator'); 
	my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');
	
	$actString = "";
	foreach my $win (sort { ($a->{refnum}) <=> ($b->{refnum})} Irssi::windows) {
	
		# since irssi is single threaded this shouldn't happen
		!ref($win) && next;

		my $name = $win->get_active_name;
		my $active = $win->{active};
                my $type = '*';

		!ref($win) && next;

                $name eq "all" && next;
                $name eq "bots" && next;
                $name eq "hilight" && next;
                $name eq "(status)" && $win->{data_level} <= 0 && next;
                $name eq "&bitlbee" && $win->{data_level} <= 0 && next;

                $type = '!' if $name eq "(status)";
		# (status) is an awfull long name, so make it short to 'S'
		# some people don't like it, so make it configurable
		if (Irssi::settings_get_bool('chanact_chop_status')
		    && $name eq "(status)") {
			$name = "S";
		}
	
		# check if we should show the mode
		$mode = "";
		if ($active->{type} eq "CHANNEL") {
			my $server = $win->{active_server};
			!ref($server) && next;

			my $channel = $server->channel_find($name);
			!ref($channel) && next;

			my $nick = $channel->nick_find($server->{nick});
			!ref($nick) && next;
			
			if ($nick->{op}) {
				$mode = "@";
			} elsif ($nick->{voice}) {
				$mode = "+";
			} elsif ($nick->{halfop}) {
				$mode = "%";
			}
                        $type = substr($name, 0, 1);
		}
                elsif ($active->{type} eq "QUERY") {
                        $type = '?';
                }

		# find the right color
		if ($win->{data_level} == 1) {
			$hilight = "{sb_act_text ";
		} elsif ($win->{data_level} == 2) {
			$hilight = "{sb_act_msg ";
		} elsif ($win->{data_level} == 3) {
			$hilight = "{sb_act_hilight ";
		} else {
			if (Irssi::settings_get_bool('chanact_show_all') == 1) {
				$hilight = "{sb_act_hilight_color %K ";
			} else {
				next;
			}
		}

		if ($abbrev) {
			$name =~ s{.*/}{};
			if ($name =~ /^[&#+!=]*(.*)/) {
				$name = substr($1, 0, $abbrev);
			}
		}

		if (Irssi::settings_get_bool('chanact_show_alias') == 1 && 
				$win->{name} =~ /^[a-zA-Z+]$/) {
			$number = $win->{name};
			$display = Irssi::settings_get_str('chanact_display_alias'); 
		} else {
			$number = $win->{refnum};
			$display = Irssi::settings_get_str('chanact_display'); 
		}

		$actString .= expand($display,"T",$type,"C",$name,"N",$number,"M",$mode,"H",$hilight,"S","}{sb_background}").$separator;
	}

	# assemble the final string
	if ($actString ne "") {
		# Remove the last separator
		$actString =~ s/$separator$//;
		
		if (Irssi::settings_get_bool('chanact_show_all') == 1) {
			$actString = "{sb ".$actString."}";
		} else {
			$actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";
		}
	}

	# no remake needed any longer
	$needRemake = 0;
}

# method called because of some events. here we dont remake the item but just
# remember that we have to remake it the next time we are called
sub chanactHasChanged()
{
	$needRemake = 1;

	Irssi::statusbar_items_redraw('chanact');
}

# function by veli@piipiip.net
# Remove alias
sub cmd_window_unalias {
	my ($data, $server, $witem) = @_;
	my $rn_start = Irssi::settings_get_int('chanact_renumber_start');
	
	unless ($data =~ /^[a-zA-Z]$/ || 
			Irssi::active_win()->{name} =~ /^[a-zA-Z]$/) {
		Irssi::print("Usage: /window_unalias <char>");
		Irssi::print("or /window_alias in window that has an alias.");
		return;
	}
	
	if ($data eq '') { $data = Irssi::active_win()->{name}; }

	if (my $oldwin = Irssi::window_find_name($data)) {
		$oldwin->set_name(undef);
		Irssi::print("Removed alias with the key '$data'.");
		
		if (Irssi::settings_get_bool('chanact_autorenumber') == 1 && 
				$oldwin->{refnum} >= $rn_start) {
			my $old_refnum = $oldwin->{refnum};
			
			# Find the first available slot and move the window
			my $newnum = 1;
			while (Irssi::window_find_refnum($newnum) ne "") { $newnum++; }
			$oldwin->set_refnum($newnum);
			
			Irssi::print("and moved it to from $old_refnum to $newnum");
		}
	}
}

# function by veli@piipiip.net
# Make an alias
sub cmd_window_alias {
	my ($data, $server, $witem) = @_;
	my $rn_start = Irssi::settings_get_int('chanact_renumber_start');

	unless ($data =~ /^[a-zA-Z+]$/) {
		Irssi::print("Usage: /window_alias <char>");
		return;
	}

	cmd_window_unalias($data, $server, $witem);
	
	my $window = $witem->window();
	my $winnum = $window->{refnum};
	
	if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&
			$window->{refnum} < $rn_start) {
		my $old_refnum = $window->{refnum};

		$winnum = $rn_start;
 
		# Find the first available slot and move the window
		while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; }
		$window->set_refnum($winnum);
		
		Irssi::print("Moved the window from $old_refnum to $winnum");
	}
	
	$window->set_name($data);
	$server->command("/bind meta-$data change_window $winnum");
	Irssi::print("Window $winnum is now known as '$data'");
}

# function by veli@piipiip.net
# Makes the aliases if names have already been set
sub cmd_rebuild_aliases {
	foreach (sort { $a->{refnum} <=> $b->{refnum} } Irssi::windows) {
		if ($_->{name} =~ /^[a-zA-Z]$/) {
			cmd_window_alias($_->{name}, $_->{active_server}, $_->{active});
		}
	}
}

# function by veli@piipiip.net
# Change the binding if the window refnum changes.
sub refnum_changed {
	my ($window, $oldref) = @_;
	my $server = Irssi::active_server();

	if ($window->{name} =~ /^[a-zA-Z]$/) {
		$server->command("/bind meta-".$window->{name}." change_window ".$window->{refnum});
	}
}

$needRemake = 1;

# Window alias command
Irssi::command_bind('window_alias','cmd_window_alias');
Irssi::command_bind('window_unalias','cmd_window_unalias');
# Irssi::command_bind('window_alias_rebuild','cmd_rebuild_aliases');

# our config item
Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S');
Irssi::settings_add_str('chanact', 'chanact_display_alias', '$H$N$M$S');
Irssi::settings_add_bool('chanact', 'chanact_show_all', 0);
Irssi::settings_add_int('chanact', 'chanact_abbreviate_names', 0);
Irssi::settings_add_bool('chanact', 'chanact_show_alias', 1);
Irssi::settings_add_str('chanact', 'chanact_separator', " ");
Irssi::settings_add_bool('chanact', 'chanact_autorenumber', 0);
Irssi::settings_add_int('chanact', 'chanact_renumber_start', 50);
Irssi::settings_add_str('chanact', 'chanact_header', "Act: ");
Irssi::settings_add_bool('chanact', 'chanact_chop_status', 1);

# register the statusbar item
Irssi::statusbar_item_register('chanact', '$0', 'chanact');
# according to cras we shall not call this
# Irssi::statusbars_recreate_items();

# register all that nifty callbacks on special events
Irssi::signal_add_last('setup changed', 'chanactHasChanged');
Irssi::signal_add_last('window hilight', 'chanactHasChanged');
Irssi::signal_add("window created", "chanactHasChanged");
Irssi::signal_add("window destroyed", "chanactHasChanged");
Irssi::signal_add("window name changed", "chanactHasChanged");
Irssi::signal_add('nick mode changed', 'chanactHasChanged');

Irssi::signal_add_last('window refnum changed', 'refnum_changed');

###############
###
#
# Changelog
# 
# 0.5.5
# - some speedups from David Leadbeater <dgl@dgl.cx>
# 
# 0.5.4
# - added help for chanact_display_alias
#
# 0.5.3
# - added '+' to the available chars of aliase's
# - added chanact_display_alias to allow different display modes if the window
#   has an alias
#
# 0.5.2
# - removed unused chanact_show_name settings (thx to Qerub)
# - fixed $mode display
# - guarded reference operations to (hopefully) fix errors on server disconnect
# 
# 0.5.1
# - small typo fixed
#
# 0.5.0
# - changed chanact_show_mode to chanact_display. reversed changes from
#   Qerub through that, but kept funcionality.
# - removed chanact_color_all since it is no longer needed
# 
# 0.4.3
# - changes by Qerub
#   + added chanact_show_mode to show the mode just before the channel name
#   + added chanact_chop_status to be able to control the (status) chopping
#     [bd] minor implementation changes
# - moved Changelog to the end of the file since it is getting pretty big
#
# 0.4.2
# - changed back to old version numbering sheme
# - added '=' to Qrczak's chanact_abbreviate_names stuff :)
# - added chanact_header
#
# 0.41q
#	- changes by Qrczak
#		+ added setting 'chanact_abbreviate_names'
#		+ windows are sorted by refnum; I didn't understand the old
#		  logic and it broke sorting for numbers above 9
#
# 0.41
#	- minor updates
#		+ fixed channel sort [veli]
#		+ removed few typos and added some documentation [veli]
#
# 0.4
#	- merge with window_alias.pl
#		+ added /window_alias from window_alias.pl by veli@piipiip.net
#		+ added setting 'chanact_show_alias'
#		+ added setting 'chanact_show_names'
#		+ changed setting 'chanact_show_mode' to int
#		+ added setting 'chanact_separator' [veli]
#		+ added setting 'chanact_autorenumber' [veli]
#		+ added setting 'chanact_renumber_start' [veli]
#		+ added /window_unalias [veli]
#		+ moved setting to their own group 'chanact' [veli]
#
# 0.3
#	- merge with chanlist.pl
#		+ added setting 'chanact_show_mode'
#		+ added setting 'chanact_show_all'
#
# 0.2
#	- added 'Act' to the item
#		- added setting 'chanact_color_all'
#		- finally found format for statusbar hilight
#
# 0.1
#	- Initial Release
#
###
################