¿Es posible en un bash interactivo? shell para ingresar un comando que genera un texto para que aparezca en el siguiente símbolo del sistema, como si el usuario hubiera escrito ese texto en ese indicador?
Quiero poder source
una secuencia de comandos que generará una línea de comando y la generará para que aparezca cuando vuelva a aparecer la solicitud después de que finalice la secuencia de comandos para que el usuario pueda editarla opcionalmente antes de presionar enter
para ejecutarlo.
Esto se puede lograr con xdotool
pero eso solo funciona cuando el terminal está en una ventana X y solo si está instalado.
[[email protected]] 100 $ xdotool type "ls -l"
[[email protected]] 101 $ ls -l <--- cursor appears here!
¿Se puede hacer esto solo con bash?
Respuesta aceptada:
Con zsh
, puede usar print -z
para colocar algo de texto en el búfer del editor de líneas para el siguiente aviso:
print -z echo test
prepararía el editor de líneas con echo test
que puede editar en el siguiente aviso.
No creo que bash
tiene una característica similar, sin embargo, en muchos sistemas, puede preparar el búfer de entrada del dispositivo terminal con el TIOCSTI
ioctl()
:
perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
for split "", join " ", @ARGV' echo test
Insertaría echo test
en el búfer de entrada del dispositivo terminal, como si se hubiera recibido del terminal.
Una variación más portátil de la Terminology
de @mike y que no sacrifica la seguridad sería enviar al emulador de terminal un query status report
bastante estándar secuencia de escape:<ESC>[5n
qué terminales responden invariablemente (como entrada) como <ESC>[0n
y vincúlelo a la cadena que desea insertar:
bind '"e[0n": "echo test"'; printf 'e[5n'
Si está dentro de la screen
de GNU , también puedes hacer:
screen -X stuff 'echo test'
Ahora, a excepción del enfoque ioctl de TIOCSTI, le estamos pidiendo al emulador de terminal que nos envíe una cadena como si estuviera escrita. Si esa cadena viene antes de readline
(bash
editor de línea) ha deshabilitado el eco local del terminal, entonces esa cadena se mostrará no en el indicador de shell, estropeando un poco la pantalla.
Para evitarlo, puede retrasar un poco el envío de la solicitud al terminal para asegurarse de que la respuesta llegue cuando readline haya desactivado el eco.
bind '"e[0n": "echo test"'; ((sleep 0.05; printf 'e[5n') &)
(aquí asumiendo tu sleep
admite resolución de subsegundos).
Idealmente, querrías hacer algo como:
bind '"e[0n": "echo test"'
stty -echo
printf 'e[5n'
wait-until-the-response-arrives
stty echo
Sin embargo bash
(al contrario de zsh
) no tiene soporte para tal wait-until-the-response-arrives
que no lee la respuesta.
Sin embargo, tiene un has-the-response-arrived-yet
función con read -t0
:
bind '"e[0n": "echo test"'
saved_settings=$(stty -g)
stty -echo -icanon min 1 time 0
printf 'e[5n'
until read -t0; do
sleep 0.02
done
stty "$saved_settings"
Lecturas adicionales
Vea la respuesta de @starfry que amplía las dos soluciones proporcionadas por @mikeserv y yo con información más detallada.