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
|
#!/usr/bin/perl
# script was written ages ago, sometime around 2008.
use warnings;
use strict;
use Irssi qw{
signal_add_last signal_add
command_bind
settings_get_int settings_add_int
settings_get_str settings_add_str
};
our $VERSION = "0.1";
our %IRSSI = (
authors => 'Urchlay',
contact => 'Urchlay on NewNet',
name => 'complete_text',
description => 'Create a dictionary from channel/msg text, ' .
'use for word completion',
license => 'Same as Perl',
url => 'none',
);
# TODO:
# - allow user to save the dictionary and reload
# - allow user to remove words from dictionary
# - better case-matching: store words in their original case or lowercase
# (user setting). If $word is initial cap, complete to full original
# case (so in #atari, A<tab> would be AtariSIO, not Atarisio)
# - add channel topic and maybe /quit msg
# - maybe expire old words based on use frequency?
# - typo support like irccomplete?
settings_add_int('complete_text', 'complete_dict_size', 5000);
settings_add_str('complete_text', 'complete_preload', "/usr/dict/words");
our $limit = settings_get_int('complete_dict_size');
our %seen;
our @dict;
our %static_seen;
our @static_dict;
sub complete_word {
my ($complist, $window, $word, $linestart, $want_space) = @_;
my $prefix = $1 if $word =~ s/^(.*\b)(\w)/$2/;
my $initial_cap = ($word =~ /^[A-Z]/);
$word = quotemeta $word; # 20080723 bkw: d'oh!
push @$complist, map { $_ = $prefix . $_ } grep { $_ =~ /^$word/i } @dict;
push @$complist, map { $_ = $prefix . $_ } grep { $_ =~ /^$word/i } @static_dict;
if($initial_cap) {
s/^(.)/uc($1)/e for @$complist;
}
}
sub add_to_dict {
for(lc($_[1]) =~ /(\w{4,})/g) {
s/^_(\w+)_$/$1/;
s/^\*(\w+)\*$/$1/;
next if $static_seen{$_};
next if $seen{$_}++;
push @dict, $_;
if(@dict >= $limit) {
my $old = shift @dict;
delete $seen{$old};
}
}
}
sub dumpdict {
print "dynamic dictionary";
print for @dict;
print scalar keys %seen;
print scalar @dict;
print "\nstatic dictionary";
# print for sort keys %static_seen;
print scalar keys %static_seen;
}
sub load_static_seen {
%static_seen = ();
@static_dict = ();
my @files = split /:/, settings_get_str('complete_preload');
for(@files) {
print "preloading words from $_";
s/^~/$ENV{HOME}/;
print "$_ not found, skipping", next unless -f $_;
open my $f, "<$_" or do { print "$_: $!"; next; };
while(<$f>) {
chomp;
next unless $_;
$static_seen{$_}++;
}
close $f;
@static_dict = sort {
(length $a <=> length $b) || ($a cmp $b)
} keys %static_seen;
}
print "preloaded " . (scalar keys %static_seen) . " words";
}
sub setup_changed {
my $new_limit = settings_get_int('complete_dict_size');
if($new_limit < @dict) {
#print "deleting " . (@dict - $new_limit) . " elements";
for(my $i=0; $i < (@dict - $new_limit); $i++) {
my $old = shift @dict;
delete $seen{$old};
}
}
$limit = $new_limit;
load_static_seen();
}
sub typo {
my $text = shift;
for(split(/\s+/, $text)) {
delete $seen{$_};
}
@dict = keys %seen;
}
load_static_seen();
signal_add_last('setup changed', \&setup_changed);
signal_add_last('complete word', \&complete_word);
command_bind('dumpdict', \&dumpdict);
command_bind('typo', \&typo);
for(
"message public", "message private",
"message own_public", "message own_private",
"message dcc", "message dcc own",
"message dcc own_action", "message dcc action")
{
signal_add_last($_, \&add_to_dict);
}
|