File Coverage

blib/lib/Lingua/Boolean/Tiny.pm
Criterion Covered Total %
statement 156 201 77.6
branch 27 34 79.4
condition 1 3 33.3
subroutine 82 110 74.5
pod 5 5 100.0
total 271 353 76.7


line stmt bran cond sub pod time code
1 1     1   29067 use 5.006002;
  1         3  
  1         36  
2 1     1   6 use strict;
  1         1  
  1         31  
3 1     1   5 use warnings;
  1         5  
  1         26  
4 1     1   1204 use utf8;
  1         10  
  1         5  
5 1     1   41 no warnings qw( void once uninitialized );
  1         1  
  1         543  
6              
7             {
8             package Lingua::Boolean::Tiny;
9            
10             require Exporter;
11             our @ISA = 'Exporter';
12            
13             our $AUTHORITY = 'cpan:TOBYINK';
14             our $VERSION = '0.007';
15             our @EXPORT = qw( boolean );
16             our (%LANG, @LANG);
17             our @BASELANG = qw( zh en es hi ru ar pt bn fr ms de ja );
18            
19             sub new
20             {
21 106     106 1 1126 require Carp;
22 106         152 my $class = shift;
23 106 50       238 my $self = $class->new_strict(@_)
24             or Carp::carp("Language not available, using English instead");
25 106 50       372 $self || "Lingua::Boolean::Tiny"->new_strict("en");
26             }
27            
28             sub new_strict
29             {
30 648     648 1 778 shift;
31 648         1379 my ($lang) = @_;
32 648 100       1801 return "Lingua::Boolean::Tiny::Union"->new(@$lang) if ref($lang);
33 577 50       1348 return "Lingua::Boolean::Tiny::Union"->new(@BASELANG) if !defined $lang;
34             my $class = $LANG{ lc $lang }
35 577   33     2238 || do { require Lingua::Boolean::Tiny::More; $LANG{ lc $lang } };
36 577 50       26569 return $class->new if $class;
37 0         0 return;
38             }
39            
40             sub boolean
41             {
42 105     105 1 44131 my $text = shift;
43 105 100       487 my $lang = __PACKAGE__->new(@_ ? $_[0] : \@LANG);
44 105         262 $lang->boolean($text);
45             }
46            
47             sub langs
48             {
49 0     0 1 0 @LANG;
50             }
51            
52             sub languages
53             {
54 0     0 1 0 map __PACKAGE__->new($_)->languages, @LANG;
55             }
56             }
57              
58             {
59             package Lingua::Boolean::Tiny::BASE;
60            
61             our $AUTHORITY = 'cpan:TOBYINK';
62             our $VERSION = '0.007';
63            
64             # Versions of ~~ and fc for legacy Perls...
65 1     1   822 use if $] >= 5.016, feature => 'fc';
  1         7  
  1         5  
