65

I'm looking to create a terminal-based environment to adapt my Bash script into. I want it to look like this:

Debian install

Peter Mortensen
  • 1,029
  • 1
  • 8
  • 10
  • 4
    Look into `dialog`, which is what this appears to use. – DopeGhoti May 26 '16 at 21:39
  • See also my older question [Why doesn't `dialog` display the menu (but accepts acceptance) when started through a command substitution expression?](http://unix.stackexchange.com/q/166211/2465) – user May 27 '16 at 13:35
  • I think a terminal-based GUI is a TUI (which is different from CLI). –  May 28 '16 at 06:21
  • "tui" is a RH term IIRC. `whiptail` > `dialog` also – Bratchley May 28 '16 at 14:45
  • @Bratchley: [GDB also uses `tui` for its split-window mode](https://sourceware.org/gdb/onlinedocs/gdb/TUI-Commands.html) (showing registers, source, and commands with `layout reg` for example, and `tui reg vec` to show vector registers in the reg window (in a not-flexible way, so that part's not really useful :/). IDK if Redhat wrote the patch that added that feature, or even how old it is. – Peter Cordes May 29 '16 at 04:21
  • You could have checked what program was producing that output by using `pstree` or similar, to see the ultimate child process. Or see what processes have that specific tty open. That would narrow it down to a few, and you could then check their man pages to find that `whiptail` was doing it. There's probably a way to find what process is in the foreground on a given terminal, but I don't know it. – Peter Cordes May 29 '16 at 04:27

4 Answers4

51
dialog --backtitle "Package configuration" \
       --title "Configuration sun-java-jre" \
       --yesno "\nBla bla bla...\n\nDo you accept?" 10 30

enter image description here

The user response is stored in the exit code, so can be printed as usual: echo $? (note that 0 means "yes", and 1 is "no" in the shell world).


Concerning other questions from the comment section:

  • to put into the dialog box the output from some command just use command substitution mechanism $(), eg:

     dialog --backtitle "$(echo abc)" --title "$(cat file)" ...
    
  • to give user multiple choices you can use --menu option instead of --yesno

  • to store the output of the user choice into variable one needs to use --stdout option or change output descriptor either via --output-fd or manually, e.g.:

    output=$(dialog --backtitle "Package configuration" \
                    --title "Configuration sun-java-jre" \
                    --menu "$(parted -l)" 15 40 4 1 "sda1" 2 "sda2" 3 "sda3" \
             3>&1 1>&2 2>&3 3>&-)
    echo "$output"
    

    This trick is needed because dialog by default outputs to stderr, not stdout.

And as always, man dialog is your friend.

jimmij
  • 46,064
  • 19
  • 123
  • 136
  • thats beautiful "Bla bla bla..." but how do you capture the output? – tempforFind Me In The Woods May 26 '16 at 23:17
  • 1
    @tempforFindMeInTheWoods if by output you mean exit code, then just as usuall: it is stored inside `?` variable, try `echo $?`. – jimmij May 26 '16 at 23:21
  • oh ok that makes sense – tempforFind Me In The Woods May 26 '16 at 23:28
  • now is there a way to output a code block (ex `parted -l`) into the little block? I see the option "--programbox" but nothing is happening – tempforFind Me In The Woods May 26 '16 at 23:40
  • @tempforFindMeInTheWoods Into which "little block" do you want to output that `parted -l`? Sorry, but I don't understand what you are trying to achieve. – jimmij May 26 '16 at 23:54
  • just the dialog. Pardon my confusing english. I need `parted -l` to be displayed and then I can put in code somehow to capture a user entry of a letter (/dev/sd?). – tempforFind Me In The Woods May 27 '16 at 00:01
  • 1
    @tempforFindMeInTheWoods If you want to present output of the command `parted -l` to the user via dialog box then probably option `--menu` is a better choice instead of `-yesno`. In such case you would have to play a bit with descriptors to store output into the variable, for example: `output=$(dialog --backtitle "Package configuration" --title "Configuration sun-java-jre" --menu "$(parted -l)" 15 40 4 1 "sda1" 2 "sda2" 3 "sda3" 3>&1 1>&2 2>&3 3>&-); echo $output` – jimmij May 27 '16 at 00:29
  • 3
    Or, you could use the `--stdout` option. – Thomas Dickey May 27 '16 at 00:45
  • 2
    All dialog options are explained in the manual: `man dialog` – Ferrybig May 27 '16 at 08:48
  • As a note to others, remember to *avoid* launching the shell script with the `-e` option, as this will cause your scripts to automatically exit with a "failure" as soon as `dialog`, `whiptail`, etc. returns a non-zero exit code, which in their case is used to tell you what the user's selection was (e.g. `yes/ok=0`, `no/cancel=1`, `ESC key=255`) rather than communicating success or failure. – code_dredd Jun 22 '18 at 21:52
37

The screenshot in the question looks like whiptail (a functionally-reduced program imitating dialog, using newt rather than ncurses). The way the title and buttons are rendered is built into each program, making them look different.

Here is a script which duplicates the original screenshot, for either whiptail or dialog:

#!/bin/sh
: ${DIALOG:=dialog}
case "$DIALOG" in
*dialog*)
        OPTS="$OPTS --cr-wrap"
        high=10
        ;;
*whiptail*)
        high=12
        ;;
