Text Interfaces with Whiptail and Dialog

Text interfaces are extremely useful when an MS-Window client is trying to connect into a Linux or Raspberry Pi node.

There are some good options for creating Bash text interfaces, two of the most popular are Whiptail and Dialog. Raspberry Pi users will be familiar with Pi configuration tool, raspi-config, which uses Whiptail to create all its menu and application screens.

Whiptail comes pre-installed on Raspbian and on many Linux images. Whiptail is a lighter version of the more complete Dialog package.

This blog will show some examples using Whiptail and Dialog.

Getting Started

For my work I preferred using Dialog, I found that it had many more options and a slightly easier interface than Whiptail. However for projects where I needed to distribute my code to other users or nodes I would keep things simple and use Whiptail.

To install Whiptail and Dialog on a Raspbian/Debian/Ubuntu:

sudo apt install whiptail
sudo apt install dialog

A simple Whiptail test to show the date/time in a message box:

whiptail --title "Time/Date" --msgbox  "$(date)" 0 0

This statement will clear the terminal screen and show a default background with message box centered in the window. A height and width of : 0 0 will autosize the message box.

Refreshing YESNO Dialog

A message box only has a single OK button. A yesno dialog has two button.

Whiptail only supports a basic yesno function. The Dialog utility supports changing the button labels and a timeout so the window can be automatically refreshed.

Below is an example that refreshed an yesno dialog every 5 seconds. The show_dlg function generates a random temperature and humidity valid, and then calls the dialog utility. The YES button, relabelled as “Refresh”, will manually force a refresh of the data and redraw the window. The NO button, relabelled as “Cancel” will close the script and clear the screen.

#!/usr/bin/bash
#
# dyesno.sh - A freshing yes/no dialog with simulated sensor data

YES=0
TIMEOUT=255

show_dlg() {  
   # simulate some data
   data1="Temperature: $(( ( RANDOM % 10 )  + 20 )) C";   
   data2="Humidity: $(( ( RANDOM % 10 )  + 30 )) %";   
   message="$data1\n\n$data2";   
   dialog --begin 2 2 --backtitle "Raspberry Pi Data - $(date +'%T' )" \
       --yes-label "Refresh" --no-label "Cancel" --timeout 5 \
       --title "DHT11 Sensor Results" --yesno  "$message" 8 30; 
} 

response=0
# Cycle is the response is YES button or the dialog timed out
while [ "$response" == "$YES" ] || [ "$response" == "$TIMEOUT" ]; do
  show_dlg
  response=$? ;# Get the output from the yesno dialog
done
clear

Radio Dialog to Toggle Pi GPIO Pins

A radio dialog allows a user to select one option from a list.

For this example I’m using 3 GPIO pins (0, 2, and 7) and the user can select one of these pins and toggle the output using the Raspberry Pi gpio utility.

The Dialog utility will output the item selected (0, 2 or 7), and the OK/Cancel button code (0=OK,1=Cancel).

#!/usr/bin/bash
#
# dradio1.sh - toggle a GPIO output pin
#
thepin=$(dialog --begin 2 2 --title "Toggle GPIO Pins" \
     --backtitle "Raspberry PI GPIO" --stdout \
     --radiolist "Select Pin:" 10 40 3 \
      0 "GPIO_0 - physical pin 11" off \
      2 "GPIO_2 - physical pin 13" off \
      7 "GPIO_7 - physical pin 7 " off )
