¿Cómo ejecutar una función en bash o zsh en cada letra que se escribe en el mensaje?

¿Cómo ejecutar una función en bash o zsh en cada letra que se escribe en el mensaje?

Se acerca depreejecutivo()ganchos para zsh y la forma en que esto se puede lograr en bash. (enlace)

¿Pero puedo conseguir elentrada actualmientras sigues escribiendo?

La idea detrás de esta pregunta es la siguiente:

Para permitir un aprendizaje más rápido de comandos, argumentos y atajos, quiero buscar el comando que se está escribiendo en una "base de datos" que proporcione sugerencias de "ayuda / información útil / atajos" y mostrarlos en otra sesión con screen/tmux mientras escribo. en el otro.

¿Es posible verificar el comando actual que se está escribiendo? Si no funciona con cada pulsación de tecla, un bucle de temporizador también podría funcionar.

Respuesta1

Sólo puedo responder por zsh, donde se puede hacer esto, sí.

En primer lugar, ya existen algunos widgets parafinalización incremental. El primero es aparentemente el de Y. Fujii. A pesar desu sitioestá en japonés, puedes descubrir fácilmente sin hablar ese idioma, cómo funciona y cómo usarlo. auto-fues una extensión del guión original.

Hasta aquí las referencias. En zsheleditor de línea zsh( zle) está a cargo del uso interactivo de la línea de comando. Además de muchas otras variables proporcionadas a los widgets (consulte man zshzle), estas son de su interés ya que desea capturar ellínea de comando actual:

$BUFFER: Todo el contenido del búfer de edición.

$LBUFFER: la parte del búfer que se encuentra a la izquierda de la posición del cursor.

$RBUFFER: la parte del búfer que se encuentra a la derecha de la posición del cursor.

¡Estas variables se pueden escribir, lo que alterará la línea de comando actual!

Para capturar cada pulsación de tecla, puede modificar el widget self-insertque se ejecuta (de forma predeterminada) para cada pulsación de tecla excepto LFo CR. Aquí hay un ejemplo, que no hace nada muy útil, pero agrega un punto a cada pulsación de tecla $RBUFFER, solo para ilustrar cómo funciona esto:

function self-insert() {
  RBUFFER+="."
  # execute some other command, but ensure they don't produce any output.
  zle .self-insert
  }
zle -N self-insert

.self-insertes el widget incorporado, por lo que no nos encontramos con un bucle infinito.

Entonces, puedes comenzar desde cero o comenzar desde el script de Fujii y modificarlo. Un beneficio de este último es que también se encarga de eliminar las pulsaciones de teclas que descuidé aquí.

Respuesta2

Para Bash puedes crear el siguiente test.shscript:

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

Es un script simple que recibe algunos códigos de teclado y los imprime en la pantalla. Ahora pásele los códigos del teclado:

$ stdbuf -o0 xinput test 'AT Translated Set 2 keyboard' | bash test.sh

Ahora, si escribe en otra terminal, debería recibir valores clave. No sé si existe alguna forma inteligente de asignar códigos clave a sus valores ASCII, así que solo estoy haciendo un mapeo simple. También puede mejorar este código para que reaccione a otras claves. Sin embargo, tenga en cuenta que el script recibirá todas las entradas del teclado, no solo pasadas a un terminal determinado.

En cuanto a la tarea en sí (verificar el comando actual que se está escribiendo), puede usarla compgen -cpara generar una lista de posibles finalizaciones según el argumento pasado:

 $ compgen -c 'ls' | head -1
 ls
 $ compgen -c 'lsp' | head -1
 lspci

información relacionada