1# BitchX TAB complete style
2# for irssi 0.7.99 by bd@bc-bd.org
3#
4# <tab> signal handling learned from dictcomplete by Timo Sirainen
5#
6# thx go out to fuchs, darix, dg, peder and all on #irssi who helped
7#
8#########
9# USAGE
10###
11#
12# In a channel window type "ab<tab>" to see a list of nicks starting
13# with "ab".
14# If you now press <tab> again, irssi will default to its own nick
15# completion method.
16# If you enter more characters you can use <tab> again to see a list
17# of the matching nicks, or to complete the nick if there is only
18# one matching.
19#
20# The last completion is saved so if you press "<tab>" with an empty
21# input line, you get the last completed nick.
22#
23# Now there is a statusbar item where you can see the completing
24# nicks instead of in the channel window. There are two ways to
25# use it:
26#
27#	1) Inside another statusbar
28#
29#		/set niq_show_in_statusbar ON
30#		/statusbar window add -before more niq
31#
32#	2) In an own statusbar
33#
34#		/statusbar niq enable
35#		/statusbar niq add niq
36#		/statusbar niq disable
37#		/set niq_show_in_statusbar ON
38#		/set niq_own_statusbar ON
39#
40#	  You can also hide the bar when not completing nicks by using
41#
42#		/set niq_hide_on_inactive ON
43#
44#########
45# OPTIONS
46#########
47#
48# /set niq_show_in_statusbar <ON|OFF>
49#		* ON  : show the completing nicks in a statusbar item
50#		* OFF : show the nicks in the channel window
51#
52# /set niq_own_statusbar <ON|OFF>
53#		* ON  : use an own statusbar for the nicks
54#		* OFF : just use an item
55#
56# /set niq_hide_on_inactive <ON|OFF>
57#		* ON  : hide the own statusbar on inactivity
58#		* OFF : dont hide it
59#
60# /set niq_color_char <ON|OFF>
61#		* ON  : colors the next unlikely character
62#		* OFF : boring no colors
63#
64###
65################
66###
67# Changelog
68#
69# Version 0.5.7
70# - use configured completion_char instead of a colon
71# - removed old, unused code
72# - fixed url
73# - fixed documentation leading to emtpy statusbar
74# - removed warning about a problem with irssi version 0.8.4
75#
76# Version 0.5.6
77# - work around an use problem
78#
79# Version 0.5.5
80# - fixed completion for nicks starting with special chars
81#
82# Version 0.5.4
83# - removed unneeded sort() of colored nicks
84# - moved colored nick generation to where it is needed
85# - the statusbar only worked with colorized nicks (duh!)
86#
87# Version 0.5.3
88#	- stop nickcompleting if last char is the completion_char
89#	  which is in most cases ':'
90#
91# Version 0.5.2
92#	- fixed vanishing statusbar. it wrongly was reset on any
93#	  privmsg.
94#
95# Version 0.5.1
96#	- changed statusbar to be off by default since most people
97#	  dont use the latest fixed version.
98#
99# Version 0.5
100#	- added own statusbar option
101#  - added color char option
102#
103# Version 0.4
104#	- added an niq statusbar
105#
106# Version 0.3
107#  - added default to irssi method on <tab><tab>
108#
109# Version 0.2
110#  - added lastcomp support
111#
112# Version 0.1
113#  - initial release
114###
115################
116
117use Irssi;
118use Irssi::TextUI;
119use strict;
120
121use vars qw($VERSION %IRSSI);
122
123$VERSION="0.5.7";
124%IRSSI = (
125	authors=> 'BC-bd',
126	contact=> 'bd@bc-bd.org',
127	name=> 'niq',
128	description=> 'BitchX like Nickcompletion at line start plus statusbar',
129	sbitems=> 'niq',
130	license=> 'GPL v2',
131	url=> 'https://bc-bd.org/cgi-bin/gitweb.cgi?p=irssi.git;a=summary',
132);
133
134my($lastword,$lastcomp,$niqString);
135
136$lastcomp = "";
137$lastword = "";
138
139# build our nick with completion_char, add to complist and stop the signal
140sub buildNickAndStop {
141	my ($complist,$nick) = @_;
142	my $push = $nick.Irssi::settings_get_str('completion_char');
143
144	$lastcomp = $nick;
145	$lastword = "";
146	push (@{$complist}, $push);
147
148	if (Irssi::settings_get_bool('niq_show_in_statusbar') == 1) {
149		drawStatusbar("");
150	}
151
152	Irssi::signal_stop();
153}
154
155# the signal handler
156sub sig_complete {
157	my ($complist, $window, $word, $linestart, $want_space) = @_;
158
159	# still allow channel- #<tab>, /set n<tab>, etc completion.
160	if ($linestart ne "") {
161		return;
162	}
163
164	# also back out if nothing has been entered and lastcomp is ""
165	if ($word eq "") {
166		if ($lastcomp ne "") {
167			buildNickAndStop($complist,$lastcomp);
168			return;
169		} else {
170			return;
171		}
172	}
173	if (rindex($word,Irssi::settings_get_str('completion_char')) == length($word) -1) {
174		chop($word);
175		buildNickAndStop($complist,$word,0);
176		return;
177	}
178
179	my $channel = $window->{active};
180
181	# the completion is ok if this is a channel
182	if ($channel->{type} ne "CHANNEL")
183	{
184		return;
185	}
186
187	my (@nicks);
188
189	# get the matching nicks but quote this l33t special chars like ^
190	my $shortestNick = 999;
191	my $quoted = quotemeta $word;
192	foreach my $n ($channel->nicks()) {
193		if ($n->{nick} =~ /^$quoted/i && $window->{active_server}->{nick} ne $n->{nick}) {
194			push(@nicks,$n->{nick});
195			if (length($n->{nick}) < $shortestNick) {
196				$shortestNick = length($n->{nick});
197			}
198		}
199	}
200
201	@nicks = sort(@nicks);
202
203	# if theres only one nick return it.
204	if (scalar @nicks eq 1)
205	{
206		buildNickAndStop($complist,$nicks[0]);
207	} elsif (scalar @nicks gt 1) {
208		# check if this is <tab> or <tab><tab>
209		if ($lastword eq $word) {
210			# <tab><tab> so default to the irssi method
211			sort(@nicks);
212			for (@nicks) {
213				$_ .= Irssi::settings_get_str ('completion_char');
214			}
215
216			push (@{$complist}, @nicks);
217
218			# but delete lastword to be ready for the next <tab>
219			$lastword = "";
220
221			if (Irssi::settings_get_bool('niq_show_in_statusbar') == 1) {
222				drawStatusbar("");
223			}
224
225			return;
226		} else {
227			# <tab> only so just print
228
229			# build string w/o colored nicks
230			if (Irssi::settings_get_bool('niq_color_char') == 1) {
231				$niqString = "";
232				foreach my $n (@nicks) {
233					my $coloredNick = $n;
234					$coloredNick =~ s/($quoted)(.)(.*)/$1%_$2%_$3/i;
235					$niqString .= "$coloredNick ";
236				}
237			} else {
238				$niqString = join(" ",@nicks);
239			}
240
241			if (Irssi::settings_get_bool('niq_show_in_statusbar') == 1) {
242				drawStatusbar($niqString);
243			} else {
244				$window->print($niqString);
245			}
246
247			Irssi::signal_stop();
248
249			# remember last word
250			$lastword = $word;
251
252			return;
253		}
254	}
255}
256
257sub emptyBar() {
258	$lastword = "";
259
260	drawStatusbar("");
261}
262
263sub drawStatusbar() {
264	my ($word) = @_;
265
266	if (Irssi::settings_get_bool('niq_own_statusbar') == 1) {
267		if (Irssi::settings_get_bool('niq_hide_on_inactive') == 1) {
268			if ($word eq "") {
269				Irssi::command("statusbar niq disable");
270			} else {
271				Irssi::command("statusbar niq enable");
272			}
273		}
274	}
275
276	$niqString = "{sb $word}";
277	Irssi::statusbar_items_redraw('niq');
278}
279
280sub niqStatusbar() {
281	my ($item, $get_size_only) = @_;
282
283	$item->default_handler($get_size_only, $niqString, undef, 1);
284}
285
286Irssi::signal_add_first('complete word', 'sig_complete');
287Irssi::signal_add_last('window changed', 'emptyBar');
288Irssi::signal_add('message own_public', 'emptyBar');
289
290Irssi::statusbar_item_register('niq', '$0', 'niqStatusbar');
291Irssi::statusbars_recreate_items();
292
293Irssi::settings_add_bool('misc', 'niq_show_in_statusbar', 0);
294Irssi::settings_add_bool('misc', 'niq_own_statusbar', 0);
295Irssi::settings_add_bool('misc', 'niq_hide_on_inactive', 1);
296Irssi::settings_add_bool('misc', 'niq_color_char', 1);
297