esac
rows=$(stty size | cut -d' ' -f1)
[ -z "$rows" ] && rows=$high
[ $rows -gt $high ] && rows=$high
cols=$(stty size | cut -d' ' -f2)
$DIALOG --backtitle "Package configuration" \
       --title "Configuring sun-java6-jre" \
       $OPTS \
       --yesno '\nIn order to install this package, you must accept the license terms, the "Operating System Distributor License for Java" (DLJ), v1.1. Not accepting will cancel the installation.\n\nDo you accept the DLJ license terms?' $rows $((cols - 5))

and for comparison, screenshot with whiptail:

screenshot with whiptail

and with dialog:

screenshot with dialog

Besides the different appearance of the title and buttons, dialog uses different colors by default (though that is configurable—see screenshots), and it uses fewer lines on the screen.

dialog (and whiptail) use libraries for managing the display of lines, colors, etc. But you may also see newt used in Red Hat anaconda program as a shared library called from python (with the same appearance). Along the same lines, the kernel configuration program started as a (cut-down) copy of dialog, and then evolved into features using a shared library (without the original lxdialog program) much like the way newt is used from python.

From bash — you could use either dialog or whiptail for the most commonly-used features. Someone wrote a wrapper for those (in perl) to allow scripts to more readily use either those or a few others, but you're better off using dialog directly since the perl module is essentially common-denominator.

The dialog sources include examples of all of the widgets along with most of the command-line options:

cdialog (ComeOn Dialog!) version 1.3-20160424
Copyright 2000-2015,2016 Thomas E. Dickey
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

* Display dialog boxes from shell scripts *

Usage: cdialog <options> { --and-widget <options> }
where options are "common" options, followed by "box" options

Special options:
  [--create-rc "file"]
Common options:
  [--ascii-lines] [--aspect <ratio>] [--backtitle <backtitle>] [--beep]
  [--beep-after] [--begin <y> <x>] [--cancel-label <str>] [--clear]
  [--colors] [--column-separator <str>] [--cr-wrap] [--date-format <str>]
  [--default-button <str>] [--default-item <str>] [--defaultno]
  [--exit-label <str>] [--extra-button] [--extra-label <str>]
  [--help-button] [--help-label <str>] [--help-status] [--help-tags]
  [--hfile <str>] [--hline <str>] [--ignore] [--input-fd <fd>]
  [--insecure] [--item-help] [--keep-tite] [--keep-window] [--last-key]
  [--max-input <n>] [--no-cancel] [--no-collapse] [--no-cr-wrap]
  [--no-items] [--no-kill] [--no-label <str>] [--no-lines] [--no-mouse]
  [--no-nl-expand] [--no-ok] [--no-shadow] [--no-tags] [--nook]
  [--ok-label <str>] [--output-fd <fd>] [--output-separator <str>]
  [--print-maxsize] [--print-size] [--print-version] [--quoted]
  [--scrollbar] [--separate-output] [--separate-widget <str>] [--shadow]
  [--single-quoted] [--size-err] [--sleep <secs>] [--stderr] [--stdout]
  [--tab-correct] [--tab-len <n>] [--time-format <str>] [--timeout <secs>]
  [--title <title>] [--trace <file>] [--trim] [--version] [--visit-items]
  [--week-start <str>] [--yes-label <str>]
