With zsh
, you can use print -z
to place some text into the line editor buffer for the next prompt:
print -z echo test
would prime the line editor with echo test
which you can edit at the next prompt.
I don't think bash
has a similar feature, however on many systems, you can prime the terminal device input buffer with the TIOCSTI
ioctl()
:
perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
for split "", join " ", @ARGV' echo test
Would insert echo test
into the terminal device input buffer, as if received from the terminal.
A more portable variation on @mike's Terminology
approach and that doesn't sacrifice security would be to send the terminal emulator a fairly standard query status report
escape sequence: <ESC>[5n
which terminals invariably reply (so as input) as <ESC>[0n
and bind that to the string you want to insert:
bind '"\e[0n": "echo test"'; printf '\e[5n'
If within GNU screen
, you can also do:
screen -X stuff 'echo test'
Now, except for the TIOCSTI ioctl approach, we're asking the terminal emulator to send us some string as if typed. If that string comes before readline
(bash
's line editor) has disabled terminal local echo, then that string will be displayed not at the shell prompt, messing up the display slightly.
To work around that, you could either delay the sending of the request to the terminal slightly to make sure the response arrives when the echo has been disabled by readline.
bind '"\e[0n": "echo test"'; ((sleep 0.05; printf '\e[5n') &)
(here assuming your sleep
supports sub-second resolution).
Ideally you'd want to do something like:
bind '"\e[0n": "echo test"'
stty -echo
printf '\e[5n'
wait-until-the-response-arrives
stty echo
However bash
(contrary to zsh
) doesn't have support for such a wait-until-the-response-arrives
that doesn't read the response.
However it has a has-the-response-arrived-yet
feature with 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"
Further reading
See @starfry's answer's that expands on the two solutions given by @mikeserv and myself with a few more detailed information.
Best Answer
Based on this answer you can use
expect
(you might have to install it first):Now you can call it (assuming you saved it as
my_function
):The only undesirable effect might be that it starts a new bash.