Como crio uma GUI baseada em terminal?

50

Estou procurando criar um ambiente baseado em terminal para adaptar meu script Bash . Eu quero que fique assim:

Instalação Debian

Encontre-me na floresta
fonte
4
Veja dialogqual é o que isso parece usar.
DopeGhoti
Eu acho que uma GUI baseada em terminal é uma TUI (que é diferente da CLI).
UniversallyUniqueID
"tui" é um termo RH IIRC. whiptail> dialogTambém
Bratchley
@Bratchley: O GDB também usa tuipara o modo de janela dividida (mostrando registros, fonte e comandos com, layout regpor exemplo, e tui reg vecpara mostrar registros vetoriais na janela reg (de uma maneira não flexível, de modo que a parte não seja realmente útil: /) . IDK se Redhat escreveu o patch que acrescentou que recurso, ou mesmo quantos anos ela tem.
Peter Cordes

Respostas:

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

insira a descrição da imagem aqui

A resposta do usuário é armazenada no código de saída, portanto pode ser impressa como de costume: echo $?(observe que 0significa "sim" e 1é "não" no mundo do shell).


Em relação a outras perguntas da seção de comentários:

  • Para colocar na caixa de diálogo a saída de algum comando, use o mecanismo de substituição de comando $(), por exemplo:

     dialog --backtitle "$(echo abc)" --title "$(cat file)" ...
    
  • para dar ao usuário várias opções, você pode usar a --menuopção em vez de--yesno

  • Para armazenar a saída da escolha do usuário na variável, é necessário usar a --stdoutopção ou alterar o descritor de saída por via --output-fdou manualmente, por exemplo:

    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"
    

    Esse truque é necessário porque, dialogpor padrão, gera stderr, não stdout.

E como sempre, man dialogé seu amigo.

jimmij
fonte
isso é lindo "Bla bla bla ..." mas como você captura a saída?
tempforFind Me nas madeiras
11
@tempforFindMeInTheWoods se, por saída, você quer dizer código de saída, como normalmente: é armazenado dentro da ?variável, tente echo $?.
jimmij
11
@tempforFindMeInTheWoods Se você deseja apresentar a saída do comando parted -lao usuário via caixa de diálogo, provavelmente a opção --menué uma opção melhor, em vez de -yesno. Nesse caso, você precisaria brincar um pouco com os descritores para armazenar a saída na variável, por exemplo: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
Ou você pode usar a --stdoutopção
Thomas Dickey 27/05
2
Todas as opções de diálogo são explicadas no manual:man dialog
Ferrybig
34

A captura de tela da pergunta se parece com whiptail (um programa com funcionalidade reduzida, imitando o diálogo , usando newt em vez de ncurses ). A maneira como o título e os botões são renderizados é incorporada a cada programa, fazendo com que pareçam diferentes.

Aqui está um script que duplica a captura de tela original, para whiptail ou caixa de diálogo:

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

e, para comparação, captura de tela com whiptail:

captura de tela com chicote

e com o diálogo:

captura de tela com caixa de diálogo

Além da aparência diferente do título e dos botões, a caixa de diálogo usa cores diferentes por padrão (embora isso seja configurável - veja as capturas de tela ) e usa menos linhas na tela.

dialog (e whiptail) usam bibliotecas para gerenciar a exibição de linhas, cores, etc. Mas você também pode ver o tritão usado no programa anaconda do Red Hat como uma biblioteca compartilhada chamada de python (com a mesma aparência). Na mesma linha, o programa de configuração do kernel começou como uma cópia (reduzida) da caixa de diálogo e depois evoluiu para recursos usando uma biblioteca compartilhada (sem o lxdialogprograma original ), da mesma forma que o newt é usado no python.

Do bash - você pode usar o diálogo ou o chicote para os recursos mais usados. Alguém escreveu um wrapper para aqueles (em perl) para permitir que os scripts usem mais facilmente esses ou alguns outros, mas é melhor usar o diálogo diretamente, pois o módulo perl é essencialmente denominador comum.

As fontes de diálogo incluem exemplos de todos os widgets, juntamente com a maioria das opções de linha de comando:

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.

Leitura adicional:

Thomas Dickey
fonte
11

Eu acredito que o pacote que você está procurando é ncurses .

A Wikipedia descreve ncurses da seguinte maneira:

ncurses (novas maldições) é uma biblioteca de programação que fornece uma API que permite ao programador escrever interfaces de usuário baseadas em texto de maneira independente do terminal. É um kit de ferramentas para o desenvolvimento de software aplicativo "semelhante a GUI", executado em um emulador de terminal

É amplamente utilizado, por exemplo, na ferramenta de configuração do kernel menuconfig: Captura de tela da ferramenta menuconfig do kernel Linux

Como você está usando o bash, você pode usar o Bash Simple Curses (como mencionado por Runium no comentário abaixo).

Thawn
fonte
11
ncursesé uma biblioteca C (Se bem entendi) OP quer um ambiente de script (para bash). menuconfigestá escrito em C. Como alternativa a dialog, como em outras respostas, você pode mencionar Bash Simple Curses, que está escrito em bash (dependendo tput).
Runium 26/05
@Runium: Obrigado pelo esclarecimento e pelo link do Bash Simple Curses.
Thawn 27/05
2
mesmo assim, foi útil mencionar que ncursesé a base disso e ela responde a uma versão mais geral da pergunta ... como a do título aqui :) #
underscore_d
-1

zenidade

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)

entrada do diálogo zenity com opções

password=$(zenity --password)

zenity --password

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

zenity - seleção de arquivo

zenity --help

zenity - resultado da ajuda

zenity --help-general 

zenity - resultado geral da ajuda

zenity --help-entry

zenity - resultado da entrada de ajuda

outras interfaces gráficas de usuário (GUI)

dialog

diálogo

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

interrompe a execução adicional do script, quebra-o. a linha: eco $? nunca acontecerá

Fogo no céu
fonte