Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Trouble Creating a Menu

by at2marty (Novice)
on Aug 12, 2012 at 16:40 UTC ( #986967=perlquestion: print w/ replies, xml ) Need Help??
at2marty has asked for the wisdom of the Perl Monks concerning the following question:

I am working on a script that presents a menu and asks the user to select a choice. I don't quite understand why it is not working like I think it should.

What I get is a blank screen, and if I make a choice, the script briefly prints the menu then continues on.

Here is a snippet of my script (it is quite long).

#!/usr/bin/perl -w use strict; my $question; my $computer; my @pc = qw(comp1 comp2 comp3 comp4 comp5); # Find out which computer to cold start system("clear"); do { print "Which computer would you like to cold start?\n"; print "1 - comp1 2 - comp2 3 - comp3 4 - comp4 5 - comp5\n"; $question = <STDIN>; chomp($question); } until ($question >= 1) & ($question <= 5); $question--; $computer = $pc[$question];

Any advice is certainly appreciated. Thanks in advance.

Comment on Trouble Creating a Menu
Download Code
Re: Trouble Creating a Menu
by Anonymous Monk on Aug 12, 2012 at 16:53 UTC
    Your problem may be from system("clear");

    But anyway, to create a question menu, I truly recommend the Term::UI module:
    use Term::UI; my $term = Term::ReadLine->new('brand'); my @pc = qw(comp1 comp2 comp3 comp4 comp5); my $reply = $term->get_reply( prompt => 'Which computer would you like + to cold start? ', choices => \@pc, default => 'none', );
Re: Trouble Creating a Menu
by BillKSmith (Chaplain) on Aug 12, 2012 at 17:03 UTC

    Works fine for me using perl 5.8.8 on window XP. (I did have to change the "clear" command to "cls".)

    I recommend using a prompt module such as IO::Prompt

Re: Trouble Creating a Menu
by zentara (Archbishop) on Aug 12, 2012 at 17:04 UTC
    Your script works for me. Maybe the addition of a bit of code will help you see what is happening at the end of the script. You need to remember that STDIN is line buffered, so if you select 2 for example, you still need to hit a Return for it to be read by $question = <STDIN>;

    If you want single key responses, see Re: Using File::Tail::select with STDIN? , where you don't need the Return key to capture a keystroke.

    #!/usr/bin/perl -w use strict; my $question; my $computer; my @pc = qw(comp1 comp2 comp3 comp4 comp5); # Find out which computer to cold start system("clear"); do { print "Which computer would you like to cold start?\n"; print "1 - comp1 2 - comp2 3 - comp3 4 - comp4 5 - comp5\n"; $question = <STDIN>; chomp($question); } until ($question >= 1) & ($question <= 5); $question--; $computer = $pc[$question]; print "$computer\n"; print "Hit Return to continue\n"; <>; # wait for a newline

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Trouble Creating a Menu
by xyzzy (Pilgrim) on Aug 12, 2012 at 17:10 UTC

    This has nothing to do with your problem, but you might want to use a HEREDOC for your menu, like so:

    do { print <<END; Which computer would you like to cold start? 1 - comp1 2 - comp2 3 - comp3 4 - comp4 5 - comp5 END ...

    I downloaded the code as shown and it works exactly as expected. Clears the screen, shows the menu, quits on a valid selection, repeats menu on an invalide selection. Not sure what is wrong with your setup.

    Also this might not be very useful or appealing if you can't get the basic script to work, but why not make the menu procedurally generated?

    until ($question >= 1 and $question <= @pc) { print "Computer list:\n"; print "$_)\t$pc[$_-1]\n" for (1..@pc); print "Which computer would you like to cold start? "; chomp($question = <STDIN>); }

    You can move the until to the front, since $question is undef so it will always run at least once.


    $,=qq.\n.;print q.\/\/____\/.,q./\ \ / / \\.,q.    /_/__.,q..
    Happy, sober, smart: pick two.

      First of all thank you everyone for the responses and the suggestions. I've learned something today.

      In particular, thanks for the HEREDOC suggestion. It just looks a little "cleaner" to me. Also, I will try to move the "until" to the front and see if that seems to clear up my problem.

Re: Trouble Creating a Menu
by aaron_baugher (Deacon) on Aug 12, 2012 at 21:20 UTC

    perlvar says "STDOUT will typically be line buffered if output is to the terminal and block buffered otherwise." Maybe something about your circumstances has perl using block buffering on STDOUT. Try setting $|=1; to turn off buffering, and see if that helps.

    Aaron B.
    Available for small or large Perl jobs; see my home node.

Re: Trouble Creating a Menu
by Marshall (Prior) on Aug 13, 2012 at 13:29 UTC
    These command loops are tricky to write.

    I should say that I do not often write menu driven command line interfaces because they are hard to automate. The UI and process is just easier with a Unix style command.

    Perhaps here ">cold comp5" would be better than a menu choice?

    Anyway, first off, I do have a decided preference for while loops as opposed to do{...}until loops. The reason is that I like to see the loop ending condition at the front of the loop. But there is no real issue with using a do loop.

    I guess the general "rules" are:
    1) prompt the user in a clear way.
    2) ignore completely any leading or trailing spaces.
    3) a blank line is just a re-prompt (not an error).
    4) protect the user from "faults" - if 0 is not allowed then that is an error input - error message and reprompt.
    5) With a menu, have a clear way for the user to "quit" without going to the extreme of the CTRL-C.
    6) Quality of error messages vary widely - application specific. There can be a lot of time spent on this. How much depends
    upon who your users are. Same thing for help messages, etc.

    Here is another way to write this menu loop:

    #!/usr/bin/perl -w use strict; my $computer; my @pcs = qw(comp1 comp2 comp3 comp4 comp5); while ( $computer = prompt4number(@pcs), $computer !~/^\s*(Q|quit|exit)\s*$/i) { next if $computer =~ /^\s$/; #simple re-prompt on blank lines if( $computer !~ /^\s*\d\s*$/ or $computer>@pcs or $computer == 0) { print "Illegal Entry -- try again!\n\n"; next; } print "OK - cold starting $pcs[$computer-1]\n"; exit(0); } print "Program would just exit ...\n"; sub prompt4number { my @pc = @_; print "\nWhich computer would you like to cold start?\n"; my $menu =1; print $menu++, " - $_\n" foreach @pc; print "enter Q|q|quit|exit to stop this program!\n"; return <STDIN>; } __END__

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (18)
As of 2014-12-18 14:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

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





    Results (56 votes), past polls