você está aqui: Home → Colunistas → Cantinho do Shell
Colaboração: Julio Cezar Neves
Data de Publicação: 16 de Agosto de 2013
Acho que nunca foi feita uma linguagem de programação tão sucinta quanto o Shell. Apesar disso, em tempos de mouse e telas coloridas, realmente ele deixava um pouco a desejar porque lhe faltavam essas habilidades, apesar de terem sido várias as tentativas, como (só para citar algumas): Zenity, Dialog, Kdialog, Xdialog, Gdialog, ...
Surge agora, um novo projeto que é um fork do Zenity e chama-se YAD
(Yet Another Dialoging shell programing). Em seu pouco tempo de vida ele
já tem mais do dobro das facilidades oferecidas pelo Zenity, seu predecessor,
e é capaz de montar praticamente todas as interfaces com os usuários em um
único formulário, definido pela opção --form
.
A intenção desse artigo não é ensinar a instalar o YAD, ou como usá-lo. O que quero deixar muito claro, é a sua qualidade da apresentação, como é fácil e sucinto usá-lo e a sua abrangência de uso. Assim sendo, vamos logo a um exemplo que usa somente um de seus 15 diálogos possíveis.
O diálogo que usaremos é o --form
que, somente ele, aceita 19 tipos de
opções de caixas distintas isto é, dentro de um formulário, podemos definir
ComboBoxes, CheckBoxes, campo escondido (senha), SpinBoxes,
caixas para seleção de arquivos, para seleção de fontes, para seleção de
cores, caixas de texto multilinha, ...
Vejamos um exemplo de um formulário que é formado somente por botões, e um mostrador, já que nossa intenção é fazer uma calculadora. O exemplo é formado por 2 programas. O primeiro, calc.yad, faz a camada de apresentação e o segundo, calc.sh, põe o bash para trabalhar, para fazer a camada de negócio, ou seja, a lógica da calculadora.
Veja o produto final:
UAUUU! Com um acabamento desses isso não pode ser Shell! Mas é sim. Shell + YAD + bc. O trio trilha troços trufados! ;)
Pela figura, você pode ver que montamos uma apresentação plana, mas que ganha relevo quando o mouse se superpõe a um botão (mouse over). Pode-se notar também que é possível introduzir dicas (tips) na definição de cada botão. Vejamos o código:
$ cat calc.yad #!/bin/bash # Calculadora usando Bash, bc e yad > ~/.mem # Será usado como memória trap 'rm ~/.mem; exit' 0 2 3 15 yad --form --columns 8 --width 500 --no-buttons \ --title "Calculadora YAD + Bash + bc" \ --field='' '' --field :LBL '' \ --field :RO 'Casas decimais' \ --field 'Decimais!Ajusta a precisão \ do cálculo':BTN "@calc.s h '' PR" \ --field=7:BTN "@echo 1:%1\7" \ --field=4:BTN "@echo 1:%1\4" \ --field=1:BTN "@echo 1:%1\1" \ --field=,:BTN "@echo 1:%1\," \ --field=8:BTN "@echo 1:%1\8" \ --field=5:BTN "@echo 1:%1\5" \ --field=2:BTN "@echo 1:%1\2" \ --field=0:BTN "@echo 1:%1\0" \ --field=9:BTN "@echo 1:%1\9" \ --field=6:BTN "@echo 1:%1\6" \ --field=3:BTN "@echo 1:%1\3" \ --field '!Enche linguiça':BTN '' \ --field=+:BTN "@echo 1:%1\+" \ --field=:BTN "@echo 1:%1\x" \ --field='??!Raiz Quadrada':BTN \ '@./calc.sh '%1' RQ %3' \ --field='±!Troca sinal':BTN \ "@./calc.sh '%1' +-" \ --field=-:BTN "@echo 1:%1\-" \ --field=÷:BTN "@echo 1:%1\/" \ --field='x?!Potenciação':BTN "@echo 1:%1\^" \ --field='1/x!Inverte':BTN \ '@./calc.sh '%1' 1X %3' \ --field==:BTN '@./calc.sh '%1' = %3' \ --field=\(:BTN "@echo 1:%1\(" \ --field='CL!Limpa':BTN "@echo 1:" \ --field='MC!Limpa memória':BTN \ "@./calc.sh '' MC" \ --field=\?:BTN "@./calc.sh %1 AP" \ --field=\):BTN "@echo 1:%1\)" \ --field='M+!Adiciona à memória':BTN " \ @./calc.sh '%1' M+ %3" \ --field='MR!Trás conteúdo da memória':BTN \ "@./calc.sh '%1' MR"
Como vocês viram o formulário é somente um composto de um diálogo --form
com
diversos campos do tipo botão (:BTN
). As contrabarras no fim da cada
linha são para informar ao Shell que a linha não terminou e o texto continua
na linha seguinte. Se não as tivesse usado, teria de escrever todo o comando
em uma única linha e aí ficaria muito difícil de explicá-lo, de lê-lo e
principalmente de depurá-lo.
No início do script, criei um arquivo chamado .mem
no diretório home
,
em seguida montei uma trap para removê-lo quando o programa terminasse ou
fosse (ex)terminado. ;) e a partir de então foi somente mais um comando yad,
onde destaco:
Diretiva | Função |
---|---|
--form | que define que o diálogo com o operador será via um formulário; |
--columns | que especifica a quantidade de colunas do formulário; |
--width | para determinar a largura mínima; |
--no-button | Para que o yad não adicione os botões padrão (Default) ao diálogo (OK e Cancelar) |
--field | que define o nome, o tipo, as dicas e a ação de cada campo do formulário. |
Como todos os demais campos são do tipo botão (:BTN), vamos entender como se comportam começando pela sua sintaxe:
—field ROTULO[!DICA]:BTN CMD
Onde:
ROTULO | é o que vem escrito no botão; |
DICA | é uma ajuda que aparece em uma etiqueta popup; |
:BTN | isso que o define como um campo botão; |
CMD | comando que será executado quando o botão for clicado. |
Se CMD começar com um arroba (@), é sinal que vou usar outros campos do
formulário. Se nessa linha houver um %N
, onde N é um numérico, ele será
trocado pelo conteúdo do campo N (enésimo campo). Para mandar um valor para o
campo M, onde M também é um número, ele deve ser mencionado com M:. Resumindo:
%N recebe valor do enésimo campo e M: coloca o valor no emésimo campo.
Para entender melhor, veja esses exemplos:
$ yad --form --field _Botão:BTN 'ls -l'
Nesse caso quando Botão for clicado, mandará a saída do "ls -l
" para
a tela. O sublinha (_
) antes do B, faz com que ele apareça sublinhado no
formulário e <ALT>+<B> passa a ser a sua tecla de atalho.
$ yad --form --field '':TXT '' \ --field Botão:BTN "@echo 1:$(ls)"
Desta vez, foi criado mais um campo no formulário, este do tipo :TXT. Esse tipo de campo é para receber textos multilinhas. Nesse caso, como CMD começava com arroba (@), o 1:$(ls), diz para a saída do ls ser feita no primeiro campo (1:).
$ yad --form --field "Arquivo:FL" '' \ --field '1ª Linha:TXT' '' \ --field 'Mostre 1ª linha:BTN' "@./aux '%1'"
Neste último caso, temos um campo para seleção de arquivo (:FL
), um do tipo
texto multilinha (:TXT
) e outro do tipo botão (:BTN
). Esse último, quando
clicado, chama o programa aux, (@./aux) passando o arquivo selecionado no
primeiro campo (%1). Veja que aux também é um script e que ele verifica se
o arquivo passado existe e, caso afirmativo, lista sua primeira linha. Veja
só o aux; é um scriptizinho xexelento:
$ cat aux [ -f $1 ] && echo 2:$(head -1 $1) || echo 2:$1 não é arquivo
Bem já vimos as diversas formas de trabalhar com botões, mas há algum tempo mandei para a Dicas-L um artigo que explicava o uso de botões no YAD. Se você se interessou pelo tema, pode vê-lo aqui. Então vamos voltar ao código da nossa calculadora: repare que existem somente dois tipos de ação com os campos do tipo botão:
—field=7:BTN "@echo 1:%1\7"
Especifica um botão cujo rótulo é 7
e que vai enviar para o campo 1
(1:
),
que é o mostrador, o valor do próprio campo 1
(%1
) concatenado com 7
. A
contrabarra (\) antes do 7
é inócua pois é para o Shell e usei-a para separar
o 1
do 7
de modo a não ser interpretado como o 17º campo (%17
).
—field='M+!Adiciona à memória':BTN " \ @./calc.sh '%1' M+ %3"
Agora o rótulo do botão é M+. !Adiciona à memória
será a dica que aparecerá
em um diálogo popup quando o mouse estiver sobre este botão e executa o
programa calc.sh passando 3 parâmetros:
%1 | O conteúdo do primeiro campo (mostrador); |
M+ | O programa calc.sh executa diversas ações diferentes, de acordo com o ponto do qual ele foi chamado. Esse parâmetro (que é um literal) serve para que calc.sh saiba que tem que incrementar o conteúdo da memória; |
%3 | O conteúdo do 3º campo, que é um somente leitura (Read Only - :RO) que guarda a precisão em decimais arbitrada pelo usuário. |
Vejamos agora o programa calc.sh:
$ cat calc.sh #!/bin/bash Prec=$(expr $3 + 0 2> /dev/null) || Prec=0 case $2 in =) Conta=$(tr 'x,' '*.' <<< "$1") echo 1:$(echo "scale=$Prec; $Conta" | bc | tr . ,) ;; RQ) Conta=$(tr 'x,' '*.' <<< "$1") echo 1:$(echo "scale=$Prec; sqrt ($Conta)" | bc | tr . ,) ;; 1X) Conta=$(tr 'x,' '*.' <<< "$1") echo 1:$(echo "scale=$Prec; 1/($Conta)" | \ bc | tr . ,) ;; M+) Num=$([ -s ~/.mem ] && cat ~/.mem || echo 0) Conta=$(tr , . <<< "$1") bc <<< "$Conta + $Num" > ~/.mem ;; MR) echo 1:$(cat ~/.mem) ;; MC) > ~/.mem ;; AP) echo 1:${1%?} ;; PR) IFS='|' read lx lx Dec lx <<< \ "$(yad --form --columns 4 \ --title "Decimais" \ --field "\tInforme precisão":LBL '' \ --field "\tentre 0 e 9 decimais":LBL '' \ --field '' '' --field :LBL '' \ --field 1:BTN '@echo 3:1' --field 4:BTN '@echo 3:4' \ --field 7:BTN '@echo 3:7' \ --field :BTN '' \ --field 2:BTN '@echo 3:2' \ --field 5:BTN '@echo 3:5' \ --field 8:BTN '@echo 3:8' \ --field 0:BTN '@echo 3:0' \ --field 3:BTN '@echo 3:3' \ --field 6:BTN '@echo 3:6' \ --field 9:BTN '@echo 3:9' \ --field :BTN '' --button OK)" echo 3:$Dec ;; +-) Conta=$(tr , . <<< "$1") echo 1:$(echo "-1 * $Conta" | bc | tr . ,) ;; *) echo 1:$1 esac
Se você não se assustar e prestar atenção, verá que este é um programa bastante simples, já que é basicamente um só case. Vou porém fazer alguns destaques:
O comando tr aparece com grande frequência isso se dá basicamente porque o mostrador da calculadora exibe virgula (,), sinal de dividir (÷), entre outros, que é necessário trocá-los antes para o bc entender e após, para que o resultado seja exibido de forma com vírgula decimal.
A linha de comando yad que se encontra neste programa, monta outro teclado para que o usuário possa escolher a precisão dos cálculos (quantidade de decimais)
Todos os itens do case que mandam a saída para o mostrador, terminam fazendo
um echo 1:...
, ou seja quando o calcula.yad recebe este valor, manda-o
para o campo 1 que é o mostrador. A exceção é o comando yad que captura
a precisão. Ela termina com um echo 3:$Dec
, para que a quantidade de
decimais ($Dec
) escolhida pelo usuário seja enviada para o campo 3 da
calculadora, que é um campo somente de leitura e foi criado para exibir
este valor.
Espero que tenha sido claro na minha explicação, de forma a permitir que você compreenda que belíssima ferramenta é o YAD.
Júlio Cezar Neves é engenheiro de produção da UFRJ, pós-graduado em informática pelo IBAM, Analista de Suporte de Sistemas desde 1969. Ex-diretor de Informática do IplanRIO, órgão de TI da Prefeitura Municipal do Rio de Janeiro. É autor do livro "Programação Shell - Linux", uma das melhores publicações nacionais de programação shell, já em sua 9ª edição. Além disto, mantém também o site http://www.julioneves.com , que oferece um material completo sobre programação shell.
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários