Преамбула
dialog
— консольная утилита, позволяющая встраивать в ваши скрипты псевдографический интерфейс. Есть и ее графические варианты Kdialog, Xdialog, позволяющие обеспечить ваши скрипты даже полноценным оконным интерфейсом в средах X-сервера.
Как пример можно привести скрипт пакетного переименования файлов (см. на GitHub) работающий в графической среде, или пакетный менеджер Slackware pkgtool
.
pkgtool вид спереди
Утилита древняя, как копролиты динозавра, но почему-то при этом на русском довольно мало примеров в сети и нет хорошей документации, и даже официальные примеры кода не полные, да еще и удалены в некоторых пакетах и их приходится искать отдельно. Слава Ктулху, примеры свободные, потому не грех и перезалить.
Примеры на GitHub
Общий синтаксис
Общий синтаксис утилиты dialog
таков:
dialog <общие_параметры> <виджет> <параметры_виджета>
Пункт меню по умолчанию
Указание пункта меню по умолчанию возможен не только в виджете --menu
, но и в других виджетах, потому прописать его надо в параметрах, указанных до вызова конкретного виджета.
Если будет указан несуществующий пункт меню или пустая строка, к ошибке это не приведет. Будет выбран первый пункт меню.
dialog --clear --title "Default Item Test" \
--default-item "Item #2" \
--menu "Select item:" \
20 51 7 \
"Item #1" "Test Item #1" \
"Item #2" "Test Item #2" \
"Item #3" "Test Item #3" 2>"/tmp/dlgres.tmp"
Код на GitHub
Сохранение пункта меню и последующий его выбор
Минус утилиты dialog
в том, что это не связанная система меню, а все-таки отдельная утилита, и, соответственно, один вызов с другим никак не связан. Так что если в скрипте несколько меню и предусматривается возврат в основное, или блуджание по системе меню, то у пользователя может возникнуть неудобство, поскольку при возвратах автоматически будет выбран первый пункт.
Но с помощью опции --default-item
можно сделать так, чтоб при возврате в одно из меню выбирался последний выбранный пункт.
Сохранение последнего выбранного пункта меню в переменную
1. Заводим переменную для временного файла:
TEMPFILE="/tmp/dlgres.tmp"
2. И переменную для хранения пути к самой утилите dialog
:
DIALOG="dialog"
Это не обязательно, но удобно, если понадобится переделать скрипт под Xdialog
или Kdialog
3. Заводим переменную для последнего выбранного пункта:
LAST_MENU1=""
4. Само меню будем вызывать из функции menu_in_variable()
Далее внутри функции:
5. Заводим константы для кодов возврата программы dialog
:
OK_C=0 #Нажата кнопка OK в диалоговом окне
ESC_C=255 #Нажата клавиша ESC
CANCEL_C=1 #Нажата кнопка Cancel в диалоговом окне
Примечание: На самом деле с отслеживанием клавиши ESC у утилиты menu
какой-то конфликт с PuTTY, почему-то утилита завершает работу с кодом 255
не только по нажатию ESC, но и по нажатию клавиш F1..F4 Не в PuTTY это не проявляется.
5. Вызываем dialog
:
$DIALOG --clear --title "Save last selected item into variable" \
--default-item "$LAST_MENU1" \
--menu "Select:" 20 60 7 \
"Item #1" "Item 1" \
"Item #2" "Item 2" \
"Item #3" "Item 3" 2>"$TEMPFILE"
Примечание: dialog
записывает в stderr
выбранный элемент меню (в случае виджета --menu
), потому перенаправляем вывод на stderr
во временный файл, путь к которому указан в переменной $TEMPFILE
(2>"$TEMPFILE"
)
6. Сохраняем код возврата:
RETVAL=$?
7. И далее его анализируем. Если нажата кнопка OK, то читаем файл с выбранным пунктом меню в переменную. Если нажата Cancel или клавиша ESC, то на stderr
утилита ничего не выведет и временный файл будет пуст.
case "$RETVAL" in
$OK_C)
LAST_MENU1=`cat "$TEMPFILE" `
#...
;;
$ESC_C)
return;;
$CANCEL_C)
return;;
esac
Далее в примере скрипт вернется в главное меню, и если зайти в предыдущее меню еще раз, то пунктом по умолчанию будет последний выбранный пункт.
Сохранение пункта меню в файл
Иногда удобно сохранять выбранный пункт меню в файл, чтоб при повторном запуске скрипта было видно, какая опция выбрана, если установка опции делается через меню.
Принципиально все делается, как и в предыдущем случае, только заводим еще одну переменную для файла, в котором будем сохранять значение (в реальном скрипте, конечно, можно записывать значение в общий файл конфигурации скрипта):
STATEFILE="./savestate"
И перед вызовом dialog
читаем файл в переменную:
if [ -e "$STATEFILE" ]; then
LAST_MENU2=`cat "$STATEFILE"`
fi
Далее вызываем dialog
, анализируем код возврата, и если что-то выбрано, копируем временный файл в файл для сохранения:
$DIALOG --clear --title "Save last selected item into file" \
--default-item "$LAST_MENU2" \
--menu "Select:" 20 60 7 \
"Item #1" "Item 1" \
"Item #2" "Item 2" \
"Item #3" "Item 3" 2>"$TEMPFILE"
RETVAL=$?
case "$RETVAL" in
$OK_C)
cp "$TEMPFILE" "$STATEFILE"
LAST_MENU2=`cat "$STATEFILE"`
;;
$ESC_C)
return;;
$CANCEL_C)
return;;
esac
Пример полностью на GitHub