PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/spellcheck.pl

https://bitbucket.org/tshirtman/irssi-spellcheck
Perl | 225 lines | 148 code | 39 blank | 38 comment | 33 complexity | 289c0887a50eaa6a3a0c0d29597224d5 MD5 | raw file
Possible License(s): GPL-2.0
  1. # Copyright © 2008 Jakub Jankowski <shasta@toxcorp.com>
  2. # Copyright © 2012 Jakub Wilk <jwilk@jwilk.net>
  3. # Copyright © 2012 Gabriel Pettier <gabriel.pettier@gmail.com>
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; version 2 dated June, 1991.
  8. #
  9. # This program is distributed in the hope that it will be useful, but
  10. # WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # General Public License for more details.
  13. use strict;
  14. use warnings;
  15. use vars qw($VERSION %IRSSI);
  16. use Irssi 20070804;
  17. use Text::Aspell;
  18. $VERSION = '0.6';
  19. %IRSSI = (
  20. authors => 'Jakub Wilk, Jakub Jankowski, Gabriel Pettier',
  21. contact => 'jwilk@jwilk.net, shasta@toxcorp.com',
  22. name => 'Spellcheck',
  23. description => 'Checks for spelling errors using Aspell.',
  24. license => 'GPLv2',
  25. url => 'https://bitbucket.org/jwilk/irssi-spellcheck',
  26. );
  27. my %speller;
  28. sub spellcheck_setup
  29. {
  30. return if (exists $speller{$_[0]} && defined $speller{$_[0]});
  31. $speller{$_[0]} = Text::Aspell->new or return undef;
  32. $speller{$_[0]}->set_option('lang', $_[0]) or return undef;
  33. $speller{$_[0]}->set_option('sug-mode', 'fast') or return undef;
  34. return 1;
  35. }
  36. # add_rest means "add (whatever you chopped from the word before
  37. # spell-checking it) to the suggestions returned"
  38. sub spellcheck_check_word
  39. {
  40. my ($lang, $word, $add_rest) = @_;
  41. my $win = Irssi::active_win();
  42. my $prefix = '';
  43. my $suffix = '';
  44. # setup Text::Aspell for that lang if needed
  45. if (!exists $speller{$lang} || !defined $speller{$lang})
  46. {
  47. if (!spellcheck_setup($lang))
  48. {
  49. $win->print("Error while setting up spell-checker for $lang");
  50. # don't change the message
  51. return;
  52. }
  53. }
  54. return if $word =~ m{^/}; # looks like a path
  55. $word =~ s/^([[:punct:]]*)//; # strip leading punctuation characters
  56. $prefix = $1 if $add_rest;
  57. $word =~ s/([[:punct:]]*)$//; # ...and trailing ones, too
  58. $suffix = $1 if $add_rest;
  59. return if $word =~ m{^\w+://}; # looks like an URL
  60. return if $word =~ m{^[^@]+@[^@]+$}; # looks like an e-mail
  61. return if $word =~ m{^[[:digit:][:punct:]]+$}; # looks like a number
  62. my $ok = $speller{$lang}->check($word);
  63. if (not defined $ok)
  64. {
  65. $win->print("Error while spell-checking for $lang");
  66. return;
  67. }
  68. unless ($ok)
  69. {
  70. my @result = map { "$prefix$_$suffix" } $speller{$lang}->suggest($word);
  71. return \@result;
  72. }
  73. return;
  74. }
  75. sub spellcheck_find_language
  76. {
  77. my ($network, $target) = @_;
  78. return Irssi::settings_get_str('spellcheck_default_language') unless (defined $network && defined $target);
  79. # support !channels correctly
  80. $target = '!' . substr($target, 6) if ($target =~ /^\!/);
  81. # lowercase net/chan
  82. $network = lc($network);
  83. $target = lc($target);
  84. # possible settings: network/channel/lang or channel/lang
  85. my @languages = split(/[ ,]/, Irssi::settings_get_str('spellcheck_languages'));
  86. for my $langstr (@languages)
  87. {
  88. # strip trailing slashes
  89. $langstr =~ s=/+$==;
  90. my ($s1, $s2, $s3) = split(/\//, $langstr, 3);
  91. my ($t, $c, $l);
  92. if (defined $s3 && $s3 ne '')
  93. {
  94. # network/channel/lang
  95. $t = lc($s1); $c = lc($s2); $l = $s3;
  96. }
  97. else
  98. {
  99. # channel/lang
  100. $c = lc($s1); $l = $s2;
  101. }
  102. if ($c eq $target && (!defined $t || $t eq $network))
  103. {
  104. return $l;
  105. }
  106. }
  107. # no match, use defaults
  108. return Irssi::settings_get_str('spellcheck_default_language');
  109. }
  110. sub spellcheck_key_pressed
  111. {
  112. my ($key) = @_;
  113. my $win = Irssi::active_win();
  114. my $correction_window;
  115. my $window_height;
  116. my $window_name = Irssi::settings_get_str('spellcheck_window_name');
  117. if ($window_name ne '')
  118. {
  119. $correction_window = Irssi::window_find_name($window_name);
  120. $window_height = Irssi::settings_get_str('spellcheck_window_height');
  121. }
  122. # I know no way to *mark* misspelled words in the input line,
  123. # that's why there's no spellcheck_print_suggestions -
  124. # because printing suggestions is our only choice.
  125. return unless Irssi::settings_get_bool('spellcheck_enabled');
  126. # hide correction window when message is sent
  127. if ($key eq 10 && $correction_window)
  128. { $correction_window->command('window hide corrections'); }
  129. # don't bother unless pressed key is space or dot
  130. return unless (chr $key eq ' ' or chr $key eq '.');
  131. # get current inputline
  132. my $inputline = Irssi::parse_special('$L');
  133. # check if inputline starts with any of cmdchars
  134. # we shouldn't spell-check commands
  135. my $cmdchars = Irssi::settings_get_str('cmdchars');
  136. my $re = qr/^[$cmdchars]/;
  137. return if ($inputline =~ $re);
  138. # get last bit from the inputline
  139. my ($word) = $inputline =~ /\s*([^\s]+)$/;
  140. defined $word or return;
  141. # find appropriate language for current window item
  142. my $lang = spellcheck_find_language($win->{active_server}->{tag}, $win->{active}->{name});
  143. my $suggestions = spellcheck_check_word($lang, $word, 0);
  144. return unless defined $suggestions;
  145. # show corrections window if hidden
  146. if ($correction_window)
  147. {
  148. $win->command("window show $window_name");
  149. $correction_window->command('window stick off');
  150. $correction_window->command("window size $window_height");
  151. }
  152. else
  153. {
  154. $correction_window = $win;
  155. }
  156. # we found a mistake, print suggestions
  157. $word =~ s/%/%%/g;
  158. my $color = Irssi::settings_get_str('spellcheck_word_color');
  159. if (scalar @$suggestions > 0)
  160. {
  161. $correction_window->print("Suggestions for $color$word%N - " . join(", ", @$suggestions));
  162. }
  163. else
  164. {
  165. $correction_window->print("No suggestions for $color$word%N");
  166. }
  167. }
  168. sub spellcheck_complete_word
  169. {
  170. my ($complist, $win, $word, $lstart, $wantspace) = @_;
  171. return unless Irssi::settings_get_bool('spellcheck_enabled');
  172. # find appropriate language for the current window item
  173. my $lang = spellcheck_find_language($win->{active_server}->{tag}, $win->{active}->{name});
  174. # add suggestions to the completion list
  175. my $suggestions = spellcheck_check_word($lang, $word, 1);
  176. push(@$complist, @$suggestions) if defined $suggestions;
  177. }
  178. Irssi::settings_add_bool('spellcheck', 'spellcheck_enabled', 1);
  179. Irssi::settings_add_str( 'spellcheck', 'spellcheck_default_language', 'en_US');
  180. Irssi::settings_add_str( 'spellcheck', 'spellcheck_languages', '');
  181. Irssi::settings_add_str( 'spellcheck', 'spellcheck_word_color', '%R');
  182. Irssi::settings_add_str( 'spellcheck', 'spellcheck_window_name', '');
  183. Irssi::settings_add_str( 'spellcheck', 'spellcheck_window_height', 10);
  184. Irssi::signal_add_first('gui key pressed', 'spellcheck_key_pressed');
  185. Irssi::signal_add_last('complete word', 'spellcheck_complete_word');
  186. # vim:ts=4 sw=4 et