Here's a little subroutine I find quite handy when writing configuration scripts (or anything that needs to prompt for values from the shell). It lets you provide a prompt string and default arguments, and also lets you force the user to choose from a default list of args.

Example:

my @choices = ("yes", "no", "y", "n"); my $choice = query("Can you use an array for the choices?", "YES", @ch +oices); my $otherChoice = query("Can you use an invalid default to force them +to type in their choice?", "yes/no", "yes", "y"); my $finalChoice = query("Oh, just enter whatever you want.");

Hope you find this useful. ;)

Edit: Changed to a while(1) loop, and checked $_[0] on advice of q[uri] in efnet #perl
Edit2: Ditched array and used named scalars instead for clarity, also took a couple clues from Jeffa++ (grep/chomp directly). Now you can supply a null default and it will work. ;) Unless you supply a list of choices of course.
# &query(Prompt String, optional default, optional list of restrictive + choices) # If the choices are provided at the end, only one of those can be ch +osen. # This is currently case insensitive. # # Example: my $val = query("Do you like config scripts?", "yes", "yes" +, "no", "y", "n"); # Will print: Do you like config scripts? [yes]: # The user can either press enter for yes, or enter one of the other a +rguments. sub query { my $prompt = (defined $_[0]) ? $_[0] : ""; my $default = (defined $_[1]) ? $_[1] : ""; my $answer; while(1) { print "$prompt [$default]: "; chomp($answer = <STDIN>); $answer = $default if ($answer eq ""); last unless $#_ > 1; last if grep $answer =~ /^\Q$_\E$/i, @_[2 .. $#_]; } return $answer; }

Replies are listed 'Best First'.
(jeffa) Re: Prompting via shell with default arguments
by jeffa (Bishop) on Feb 02, 2003 at 01:18 UTC
    This (hopefully) has the same functionality as your code, with the execption of allowing the user of submitting nothing when there are no default arguments supplied by the programmer. (gotta love Carter's Compass! ok, ok, i just moved the return out of the loop)
    sub query { my ($str,@argv) = @_; my $answer; while (1) { print "$str ", $argv[0] ? "[$argv[0]]: " : ": "; chomp($answer = <STDIN>); last unless @argv; last if grep $answer =~ /^\Q$_\E$/i, @argv; } return $answer; }
    I feel inclined to replace the regular expression used in that grep to
    last if grep $answer eq $_, @argv;
    ... i see no need to use a regex if you have to match the entire string.

    UPDATE:
    Ahhh, i missed that you were allowing case insensitive answers via the regex. Here is another version that uses lc to match upper and lower cases. This code also fullfills the requirement of allowing the user to pick a default option. I missed that one the first time around ;)

    sub query2 { my ($str,@argv) = @_; my $answer; while (1) { print "$str ", $argv[0] ? "[$argv[0]]: " : ": "; chomp($answer = <STDIN>); return $answer if !@argv or grep lc($answer) eq lc($_), @argv; return $argv[0] unless $answer; } }
    I also noticed you changed your original code. It looks much better now, but you should replace
    $answer = $default if ($answer eq ""); # with this instead $answer ||= $default;

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Ahh, can't believe I didn't even think of using grep (although I did write this code a while ago). Also, that well-placed last does the trick of a null default argument nicely. But, as far as the regexp on the grep goes, I guess that's up to the behavior you want. I typically make it case insensitive, but if you didn't want that, the eq would work fine of course.

      The only other difference is the behavior on them using the default option I believe. In yours, it will treat the supplied default as one of the restricted arguments. I just wanted to be able to have a suggested argument that wasn't required (like a possible path to a file).

      Thanks for the reply. ;)

      ----------------
      BP - DG - WB
      If I were to use the following to check for a default answer:

      $answer ||= $default;

      That will likely not differentiate if the user were to enter an equivalent "false" value (like "0"). Which may not be desired behavior depending on what the question was. Also, is using the two lc()'s more efficient then the regexp? (Not that speed is a big factor in this situation)

      And don't forget if someone wants to do:

      query("Make a decision!", "yes/no", @choices); #see snippet for @choices

      Although that could be easily done in the prompt string. :D

      ----------------
      BP - DG - WB