Box options:
  --buildlist    <text> <height> <width> <list-height> <tag1> <item1> <status1>...
  --calendar     <text> <height> <width> <day> <month> <year>
  --checklist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
  --dselect      <directory> <height> <width>
  --editbox      <file> <height> <width>
  --form         <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>...
  --fselect      <filepath> <height> <width>
  --gauge        <text> <height> <width> [<percent>]
  --infobox      <text> <height> <width>
  --inputbox     <text> <height> <width> [<init>]
  --inputmenu    <text> <height> <width> <menu height> <tag1> <item1>...
  --menu         <text> <height> <width> <menu height> <tag1> <item1>...
  --mixedform    <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1> <itype>...
  --mixedgauge   <text> <height> <width> <percent> <tag1> <item1>...
  --msgbox       <text> <height> <width>
  --passwordbox  <text> <height> <width> [<init>]
  --passwordform <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>...
  --pause        <text> <height> <width> <seconds>
  --prgbox       <text> <command> <height> <width>
  --programbox   <text> <height> <width>
  --progressbox  <text> <height> <width>
  --radiolist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
  --rangebox     <text> <height> <width> <min-value> <max-value> <default-value>
  --tailbox      <file> <height> <width>
  --tailboxbg    <file> <height> <width>
  --textbox      <file> <height> <width>
  --timebox      <text> <height> <width> <hour> <minute> <second>
  --treeview     <text> <height> <width> <list-height> <tag1> <item1> <status1> <depth1>...
  --yesno        <text> <height> <width>

Auto-size with height and width = 0. Maximize with height and width = -1.
Global-auto-size if also menu_height/list_height = 0.

Further reading:

Thomas Dickey
  • 75,040
  • 9
  • 171
  • 268
14

I believe the package you are looking for is ncurses.

Wikipedia describes ncurses as follows:

ncurses (new curses) is a programming library providing an API that allows the programmer to write text-based user interfaces in a terminal-independent manner. It is a toolkit for developing "GUI-like" application software that runs under a terminal emulator

It is widely used, for example, in the menuconfig kernel configuration tool: Screen shot of Linux kernel menuconfig tool

Since you are using bash, you can use Bash Simple Curses (as mentioned by Runium in the comment below).

Thawn
  • 992
  • 6
  • 13
  • 12
    `ncurses` is a C-library. (If I understand correctly) OP wants a *scripting* environment (for bash). `menuconfig` is written in C. As an alternative to `dialog`, as per other answer, you could perhaps mention [Bash Simple Curses](https://github.com/metal3d/bashsimplecurses) which is written in bash (relying on `tput`). – Runium May 26 '16 at 22:23
  • @Runium: Thanks for the clarification and the link to Bash Simple Curses. – Thawn May 27 '16 at 06:09
  • 2
    still, it was useful to mention that `ncurses` is the basis of this, and it answers a more general version of the question... like the one in the title here :) – underscore_d May 28 '16 at 18:49
0

zenity

zenity --file-selection --directory

.

# var means variable

var\
=$(
zenity --entry                   \
       --title="title"           \
       --text="text"             \
       --entry-text="entry text" \ 
)                                \
&&
echo "$var"

zenity dialog entry with options

password=$(zenity --password)

zenity --password

file="$(zenity --file-selection)"

zenity --file-selection

# ls is a command to list files in a directory

ls $(zenity --file-selection --directory)

# Help

zenity --help

zenity --help result

zenity --help-general 

zenity --help-general result

zenity --help-entry

zenity --help-entry result

other graphical user interfaces (gui)

dialog

dialog

dialog                               \
 --backtitle "backtitle"             \
 --title "title"                     \
 --yesno                             \
 "bla bla bla...\n\n Do you accept?" \
 0 -1                                
echo $?

stops further execution of the script , breaks it . the command echo $? , will never happen

abc
  • 208
  • 2
  • 6
  • 2
    Zenity is a good idea in your desktop where you are running a terminal in graphical environment like Ubuntu but when it is not useful for servers. I think the questioner is asking for those old Windows 95 installation interfaces. – Macindows Nov 26 '19 at 06:15