bash: Gibt es eine Möglichkeit, Bind-Befehle (z. B. „Aktuelle Zeile neu zeichnen“) programmgesteuert aufzurufen?

bash: Gibt es eine Möglichkeit, Bind-Befehle (z. B. „Aktuelle Zeile neu zeichnen“) programmgesteuert aufzurufen?

Ich bin auf eine Reihe von Erklärungen gestoßen, wie man redraw-current-linemit einem Tastendruck zuordnet bind, aber ich möchte die Eingabeaufforderung aus anderen Gründen (z. B. Timer, Hintergrundjob) neu zeichnen, ohne dass der Benutzer einen Tastendruck eingibt. Ich dachte, das wäre einfach, aber ich kann nichts finden. Danke!

Antwort1

Ich hatte das gleiche Problem, aber ich habe nichts zufriedenstellendes gefunden, daher hier einige Workarounds.

${PS1@P}

In neueren Bash-Versionen können Sie die Eingabeaufforderung einfach selbst ausdrucken echo "${PS1@P}". Die ${var@P}Form der Variablenerweiterungen bedeutet, Eingabeaufforderungs-Escapes innerhalb einer Variablen zu erweitern.

kill -WINCH "$$"

Ein weiterer Trick, den Sie ausprobieren können, besteht darin, Ihre Shell mit zu beenden SIGWINCH. Dadurch wird readline veranlasst, die Eingabeaufforderung neu zu zeichnen. Beispiel:

$ (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)

Ein weiterer Trick besteht darin, einen unbenutzten Schlüssel wie redraw-current-lineüblich zu binden und diesen Schlüssel dann mit dem TIOCSTIioctl zu simulieren (dies funktioniert immer noch ohne zusätzliche Berechtigungen auf demaktuelltty in Linux). Dafür benötigen Sie jedoch entweder C, Perl, Python usw.:

$ 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 ...

Dieser letzte Trick ist nur für Linux verfügbar. TIOCSTIAuf anderen Systemen, die ihn möglicherweise unterstützen, ist die Ioctl-Nummer anders.


Notiz:falls jemand meint, dass ich das tun sollte, require "sys/ioctl.h"anstatt die Ioctl-Nummer fest zu verdrahten:Nein, das sollte ich nicht. Selbst wenn es zufällig funktioniert inDasFall, Perl h2phist kaputt, und die .phDateien solltennichtverwendet werden:

$ 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

Beachten Sie das zusätzliche Bit im Original: 80045430!=80005430

verwandte Informationen