File Coverage

lib/App/Info/Handler/Prompt.pm
Criterion Covered Total %
statement 31 32 96.8
branch 12 14 85.7
condition 8 12 66.6
subroutine 5 5 100.0
pod 2 2 100.0
total 58 65 89.2


line stmt bran cond sub pod time code
1             package App::Info::Handler::Prompt;
2              
3             =head1 NAME
4              
5             App::Info::Handler::Prompt - Prompting App::Info event handler
6              
7             =head1 SYNOPSIS
8              
9             use App::Info::Category::FooApp;
10             use App::Info::Handler::Print;
11              
12             my $prompter = App::Info::Handler::Print->new;
13             my $app = App::Info::Category::FooApp->new( on_unknown => $prompter );
14              
15             # Or...
16             my $app = App::Info::Category::FooApp->new( on_confirm => 'prompt' );
17              
18             =head1 DESCRIPTION
19              
20             App::Info::Handler::Prompt objects handle App::Info events by printing their
21             messages to C and then accepting a new value from C. The new
22             value is validated by any callback supplied by the App::Info concrete subclass
23             that triggered the event. If the value is valid, App::Info::Handler::Prompt
24             assigns the new value to the event request. If it isn't it prints the error
25             message associated with the event request, and then prompts for the data
26             again.
27              
28             Although designed with unknown and confirm events in mind,
29             App::Info::Handler::Prompt handles info and error events as well. It will
30             simply print info event messages to C and print error event messages
31             to C. For more interesting info and error event handling, see
32             L and
33             L.
34              
35             Upon loading, App::Info::Handler::Print registers itself with
36             App::Info::Handler, setting up a single string, "prompt", that can be passed
37             to an App::Info concrete subclass constructor. This string is a shortcut that
38             tells App::Info how to create an App::Info::Handler::Print object for handling
39             events.
40              
41             =cut
42              
43 2     2   2751 use strict;
  2         6  
  2         78  
44 2     2   12 use App::Info::Handler;
  2         39  
  2         49  
45 2     2   9 use vars qw($VERSION @ISA);
  2         4  
  2         2117  
46             $VERSION = '0.57';
47             @ISA = qw(App::Info::Handler);
48              
49             # Register ourselves.
50             App::Info::Handler->register_handler
51             ('prompt' => sub { __PACKAGE__->new } );
52              
53             =head1 INTERFACE
54              
55             =head2 Constructor
56              
57             =head3 new
58              
59             my $prompter = App::Info::Handler::Prompt->new;
60              
61             Constructs a new App::Info::Handler::Prompt object and returns it. No special
62             arguments are required.
63              
64             =cut
65              
66             sub new {
67 3     3 1 63 my $pkg = shift;
68 3         39 my $self = $pkg->SUPER::new(@_);
69 3   33     39 $self->{tty} = -t STDIN && ( -t STDOUT || !( -f STDOUT || -c STDOUT ) );
70             # We're done!
71 3         20 return $self;
72             }
73              
74             my $get_ans = sub {
75             my ($prompt, $tty, $def) = @_;
76             # Print the message.
77             local $| = 1;
78             local $\;
79             print $prompt;
80              
81             # Collect the answer.
82             my $ans;
83             if ($tty) {
84             $ans = ;
85             if (defined $ans ) {
86             chomp $ans;
87             } else { # user hit ctrl-D
88             print "\n";
89             }
90             } else {
91             print "$def\n" if defined $def;
92             }
93             return $ans;
94             };
95              
96             sub handler {
97 14     14 1 25 my ($self, $req) = @_;
98 14         19 my $ans;
99 14         43 my $type = $req->type;
100 14 100 100     90 if ($type eq 'unknown' || $type eq 'confirm') {
    100          
    50          
101             # We'll want to prompt for a new value.
102 12         39 my $val = $req->value;
103 12 100       40 my ($def, $dispdef) = defined $val ? ($val, " [$val] ") : ('', ' ');
104 12 50       35 my $msg = $req->message or Carp::croak("No message in request");
105 12         27 $msg .= $dispdef;
106              
107             # Get the answer.
108 12         37 $ans = $get_ans->($msg, $self->{tty}, $def);
109             # Just return if they entered an empty string or we couldnt' get an
110             # answer.
111 12 100 66     73 return 1 unless defined $ans && $ans ne '';
112              
113             # Validate the answer.
114 10         31 my $err = $req->error;
115 10         29 while (!$req->value($ans)) {
116 8         40 print "$err: '$ans'\n";
117 8         47 $ans = $get_ans->($msg, $self->{tty}, $def);
118 8 100 66     70 return 1 unless defined $ans && $ans ne '';
119             }
120              
121             } elsif ($type eq 'info') {
122             # Just print the message.
123 1         8 print STDOUT $req->message, "\n";
124             } elsif ($type eq 'error') {
125             # Just print the message.
126 1         56 print STDERR $req->message, "\n";
127             } else {
128             # This shouldn't happen.
129 0         0 Carp::croak("Invalid request type '$type'");
130             }
131              
132             # Return true to indicate that we've handled the request.
133 8         336 return 1;
134             }
135              
136             1;
137             __END__