summaryrefslogtreecommitdiffstats
path: root/scripts/irccomplete.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/irccomplete.pl')
-rw-r--r--scripts/irccomplete.pl213
1 files changed, 213 insertions, 0 deletions
diff --git a/scripts/irccomplete.pl b/scripts/irccomplete.pl
new file mode 100644
index 0000000..d2ac527
--- /dev/null
+++ b/scripts/irccomplete.pl
@@ -0,0 +1,213 @@
+# TAB complete words from dictionary
+# for irssi 0.7.99 by Timo Sirainen
+# Greatly modified by Erkki Seppälä to build dictionary of said words
+
+use strict;
+use Irssi;
+
+use vars qw($VERSION %IRSSI);
+$VERSION = "0.1";
+%IRSSI = (
+ authors => "Erkki Seppälä",
+ contact => "flux\@inside.org",
+ name => "IRC Completion",
+ description => "Adds words from IRC to your tab-completion list, plus fixes typos",
+ license => "Public Domain",
+ url => "http://xulfad.inside.org/~flux/software/irssi/",
+ changed => "Thu Feb 7 22:45:55 EET 2002"
+);
+
+
+my @wordHistory;
+my %words;
+my %permanent;
+
+my $wordChars = join("", ('a'..'z', '0'..'9', 'öä'));
+my $maxWords = 5000;
+my $minWordLength = 4;
+my $maxWordLength = 80;
+my $maxTypoLength = 10;
+my $permanentThreshold = 1;
+
+my %typoWords;
+my $correctWordCounter = 1;
+my %correctWordsByIndex;
+my %correctWordsByWord;
+
+# by word
+sub addCorrectWord {
+ my $index = $correctWordsByWord{$_[0]} or 0;
+ if ($index > 0) {
+ ++$correctWordsByIndex{$index}->[1];
+ return $index;
+ } else {
+ $correctWordsByIndex{$correctWordCounter} = [$_[0], 1];
+ $correctWordsByWord{$_[0]} = $correctWordCounter;
+ ++$correctWordCounter;
+ return $correctWordCounter - 1;
+ }
+};
+
+# by word
+sub delCorrectWord {
+ my ($word) = @_;
+ my $index = $correctWordsByWord{$word};
+ if (--$correctWordsByIndex{$index}->[1] == 0) {
+ delete $correctWordsByWord{$correctWordsByIndex{$index}->[0]};
+ delete $correctWordsByIndex{$index};
+ }
+}
+
+sub sig_complete {
+ my ($complist, $window, $word, $linestart, $want_space) = @_;
+
+ $word =~ s/([^a-zA-Z0-9])/\\\1/g;
+
+ @$complist = reverse (@$complist, grep(/^$word/, (keys %permanent, keys %words)));
+
+ if (exists $typoWords{$word}) {
+ my $correctWord = $correctWordsByIndex{$typoWords{$word}->[0]}->[0];
+ @$complist = (@$complist, $correctWord);
+ }
+
+ my $n;
+ my %m = map { ($_ => $n++); } @$complist;
+ @$complist = ();
+ my %m2;
+ foreach my $key (sort keys %m) {
+ $m2{$m{$key}}=$key;
+ }
+ foreach my $key (reverse sort keys %m2) {
+ push @$complist, $m2{$key};
+ }
+}
+
+# $word, $removes
+sub generate_drops {
+ my ($word, $changes) = @_;
+ my @list;
+ for (my $c = 0; $c < length($word) - 1; ++$c) {
+ my $misWord = substr($word, 0, $c) . substr($word, $c + 1);
+ if ($changes > 1) {
+ push @list, generate_drops($misWord, $changes - 1);
+ } else {
+ push @list, $misWord;
+ }
+ }
+ return @list;
+}
+
+sub generate_translations {
+ my ($word, $changes) = @_;
+ my @list;
+ for (my $c = 1; $c < length($word); ++$c) {
+ my $misWord = substr($word, 0, $c - 1) . substr($word, $c, 1) . substr($word, $c - 1, 1) . substr($word, $c + 1);
+ if ($changes > 1) {
+ push @list, generate_drops($misWord, $changes - 1);
+ } else {
+ push @list, $misWord;
+ }
+ }
+ return @list;
+}
+
+# $word
+sub generate_typos {
+ my $maxTypoLength = Irssi::settings_get_int('irccomplete_maximum_typo_length');
+ my ($word) = @_;
+
+ if (length($word) > $maxTypoLength) {
+ return ();
+ } else {
+ return (generate_drops($word, 1), generate_translations($word));
+ }
+}
+
+sub sig_message {
+ my ($server, $message) = @_;
+ my $maxWords = Irssi::settings_get_int('irccomplete_words');
+ my $minWordLength = Irssi::settings_get_int('irccomplete_minimum_length');
+ my $maxWordLength = Irssi::settings_get_int('irccomplete_maximum_length');
+ my $wordChars = Irssi::settings_get_str("irccomplete_word_characters");
+ my $permanentThreshold = Irssi::settings_get_int('irccomplete_permanent_percent');
+ foreach my $word (split(/[^$wordChars]/, $message)) {
+ if (length($word) >= $minWordLength && length($word) <= $maxWordLength) {
+ if (++$words{$word} > $permanentThreshold / 100.0 * $maxWords) {
+ if (++$permanent{$word} == 1) {
+ #Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'irccomplete_permanent', $word);
+ Irssi::print "Added $word to the list of permanent words";
+ }
+ }
+ push @wordHistory, $word;
+ my $wordIndex = addCorrectWord($word);
+ foreach my $misword (generate_typos($word, 1)) {
+ if (!exists $typoWords{$misword}) {
+ $typoWords{$misword} = [$wordIndex, 1];
+ } else {
+ ++$typoWords{$misword}->[1];
+ }
+ }
+ while (@wordHistory > $maxWords) {
+ my $word = shift @wordHistory;
+ if (--$words{$word} == 0) {
+ delete $words{$word};
+ }
+ foreach my $misword (generate_typos($word, 1)) {
+ if (--$typoWords{$misword}->[1] == 0) {
+ delete $typoWords{$misword};
+ }
+ }
+ delCorrectWord($word);
+ }
+ }
+ }
+
+
+ return 1;
+}
+
+sub cmd_typowords {
+ Irssi::print (scalar(@wordHistory) . " words, " .
+ scalar(keys %typoWords) . " typowords, " .
+ scalar(keys %correctWordsByWord) . "x" . scalar(keys %correctWordsByIndex) . " correct words");
+ my $line = "";
+
+ foreach my $word (keys %typoWords) {
+ $line .= $word . "|" . $typoWords{$word}->[0] . " ";
+ }
+ Irssi::print "$line";
+ $line = "";
+
+ foreach my $index (keys %correctWordsByIndex) {
+ $line .= $index . ":[" . join("|", @{$correctWordsByIndex{$index}}) . "] ";
+ }
+ Irssi::print "$line";
+ $line = "";
+
+ foreach my $word (keys %correctWordsByWord) {
+ $line .= $word . ":" . $correctWordsByWord{$word} . " ";
+ }
+ Irssi::print "$line";
+ $line = "";
+
+ return 1;
+};
+
+Irssi::theme_register(['irccomplete_permanent', 'Added $1 to the list of permanent words']);
+
+Irssi::settings_add_str("misc", "irccomplete_word_characters", $wordChars);
+Irssi::settings_add_int("misc", "irccomplete_words", $maxWords);
+Irssi::settings_add_int("misc", "irccomplete_minimum_length", $minWordLength);
+Irssi::settings_add_int("misc", "irccomplete_maximum_length", $maxWordLength);
+Irssi::settings_add_int("misc", "irccomplete_maximum_typo_length", $maxTypoLength);
+Irssi::settings_add_int("misc", "irccomplete_permanent_percent", $permanentThreshold);
+
+foreach my $sig ("message public", "message private",
+ "message own_public", "message own_private",
+ "message topic") {
+#foreach my $sig ("message own_public", "message own_private") {
+ Irssi::signal_add($sig, "sig_message");
+}
+Irssi::signal_add_last('complete word', 'sig_complete');
+
+Irssi::command_bind("irccomplete_typowords", "cmd_typowords");