quinta-feira, 21 de maio de 2009

Do fundo do baú





Em algum outro baú, mais fundo, devo ter as apostilas dos cursos. :-)

quinta-feira, 7 de maio de 2009

Disparador de programas para Sawfish

Havia tempos que eu queria um disparador de aplicações para usar com o Sawfish. Nunca tinha encontrado um que tivesse me agradado. Basicamente, gostaria de um que fosse simples, permitisse completar o nome de programas com TAB, que fosse rápido e que não ocupasse muita memória. Com uma rápida pesquisa na Internet, achei o código em http://www.skamphausen.de/cgi-bin/ska/download/runner.jl, o qual faz exatamente o que eu queria e satisfaz todos os meus requisitos: como é implementado em rep, não é preciso nem criar um novo processo; e a implementação é minúscula.

Depois de uma leve refatorada no código, estou usando o seguinte:

(require 'prompt)

(define (uniq l #!optional in)
;; Elimina replicas na lista L usando o procedimento IN para
;; verificar se um dado elemento se encontra na lista.
(let ((unique '()))
(let loop ((l l))
(if (null l)
unique
(let ((head (car l)))
(unless ((or in member) head unique)
(setq unique (cons head unique)))
(loop (cdr l)))))
(reverse unique)))

(define runner
(let* ((paths (uniq (delete-if-not file-directory-p
(string-split ":" (getenv "PATH")))))
(completions (uniq (apply append (mapcar directory-files paths)))))
(lambda ()
(interactive)
(let ((cmd (prompt-from-list completions "Run: " "" t)))
(system (concat cmd " &"))))))


Adicionei o procedimento uniq para eliminar eventuais réplicas na lista de comandos. Ela é mais flexível que uniquify-list, do Sawfish (a comparação é feita exclusivamente usando eq). uniq aceita um argumento opcional que é o procedimento de comparação (em caso de omissão, usa member).

O procedimento runner monta uma lista de elementos para serem usados como possíveis alternativas para completar palavras digitadas pelo usuário (tab completion), a qual é usada por prompt-from-list, do módulo prompt. As alternativas são os arquivos nos diretórios apontados pela variável de ambiente PATH.

Associei o procedimento runner à combinação de teclas H-RET (Hyper-Enter):

(bind-keys global-keymap
...
"H-RET" (lambda () (runner))
...)


A seguir está um screenshot:



O prompt criado pelo procedimento prompt-from-list define um mapa de teclas. Assim, quando em uso, o prompt aceita as seguintes combinações de teclas associadas a procedimentos (de prompt.jl, so Sawfish):

(bind-keys prompt-keymap
"ESC" prompt-exit
"C-g" prompt-exit
"C-u" prompt-clear
"BS" prompt-backspace
"C-k" prompt-kill-line
"Left" prompt-backward-character
"C-b" prompt-backward-character
"Right" prompt-forward-character
"C-f" prompt-forward-character
"C-Left" prompt-backward-word
"M-b" prompt-backward-word
"A-b" prompt-backward-word
"C-Right" prompt-forward-word
"M-f" prompt-forward-word
"A-f" prompt-forward-word
"C-a" prompt-beginning-of-line
"C-e" prompt-end-of-line
"TAB" prompt-complete
"RET" prompt-accept
"Up" prompt-previous
"Down" prompt-next
"M-n" prompt-next
"M-p" prompt-previous
"A-n" prompt-next
"A-p" prompt-previous))