Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
218 lines (185 sloc) 7 KB
#!/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'}
#
#
# $Id: spellcheck.pl 5 2008-05-28 22:31:06Z shasta $
#
use strict;
use vars qw($VERSION %IRSSI);
use Irssi 20070804;
use Text::Aspell;
$VERSION = '0.4';
%IRSSI = (
authors => 'Jakub Jankowski',
contact => 'shasta@toxcorp.com',
name => 'Spellcheck',
description => 'Checks for spelling errors using Aspell.',
license => 'GPLv2',
url => 'http://toxcorp.com/irc/irssi/spellcheck/',
);
my %speller;
sub spellcheck_setup
{
return if (exists $speller{$_[0]} && defined $speller{$_[0]});
$speller{$_[0]} = Text::Aspell->new or return undef;
$speller{$_[0]}->set_option('lang', $_[0]) or return undef;
$speller{$_[0]}->set_option('sug-mode', 'fast') or return undef;
return 1;
}
# add_rest means "add (whatever you chopped from the word before
# spellchecking it) to the suggestions returned"
sub spellcheck_check_word
{
my ($lang, $word, $add_rest) = @_;
my $win = Irssi::active_win();
my @suggestions = ();
# 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;
}
}
# 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))
{
push(@suggestions, $add_rest ? $_ . $rest : $_) for ($speller{$lang}->suggest($stripped));
}
return @suggestions;
}
sub spellcheck_find_language
{
my ($network, $target) = @_;
return Irssi::settings_get_str('spellcheck_default_language') unless (defined $network && defined $target);
# support !channels correctly
$target = '!' . substr($target, 6) if ($target =~ /^\!/);
# lowercase net/chan
$network = lc($network);
$target = lc($target);
# possible settings: network/channel/lang or channel/lang
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;
}
}
# Irssi::print("Debug: language not found, using default");
# no match, use defaults
return Irssi::settings_get_str('spellcheck_default_language');
}
sub spellcheck_key_pressed
{
my ($key) = @_;
my $win = Irssi::active_win();
# I know no way to *mark* misspelled words in the input line,
# that's why there's no spellcheck_print_suggestions -
# because printing suggestions is our only choice.
return unless Irssi::settings_get_bool('spellcheck_enabled');
# don't bother unless pressed key is space or dot
return unless (chr $key eq ' ' or chr $key eq '.');
# get current inputline
my $inputline = Irssi::parse_special('$L');
# check if inputline starts with any of cmdchars
# we shouldn't spellcheck commands
my $cmdchars = Irssi::settings_get_str('cmdchars');
my $cmdre = qr/^[$cmdchars]/;
return if ($inputline =~ $cmdre);
# 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);
# 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);
# we found a mistake, print suggestions
$win->print("Suggestions for $word - " . join(", ", @suggestions));
}
sub spellcheck_complete_word
{
my ($complist, $win, $word, $lstart, $wantspace) = @_;
return unless Irssi::settings_get_bool('spellcheck_enabled');
# find appropriate language for the current window item
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));
}
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::signal_add_first('gui key pressed', 'spellcheck_key_pressed');
Irssi::signal_add_last('complete word', 'spellcheck_complete_word');