File Coverage

blib/lib/Lingua/TypoGenerator.pm
Criterion Covered Total %
statement 52 52 100.0
branch 11 14 78.5
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 68 72 94.4


line stmt bran cond sub pod time code
1             package Lingua::TypoGenerator;
2              
3 1     1   26506 use 5.006;
  1         4  
  1         48  
4 1     1   2158 use utf8;
  1         13  
  1         6  
5 1     1   44 use strict;
  1         8  
  1         67  
6              
7             our $VERSION = '0.01';
8              
9 1     1   7 use base 'Exporter';
  1         3  
  1         791  
10             our @EXPORT_OK = qw(typos);
11              
12             our $HTYPOS = " qwertyuiop asdfghjkl zxcvbnm ýúíó ùìò ÿüïö ûîô";
13             our @ACCENT_CLASSES = qw(
14             aáàâäãå
15             eéèêë
16             iíìîï
17             oóòôöõø
18             uúùûü
19             yýÿ
20            
21             );
22              
23              
24             # Takes one word and returns a list of probable typos
25             sub typos {
26 3     3 0 7965 my ($s, %args) = @_;
27 3         7 my %seen;
28              
29             # Typos involving one character
30 3         13 for (my $i = 0; $i < length $s; ++$i){
31 21         39 my $c = substr($s, $i, 1);
32              
33 21 50       237 next unless $c =~ /\w/;
34              
35 21         29 my $t = $s; # deletions
36 21         28 substr($t, $i, 1) = "";
37 21         47 $seen{$t} = 1;
38              
39             # horizontal keyboard typos
40 21 50       655 if($HTYPOS =~ /(.)$c(.)/i){
41 21 100       60 if ($1 ne ' '){
42 19         25 $t = $s;
43 19         44 substr($t, $i, 1) = $1;
44 19         220 $seen{$t} = 1;
45             }
46 21 100       50 if ($2 ne ' '){
47 20         25 $t = $s;
48 20         37 substr($t, $i, 1) = $2;
49 20         47 $seen{$t} = 1;
50             }
51             }
52              
53 21 100       247 if ($args{accents}) {
54 7         182 for (@ACCENT_CLASSES) {
55 49         58 my $class = $_;
56 49 100       1188 if($class =~ s/$c//i){
57 5         14 for my $letter (split(//, $class)){
58 19         26 $t = $s;
59 19         29 substr($t, $i, 1) = $letter;
60 19         60 $seen{$t} = 1;
61             }
62             }
63             }
64             }
65             }
66              
67             # Typos involving a pair of adjacent characters
68 3         31 for (my $i = 1; $i < length $s; ++$i){
69 18         26 my $t = $s;
70              
71 18 50       67 next unless substr($t, $i - 1, 2) =~ /\w\w/;
72              
73 18         28 my $c = substr $t, $i, 1; # transpositions
74 18         28 substr($t, $i, 1) = substr($t, $i - 1, 1);
75 18         25 substr($t, $i - 1, 1) = $c;
76 18         38 $seen{$t} = 1;
77              
78 18         30 $t = $s; # duplications with replacement
79 18         25 substr($t, $i, 1) = substr($t, $i - 1, 1);
80 18         34 $seen{$t} = 1;
81              
82 18         22 $t = $s; # duplications with insertion
83 18         25 substr($t, $i, 0) = substr($t, $i - 1, 1);
84 18         63 $seen{$t} = 1;
85             }
86              
87 3         4 delete $seen{$s}; # make sure to exclude original word!
88              
89 3         153 return sort keys %seen;
90             }
91              
92             1;
93              
94             __END__