Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Using IO::Prompt's menu

by ghenry (Vicar)
on Sep 29, 2005 at 22:22 UTC ( #496268=perlquestion: print w/ replies, xml ) Need Help??
ghenry has asked for the wisdom of the Perl Monks concerning the following question:

Dear Master Monks,

Why does pod2usage("$0: No files given.") if ( ( @ARGV == 0 ) && ( -t STDIN ) ); render my menu useless?

#!/usr/bin/perl ########################################################## # # # Author: Gavin Henry # # Web: http://www.perl.me.uk # # # # Version: 0.1 - 29.09.05 # # # # Quick wrapper script to convert an avi # # to a dvd image, using howto at: # # # # http://mightylegends.zapto.org/dvd/dvdauthor_howto.php # # # # Licence: GPL # # # ########################################################## use strict; use warnings; use IO::Prompt; use Pod::Usage; use Getopt::Long; # Straight from the Pod::Usage docs ###################### my $man = 0; my $help = 0; ## Parse options and print usage if there is a syntax error, ## or if usage was explicitly requested. GetOptions( 'help|?' => \$help, man => \$man ) or pod2usage(2); pod2usage(1) if $help; pod2usage( -verbose => 2 ) if $man; ## If no arguments were given, then allow STDIN to be used only ## if it's not connected to a terminal (otherwise print usage) pod2usage("$0: No files given.") if ( ( @ARGV == 0 ) && ( -t STDIN ) ) +; ########################################################## # After we have tested to see we were given a filename and to be # used for later my $avi = $ARGV[0]; # use menu option from IO::Prompt my $choice = prompt 'Please choose your format...', -1, -menu => [ 'PAL', 'NTSC', 'Quit', ]; print "You chose: [$choice]\n\n"; # This is where all the encoding will go once I have figured # out what's wrong with the menu above if ( $choice eq 'PAL' ) { print "You must be in Europe or Australia, encoding to PAL format\ +n"; } elsif ( $choice eq 'NTSC' ) { print "You must be in America, encoding to NTSC format\n"; } elsif ( $choice eq 'Quit' ) { print "Bye, bye\n"; exit 0; } else { print "Nothing selected.\n"; exit 0; } __END__ =head1 NAME avi2dvd - a Perl wrapper script for converting an avi to dvd image =head1 SYNOPSIS ./avi2dvd avifile =head1 DESCRIPTION Following http://mightylegends.zapto.org/dvd/dvdauthor_howto.php I got sick of typing all the commands, so wrote this little wrapper script. It uses: IO::Prompt Pod::Usage Getopt::Long =head1 SEE ALSO http://mightylegends.zapto.org/dvd/dvdauthor_howto.php =head1 VERSION This man page documents avi2dvd version 0.1 =head1 CREDITS Rick Harris: http://mightylegends.zapto.org/dvd/dvdauthor_howto.php =head1 AUTHOR name : Gavin Henry email : ghenry at perl dot me dot uk web : http://www.perl.me.uk PM : http://aberdeen.pm.org =head1 COPYRIGHT Copyright (c) 2005 by Gavin Henry =head1 LICENSE This package is free software; you can redistribute it and/or modify i +t under the terms of the "GNU General Public License". Please refer to http://www.gnu.org/licenses/gpl.txt for details. =head1 DISCLAIMER This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "GNU General Public License" for more details.
Thanks.

Walking the road to enlightenment... I found a penguin and a camel on the way.....
Fancy a yourname@perl.me.uk? Just ask!!!

Comment on Using IO::Prompt's menu
Select or Download Code
Re: Using IO::Prompt's menu
by Tanktalus (Canon) on Sep 29, 2005 at 23:40 UTC

    Ok, I went to install IO::Prompt. For whatever reason, the CPAN module wanted to install v0.02. Blech.

    So I downloaded 0.99.2. It wanted "version". Fine, CPAN installed that ok. perl Build.PL, ./Build, ./Build test. Now it decides it wants Want. Why didn't it tell me this during the Build.PL stage?

    Ok, got it installed. Remove everything to do with Pod::Usage. Still doesn't work.

    Change my $avi = $ARGV[0]; to my $avi = shift;. Works now. Put back Pod::Usage stuff. Still works.

    Seems that IO::Prompt wants to take stuff from the command line if there's anything there before going to the console. ;-)

      Thanks for your time Tanktalus.

      I forgot that shift does that with @ARGV:

      If ARRAY is omitted, shifts the @_ array within the lexical scope of s +ubroutines and formats, and the @ARGV array at file scopes or within the lexical scopes establ +ished by the "eval ",

      But I am still puzzled as to why IO::Prompt would do that. If you are presenting a menu, you want the user to select something, not pass in an option on the commandline. If you did, you would use Getopt::* for that.

      Do you think this is a bug?
      Gavin.

      Walking the road to enlightenment... I found a penguin and a camel on the way.....
      Fancy a yourname@perl.me.uk? Just ask!!!

        First off, I submitted a bug for the Want prereq. Guess who responded. TheDamian. Very quickly, too, I might add. "Patched." So perhaps he can chime in here.

        My guess is that it'll be viewed as a documentation bug and that this is viewed as a "feature". Personally, I agree that it's not expected and, although I think it may not follow the principle of least surprise, I can also see how it could be seen as a "cool" feature.

        I would think that it should be an option, though, to the prompt function. "-parseargv", perhaps. Default would be to ignore @ARGV. This way, we get the principle of least surprise while still keeping the cool feature. The downside to this is that it would break any scripts that rely on the current behaviour. Not breaking these scripts, however, would break the principle of least surprise, IMO.

        But we'll have to leave it to TheDamian to decide. After all, I'm just but a young whippersnapper who barely knows the difference between map and for, nevermind an esteemed user of TheDamian's modules. ;-)

        But I am still puzzled as to why IO::Prompt would do that.

        IO::Prompt is designed to be a drop-in replacement for the "diamond operator" (i.e. for: <>). It writes out its prompt to STDOUT and then does a <> to get the reply.

        But the diamond operator is just a shorthand for <ARGV>, a readline on the magic filehandle that normally is attached to STDIN...unless you specify a filename on the commandline.

        So it shouldn't really be a surprise that, if you put something on the commandline (as you typically do when running this program), <ARGV> attempts to open-and-read from that something. That's just standard Perl behaviour...which prompt() valiantly tries to preserve.

        Of course, standard Perl behaviour isn't always what you want (as in this example). And that's why prompt() also has a -tty option, so you can explicitly say "Don't work like Perl's <ARGV> works; always read from the terminal instead".

        You might like to try replacing:

        my $choice = prompt 'Please choose your format...', -1, -menu => [ 'PAL', 'NTSC', 'Quit', ];

        (which means "Prompt, reading from wherever <ARGV> reads from") with this:

        my $choice = prompt -tty, 'Please choose your format...', -1, -menu => [ 'PAL', 'NTSC', 'Quit', ];

        (which means "Prompt, always reading from the terminal").

        If you are presenting a menu, you want the user to select something, not pass in an option on the commandline. If you did, you would use Getopt::* for that.

        That's not quite what's happening here. If <ARGV> (or prompt()) finds a string on the commandline, it tries to open the file whose name is that string, and then reads from that file.

        Why would you want that? Well, you might want that behaviour because you've written a script that automates the use of your program, and you want to feed the program its required input from a "prerecorded" file, which you specify on the commandline. Again, this is standard Perl behaviour, not my invention. I'm merely trying to preserve it when replacing <ARGV>.

        As you can see, "least surprise" is a difficult thing to achieve. It depends entirely on what people find surprising, which in turn depends on what features of Perl they're familiar with.

        However, it certainly would be a good idea for me to rework the docs a little to emphasize the "just like <ARGV>" behaviour of the module, with all that implies.

        Thanks for bringing this "surprise" to my attention.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://496268]
Approved by pjf
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (7)
As of 2014-12-23 02:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (133 votes), past polls