Skip to main content
deleted 12 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

Or you could delay the TIOCSTI ioctl enough for readline to have time to initialise and disable:

Or you could delay the TIOCSTI ioctl enough for readline to have time to initialise and disable:

Or you could delay the TIOCSTI ioctl enough for readline to have time to initialise:

added 627 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

If, like in the zsh approaches, you want to handle the case where the user enters text before the prompt is displayed, you could either

  • drain that by doing a tcflush(0, TCIFLUSH) in perl before the TIOCSTI ioctl (also needs a -MPOSIX option), or

  • like in the zsh approach, ensure the foo is inserted at the start of the buffer by inserting a ^A (assuming you use the emacs (default) editing mode where that moves the cursor to the beginning of the line) before foo and ^E after (to move to the end):

      insert_with_delay 0.05 $'\1foo \5'
    

or

    bind $'"\u200b":"\1foo \5"'

If, like in the zsh approaches, you want to handle the case where the user enters text before the prompt is displayed, you could either

  • drain that by doing a tcflush(0, TCIFLUSH) in perl before the TIOCSTI ioctl (also needs a -MPOSIX option), or

  • like in the zsh approach, ensure the foo is inserted at the start of the buffer by inserting a ^A (assuming you use the emacs (default) editing mode where that moves the cursor to the beginning of the line) before foo and ^E after (to move to the end):

      insert_with_delay 0.05 $'\1foo \5'
    

or

    bind $'"\u200b":"\1foo \5"'
added 985 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

With zsh, it should just be a matter of:

precmd() print -z 'foo '

Or to avoid it overriding commands queued by the user with Alt+q:

zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init

With bash, instead of xdotool, you could use the TIOCSTI ioctl:

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'

It's preferable to xdotool because it's inserting those characters directly in the input buffer of the device bash is reading from. xdotool would only work if there's a X server running (wouldn't work on the console or real terminals or over ssh (without -X) for instance), that it is the one identified by $DISPLAY and that's the one you're interacting with, and that the terminal emulator bash is running in has the focus when $PROMPT_COMMAND is evaluated.

Now, like in your xdotool case, because it'sthe ioctl() is done before the prompt is displayed and the tty terminal line discipline is put out of icanon without echoicanon+echo mode by readline, you're likely to see the echo of that foo by the tty line discipline messing up the display.

You could work around that by instead inserting a string whose echo is invisible (like U+200B if using exclusively Unicode locales) and bind that to an action that inserts "foo ":

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"

Or you could delay the TIOCSTI ioctl enough for readline to have time to initialise and disable:

insert_with_delay() {
  perl -le 'require "sys/ioctl.ph";
            $delay = shift @ARGV;
            unless(fork) {
              select undef, undef, undef, $delay;
              ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
            }' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'

With zsh, it should just be a matter of:

precmd() print -z 'foo '

Or to avoid it overriding commands queued by the user with Alt+q:

zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init

With bash, instead of xdotool, you could use the TIOCSTI ioctl:

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'

Now, because it's done before the prompt is displayed and the terminal line discipline is put out of icanon without echo by readline, you're likely to see the echo of that foo by the line discipline messing up the display.

You could work around that by instead inserting a string whose echo is invisible (like U+200B if using exclusively Unicode locales) and bind that to an action that inserts "foo ":

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"

With zsh, it should just be a matter of:

precmd() print -z 'foo '

Or to avoid it overriding commands queued by the user with Alt+q:

zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init

With bash, instead of xdotool, you could use the TIOCSTI ioctl:

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'

It's preferable to xdotool because it's inserting those characters directly in the input buffer of the device bash is reading from. xdotool would only work if there's a X server running (wouldn't work on the console or real terminals or over ssh (without -X) for instance), that it is the one identified by $DISPLAY and that's the one you're interacting with, and that the terminal emulator bash is running in has the focus when $PROMPT_COMMAND is evaluated.

Now, like in your xdotool case, because the ioctl() is done before the prompt is displayed and the tty terminal line discipline is put out of icanon+echo mode by readline, you're likely to see the echo of that foo by the tty line discipline messing up the display.

You could work around that by instead inserting a string whose echo is invisible (like U+200B if using exclusively Unicode locales) and bind that to an action that inserts "foo ":

insert() {
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"

Or you could delay the TIOCSTI ioctl enough for readline to have time to initialise and disable:

insert_with_delay() {
  perl -le 'require "sys/ioctl.ph";
            $delay = shift @ARGV;
            unless(fork) {
              select undef, undef, undef, $delay;
              ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
            }' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'
added 44 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k
Loading
added 44 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k
Loading
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k
Loading