File Coverage

blib/lib/IO/Prompt/Hooked.pm
Criterion Covered Total %
statement 50 50 100.0
branch 18 18 100.0
condition 15 15 100.0
subroutine 13 13 100.0
pod 2 2 100.0
total 98 98 100.0


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             package IO::Prompt::Hooked;
3              
4 3     3   189132 use 5.006000;
  3         11  
  3         130  
5 3     3   15 use strict;
  3         6  
  3         90  
6 3     3   16 use warnings;
  3         7  
  3         114  
7 3     3   2041 use Params::Smart;
  3         20809  
  3         323  
8 3     3   2045 use IO::Prompt::Tiny ();
  3         1211  
  3         168  
9              
10             our $VERSION = '0.10';
11              
12 3     3   751 use parent 'Exporter';
  3         291  
  3         22  
13              
14             our @EXPORT = qw( prompt );
15             our @EXPORT_OK = qw( terminate_input );
16              
17             # Steal a subroutine from IO::Prompt::Tiny (Not published in the API)!
18             *_is_interactive = \&IO::Prompt::Tiny::_is_interactive;
19              
20             # Template for Params::Smart validation.
21             my @params = (
22             { name => 'message', required => 0, default => '' },
23             { name => 'default', required => 0, },
24             { name => 'tries', required => 0, name_only => 1, default => -1 },
25             {
26             name => 'validate',
27             required => 0,
28             name_only => 1,
29             default => sub { 1 }
30             },
31             {
32             name => 'error',
33             required => 0,
34             name_only => 1,
35             default => sub { q{} }
36             },
37             {
38             name => 'escape',
39             required => 0,
40             name_only => 1,
41             default => sub { 0 }
42             },
43             );
44              
45             sub prompt {
46 49     49 1 37692 my @params = _unpack_prompt_params(@_);
47 49         128 return _hooked_prompt(@params);
48             }
49              
50             sub terminate_input {
51 3     3   729 no warnings 'exiting';
  3         7  
  3         1400  
52 2     2 1 16 last;
53              
54             # Return, here, would be pointless.
55             }
56              
57             sub _unpack_prompt_params {
58 49 100   49   234 my @args = ref $_[0] ? %{ shift() } : @_;
  2         6  
59 49         166 my %args = Params(@params)->args(@args);
60              
61 49 100       6291 $args{message} = defined $args{message} ? $args{message} : '';
62             # 'validate' and 'escape' can be passed a regex object instead of
63             # a subref.
64 49         86 for my $arg (qw( validate escape )) {
65 98 100       819 if ( ref $args{$arg} eq 'Regexp' ) {
66 22         34 my $regex = $args{$arg};
67 22     33   92 $args{$arg} = sub { $_[0] =~ $regex; };
  33         212  
68             }
69             }
70              
71             # Error can be passed a string or a subref.
72 49 100       251 if ( ref( $args{error} ) ne 'CODE' ) {
73 14         23 my $message = $args{error};
74 14     12   47 $args{error} = sub { $message };
  12         51  
75             }
76              
77             # If we're not interactive, make sure there's a tries limit.
78 49 100 100     234 if ( ( $ENV{PERL_MM_USE_DEFAULT} || !_is_interactive() )
      100        
79             && $args{tries} < 0 )
80             {
81 5         72 $args{tries} = 1;
82             }
83              
84 49         452 return @args{qw( message default tries validate error escape )};
85             }
86              
87             sub _hooked_prompt {
88 49     49   94 my ( $msg, $default, $tries, $validate_cb, $error_cb, $escape_cb ) = @_;
89              
90             # Short-circuit to the default, whatever it is if we start out with $tries==0.
91 49 100 100     210 return $default
92             if defined $tries && $tries == 0;
93              
94 48         99 while ($tries) {
95              
96 112         519 my $raw = IO::Prompt::Tiny::prompt( $msg, $default );
97              
98 112         1248 $tries--;
99              
100 112 100       225 last if $escape_cb->( $raw, $tries );
101              
102 108 100       302 return $raw if $validate_cb->( $raw, $tries );
103              
104 80 100 100     286 if ( my $error_msg =
      100        
105             $error_cb->( $raw, $tries )
106             and _is_interactive()
107             and !$ENV{PERL_MM_USE_DEFAULT} )
108             {
109 12         1635 print $error_msg;
110             }
111             }
112              
113 20         214 return; # If we arrived here, no valid input accepted.
114             }
115              
116             1;
117              
118             __END__