Ask
view release on metacpan or search on metacpan
use Ask ':all';
if (question("Are you happy?")
and question("Do you know it?")
and question("Really want to show it?")) {
info("Then clap your hands!");
}
DESCRIPTION
The `Ask` suite is a set of modules for interacting with users; prompting
them for information, displaying messages, warnings and errors, etc.
There are already countless CPAN modules for doing this sort of thing, but
what sets `Ask` apart from them is that `Ask` will detect how your script
is being run (in a terminal, headless, etc) and choose an appropriate way
to interact with the user.
Class Methods
`Ask->instance`
Singleton pattern. Can also be passed an argument to use it as a
articles/ask-introduction.pod view on Meta::CPAN
=head1 Ask not what your user can do for you...
In many scripts, we need to prompt the end user for information - this
could be a prompt for a file name, a selection from a list of options,
or an answer to a yes/no question.
The traditional approach to this sort of question is to print your
question to STDOUT, read a line from STDIN, and apply some sort of
parsing to the answer...
use 5.010;
use strict;
use warnings;
articles/ask-introduction.pod view on Meta::CPAN
$answer = 0 if /^N/i;
}
say "Adding fries!" if $answer;
One issue with this approach is: what happens when your script is not
running in a terminal?
One attempt at solving this problem is L<IO::Prompt::Tiny> and its ilk.
This performs a simple test to determine if the script is running on an
interactive terminal and only prompts the user if the terminal is
interactive. When the script is being run non-interactively (or if the
C<PERL_MM_USE_DEFAULT> environment variable is set), then it returns a
default answer instead.
use 5.010;
use strict;
use warnings;
use IO::Prompt::Tiny qw(prompt);
my $answer;
until (defined $answer) {
# In non-interactive mode, assume they want no fries...
$_ = prompt("Would you like fries with that?", "No");
$answer = 1 if /^Y/i;
$answer = 0 if /^N/i;
}
say "Adding fries!" if $answer;
The problem with this is that it makes the assumption that when the
terminal is non-interactive, there is absolutely no other way to prompt
the user, and you should be happy with the default answer. This is not
always a good assumption.
=head2 Opening up a dialogue
On some operating systems, double-clicking a Perl file will launch it
without a terminal. In these cases, you can probably interact with the
user by launching a dialog box. But how to do that? Doesn't that
require complex programming in L<Tk> or L<Wx> (modules which are not
in core, and not always straightforward to build)?
use Ask ':all';
if (question("Are you happy?")
and question("Do you know it?")
and question("Really want to show it?")) {
info("Then clap your hands!");
}
=head1 DESCRIPTION
The C<Ask> suite is a set of modules for interacting with users; prompting
them for information, displaying messages, warnings and errors, etc.
There are already countless CPAN modules for doing this sort of thing, but
what sets C<Ask> apart from them is that C<Ask> will detect how your script
is being run (in a terminal, headless, etc) and choose an appropriate way
to interact with the user.
=head2 Class Methods
=over
lib/Ask/Caroline.pm view on Meta::CPAN
}
sub quality {
my ( $self ) = ( shift );
( ref( $self ) ? $self : 'Caroline'->new )->is_supported ? 90 : 30;
}
sub entry {
my ( $self, %opts ) = ( shift, @_ );
$opts{prompt} = 'entry> ' unless exists $opts{prompt};
if ( exists $opts{completion} ) {
$self->completion( $opts{completion} );
}
else {
$self->completion(
sub {
return $opts{default};
}
);
lib/Ask/Caroline.pm view on Meta::CPAN
my ( $line, $tio );
if (
$opts{hide_text}
and do { require POSIX; $tio = 'POSIX::Termios'->new }
)
{
$tio->getattr( 0 );
$tio->setlflag( $tio->getlflag & ~POSIX::ECHO() );
$tio->setattr( 0 );
print STDOUT $opts{prompt}; # no new line;
STDOUT->flush;
chomp( $line = <STDIN> );
$tio->setlflag( $tio->getlflag | POSIX::ECHO() );
$tio->setattr( 0 );
print STDOUT "\r\n";
STDOUT->flush;
} #/ if ( $opts{hide_text} ...)
else {
chomp( $line = $self->caroline->readline( $opts{prompt} ) );
}
$self->clear_completion;
return $line;
} #/ sub entry
sub question {
my ( $self, %opts ) = ( shift, @_ );
$opts{prompt} = 'y/n> ' unless exists $opts{prompt};
my $response = $self->entry( %opts );
my $lang = $self->_lang_support( $opts{lang} );
$lang->boolean( $response );
}
sub print_findings {
my ( $self, $findings, $fh ) = ( shift, @_ );
if ( my @copy = @$findings ) {
lib/Ask/Caroline.pm view on Meta::CPAN
} #/ if ( my @copy = @$findings)
return;
} #/ sub print_findings
sub file_selection {
my ( $self, %opts ) = ( shift, @_ );
my $single = !$opts{multiple};
$opts{prompt} = sprintf( '%s> ', $opts{directory} ? 'directory' : 'file' )
unless exists $opts{prompt};
unless ( $opts{text} ) {
$opts{text} =
$single
? (
$opts{directory} ? 'Please choose a directory.' : 'Please choose a file.' )
: (
$opts{directory}
? 'Please choose some directories.'
: 'Please choose some files.'
lib/Ask/Caroline.pm view on Meta::CPAN
$self->print_findings( \@printable, \*STDOUT );
return map "$_", ( $got->is_dir ? $got : () ), @kids;
}
);
my @chosen;
CHOICE: while ( 1 ) {
chomp( my $line = $self->caroline->readline( $opts{prompt} ) );
if ( $line eq '' ) {
$single ? next( CHOICE ) : last( CHOICE );
}
if ( $opts{existing} and not path( $line )->exists ) {
$self->error(
text => sprintf( 'Does not exist: %s. Please try again.', $line ),
);
}
lib/Ask/Caroline.pm view on Meta::CPAN
sub single_choice {
shift->multiple_choice( @_, _single => 1 );
}
sub multiple_choice {
my ( $self, %opts ) = ( shift, @_ );
my $single = $opts{_single};
$opts{prompt} = 'choice> ' unless exists $opts{prompt};
if ( exists $opts{text} ) {
$self->info(
text => $opts{text},
colour => $opts{colour} || 'bright_cyan',
);
}
my %allowed;
my @choices_list = map {
lib/Ask/Caroline.pm view on Meta::CPAN
my @found = grep /^$got/, map $_->[0], @{ $opts{choices} };
$self->print_findings( \@found, \*STDOUT );
return @found;
}
);
my @chosen;
CHOICE: while ( 1 ) {
chomp( my $line = $self->caroline->readline( $opts{prompt} ) );
if ( $line eq '' ) {
$single ? next( CHOICE ) : last( CHOICE );
}
if ( $allowed{$line} ) {
push @chosen, $line;
last CHOICE if $single;
}
else {
lib/Ask/Question.pm view on Meta::CPAN
The text of the question. If a coderef is given, that coderef will be
forwarded any of the arguments to C<< $question->(...) >>.
=item C<< backend >> I<< Object >>
A blessed object implementing L<Ask::API>. Defaults to the result of
C<< Ask->detect >>.
=item C<< title >> I<< Str >>
A title to use for question prompts, used by certain Ask backends.
=item C<< type >> I<< TypeTiny >>
A type constraint to check answers against. If the answer provided by the
user fails a type check (after coercion, if the type has a coercion), they
will be prompted to answer again.
=item C<< spec >> I<< HashRef >>
If this Ask::Question is being used as the default for an attrbute spec,
this can be used to hold the specification hash for the attribute, and
Ask::Question will attempt to find missing information like C<type> from
the spec hash.
=item C<< multiple >> I<< Bool >>
( run in 1.163 second using v1.01-cache-2.11-cpan-6aa56a78535 )