=head1 NAME chump - like "chomp" but also checks your spelling =head1 SYNOPSIS use 5.010; use chump lang => 'en'; while (<>) { chump; say $_; last unless $_; } #### =head1 DESCRIPTION The chump package exports a function C which acts just like the Perl built-in C (i.e. removes a trailing new line character) but also corrects any spelling mistakes in the string. =head2 Functions =over =item * C<< chump($string) >> Modifies C<$string> in-place, removing a trailing new line character if there is one, and correcting any spelling mistakes. =back =head2 Import Options Any options passed on the "use" line are passed on to Text::Aspell. Options are lexically scoped, and scopes are not cumulative. { use chump lang => 'fr', mode => 'email'; my $line = <>; chump $line; # check spelling in French. { use chump lang => 'en'; my $line2 = <>; chump $line2; # check spelling in English # but not in email mode. } my $line3 = <>; chump $line3; # in French and email mode again. } =head2 Unimport Do not unimport the module. =cut package chump; use JSON qw//; use Text::Aspell; use strict 'subs', 'vars'; sub import { my $class = shift; my $caller = caller; *{"$caller\::chump"} = \&chump; if (@_) { $^H{+__PACKAGE__} = _serialize_options(@_); } } sub unimport { warn "You think you no chump?\n"; } sub _serialize_options { JSON::to_json({ @_ }); } sub _deserialize_options { return unless $_[0]; my $r = JSON::from_json($_[0]); %{ $r || {} }; } sub chump (_) { my $spell = Text::Aspell->new; my @caller = caller(0); my %opts = _deserialize_options($caller[10]{+__PACKAGE__}); foreach my $key (keys %opts) { $spell->set_option($key, $opts{$key}); } my @parts = split /([[:alpha:]]+)/, $_[0]; my $count; for my $i (0 .. $#parts) { if ($parts[$i] =~ /^[[:alpha:]]+$/) { next if $spell->check($parts[$i]); my ($guess) = $spell->suggest($parts[$i]); $guess = '?' x (length $parts[$i]) unless defined $guess; $parts[$i] = $guess; $count++; } } $_[0] = join q{}, @parts; return $count + chomp $_[0]; } __PACKAGE__