html/spell.pl
1 #!/usr/bin/perl -w
2 #
3 # Michael Kowalchuk <michael_kowalchuk@umanitoba.ca> presents:
4 #
5 # A spell checker for irssi
6 # Requires Lingua::Ispell and ispell
7 #
8 # Usage:
9 # Load the script
10 # Type /bind meta-s /_spellcheck
11 # Hit meta+s (alt+s) to check your spelling
12 #
13 # This script also implements /spell <line> which shows more spelling suggestions than
14 # the hotkey (99).
15 #
16 # Options:
17 # spell_max_guesses (def: 1)
18 # spell_error_effect (def: %U = underline, others are %8 = reverse, %9 = bold)
19 # see http://irssi.org/documentation/formats
20 #
21 #
22 # History
23 # First version: inline spellchecking, terrible, unreleased [Tue Aug 2 00:32:27 CDT 2005]
24 # New version: Spellcheck on request [Mon Jan 2 17:02:12 CST 2006]
25 #
26 # Todo
27 # Is there a way for a script to clear its mess like '/lastlog -clear' does?
28 #
29
30 use strict;
31 use Irssi;
32 use List::Util qw( min );
33 use Irssi::TextUI;
34 use Lingua::Ispell;
35
36 use vars qw($VERSION %IRSSI);
37 $VERSION = '1.0';
38 %IRSSI = (
39 authors => 'Michael Kowalchuk',
40 contact => 'michael_kowalchuk@umanitoba.ca',
41 name => 'spell',
42 description => 'A spell checker for irssi. Hit alt+s and your line will echoed to the active window with mistakes underlined and suggestions noted. /spell is also provided. Requires Lingua::Ispell and Ispell.',
43 license => 'MIT',
44 url => 'http://home.cc.umanitoba.ca/~umkowa17/',
45 changed => 'Mon Jan 2 17:02:12 CST 2006'
46 );
47
48 sub check_line {
49 my ($inputline, $guesses) = @_;
50
51 my $error_start = Irssi::settings_get_str($IRSSI{'name'}.'_error_effect');
52 my $error_end = "%n"; # previous colour
53
54 # ISpell has a limit of 99 characters in a word
55 if ( $inputline =~ /\w{99}/ ) {
56 return "unable to spellcheck";
57 }
58
59 # Reads in a list of hashes for each error with the keys term, type, and offset
60 my @errs = Lingua::Ispell::spellcheck( $inputline );
61
62 if( @errs > 0 ) {
63 # Reconstruct the line with suggestions built in
64 my $outputline;
65 my $last_end = 0;
66 foreach(@errs) {
67 my $off=$_->{'offset'}-1; # ispell counts from 1
68 my $before = substr($inputline, $last_end, $off - $last_end);
69
70 $last_end = $off + length($_->{'term'});
71
72 # Give speling [spelling, spelunking?] suggestions
73 my $extra_info = "";
74 if( $guesses > 0 ) {
75 if( $_->{'type'} eq 'miss' ) {
76 # Show near-misses, there will be 1..n of them
77 my @misses = @{$_->{'misses'}};
78
79 my $miss_len = @misses;
80 my $shown_guesses = min( $miss_len, $guesses);
81
82 my @shown = @misses[0..$shown_guesses - 1];
83
84 $extra_info = " (" . join(", ", @shown ) . "?)";
85 }
86 elsif( $_->{'type'} eq 'root' ) {
87 # Show root suggestions, there will be exactly 1
88 $extra_info = " (" . $_->{'root'} . "?)";
89 }
90 }
91
92 $outputline .= $before . $error_start . $_->{'term'} . $error_end . $extra_info;
93 }
94 $outputline .= substr($inputline, $last_end);
95
96 return $outputline;
97 }
98 else {
99 return "no errors";
100 }
101 }
102
103 # Read from the input line
104 sub cmd_spellcheck {
105 my $inputline = Irssi::parse_special("\$L");
106 my $guesses = Irssi::settings_get_int($IRSSI{'name'}.'_max_guesses');
107
108 Irssi::active_win()->print("spell: " . check_line($inputline, $guesses), MSGLEVEL_CRAP );
109 }
110
111 # Read from the argument list
112 sub cmd_spell {
113 my ($inputline) = @_;
114 my $guesses = 99;
115
116 Irssi::active_win()->print("spell: " . check_line($inputline, $guesses), MSGLEVEL_CRAP );
117 }
118
119
120 Irssi::settings_add_str('misc', $IRSSI{'name'} . '_error_effect', "%U");
121 Irssi::settings_add_int('misc', $IRSSI{'name'} . '_max_guesses', 1);
122
123 Irssi::command_bind('_spellcheck', 'cmd_spellcheck');
124 Irssi::command_bind('spell', 'cmd_spell');
125