How to use ncurses widgets in shell scripts on Linux

In this tutorial we will learn the basics of the dialog utility, in order to use ncurses widget in our shell scripts. We will see how to install dialog in the most used Linux distributions, some of the common options we can use to alter the behavior of dialog, how to use some widgets; among the others: inputbox, checklist, radiolist and yesno. Finally, we will see how to use the data obtained by the widget processing.

In this tutorial you will learn:

  • How to install the dialog utility on Linux
  • What are the most relevant dialog options
  • How to use the inputbox, checklist, radiolist, passwordbox, msbox, calendar and yesno widgets
  • How to manage data derived from the widget processing

Software Requirements and Conventions Used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution-independent
Software The dialog utility is needed to follow this tutorial
Other Familiarity with the command line interface and shell redirections
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

Installation on Linux

The dialog utility is available in all the major Linux distributions default repositories, therefore we can use our favorite package manager to install it. If we are  using Fedora, for example, we can run:



$ sudo dnf install dialog

On Debian we can run:

$ sudo apt-get install dialog

The dialog utility is also contained in the Archlinux core repository, so we can install it via pacman:

$ sudo pacman -S dialog

Installing commands applies also to derivatives of the distributions mentioned above.

Common dialog options

We call this options “common” because they can be used independently of the type of widget we want to use. Here we will just see some of them, the ones which may be of immediate interest when we start using dialog.

Settings a widget box title: the –title option

By using the --title option we can specify a string which will be used as the widget title; it will be displayed at the top of the box. Here is an example:

$ dialog --title "Dialog title" --inputbox "Enter your name:" 0 0

Here is what is displayed as the result of the command above:



Combining widgets: the –and-widget option:

The --and-widget option, can be used to “chain” more widgets, so that after we use the first, we are immediately prompted with the second. The chain is stopped when one of the dialogs returns a non-zero exist status. An example of its usage is:

$ dialog \
  --inputbox "Enter your name:" 0 0 \
  --and-widget --inputbox "Enter your age:" 0 0

Once we launch the command above, the first input widget used to prompt us for our name will be displayed. Once we confirm the input by clicking on the OK button, the next widget will be displayed, and we will be prompted to input our age.

Clearing the screen with the –clear option

When we use the --and-widget option the content created by one widget overrides that produced by the previous one. If the widgets don’t occupy the exact same screen space, the two contents would be mixed, and this would create a mess.

To avoid contents overlapping, we can use the --clear option; when we do, the content of a widget is erased before the next widget is displayed: only the background color is preserved.

Setting the a button as highlighted by default: the –default-button option

Depending on the widget we are using, more than one button can be displayed onscreen and by default one of them is highlighted by default, determining the default action to be performed when the user presses enter.

We can override the
widget default by using the --default-button option followed by the name of the button, one among ok, yes, cancel, no, help or extra.



This option can be really useful, for example, when prompting for confirmation before executing a potentially
dangerous action:

$ dialog --default-button "no" --inputbox "Enter your name:" 0 0

As you can see from the screenshot, we made so that the “no” button is selected by default, so that the user should explicitly select “yes” to confirm its choice.

Setting the default selected element in a list with –default-item

When we use a checklist or a menu widget, the first element in the list of the possible choices is selected by default. By using the --default-item option and referencing an element, we can use it as an alternative default:

$ dialog --default-item 2 --checklist "Select:" 0 0 5 \
  1 "First element" off \
  2 "Second element" off \
  3 "Third element" off


As you can see, in the example above, we referenced the element by its tag, 2 in this case (we will expand on this later).

Specifying a time delay after confirmation: the –sleep option

Sometimes we may want our application to wait for a certain number of seconds after processing a dialog box. To reach this behavior we can use the --sleep option and provide the number of seconds to wait as a value:

$ dialog --sleep 3 --inputbox "Enter your name:" 0 0

As the result of the above command, after the inputbox widget is displayed, and the user hits the ENTER key, 3 seconds are waited before the next command in the calling script is performed.

Providing a choice timeout

In some cases we may want to give the user a maximum number of seconds to perform its choice. The dialog application provides the --timeout option to obtain said behavior. The number of timeout seconds must be passed as the argument of the option. If after the specified amount of seconds provided the user doesn’t perform its choice, the application will exit with an error status:

$ dialog --timeout 3 --inputbox "Enter your name:" 0 0

Setting alternative labels for buttons

The dialog utility provides a series of options to override the default label for buttons: we can use the --exit-label, --extra-label, --help-label, --no-label, --ok-label, --yes-label to change the labels of the “exit”, “extra”, “help”, “no”, “ok” and “yes” buttons, respectively.

Each of the aforementioned options take a string as argument, which is use as the button label. Here is an example of the option usage:

$ dialog --default-button "no" \
  --no-label "I don't" \
  --yes-label "I do" \
  --yesno "Do you really want to format the partition?" 0 0

The above command will produce the following result:



Dialog widgets

Until now we saw some of the most useful dialog “common” options. Now we will see how to use some of the available widgets in details. Before proceeding, we must specify the general syntax. When we launch a dialog we must always provide three parameters:

  1. The text to be displayed in the widget;
  2. The widget width;
  3. The widget height;

If we provide a value of 0 for width or height, the value of the corresponding attribute is set automatically.

The inputbox widget

