Как я могу создать основанный на терминале GUI?

50

Я ищу создание терминальной среды для адаптации моего Bash- скрипта. Я хочу, чтобы это выглядело так:

Установка Debian

В поисках меня в лесу
источник
4
Посмотрите dialog, что это, кажется, использовать.
DopeGhoti
Я думаю, что основанный на терминале GUI является TUI (который отличается от CLI).
UniversallyUniqueID
«туи» является относительным термином IIRC. whiptail> dialogтакже
Братчли
@Bratchley: GDB также использует tuiдля своего режима разделенного окна (например, показ регистров, источника и команд) layout regи tui reg vecдля отображения векторных регистров в окне регистров (негибким способом, так что эта часть не очень полезна: /) IDK, если Redhat написал патч, который добавил эту функцию, или даже сколько ему лет
Питер Кордес

Ответы:

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

введите описание изображения здесь

Ответ пользователя хранится в коде завершения, поэтому может быть напечатан как обычно: echo $?(обратите внимание, что 0означает «да» и 1«нет» в мире оболочки).


По поводу других вопросов из раздела комментариев:

  • чтобы поместить в диалоговое окно вывод какой-либо команды, просто используйте механизм подстановки команд $(), например:

     dialog --backtitle "$(echo abc)" --title "$(cat file)" ...
    
  • чтобы дать пользователю несколько вариантов, вы можете использовать --menuопцию вместо--yesno

  • Чтобы сохранить выходные данные выбора пользователя в переменную, необходимо использовать --stdoutпараметр или изменить дескриптор вывода с помощью --output-fdили вручную, например:

    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"
    

    Этот прием необходим, потому что dialogпо умолчанию выводит в stderr, а не в stdout.

И, как всегда, man dialogтвой друг.

jimmij
источник
это прекрасно "Бла бла бла ...", но как вы захватываете результат?
tempforFind Me In The Woods
1
@tempforFindMeInTheWoods, если под выводом вы подразумеваете код выхода, то как обычно: он хранится внутри ?переменной, попробуйте echo $?.
Джимми
1
@tempforFindMeInTheWoods Если вы хотите представить вывод команды parted -lпользователю через диалоговое окно, то, вероятно --menu, лучше использовать вариант вместо -yesno. В таком случае вам придется немного поиграть с дескрипторами, чтобы сохранить вывод в переменную, например: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
3
Или вы можете использовать --stdoutопцию.
Томас Дики
2
Все параметры диалога объяснены в руководстве:man dialog
Ferrybig
34

Снимок экрана в вопросе выглядит как хлыстохвост (функционально сокращенная программа, имитирующая диалог , использующий newt, а не ncurses ). Способ визуализации заголовка и кнопок встроен в каждую программу, благодаря чему они выглядят по-разному.

Вот скрипт, который дублирует оригинальный снимок экрана, либо для кнута, либо для диалога:

#!/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))

и для сравнения, скриншот с хлыстом:

скриншот с хлыстом

и с диалогом:

скриншот с диалогом

Помимо различного вида заголовка и кнопок, в диалоговом окне по умолчанию используются разные цвета (хотя это настраивается - см. Скриншоты ), и на экране используется меньше строк.

Диалог (и whiptail) использует библиотеки для управления отображением линий, цветов и т. д. Но вы также можете увидеть тритон, используемый в программе Anaconda Red Hat в качестве общей библиотеки, вызываемой из python (с таким же внешним видом). В том же духе программа конфигурирования ядра начиналась как (урезанная) копия диалога, а затем развивалась до функций, использующих разделяемую библиотеку (без исходной lxdialogпрограммы), во многом аналогично тому, как newt используется в python.

Из Bash - вы можете использовать либо диалог или whiptail для наиболее часто используемых функций. Кто-то написал оболочку для них (в perl), чтобы позволить сценариям с большей готовностью использовать либо те, либо несколько других, но лучше использовать диалог напрямую, так как модуль perl по существу является общим знаменателем.

Источники диалога включают примеры всех виджетов наряду с большинством параметров командной строки:

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.

Дальнейшее чтение:

Томас Дики
источник
11

Я считаю, что пакет, который вы ищете, это ncurses .

Википедия описывает ncurses следующим образом:

ncurses (новые curses) - это библиотека программирования, предоставляющая API, который позволяет программисту писать текстовые пользовательские интерфейсы независимо от терминала. Это инструментарий для разработки "GUI-подобного" программного обеспечения, которое работает под эмулятором терминала.

Он широко используется, например, в инструменте конфигурации ядра menuconfig: Снимок экрана утилиты menuconfig для ядра Linux

Поскольку вы используете bash, вы можете использовать Bash Simple Curses (как упомянуто Runium в комментарии ниже).

растаявший
источник
11
ncursesэто C-библиотека. (Если я правильно понимаю) OP хочет среду сценариев (для bash). menuconfigнаписан на C. В качестве альтернативы dialog, как в другом ответе, вы могли бы упомянуть Bash Simple Curses, который написан на bash (полагаясь на tput).
Runium
@Runium: Спасибо за разъяснения и ссылку на Bash Simple Curses.
Таун
2
тем не менее, было полезно упомянуть, что это ncursesявляется основой этого, и он отвечает на более общую версию вопроса ... как в названии здесь :)
underscore_d
-1

Zenity

zenity --file-selection --directory

,

# var means variable

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

,

# ls is a command to list files in a directory

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

запись диалога zenity с опциями

password=$(zenity --password)

zenity - пароль

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

zenity --file-selection

zenity --help

zenity - помочь результат

zenity --help-general 

zenity --help-общий результат

zenity --help-entry

zenity --help-entry result

другие графические пользовательские интерфейсы (GUI)

dialog

диалог

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

останавливает дальнейшее выполнение сценария, прерывает его. строка: echo $? никогда не случится

FireInTheSky
источник