File Coverage

blib/lib/Text/Cloze.pm
Criterion Covered Total %
statement 45 45 100.0
branch 13 14 92.8
condition 2 3 66.6
subroutine 10 10 100.0
pod 4 4 100.0
total 74 76 97.3


line stmt bran cond sub pod time code
1             package Text::Cloze;
2              
3 4     4   94826 use warnings;
  4         9  
  4         102  
4 4     4   19 use strict;
  4         7  
  4         96  
5 4     4   19 use Carp;
  4         9  
  4         376  
6              
7 4     4   8201 use version; our $VERSION = qv('0.0.1');
  4         9100  
  4         24  
8              
9 4     4   342 use List::Util qw/shuffle/;
  4         8  
  4         4309  
10              
11             my %default = (
12             hint => 'blank',
13             max => 0,
14             regex => '\\S+',
15             start => 1,
16             stop => 1,
17             word => 5,
18             );
19              
20             sub new {
21 1     1 1 11 my ($class, %args) = @_;
22 1 50       4 $args{start} = $args{stop} = delete $args{sentence} if $args{sentence};
23 1   66     22 $args{$_} ||= $default{$_} for keys %default;
24             bless sub {
25 3     3   602 my ( $pre, $change, $post ) = change( shift , @args{qw/start stop/} );
26 3         4 my $n = 0;
27 3         4 my @removed = ();
28 3 100       20 $change =~ s{$args{regex}}
  384         1160  
29             {++$n % $args{word} ? $& : replace( $removed[@removed] = $&, $args{hint} )}eg;
30 3         138 s/^\W+//, s/\W+$//, $_ = ucfirst for @removed;
31 3         64 return ( @removed, $pre.$change.$post );
32 1         7 }, $class;
33             }
34              
35             sub change {
36 4     4 1 11 my ( $text, $start, $stop ) = @_;
37 4         10 my ( $pre, $change, $post ) = ('') x 3;
38 4         12 my @sentences = sentences_from( $text );
39 4         16 for ( my $i = 0; $i < @sentences; $i++ ) {
40 48 100       79 $pre .= $sentences[$i], next if $i < $start;
41 44 100       88 $post .= $sentences[$i], next if $i >= @sentences - $stop;
42 40         86 $change .= $sentences[$i];
43             }
44 4         17 return ( $pre, $change, $post );
45             }
46              
47             sub sentences_from {
48 4     4 1 5 local $_ = shift;
49 4         399 return m/
50             [(`'"]* # Beginning punctuation
51              
52             .+? # Sentence words
53            
54             (?:
55             # End of sentence
56             [.?!] [)`'"]*
57              
58             (?:
59             # slurp rest of whitespace at end of string...
60             (?: \s* \Z )
61             | # or look ahead to make sure another sentence occurs
62             (?= \s+ [(`'"]* [A-Z] )
63             )
64             | \Z
65             )
66             /xmsg;
67              
68             }
69              
70             sub replace {
71 82     82 1 109 my ( $word, $hint ) = @_;
72 82         107 my ( $punct_begin, $punct_end, $return ) = ('') x 3;
73 82         196 $punct_begin .= $_, $word =~ s/^\W+// for $word =~ m/^\W+/g;
74 82         248 $punct_end .= $_, $word =~ s/\W+$// for $word =~ m/\W+$/g;
75 82 100       209 $return .= '_' x 15 if $hint =~ /blank/;
76 82         98 $return = $punct_begin.$return;
77 82 100       161 $return .= '('.( length $word ).')' if $hint =~ /count/;
78 82 100       182 $return .= '('.( join '', shuffle(split '', $word) ).')' if $hint =~ /scramble/;
79 82         253 $return .= $punct_end;
80             }
81              
82             1; # Magic true value required at end of module
83             __END__