The inputbox widget is used to prompt the user to respond to a question with a textual input. The text parameter is used to provide the question: if the string is longer than the dialog box, the latter will become scrollable. To use this widget we invoke dialog with the --inputbox option:

On exit, the input provided by the user is displayed on dialog output, which by default is stderr.

The checklist widget

We already saw how the checklist widget looks like in previous examples: in this type of widget a series of choices are provided to the user which can select one or more of them. To use this widget we must use the --checklist option, and, in addition to the standard three parameters which must be passed to all widgets, we must provide also the list-height and the choices to be displayed.



The line-height parameter is used to set how many lines should be displayed at once: if the numbers of lines is less than the available choices, the menu will become scrollable. If we provide 0 as the value of line-height the number of lines will correspond to the number of choices.

For each choice we must provide an identifier (tag), a name and a status which can be off or on. If the status is on the choice will be checked by default. Once we confirm our choices the tags related to the entry we checked will be displayed on stderr:

$ dialog --checklist "Select items:" 0 0 0 \
  1 "Choice number one" off \
  2 "Choice number two" on \
  3 "Choice number three" off \
  4 "Choice number four" on

With the command above we launched the menu with 4 options, and set options 2 and 4 checked by default. The output of the command is the following:

The radiolist widget

The radiolist widget is launched when dialog is invoked with the --radiolist option. It works similarly to the checklist widget, with the difference that choices are mutually exclusive, so only one element can be selected. Here is how we use the widget:

$ dialog --radiolist "Select items:" 0 0 0 \
  1 "Choice number one" Off \
  2 "Choice number two" on \
  3 "Choice number three" off \
  4 "Choice number four" Off

Since the choices are mutually exclusive, only the first option set to On will selected as a default.



Ask the user for a password using the passwordbox widget

The passwordbox widget is used to let prompt a user to enter a password. For security reasons, the text entered by the user is not displayed. This behavior can be modified by using the --insecure option: if we do, the widget will display an asterisk for each letter of the password entered in the corresponding field.

We use the widget by launching dialog with the --passwordbox option:

$ dialog --insecure --passwordbox "Enter your password:" 0 0

The output of the command above is:

Displaying a message with the msgbox widget

The usage of this widget is really simple: it is invoked by calling dialog with the --msgbox option and displays a message which is the content of the text parameter. A single OK button is displayed:

$ dialog --msgbox "This is a very important message that should be read carefully!" 0 0


The calendar widget

We can use the calendar widget by invoking the dialog utility with the --calendar option. The widget let us select a date by choosing month, day and year which are displayed in separate sections of the widget. It is possible to provide a default date by passing it as part of the command.

To start the widget with the “fifth day of May of the year 2020” as the default date, for example, we would run the following command:

$ dialog --calendar "Select a date:" 0 0 27 05 2020

It will produce the following output:



We can move between the widget sections using the TAB key, and change parameters by using the arrow keys. Once we confirm the selection, it is displayed to stderr in the format day/month/year; this can be modified by using the --date-format option with a format compatible with strftime specified as argument. To make the output in the format year/month/day, for example, we would run:

$ dialog --date-format %Y/%m/%d --calendar "Select a date" 0 0 27 05 2020

Prompt the user for confirmation: the yesno widget

We already encountered this widget: it let us prompt the user for confirmation. When using it, we specify the question to be asked via the text parameter. Depending on the user choice an exit status is returned: 0 if the user confirms by clicking on the Yes button, 1 otherwise.

To invoke this widget we must use the --yesno option:

$ dialog --yesno "Do you confirm?" 0 0

Here is the widget:

Managing the output produced by a widget

By default, the output produced by a widget is displayed on stderr, so for example, to store the data obtained from a widget to a file, all we have to do is redirect stderr to said file (if you are not familiar with redirections you may want to take a look at Introduction to bash shell redirections tutorial):

$ dialog --checklist "Select items:" 0 0 0 \
  1 "Choice number one" off \
  2 "Choice number two" on \
  3 "Choice number three" off \
  4 "Choice number four" on 2> choice.txt

Once the user confirms its choices, they will be written, space-separated into the choice.txt file.

What if we want to store the selection directly into a variable? To accomplish the task we must use the --stdout option, so that the output of the widget is displayed on stdin instead of stderr:

$ choices="$(dialog --stdout --checklist "Select items:" 0 0 0 \
  1 "Choice number one" off \
  2 "Choice number two" on \
  3 "Choice number three" off \
  4 "Choice number four" on)"


In the example above, the result of the widget processing, will be accessible via the choices variable. Perhaps we may want to loop over them:

$ for choice in ${choices}; do echo "${choice}"; done
2
4

To manage the process of the yesno widget we must behave differently. Said widget, as we already saw, doesn’t produce any output but changes the exit code of the command used to dislay it accordingly to the user choice. If the user confirms, and answers affirmatively to the question, the exit code is set to 0, otherwise to 1 (this may seem odd, but remember that 0 means OK while 1 is an exit status that means that a command was not succesfull). Knowing this we can write something like:

if dialog --yesno "Do you want to open an instance of gnome-terminal ?" 0 0; then
  clear
  gnome-terminal
fi

Conclusions

In this tutorial we saw how we can use the dialog application to use ncurses widget in shell scripts. First we saw some common options which can be used independently of the widget type, than we took a look at some widgets specifically. There are many more widgets that can be used with dialog: for a complete list I suggest you to take a look at the application manual.



Comments and Discussions
Linux Forum