[Linuxcommand-announce] [LinuxCommand.org: Tips, News And Rants] dialog
Brought to you by:
bshotts
|
From: William S. <bs...@pa...> - 2010-03-01 05:25:48
|
Now that we have covered launching a script from the GUI, it's time to
look at how to make our scripts a little more "graphical."
Interestingly, there are a number of tools that we can use to produce
user interfaces for shell scripts. In this installment, we will
concentrate on the most mature of these tools, dialog.
The dialog program lets scripts display dialog boxes for user
interaction. It does this in a text-based manner, using the ncurses
library. It can produce a variety of user interface elements and can
pass user input back to a script for processing. The dialog package is
not installed by default on most Linux distributions, but is readily
available in most distribution repositories.
dialog has been around for a long time and has gone through a number of
incarnations. The current version (which is maintained by the Debian
project) contains a number of features not found in earlier versions.
To demonstrate a few of the powers of dialog, we will write a script
that displays a series of dialog boxes and provide some ideas of how to
work with the output. We'll start the script with the following code:
#!/bin/bash
# dialog-demo: script to demonstrate the dialog utility
BACKTITLE="Dialog Demonstration"
# message box
dialog --title "Message Box" \
--backtitle "$BACKTITLE" \
--msgbox "This is a message box which simply\
displays some text and an OK button." \
9 50
The script invokes the dialog program with a series of options to set
the title for the dialog box, the title for the background screen, the
dialog box type (in this example a message box), the text to appear in
the box and the size of the box (9 lines high by 50 characters wide).
When we run the script we get the following results:
Next we'll add the following code to the end of the script to generate
another kind of dialog called a yes/no box. In addition to the dialog
box itself, we will also include some code to act on the results of the
user's selection:
# yes/no box
dialog --title "Yes/No Box" \
--backtitle "$BACKTITLE" \
--yesno "This is a yes/no box. It has two buttons." \
9 50
# examine the exit status and act on it
case $? in
0) dialog --title "Yes" \
--backtitle "$BACKTITLE" \
--msgbox "You answered \"Yes\"" \
9 50
;;
1) dialog --title "No" \
--backtitle "$BACKTITLE" \
--msgbox "You answered \"No\"" \
9 50
;;
255) dialog --title "Esc" \
--backtitle "$BACKTITLE" \
--msgbox "You pressed Esc" \
9 50
;;
esac
The yes/no box offers the user three choices: yes, no, and a cancel
which occurs if the Esc key is pressed. To select a button, the user my
use the Tab key to switch from button to button or, if dialog is being
run inside a terminal emulator on a graphical desktop, the mouse may be
used to select a button.
dialog communicates the user's choice back to the script via its exit
status. In the code that follows the yes/no box, we evaluate the exit
status. If the yes button is pressed, the exit status is 0, if the no
button is pressed, the exit status is 1, and if Esc is pressed, the
exit status is 255.
dialog can provide more than just simple button presses. It can support
edit boxes. forms, menus, file selectors. etc. When returning more
complex data, dialog outputs its results on standard error. To
demonstrate how this works, we will insert the following code near the
beginning of the script (just after the BACKTITLE=... line) to define a
function (read_tempfile) that will display the dialog output:
TEMPFILE=/tmp/dialog-demo.$$
read_tempfile() {
# display what is returned in the temp file
local tempfile
# read file contents then delete
tempfile=$(cat $TEMPFILE)
rm $TEMPFILE
# message box to display contents
dialog --title "Tempfile Contents" \
--backtitle "$BACKTITLE" \
--msgbox "The temp file contains: $tempfile" \
0 0
}
Next, we will add the following code to the end of our script to
display a menu box:
# menu
dialog --title "Menu" \
--backtitle "$BACKTITLE" \
--menu "This is a menu. Please select one of the following:" \
15 50 10 \
1 "Item number 1" \
2 "Item number 2" \
3 "Item number 3" 2> $TEMPFILE
read_tempfile
This code displays a menu containing three items. Each item consists of
two elements; a "tag" which is returned when a choice is made and
an "item string" which describes the menu selection. In the example
code above, we see that the first menu item has the tag "1" and the
item string "Item number 1." When we execute the code, dialog displays
the following menu:
To capture and display the output of the menu, we redirect the standard
error of dialog to the file named in the constant TEMPFILE. The
read_tempfile function assigns the contents of the temporary file to a
variable (tempfile) and passes it to dialog to display in a message
box. After the menu is displayed and a selection is made by the user,
the message box appears and displays the data returned to the script.
Next, we will add a checklist dialog by adding the following code to
the end of the script.
# checklist
dialog --title "Checklist" \
--backtitle "$BACKTITLE" \
--checklist "This is a checklist. Please from the following:" \
15 50 10 \
1 "Item number 1" off \
2 "Item number 2" off \
3 "Item number 3" off 2> $TEMPFILE
read_tempfile
As we can see, this code is almost the same as the code used to create
the menu dialog. The main difference is that the items in the checklist
add a third field called "status." The value of status may be
either "on" or "off" and will determine if a selection is already
selected or deselected when the program is run:
The user may select one or more checkbox items by pressing the space
bar.
Next, we will add the following code to the end of the script to
display a file selector:
# file selector
dialog --title "File Selector" \
--backtitle "$BACKTITLE" \
--fselect ~/ 10 30 2> $TEMPFILE
read_tempfile
For the file selector, dialog is passed the base directory for the
selection (in this example the directory ~/) and the size of selector.
For this example we specify 10 files in the list and a 30 character
wide dialog.
I think the file selector is easy to code, but awkward to use. You move
around the dialog with the Tab key and select directories and files
with the space bar.
One of the more novel types of boxes provided by dialog is the "gauge"
which displays a progress bar. To try out this feature, we will add
this code to the end of the script:
# gauge
# generate a stream of integers (percent) and pipe into dialog
percent=0
while (( percent < 101 )); do
echo $percent
sleep 1
percent=$((percent + 10))
done | dialog --title "Gauge" \
--backtitle "$BACKTITLE" \
--gauge "This is a gauge. It shows a progress bar." \
0 0
The gauge dialog does not output anything, rather it accepts a stream
of integers (representing the percent of completion) via standard
input. To provide this, we create a while loop to generate the stream
of integers and pipe the results of the loop into dialog. When the
script runs, the stream of numbers causes the progress bar to advance:
Note too, that we specified the size of the dialog as 0 0. When this is
done, dialog attempts to auto-size the box to fit in the minimum
necessary space.
Finally, we'll add another of the novel dialogs, a calendar:
# calendar
dialog --title "Calendar" \
--backtitle "$BACKTITLE" \
--calendar "This is a calendar." \
0 0 \
0 0 0 2> $TEMPFILE
read_tempfile
The calendar dialog box is given a date in day month year format. If
the year is specified as zero, as it is in this example, the current
date is used. The user can then select a date and the date is returned
to the script.
This concludes our brief look at dialog. As you can imagine, dialog can
be very handy for adding improved user interfaces for those scripts
that require it. While we have covered its general themes, dialog has
many more options and features. Check out the documentation link below
for the complete story.
Further Reading
Documentation for dialog:
- http://invisible-island.net/dialog/manpage/dialog.html
Other dialog-like programs:
- http://library.gnome.org/users/zenity/stable/
- http://xdialog.free.fr/doc/index.html
--
Posted By William Shotts to LinuxCommand.org: Tips, News And Rants at
3/01/2010 12:25:00 AM |