clear
# Toggle if OK entered and a pin is selected
if [ "$?" == "0" ] && (( ${#thepin} > 0 )) ; then
  echo "Toggling (wPi) pin: $thepin"
  gpio toggle $thepin
  echo "Pin $thepin is: $(gpio read $thepin)"
fi   

Weather Station Form

A Form dialog can be used text with captions and allow user input to saved. Below is an example of a Weather station with view only and editable data.

#!/usr/bin/bash
#
# dform1.sh - Form to show data, and allow data entry

# Weather Sensor inputs (connect real inputs here)
wspeed="5 kph"
wdir="NW (350)"
wtemp="11 C"

# Show a dialog with viewonly and data entry values, save to a file
dialog --begin 2 2 --ok-label "Save" --backtitle "Pi Weather Station" \
     --title "North Beach" --stdout  \
     --form  "Data at : $(date +'%T' )"  12 65 0 \
	"Wind Speed :"      1 1 "$wspeed"  1 30 0 0 \
	"Wind Direction:"   2 1 "$wdir"    2 30 0 0 \
	"Water Temp:"       3 1 "$wtemp"   3 30 0 0 \
	"Beach Conditions:" 4 1 ""  	   4 30 30 30 \
	"Wildlife:"         5 1 ""  	   5 30 30 30 > beach.txt     
clear

The syntax for the form is:

--form text height width formheight [ label y x item y x flen ilen ]

where: y = line position
       x = position in line
    item = view only or editable data
    flen = field length , 0 = view only
    ilen = input length , 0 = view only

For this example the last 2 items (Beach Conditions and Wildlife) have a field and input length defined to 30 characters so data can be entered into these fields. If the OK button is selected the user entered data is saved to the file beach.txt.

Menu Example

Menuing applications are probably the most useful feature in the Whiptail and Dialog utilities.

Below is an System Information application, that has 3 options: node, disk space, and memory stats. Each of the menu items call a display_dialog function that presents the results of a Bash statement in a message box.

#!/bin/bash
#
# dmenu.sh - Bash Dialog Menu showing some system stats
#

# Display menu results in a msgbox
display_result() {
  dialog --title "$1" \
    --backtitle "System Information" \
    --no-collapse \
    --msgbox "$result" 0 0
}

while true; do
  selection=$(dialog --stdout \
    --backtitle "System Information" \
    --title "Key Features" \
    --clear \
    --cancel-label "Exit" \
    --menu "Please select:" 0 0 4 \
    "1" "Display Node Information" \
    "2" "Display Disk Space" \
    "3" "Display Memory Stats" \
     )
  exit_status=$?
  if [ $exit_status == 1 ] ; then
      clear
      exit
  fi
  case $selection in
    1 )
      result=$(echo "Hostname: $HOSTNAME"; uptime)
      display_result "System Information"
      ;;
    2 )
      result=$(df -h)
      display_result "Disk Space"
      ;;
    3 )
      result=$(vmstat --stats)
      display_result "Memory Stats"
      ;;
  esac
done

Changing Whiptail Default Colors

Whiptail uses the newt graphic library. A NEWT_COLORS variable can be created with custom colors. An example would be:

export NEWT_COLORS='
  window=,red
  border=white,red
  textbox=white,red
  button=black,white'
# to reset the color back to default use:
# unset NEWT_COLORS

A full definition of all the options and colors:

root                  root fg, bg
border                border fg, bg
window                window fg, bg
shadow                shadow fg, bg
title                 title fg, bg
button                button fg, bg
actbutton             active button fg, bg
checkbox              checkbox fg, bg
actcheckbox           active checkbox fg, bg
entry                 entry box fg, bg
label                 label fg, bg
listbox               listbox fg, bg
actlistbox            active listbox fg, bg
textbox               textbox fg, bg
acttextbox            active textbox fg, bg
helpline              help line
roottext              root text
emptyscale            scale full
fullscale             scale empty
disentry              disabled entry fg, bg
compactbutton         compact button fg, bg
actsellistbox         active & sel listbox
sellistbox            selected listbox

bg and fg can be:

color0  or black
color1  or red
color2  or green
color3  or brown
color4  or blue
color5  or magenta
color6  or cyan
color7  or lightgray
color8  or gray
color9  or brightred
color10 or brightgreen
color11 or yellow
color12 or brightblue
color13 or brightmagenta
color14 or brightcyan
color15 or white

Changing Default Dialog Colors

The custom Dialog colors are defined in the file: ~/.dialogrc

To create and edit this file:

dialog --create-rc  ~/.dialogrc
nano $HOME/.dialogrc

Within the ~/.dialogrc file, an important option is:

# Shadow dialog boxes? This also turns on color.
use_shadow = OFF

Dialog supports inline color (this isn’t supported in Whiptail) with the –colors option. Inline colors are defined with by “/Zx”:

ANSI colors:

/Z0 = black
/Z1 = red
/Z2 = green
/Z3 = yellow
/Z4 = blue
/Z5 = magenta
/Z6 = cyan
/Z7 = white

Other options:

/Zb = bold, /ZB = reset bold
/Zr = reverse, /ZR = reset reverse
/Zu = underline, /ZU = reset underline
/Zn = restore settings to normal

An example:

$ msg="Temperature: \Zb\Z3 28 \Zn Deg C"
$ dialog --title "Outside" --colors --msgbox  "$msg" 0 0 ; clear

Final Comments

I’m a big fan of Zenity and YAD X-Window dialog tools, and I found that it wasn’t a big transition to use Whiptail and Dialog.

It’s important to note that the Dialog option –stdout is needed if you want to pass the Dialog output to a variable. Passing the output from Whiptail is a little trickier, use: 3>&2 2>&1 1>&3

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s