Tcl/Tk
Faz mais de um mês que não escrevo nada sobre Informática! Como já faz tempo que quero escrever sobre Tcl/Tk, vamos lá!
Tcl (Tool Command Language) é uma linguagem de script de código aberto muito poderosa. Desenvolvido por John Ousterhout, é costume dizer que é uma linguagem fácil, mas discordo.
É baseada em comandos (há uma variante orientada a objetos, chamada [incr Tcl]) com uma proposta interessante: tudo são strings!
Uma string em Tcl não precisa de delimitador, a menos que possua caracteres não-permitidos, como espaço e mudança de linha. Neste caso, o delimitador padrão é "
(ou chaves).
Vamos a alguns exemplos...
Para se alterar ou ler o valor de uma variável usa-se o comando set
. No exemplo a seguir, o script lê o valor da variável e retorna o dobro:
puts -nonewline stdout {Informe um número: }
gets stdin num
set num [expr [set num] * 2]
puts stdout "O dobro é [set num]"
O primeiro comando (
puts
) grava na saída padrão (stdout
, a tela) a string «Informe um número:
» sem mudar de linha (-nonewline
). As chaves ({
...}
) também delimitam uma string, mas não interpretam colchetes (veja adiante).Então o comando
gets
lê da entrada padrão (stdin
, o teclado) um valor e atribui à variável num
.No próximo comando,
set
, usamos colchetes ([
...]
). Os colchetes interpretam um comando e são substituídos por seu retorno.Ou seja, se foi atribuído o número 123 à variável
num
, no comando:expr [set num] * 2
A parte entre colchetes,
set num
, retorna o valor de num
, portanto 123, então os colchetes serão substituídos, recriando a string do comando assim:expr 123 * 2
O comando
expr
avalia uma expressão matemática e retorna seu valor. Então:set num [expr [set num] * 2]
Calcula o dobro do conteúdo de
num
e atribui a num
.O último comando grava na saída padrão (exibe na tela, ora pois!) a string «
O dobro é [set num]
», substituindo os colchetes pelo valor de num
.Repare que no primeiro
puts
, a string está protegida por chaves, e no segundo por aspas. Sempre dou preferência ao uso de chaves, mas as chaves protegem a string de interpretação, enquanto que aspas permitem a interpretação de colchetes (e cifrão, veja a seguir).Agora, há um jeito de simplificar este código: seguindo as sintaxes de Shell e de Perl, existe uma forma simplificada de escrever
set num
com cifrão ($
):puts -nonewline stdout {Informe um número: }
gets stdin num
set num [expr $num * 2]
puts stdout "O dobro é $num"
Estruturas de controle
Dada a introdução, quero agora comentar algumas estruturas de controle de fluxo...
O primeiro comando é
if
. Sua estrutura é assim: if condição bloco1 [else bloco2]
. Aqui, condição
, bloco1
e bloco2
são strings (como não poderia deixar de ser). Então:if {$sair == 1} {
puts stdout Tchau
exit
}
Se o conteúdo da variável
sair
for igual a um, exibe Tchau
e sai. Como em outras linguagens, o bloco do else
é executado se a condição for falsa.A igualdade dupla (
==
) é usada para comparar valores numéricos. Para a comparação de strings, é usado o comando string
com a opção equal
:if [string equal $var1 $var2] {
puts stdout {São iguais!}
} else {
puts stdout {São diferentes!}
}
Se quiser uma comparação ignorando maiúsculas e minúsculas, é só usar
string equal -nocase
. Repare que aqui a string interpretada pelo if
como condição não é o comando em si, mas seu resultado.Outro comando é o famigerado
for
.A estrutura:
for inicialização condição passo bloco
. Novamente cada termo é uma string.Vamos a um exemplo simples:
for {set i 0} {$i < 10} {incr i} {puts stdout $i}
Vai exibir todos os número de 0 a 9. Mas o comando é feio e difícil de guardar, né?
Então, existe um variante do Tcl chamado TclX (Tcl estendido), com um comando muito útil:
loop
.loop i 0 10 {
echo $i
}
O comando
echo
de TclX é equivalente a puts stdout
de Tcl. Em loop
é possível passar mais um argumento entre o máximo e o bloco como passo (tipo: loop i 0 20 2 {
...).Obs.: TclX aceita todos os comandos de Tcl e implementa (estende) mais alguns.
Outros comandos de controle de fluxo interessantes em Tcl são:
while
, switch
e foreach
.Funções
O comando para criar uma função é
proc
, que recebe como primeira string a lista de argumentos (separados por espaços) e como segunda string o bloco de comandos. Ex.:proc fib n {
set a 0
set b 1
set c 1
while {$c <= $n} {
set aux $a
set a $b
incr b $aux
incr c
}
return $b
}
Então
fib
vai calcular a sequência de Fibonacci:for {set i 0} {$i < 10} {incr i} {
puts stdout [fib $i]
}
Tk
Agora a parte mais interessante: Tk!
Tk é o toolkit gráfico de Tcl. O comando para usar Tcl com Tk é
wish
(e para usar TclX com Tk é wishx
).Em Tk a janela raiz é representada por um ponto (
.
).Vamos criar um olá mundo!!!
#!/bin/sh
#\
exec wish "$0" "$@"
tk appname Ola
tk_setPalette gray
label .lbOla -text {Olá Mundo!!!}
button .btOk -text Ok -command exit
pack .lbOla .btOk
As três primeiras linhas são um cabeçalho pra podermos tornar o script executável.
O primeiro comando (
tk appname
) define o nome da aplicação (Ola
), e o comando seguinte (tk_setPalette
) diz pra usar como cores variantes de cinza (gray
).O comando
label
cria um rótulo (label) chamado lbOla
na janela raiz (.
) com o texto «Olá Mundo!!!
». O comando button
cria um botão chamado btOk
na janela raiz (.
) com o texto «Ok
» e que, ao ser clicado (-command
), executa exit
(sair).O comando
pack
indica que será usado o geometry manager pack
. Geometry managers são gerenciadores de widgets (objetos gráficos) e geometria. Tk usa três: pack
(«empacota» em relação a posições esquerda, direita, em cima, em baixo, e tenta manter estas relações), grid
(usa uma tabela – grade – colocando os widgets nas células da tabela) e place
(desaconselhável: coloca os widgets em posições absolutas).O gerenciador
pack
por padrão coloca os widgets a partir de cima (top), um de baixo do outro, centralizando (é possível mudar isso usando -side
).Para colocar os widgets um do lado do outro a partir da esquerda, usa-se
-side left
, a partir da direita: -side right
. Para «amarrar» um widget em baixo, usa-se -side bottom
.O
grid
prende os widgets centralizados (é configurável) em células. A célula exata é informada através dos números de linha (-row
) e coluna (-column
). É possível que um widget ocupe mais de uma coluna (-columnspan
) ou mais de uma linha (-rowspan
).O script acima poderia ser reescrito usando
grid
assim:#!/bin/sh
#\
exec wish "$0" "$@"
tk appname Ola
tk_setPalette gray
label .lbOla -text {Olá Mundo!!!}
button .btOk -text Ok -command exit
grid .lbOla -row 0 -column 0
grid .btOk -row 1 -column 0
Para saber mais
O melhor lugar para se encontra mais informações sobre Tcl/Tk é na secção
(n)
(new) das manpages, mas um macete indispensável é digitar o seguinte comando no shell de um xterm
:tcl <<< tclhelp
[]'s
PS: Procure screenshots no Google!