Eu sei sobrepréexec()ganchos para zsh e a maneira como isso pode ser feito no bash. (link)
Mas posso pegar oentrada atualenquanto ainda digita?
A ideia por trás desta pergunta é a seguinte:
para permitir um aprendizado mais rápido de comandos, argumentos e atalhos, quero pesquisar o comando que está sendo digitado em um "banco de dados" fornecendo dicas de "ajuda / bom saber / atalho" e mostrá-las em outra sessão com screen/tmux enquanto digita no outro.
É possível verificar o comando atual que está sendo digitado? Se não funcionar a cada pressionamento de tecla, um loop de temporizador também poderá funcionar.
Responder1
Só posso responder zsh
onde isso pode ser feito, sim.
Primeiro, já existem alguns widgets paraconclusão incremental. O primeiro é aparentemente o de Y. Fujii. Emboraseu siteestá em japonês, você pode descobrir facilmente, sem falar esse idioma, como funciona e como usá-lo. Fu automáticoé uma extensão do script original.
Até agora as referências. Nozsh
editor de linha zsh( zle
) é responsável pelo uso interativo da linha de comando. Além de muitas outras variáveis fornecidas aos widgets (consulte Recursos man zshzle
), elas são de seu interesse, pois você deseja capturar olinha de comando atual:
$BUFFER: todo o conteúdo do buffer de edição.
$LBUFFER: A parte do buffer que fica à esquerda da posição do cursor.
$RBUFFER: A parte do buffer que fica à direita da posição do cursor.
Estas variáveis são graváveis, o que alterará a linha de comando atual!
Para capturar cada pressionamento de tecla, você pode modificar o widget self-insert
que é executado (por padrão) para cada pressionamento de tecla, exceto LF
ou CR
. Aqui está um exemplo, que não faz nada de muito útil, mas acrescenta um ponto a cada pressionamento de tecla $RBUFFER
- apenas para ilustrar como isso funciona:
function self-insert() {
RBUFFER+="."
# execute some other command, but ensure they don't produce any output.
zle .self-insert
}
zle -N self-insert
.self-insert
é o widget integrado, então não entramos em um loop infinito.
Portanto, você pode começar do zero ou partir do script do Fujii e modificá-lo. Um benefício deste último é que ele também lida com a exclusão de pressionamentos de tecla que negligenciei aqui.
Responder2
Para Bash você pode criar o seguinte test.sh
script:
#!/usr/bin/env bash
ARRAY=('1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '=' 'BACKSPACE' ''
'q' 'w' 'e' 'r' 't' 'y' 'u' 'i' 'o' 'p' '[' ']' 'NEWLINE' ''
'a' 's' 'd' 'f' 'g' 'h' 'j' 'k' 'l' ';' "'" '' '' '' 'z' 'x' 'c'
'v' 'b' 'n' 'm' '0' ',' '.' '/' '' '' 'SPACE')
while read row
do
if [[ "$row" == *press* ]]
then
index=$((${row/key press /}-10))
if [[ "${ARRAY[$index]}" == 'NEWLINE' ]]
then
printf "\n"
elif [[ "${ARRAY[$index]}" == 'BACKSPACE' ]]
then
echo -ne "\b \b"
elif [[ "${ARRAY[$index]}" == 'SPACE' ]]
then
printf " "
else
printf "%s" "${ARRAY[$index]}"
fi
fi
done
É um script simples que recebe alguns códigos do teclado e os imprime na tela. Agora passe os códigos do teclado para ele:
$ stdbuf -o0 xinput test 'AT Translated Set 2 keyboard' | bash test.sh
Agora, se você digitar em outro terminal, ele deverá receber valores-chave. Não sei se existe alguma maneira inteligente de mapear códigos-chave para seus valores ASCII, então estou apenas fazendo um mapeamento simples. Você também pode melhorar esse código para reagir a outras chaves. Observe, entretanto, que o script receberá todas as entradas do teclado, não apenas passadas para um determinado terminal.
Quanto à tarefa em si (verificando o comando atual que está sendo digitado), você pode usar compgen -c
para gerar uma lista de possíveis conclusões com base no argumento passado:
$ compgen -c 'ls' | head -1
ls
$ compgen -c 'lsp' | head -1
lspci