-#!/usr/bin/perl -w
-
-# ** This script is a 10-minutes-hack, so it's EXPERIMENTAL. **
-#
-# Requires:
-# - Irssi 0.8.12 or newer (http://irssi.org/).
-# - GNU Aspell with appropriate dictionaries (http://aspell.net/).
-# - Perl module Text::Aspell (available from CPAN).
-#
-#
-# Description:
-# Works as you type, printing suggestions when Aspell thinks
-# your last word was misspelled.
-# It also adds suggestions to the list of tabcompletions,
-# so once you know last word is wrong, you can go back
-# and tabcomplete through what Aspell suggests.
-#
-#
-# Settings:
-#
-# spellcheck_languages -- a list of space and/or comma
-# separated languages to use on certain networks/channels.
-# Example:
-# /set spellcheck_languages netA/#chan1/en_US, #chan2/fi_FI, netB/!chan3/pl_PL
-# will use en_US for #chan1 on network netA, fi_FI for #chan2
-# on every network, and pl_PL for !chan3 on network netB.
-# By default this setting is empty.
-#
-# spellcheck_default_language -- language to use in empty
-# windows, or when nothing from spellcheck_languages matches.
-# Defaults to 'en_US'.
-#
-# spellcheck_enabled [ON/OFF] -- self explaining. Sometimes
-# (like when pasting foreign-language text) you don't want
-# the script to spit out lots of suggestions, and turning it
-# off for a while is the easiest way. By default it's ON.
-#
-#
-# BUGS:
-# - won't catch all mistakes
-# - picking actual words from what you type is very kludgy,
-# you may occasionally see some leftovers like digits or punctuation
-# - works every time you press space or a dot (so won't work for
-# the last word before pressing enter, unless you're using dot
-# to finish your sentences)
-# - when you press space and realize that the word is wrong,
-# you can't tabcomplete to the suggestions right away - you need
-# to use backspace and then tabcomplete. With dot you get an extra
-# space after tabcompletion.
-# - all words will be marked and no suggestions given if
-# dictionary is missing (ie. wrong spellcheck_default_language)
-# - probably more, please report to $IRSSI{'contact'}
+# Copyright © 2008 Jakub Jankowski <shasta@toxcorp.com>
+# Copyright © 2012 Jakub Wilk <jwilk@jwilk.net>
#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 dated June, 1991.
#
-# $Id: spellcheck.pl 5 2008-05-28 22:31:06Z shasta $
-#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
use strict;
+use warnings;
+
use vars qw($VERSION %IRSSI);
use Irssi 20070804;
use Text::Aspell;
-$VERSION = '0.4';
+$VERSION = '0.5';
%IRSSI = (
- authors => 'Jakub Jankowski',
- contact => 'shasta@toxcorp.com',
+ authors => 'Jakub Wilk, Jakub Jankowski',
+ contact => 'jwilk@jwilk.net, shasta@toxcorp.com',
name => 'Spellcheck',
description => 'Checks for spelling errors using Aspell.',
license => 'GPLv2',
- url => 'http://toxcorp.com/irc/irssi/spellcheck/',
+ url => 'https://bitbucket.org/jwilk/irssi-spellcheck',
);
my %speller;
}
# add_rest means "add (whatever you chopped from the word before
-# spellchecking it) to the suggestions returned"
+# spell-checking it) to the suggestions returned"
sub spellcheck_check_word
{
my ($lang, $word, $add_rest) = @_;
my $win = Irssi::active_win();
- my @suggestions = ();
+ my $prefix = '';
+ my $suffix = '';
# setup Text::Aspell for that lang if needed
if (!exists $speller{$lang} || !defined $speller{$lang})
{
- if (!spellcheck_setup($lang))
- {
- $win->print("Error while setting up spellchecker for $lang");
- # don't change the message
- return @suggestions;
- }
+ if (!spellcheck_setup($lang))
+ {
+ $win->print("Error while setting up spell-checker for $lang");
+ # don't change the message
+ return;
+ }
}
- # do the spellchecking
- my ($stripped, $rest) = $word =~ /([^[:punct:][:digit:]]{2,})(.*)/; # HAX
- # Irssi::print("Debug: stripped $word is '$stripped', rest is '$rest'");
- if (defined $stripped && !$speller{$lang}->check($stripped))
+ return if $word =~ m{^/}; # looks like a path
+ $word =~ s/^([[:punct:]]*)//; # strip leading punctuation characters
+ $prefix = $1 if $add_rest;
+ $word =~ s/([[:punct:]]*)$//; # ...and trailing ones, too
+ $suffix = $1 if $add_rest;
+ return if $word =~ m{^\w+://}; # looks like an URL
+ return if $word =~ m{^[^@]+@[^@]+$}; # looks like an e-mail
+ return if $word =~ m{^[[:digit:][:punct:]]+$}; # looks like a number
+
+ my $ok = $speller{$lang}->check($word);
+ if (not defined $ok)
+ {
+ $win->print("Error while spell-checking for $lang");
+ return;
+ }
+ unless ($ok)
{
- push(@suggestions, $add_rest ? $_ . $rest : $_) for ($speller{$lang}->suggest($stripped));
+ my @result = map { "$prefix$_$suffix" } $speller{$lang}->suggest($word);
+ return \@result;
}
- return @suggestions;
+ return;
}
sub spellcheck_find_language
my @languages = split(/[ ,]/, Irssi::settings_get_str('spellcheck_languages'));
for my $langstr (@languages)
{
- # strip trailing slashes
- $langstr =~ s=/+$==;
- # Irssi::print("Debug: checking network $network target $target against langstr $langstr");
- my ($s1, $s2, $s3) = split(/\//, $langstr, 3);
- my ($t, $c, $l);
- if (defined $s3 && $s3 ne '')
- {
- # network/channel/lang
- $t = lc($s1); $c = lc($s2); $l = $s3;
- }
- else
- {
- # channel/lang
- $c = lc($s1); $l = $s2;
- }
-
- if ($c eq $target && (!defined $t || $t eq $network))
- {
- # Irssi::print("Debug: language found: $l");
- return $l;
- }
+ # strip trailing slashes
+ $langstr =~ s=/+$==;
+ my ($s1, $s2, $s3) = split(/\//, $langstr, 3);
+ my ($t, $c, $l);
+ if (defined $s3 && $s3 ne '')
+ {
+ # network/channel/lang
+ $t = lc($s1); $c = lc($s2); $l = $s3;
+ }
+ else
+ {
+ # channel/lang
+ $c = lc($s1); $l = $s2;
+ }
+
+ if ($c eq $target && (!defined $t || $t eq $network))
+ {
+ return $l;
+ }
}
- # Irssi::print("Debug: language not found, using default");
# no match, use defaults
return Irssi::settings_get_str('spellcheck_default_language');
}
my $inputline = Irssi::parse_special('$L');
# check if inputline starts with any of cmdchars
- # we shouldn't spellcheck commands
+ # we shouldn't spell-check commands
my $cmdchars = Irssi::settings_get_str('cmdchars');
- my $cmdre = qr/^[$cmdchars]/;
- return if ($inputline =~ $cmdre);
+ my $re = qr/^[$cmdchars]/;
+ return if ($inputline =~ $re);
# get last bit from the inputline
my ($word) = $inputline =~ /\s*([^\s]+)$/;
-
- # do not spellcheck urls
- my $urlre = qr/(^[a-zA-Z]+:\/\/\S+)|(^www)/;
- return if ($word =~ $urlre);
+ defined $word or return;
# find appropriate language for current window item
my $lang = spellcheck_find_language($win->{active_server}->{tag}, $win->{active}->{name});
- my @suggestions = spellcheck_check_word($lang, $word, 0);
- # Irssi::print("Debug: spellcheck_check_word($word) returned array of " . scalar @suggestions);
- return if (scalar @suggestions == 0);
+ my $suggestions = spellcheck_check_word($lang, $word, 0);
+
+ return unless defined $suggestions;
# we found a mistake, print suggestions
- $win->print("Suggestions for $word - " . join(", ", @suggestions));
+ $word =~ s/%/%%/g;
+ my $color = Irssi::settings_get_str('spellcheck_word_color');
+ if (scalar @$suggestions > 0)
+ {
+ $win->print("Suggestions for $color$word%N - " . join(", ", @$suggestions));
+ }
+ else
+ {
+ $win->print("No suggestions for $color$word%N");
+ }
}
my $lang = spellcheck_find_language($win->{active_server}->{tag}, $win->{active}->{name});
# add suggestions to the completion list
- push(@$complist, spellcheck_check_word($lang, $word, 1));
+ my $suggestions = spellcheck_check_word($lang, $word, 1);
+ push(@$complist, @$suggestions) if defined $suggestions;
}
Irssi::settings_add_bool('spellcheck', 'spellcheck_enabled', 1);
Irssi::settings_add_str( 'spellcheck', 'spellcheck_default_language', 'en_US');
Irssi::settings_add_str( 'spellcheck', 'spellcheck_languages', '');
+Irssi::settings_add_str( 'spellcheck', 'spellcheck_word_color', '%R');
Irssi::signal_add_first('gui key pressed', 'spellcheck_key_pressed');
Irssi::signal_add_last('complete word', 'spellcheck_complete_word');
+
+# vim:ts=4 sw=4 et