最近在寫一些純文字介面的工具,但是在操作上對非資訊人員還是不夠直覺
想知道怎麼開發類似於 BIOS 的文字操控介面,但是礙於不曉得相關的資訊
後來終於讓我查到關鍵字 Text-based user interface/TUI,然後選擇了一個看起來比較靠普的

Dialog

Linux Dialog 是可以在 Terminal 上快速建立圖形交互介面的工具,功能十分強大、方便

撰寫 Shell Script 再搭配 Dialog 可以讓人比較直覺得操作,減少操作上的不便

雖然現在比較多使用網頁進行交互操作,但是可以不必特地架設網頁伺服器,減少一些不必要的問題

安裝

看起來 Dialog 是還有持續在維護,Mac 透過 brew 安裝的版本甚至是 20200327 的版本

可見還是有許多人喜愛以這種風格呈現操作介面

1
2
3
4
brew install dialog

dialog --version
> Version: 1.3-20200327
1
2
3
4
apt-get install dialog

dialog --version
> Version 1.3-20171209
1
2
3
4
yum install dialog

dialog --version
> Version 1.2-20200523

參數

輔助

可能經常會使用的輔助參數,還有一些其他的參數可以透過手冊 dialog(1) - Linux man page 查閱

# 視窗不顯示陰影
--no-shadow
# 結束視窗後清除螢幕
--clear

# 取代按鈕字串
--ok-label <str>
--cancel-label <str>

# 額外按鈕
--extra-button
# 額外按鈕的標籤
--exit-label <str>

# 頂端顯示字串
--backtitle <backtitle>

視窗類型

可能經常會使用的視窗類型,還有一些其他的視窗可以透過手冊 dialog(1) - Linux man page 查閱

# 日曆,選擇時間
--calendar     <text> <height> <width> <day> <month> <year>
# 選項清單,選項可以進行複選
--checklist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
# 編輯視窗,編輯文檔
--editbox      <file> <height> <width>
# 表單,可以依照表格輸入
--form         <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>...
# 進度條,顯示進度資訊
--gauge        <text> <height> <width> [<percent>]
# 輸入框,用來輸入訊息
--inputbox     <text> <height> <width> [<init>]
# 選單,選擇清單
--menu         <text> <height> <width> <menu height> <tag1> <item1>...
# 訊息框,顯示資訊
--msgbox       <text> <height> <width>
# 密碼輸入框,輸入私密資訊
--passwordbox  <text> <height> <width> [<init>]
# 單選選單,只能單選一個選項
--radiolist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
# 文檔視窗,顯示文檔內容
--textbox      <file> <height> <width>
# 確認視窗,確認訊息正確與否
--yesno        <text> <height> <width>

簡易範例

MsgBox

把資訊呈現在資訊在訊息框中

1
2
# dialog --title <title> --msgbox <text> <height> <width>
dialog --title "MsgBox" --msgbox "Hello Dialog" 10 50

比較會使用到的選單視窗

1
2
3
4
# dialog --title <title> --menu <text> <height> <width> <tag1> <item1>...
dialog --title "Menu" --menu "Chooseg" 10 50 2 \
1 "Option 1" \
2 "Option 2"

ProcessBar

處理時可以顯示的進度條

1
2
# dialog --title <title> --gauge <text> <height> <width> <percent>
dialog --title "ProcessBar" --gauge "Example" 10 50 99

InputBox

輸入單一資訊的輸入框,會顯示輸入

1
2
# dialog --title <title> --inputbox <text> <height> <width>
dialog --title "InputBox" --inputbox "Input:" 10 50 

PasswordBox

輸入密碼的輸入框,不會顯示輸入

1
2
# dialog --title <title> --passwordbox <text> <height> <width>
dialog --title "PasswordBox" --passwordbox "Input:" 10 50 

Form

需要輸入一份的資料,可以透過表單

1
2
3
4
5
6
# dialog --title <title> --form <text> <height> <width> <form height> \
#<label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>... 
dialog --title "Form" --form "Example Form" 10 50 3 \
"Username:" 1 1 "" 1 15 25 0 \
"Age:" 2 1 "" 2 15 25 0 \
"Department:" 3 1 "" 3 15 25 0

YesNo

確認或取消的視窗

請幫我點廣告…NO!!

1
2
# dialog --title <title> --yesno <text> <height> <width>
dialog --title "Yes/No" --yesno "Please click on the ad" 10 50

TextBox

顯示文字檔內容

1
2
# dialog --title <title> --textbox <Filepath> <height> <width>
dialog --title "TextBox" --textbox /Users/cody/Desktop/example.txt 10 50

實際應用

透過以上的範例撰寫一個比較實際的 Shell Script

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#/bin/bash

OK=0
CANCEL=1
ESC=255
BACKTITLE="Cody Blog - Example"

Menu(){
    while :
    do {
        Selection=$(dialog --title "CodyBlog - Menu" --clear \
            --backtitle "$BACKTITLE" \
            --cancel-label "Exit" \
            --menu "Choose one" 12 45 5 \
            1 "Test 01" \
            2 "Test 02" \
            2>&1 > /dev/tty)

        result=$?
        if [ $result -eq $OK ]; then
            Select $Selection
        elif [ $result -eq $CANCEL ] || [ $result -eq $ESC ]; then
            Exit
        fi
    } done
}

Select(){
    Choice=$1

    case $Choice in
        1)  # Option 1
            Option1
            ;;
        2)  # Option 2
            Option2
            ;;
    esac
}

Option1(){
    while :
    do {
        exec 3>&1
        Input=$(dialog --title "$Title" --clear \
            --backtitle "$BACKTITLE" \
            --form "Please input:" 10 70 5  \
            "Input1:" 1  2 "" 1  14  48  0 \
            "Input2:" 2  2 "" 2  14  48  0 \
            2>&1 1>&3)
        result=$?
        exec 3>&-

        IFS=$'\n'
        Values=($Input)
        unset IFS

        if [ $result -eq $CANCEL ] || [ $result -eq $ESC ]; then
            break
        elif [ $result -eq $OK ]; then
            MsgBox "${Values[0]}" "${Values[1]}"
            if [ $result -eq $OK ]; then
                break
            fi
        fi
    } done
}

Option2(){
    while :
    do {
        Number=$(dialog --title 'Option 2' --clear \
        --backtitle "$BACKTITLE" \
        --radiolist 'Select Item:' 15 70 2 \
        1 Radiolist1 off \
        2 Radiolist2 on \
        2>&1 > /dev/tty)
        result=$?
        
        if [ $result -eq $CANCEL ] || [ $result -eq $ESC ]; then
            break
        elif [ $result -eq $OK ]; then
            MsgBox "$Number"
            break
        fi
    } done
}

MsgBox(){
    Input1=$1
    Input2=$2

    Msg="$Input1\n"
    Msg="${Msg}$Input2"

    dialog --title "MsgBox" --clear \
    --backtitle "$BACKTITLE" \
    --yesno "$Msg" 10 70

    result=$?
}

Exit(){
    clear
    echo "Program Terminated."
    exit
}

Menu

結論

第一次寫 Shell Script 寫的那麼開心,這樣的介面真的很讓人賞心悅目

而且操作起來方便許多,使用者從介面上的理解會比純文字介面的理解上可能會稍許好的多

提供給其他人使用也會更容易上手,其實只是撰寫 PPT 文件、技術文件比較好看

Ref

  1. dialog(1) - Linux man page
  2. Bash display dialog boxes
  3. Create menus and dialogs for shell scripts