bash: Existe uma maneira de invocar comandos de ligação (por exemplo, redraw-current-line) programaticamente?

bash: Existe uma maneira de invocar comandos de ligação (por exemplo, redraw-current-line) programaticamente?

Encontrei várias explicações sobre como mapear redraw-current-lineum pressionamento de tecla usando bind, mas gostaria de redesenhar o prompt por outros motivos (por exemplo, cronômetro, trabalho em segundo plano), sem que o usuário digite um pressionamento de tecla. Presumi que seria fácil, mas não consigo encontrar nada. Obrigado!

Responder1

Eu tive o mesmo problema, mas não encontrei nada satisfatório, então aqui estão algumas soluções alternativas.

${PS1@P}

Nas versões mais recentes do bash, você pode simplesmente imprimir o prompt com echo "${PS1@P}". A ${var@P}forma de expansões de variáveis ​​significa expandir escapes de prompt dentro de uma variável.

kill -WINCH "$$"

Outro truque que você pode tentar é matar seu shell com SIGWINCH. Isso fará com que o readline redesenhe o prompt. Exemplo:

$ (sleep 2; echo foo; sleep 2; kill -WINCH "$$") &
[1] 2295
<immediately press l and s; the "foo" text will mess up the current line>
$ lsfoo
<after 1s the prompt is redrawn again without the parasitic text>
$ ls

ioctl(TIOCSTI)

Ainda outro truque é vincular alguma chave não utilizada redraw-current-linecomo de costume e, em seguida, simular essa chave com o TIOCSTIioctl (ele ainda funciona sem privilégios extras noatualtty no Linux). Mas você precisaria de C, perl, python, etc para isso:

$ bind '"\xff": redraw-current-line'
$ redraw_current_line(){ perl -e 'ioctl STDIN, 0x5412, $x = "\xff"' </dev/tty; }
$ (sleep 2; echo foo; sleep 2; redraw_current_line) &
.... same as in SIGWINCH example ...

Este último truque é apenas para Linux; o número ioctl para TIOCSTIoutro sistema que possa suportá-lo é diferente.


Observação:se alguém achar que eu deveria, require "sys/ioctl.h"em vez de conectar o número ioctl:Não, eu não deveria. Mesmo que funcione por acaso emessecaso, o perl h2phestá instalado e os .pharquivos devemnãoser usado:

$ perl -e 'require "sys/ioctl.ph"; printf "%x\n", TIOCGPTN()'
80005430
$ cc -include stdio.h -include sys/ioctl.h -xc - \
   <<<'int main(){printf("%lx\n",TIOCGPTN);}' -o /tmp/foo && /tmp/foo
80045430

Observe a parte extra da coisa real 80045430:!80005430

informação relacionada