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