A Perl function to prompt users during interactive command-line input

For many Unix users, Perl has replaced the Bourne shell, C shell, and Korn shell as a preferred programming language for many scripting duties and short programs.

Used as a scripting language, Perl programs often require you to prompt the user to enter some type of input. I've found that instead of writing separate "prompting" code in each of my Perl scripts, it's easier to create one prompting routine that can be used in almost all Perl programs.

In this article we'll take a look at a promptUser() function and demonstrate it's use in a short driver program.

Capabilities of the Perl promptUser() function

Before getting started, let's summarize the capabilities we want in the promptUser() function:

  • It prompts the user for input, and waits until they type their response and hit the [Enter] key.
  • It lets you specify the prompt to display to the user.
  • It lets you alternately specify a default value for the user input; this lets the user just hit the [Enter] key if they want to accept the default value.
  • When it exits, it returns either (a) the default value or (b) the user input back to the calling program, depending on what the user entered.

The blackbox view of the function

Okay, now let's take a look at the function from a "blackbox" perspective - what goes in, and what comes out. 

Example 1 - Providing only the $promptString as input

The promptUser() function accepts one or two arguments as input. The first argument is the text string that you want to use as a prompt. This can often be something like "Enter your age", or "Enter the home directory". Here's how you'd call the function in a Perl program to prompt the user to enter their home directory:

$homeDir = &promptUser("Enter the home directory");

With this code, the user would see this prompt:

Enter the home directory: _

Example 2 - Providing both the $promptString and a $defaultValue as input arguments

In a second example, suppose you're writing a Perl program to install user accounts. Assuming you already know that a user's name is fred, and the normal home directory for a user named fred would be /home/fred, you might call the promptUser() function with these two arguments:

$homeDir = &promptUser("Enter the home directory", "/home/fred");

In this example, you're providing both (a) the prompt and (b) the default value (/home/fred) to the promptUser() function. When the user sees the prompt on screen it will now look like this:

Enter the home directory [/home/fred]: _

The Perl command line input source code

Okay, now that you've seen how the promptUser function works, and what it's output looks like, let's look at the code. The source code for the promptUser function and a simple driver program is shown in Listing 1. (A driver program is often used to test functions and methods when they're first created, or when they're being debugged.) Because the source code is well-documented, we'll only discuss its key features.

#!/usr/local/bin/perl
#-------------------------------------------------------------------------#
# promptUser, a Perl subroutine to prompt a user for input.
# Copyright 2010 Alvin Alexander, http://www.devdaily.com
# This code is shared here under the 
# Creative Commons Attribution-ShareAlike Unported 3.0 license.
# See http://creativecommons.org/licenses/by-sa/3.0/ for more information.
#-------------------------------------------------------------------------#

#------------------------------------------#
#  "driver" program to test &promptUser()  #
#------------------------------------------#

$username = &promptUser("Enter the username ");
$password = &promptUser("Enter the password ");
$homeDir  = &promptUser("Enter the home directory ", "/home/$username");

print "$username, $password, $homeDir\n";


#----------------------------(  promptUser  )-----------------------------#
#                                                                         #
#  FUNCTION:	promptUser                                                #
#                                                                         #
#  PURPOSE:	Prompt the user for some type of input, and return the    #
#		input back to the calling program.                        #
#                                                                         #
#  ARGS:	$promptString - what you want to prompt the user with     #
#		$defaultValue - (optional) a default value for the prompt #
#                                                                         #
#-------------------------------------------------------------------------#

sub promptUser {

   #-------------------------------------------------------------------#
   #  two possible input arguments - $promptString, and $defaultValue  #
   #  make the input arguments local variables.                        #
   #-------------------------------------------------------------------#

   local($promptString,$defaultValue) = @_;

   #-------------------------------------------------------------------#
   #  if there is a default value, use the first print statement; if   #
   #  no default is provided, print the second string.                 #
   #-------------------------------------------------------------------#

   if ($defaultValue) {
      print $promptString, "[", $defaultValue, "]: ";
   } else {
      print $promptString, ": ";
   }

   $| = 1;               # force a flush after our print
   $_ = <STDIN>;         # get the input from STDIN (presumably the keyboard)


   #------------------------------------------------------------------#
   # remove the newline character from the end of the input the user  #
   # gave us.                                                         #
   #------------------------------------------------------------------#

   chomp;

   #-----------------------------------------------------------------#
   #  if we had a $default value, and the user gave us input, then   #
   #  return the input; if we had a default, and they gave us no     #
   #  no input, return the $defaultValue.                            #
   #                                                                 # 
   #  if we did not have a default value, then just return whatever  #
   #  the user gave us.  if they just hit the <enter> key,           #
   #  the calling routine will have to deal with that.               #
   #-----------------------------------------------------------------#

   if ("$defaultValue") {
      return $_ ? $_ : $defaultValue;    # return $_ if it has a value
   } else {
      return $_;
   }
}

Listing 1 (above): The promptUser function can be used to prompt users for input from many Perl programs.

The driver program is shown at the beginning of the source code. In our driver, the promptUser function is called three times - twice without a default value, and once with a default value specified.

Next comes the promptUser function. As discussed, the promptUser function accepts two arguments as input: $promptString and $defaultValue. These two values are converted to local values when they're created in the first step of the function. As we all know, this is much better than using global variables.

Next, the prompt is displayed to the user. If a $defaultValue was provided, the first print statement will be used; otherwise the second print statement will be used. (Remember that $defaultValue is treated as false if it's value is zero or null.)

Then we set the special variable $| to a non-zero value to flush the output, and then read the input from STDIN ("standard input"). Assuming that this function is used in an interactive program, STDIN will be the user's keyboard. After the data is read, the chomp function is called to remove any newline characters at the end of the user input.

At the end of the function we again check the value of $defaultValue. If a default value was provided, we check the user input. If the user just hit the [Enter] key, we return the value of $defaultValue. If the user entered some type of input, we'll return $_ instead. That's what happens in this syntax:

return $_ ? $_ : defaultValue;

Now, if a $defaultValue was not provided when this function was called, we simply return $_ to the calling program. In this case it's possible to return a null value to the calling program, so the calling program must be smart enough to deal with that possibility.