66 1 50   1   206 BEGIN { eval q[fc("1")] or eval q[sub fc($) { lc $_[0] }] };
67            
68             eval q
69 1     1   546 {
  0     1   0  
  0     1   0  
  1     348   23  
  1         3  
  1         59  
  1         7  
  1         1  
  1         83  
  348         2863  
70             use match::simple qw(match);
71             1;
72             }
73             or eval q
74             {
75             use v5.10.1;
76             no warnings;
77             sub match { $_[0] ~~ $_[1] };
78             1;
79             }
80             or eval q
81             {
82             sub match
83             {
84             my ($a, $b) = @_;
85             if (ref($b) eq 'ARRAY')
86             {
87             for my $b2 (@$b)
88             {
89             return 1 if match($a, $b2);
90             }
91             }
92             ref($b) eq 'Regexp' and return $a =~ $b;
93             ref($b) eq 'CODE' and return $b->($a);
94             return $a eq $b;
95             }
96             };
97            
98             sub boolean
99             {
100 210     210   378 my $self = shift;
101 210         230 my ($text) = @_;
102            
103 210         654 $text =~ s/(?:^\s+)|(?:\s+$)//gs;
104            
105 210 100       7102 return 1 if fc $text eq fc $self->yes;
106 198 100       6684 return 0 if fc $text eq fc $self->no;
107 180 100       5596 return 1 if match($text, $self->yes_expr);
108 168 100       6181 return 0 if match($text, $self->no_expr);
109 138 100       341 return 1 if $text eq 1;
110 135 100       246 return 0 if $text eq 0;
111 129         242 return undef;
112             }
113            
114             sub yesno
115             {
116 2 100   2   67 $_[1] ? $_[0]->yes : $_[0]->no
117             }
118            
119             sub make_classes
120             {
121 1     1   2 my $base = shift;
122 1     1   5 no strict 'refs';
  1         2  
  1         178  
123 1         5 for (@_)
124             {
125 12         30 my ($lang, $codes, $yes, $no, $yes_expr, $no_expr) = @$_;
126 12 50       27 $yes_expr = $yes unless defined $yes_expr;
127 12 50       24 $no_expr = $no unless defined $no_expr;
128 12         26 my $class = "Lingua::Boolean::Tiny::$lang";
129 12         14 ${"$class\::AUTHORITY"} = $AUTHORITY;
  12         101  
130 12         15 ${"$class\::VERSION"} = $VERSION;
  12         57  
131 12         16 @{"$class\::ISA"} = ($base);
  12         275  
132 1     1   4 no warnings qw( closure );
  1         2  
  1         633  
133             eval qq
134 12     0   2842 {
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     0   0  
  0     40   0  
  0     72   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     40   0  
  0     105   0  
  0     40   0  
  40     10   74  
  40     10   616  
  72     69   111  
  72     4   582  
  40     10   59  
  40     10   274  
  40     10   98  
  40     10   380  
  40     4   62  
  40     4   270  
  40     18   69  
  40     10   257  
  40     10   61  
  40     10   382  
  40     35   70  
  40     10   290  
  40     53   60  
  40     8   267  
  40     4   64  
  40     10   276  
  40     4   67  
  40     4   410  
  105     10   159  
  105     10   954  
  40     40   365  
  10     4   77  
  10     10   55  
  69     10   292  
  4     10   11  
  10     10   427  
  10     4   183  
  10     4   34  
  10     24   41  
  4     10   14  
  4     75   53  
  18     4   70  
  10     57   443  
  10     40   424  
  10     10   262  
  35     4   1011  
  10     10   258  
  53     10   1428  
  8     4   181  
  4     10   102  
  10     10   269  
  4     11   176  
  4     10   126  
  10         264  
  10         321  
  40         485  
  4         125  
  10         41  
  10         39  
  10         300  
  10         60  
  4         14  
  4         14  
  24         93  
  10         269  
  75         320  
  4         87  
  57         1887  
  40         1219  
  10         410  
  4         99  
  10         256  
  10         320  
  4         100  
  10         308  
  10         333  
  11         258  
  10         258  
135             package $class;
136             sub new { my \$k = shift; bless qr{$lang}, \$k };
137             sub yes { \$yes };
138             sub no { \$no };
139             sub yes_expr { \$yes_expr };
140             sub no_expr { \$no_expr };
141             sub languages { \$lang };
142             sub langs { \@{ \$codes } };
143             };
144 12         50 for my $lang (@$codes)
145             {
146 28         85 $Lingua::Boolean::Tiny::LANG{$lang} = $class;
147             }
148 12         85 push @Lingua::Boolean::Tiny::LANG, $codes->[0];
149             }
150            
151 1         54 return 1;
152             }
153             }
154              
155             {
156             package Lingua::Boolean::Tiny::Union;
157            
158             our $AUTHORITY = 'cpan:TOBYINK';
159             our $VERSION = '0.007';
160            
161             sub new
162             {
163 71     71   87 my $class = shift;
164 71         197 bless [ grep defined, map "Lingua::Boolean::Tiny"->new_strict($_), @_ ] => $class;
165             }
166            
167             sub boolean
168             {
169 71     71   78 my $self = shift;
170 71         147 for (@$self)
171             {
172 176         518 my $r = $_->boolean(@_);
173 176 100       1059 return $r if defined $r;
174             }
175 8         65 return undef;
176             }
177            
178             sub langs
179             {
180 0     0     my $self = shift;
181 0           map $_->langs, @$self;
182             }
183            
184             sub languages
185             {
186 0     0     my $self = shift;
187 0           map $_->languages, @$self;
188             }
189             }
190              
191             "Lingua::Boolean::Tiny::BASE"->make_classes(
192             [
193             Chinese => [qw( zh zho chi )],
194             q/是/ => q/不是/,
195             [qr{^[yY是]}, qw( 是 對 是 对 ), qr{^[ds]h[ìi]$}i],
196             [qr{^[nN不否]}, qw( 不是 不對 不是 不对 ), qr{^b[úu]\s*[ds]h[ìi]$}i],
197             ],
198             [
199             English => [qw( en eng )],
200             qw( yes no ),
201             [qr{^y(?:es)?$}i, qr{^on$}i, qr{^ok$}i, qr{^true$}i],
202             [qr{^no?$}i, qr{^off$}i, qr{not ?ok$}i, qr{^false$}i],
203             ],
204             [
205             Spanish => [qw( es spa )],
206             qw( sí no ),
207             qr{^[sSyY]},
208             qr{^[nN]$},
209             ],
210             [
211             Hindi => [qw( hi hin )],
212             q/हाँ/ => q/नहीं/,
213 1     1   5 ["हाँ", qr{^h[aā]̃$}i, "जी", qr{^j[īi]$}i, "जी हाँ", qr{^j[īi]\s*h[aā]̃$}i, qr{^ji\s*ha$}i, qr{^[yY]}],
  1         2  
  1         11  
214             ["नहीं", qr{^nahī̃$}i, "जी नहीं", qr{^jī nahī̃$}i, qr{^ji\s*nahi$}i, qr{^[nN]}],
215             ],
216             [
217             Russian => [qw( ru rus )],
218             qw( да нет ),
219             [qr{^[ДдYy]}, qr{^да$}i, qr{^da$}i],
220             [qr{^[НнNn]}, qr{^нет$}i, qr{^n[iy]?et$}i],
221             ],
222             [
223             Arabic => [qw( ar ara )],
224             q/نعم/ => q/ﻻ/,
225             qr{^[نyY].*},
226             qr{^[لnN].*},
227             ],
228             [
229             Portuguese => [qw( pt por )],
230             qw( sim não ),
231             [qr{^[SsyY].*}, qr{^sim$}i],
232             [qr{^[nN].*}, qr{^n[aã]o$}i],
233             ],
234             [
235             Bengali => [qw( bn ben )],
236             q/হ্যাঁ/ => q/না/,
237             [qr{^[হ্যাঁyY]}, q/জি/, q/হ্যাঁ/, qr{^ji$}i, qr{^h[eê][nñ]$}i],
238             [qr{^[নাnN]}, q/না/, qr{^n[aā]$}i],
239             ],
240             [
241             French => [qw( fr fre fra )],
242             qw( oui non ),
243             [qr{^[oOjJyYsS1].*}, qr{^oui$}i, qr{^ok$}i, qr{^vraie?$}i],
244             [qr{^[nN0].*}, qr{^n(?:on?)?$}i, qr{^faux$}i],
245             ],
246             [
247             Malay => [qw( ms may msa )],
248             qw( ya tidak ),
249             [qr{^[Yy]}, qr{^ya$}i, qr{^ha'?ah$}i],
250             [qr{^[Tt]}, qr{^tidak$}i, qr{^tak$}i],
251             ],
252             [
253             German => [qw( de deu ger )],
254             qw( ja nein ),
255             [qr{^[jJyY].*}, qr{^ja?$}i],
256             [qr{^[nN].*}, qr{^n(?:ein)?$}i, qr{^y}i],
257             ],
258             [
259             Japanese => [qw( ja jpn )],
260             q/はい/ => q/いいえ/,
261             [qr{^([yYyY]|はい|ハイ)}, q/はい/, q/ええ/, q/うん/, qr{^hai$}i, qr{^[eē]$}i, qr{^un$}i, qr{^n̄$}i],
262             [qr{^([nNnN]|いいえ|イイエ)}, q/いいえ/, q/いえ/, q/ううん/, q/違う/, qr{^[íi]?ie$}i, qr{^uun$}i, qr{^[n̄n]n$}i, qr{^chigau$}i],
263             ],
264             );
265              
266             __END__