File Coverage

blib/lib/App/Cmd/Plugin/Prompt.pm
Criterion Covered Total %
statement 12 45 26.6
branch 0 24 0.0
condition 0 29 0.0
subroutine 4 11 36.3
pod 3 3 100.0
total 19 112 16.9


line stmt bran cond sub pod time code
1 1     1   55286 use strict;
  1         9  
  1         25  
2 1     1   5 use warnings;
  1         2  
  1         57  
3             package App::Cmd::Plugin::Prompt 1.006;
4             # ABSTRACT: plug prompting routines into your commands
5 1         8 use App::Cmd::Setup -plugin => {
6             exports => [ qw(prompt_str prompt_yn prompt_any_key) ],
7 1     1   378 };
  1         40321  
8              
9 1     1   904 use Term::ReadKey;
  1         1685  
  1         564  
10              
11             #pod =head1 SYNOPSIS
12             #pod
13             #pod In your app:
14             #pod
15             #pod package MyApp;
16             #pod use App::Cmd::Setup -app => {
17             #pod plugins => [ qw(Prompt) ],
18             #pod };
19             #pod
20             #pod In your command:
21             #pod
22             #pod package MyApp::Command::dostuff;
23             #pod use MyApp -command;
24             #pod
25             #pod sub run {
26             #pod my ($self, $opt, $args) = @_;
27             #pod
28             #pod return unless prompt_yn('really do stuff?', { default => 1 });
29             #pod
30             #pod ...
31             #pod }
32             #pod
33             #pod =head1 SUBROUTINES
34             #pod
35             #pod =head2 prompt_str
36             #pod
37             #pod my $input = prompt_str($prompt, \%opt)
38             #pod
39             #pod This prompts a user for string input. It can be directed to
40             #pod persist until input is 'acceptable'.
41             #pod
42             #pod Valid options are:
43             #pod
44             #pod =over 4
45             #pod
46             #pod =item *
47             #pod
48             #pod B optional coderef, which, when invoked, returns the
49             #pod user's response; default is to read from STDIN.
50             #pod
51             #pod =item *
52             #pod
53             #pod B optional coderef, which, when invoked (with two
54             #pod arguments: the prompt and the choices/default), should
55             #pod prompt the user; default is to write to STDOUT.
56             #pod
57             #pod =item *
58             #pod
59             #pod B an optional coderef which any input is passed into
60             #pod and which must return true in order for the program to
61             #pod continue
62             #pod
63             #pod =item *
64             #pod
65             #pod B may be any string; must pass the 'valid' coderef
66             #pod (if given)
67             #pod
68             #pod =item *
69             #pod
70             #pod B what to display after the prompt; default is
71             #pod either the 'default' parameter or nothing
72             #pod
73             #pod =item *
74             #pod
75             #pod B do not test the 'default' parameter
76             #pod against the 'valid' coderef
77             #pod
78             #pod =item *
79             #pod
80             #pod B error message to throw when the
81             #pod 'default' parameter is not valid (does not pass the 'valid'
82             #pod coderef)
83             #pod
84             #pod =back
85             #pod
86             #pod =cut
87              
88             sub prompt_str {
89 0     0 1   my ($plugin, $cmd, $message, $opt) = @_;
90 0 0 0       if ($opt->{default} && $opt->{valid} && ! $opt->{no_valid_default}) {
      0        
91             Carp::croak(
92             $opt->{invalid_default_error} || "'default' must pass 'valid' parameter"
93 0 0 0       ) unless $opt->{valid}->($opt->{default});
94             }
95 0   0 0     $opt->{input} ||= sub { scalar };
  0            
96 0   0 0     $opt->{valid} ||= sub { 1 };
  0            
97             $opt->{output} ||= sub {
98 0 0   0     if (defined $_[1]) {
99 0           printf "%s [%s]: ", @_;
100             } else {
101 0           printf "%s: ", $_[0];
102             }
103 0   0       };
104              
105 0           my $response;
106 0   0       while (!defined($response) || !$opt->{valid}->($response)) {
107             $opt->{output}->(
108             $message,
109 0   0       ($opt->{choices} || $opt->{default} || undef),
110             );
111 0           $response = $opt->{input}->();
112 0           chomp($response);
113 0 0 0       if ($opt->{default} && ! length($response)) {
114 0           $response = $opt->{default};
115             }
116             }
117 0           return $response;
118             }
119              
120             #pod =head2 prompt_yn
121             #pod
122             #pod my $bool = prompt_yn($prompt, \%opt);
123             #pod
124             #pod This prompts the user for a yes or no response and won't give up until it gets
125             #pod one. It returns true for yes and false for no.
126             #pod
127             #pod Valid options are:
128             #pod
129             #pod default: may be yes or no, indicating how to interpret an empty response;
130             #pod if empty, require an explicit answer; defaults to empty
131             #pod
132             #pod =cut
133              
134             sub prompt_yn {
135 0     0 1   my ($plugin, $cmd, $message, $opt) = @_;
136              
137             Carp::croak("default must be y or n or 0 or 1")
138             if defined $opt->{default}
139 0 0 0       and $opt->{default} !~ /\A[yn01]\z/;
140              
141             my $choices = (not defined $opt->{default}) ? 'y/n'
142             : $opt->{default} eq 'y' ? 'Y/n'
143             : $opt->{default} eq 'n' ? 'y/N'
144 0 0         : $opt->{default} ? 'Y/n'
    0          
    0          
    0          
145             : 'y/N';
146              
147             my $default = ($opt->{default}||'') =~ /\A\d\z/
148             ? ($opt->{default} ? 'y' : 'n')
149 0 0 0       : $opt->{default};
    0          
150              
151             my $response = $plugin->prompt_str(
152             $cmd,
153             $message,
154             {
155             choices => $choices,
156 0 0   0     valid => sub { lc($_[0]) eq 'y' || lc($_[0]) eq 'n' },
157 0           default => $default,
158             },
159             );
160              
161 0           return lc($response) eq 'y';
162             }
163              
164             #pod =head2 prompt_any_key($prompt)
165             #pod
166             #pod my $input = prompt_any_key($prompt);
167             #pod
168             #pod This routine prompts the user to "press any key to continue." C<$prompt>, if
169             #pod supplied, is the text to prompt with.
170             #pod
171             #pod =cut
172              
173             sub prompt_any_key {
174 0     0 1   my ($plugin, $cmd, $prompt) = @_;
175              
176 0   0       $prompt ||= "press any key to continue";
177 0           print $prompt;
178 0           Term::ReadKey::ReadMode 'cbreak';
179 0           Term::ReadKey::ReadKey(0);
180 0           Term::ReadKey::ReadMode 'normal';
181 0           print "\n";
182             }
183              
184             #pod =head1 SEE ALSO
185             #pod
186             #pod L
187             #pod
188             #pod =cut
189              
190             1;
191              
192             __END__