bash:有没有办法以编程方式调用绑定命令(例如redraw-current-line)?

Bea*_*axi 2 bash readline

我遇到过许多关于如何redraw-current-line使用映射到击键的解释bind,但我想出于其他原因(例如计时器、后台作业)重新绘制提示,而无需用户输入击键。我以为这很容易,但我找不到任何东西。谢谢!

小智 6

我遇到了同样的问题,但没有找到令人满意的东西,所以这里有一些解决方法。

\n\n

${PS1@P}

\n\n

在较新的 bash 版本中,您可以使用 自行打印提示echo "${PS1@P}"。变量扩展的形式${var@P}是指在变量内部扩展提示转义符。

\n\n

kill -WINCH "$$"

\n\n

您可以尝试的另一个技巧是使用 杀死您的 shell SIGWINCH。这将导致 readline 重新绘制提示。例子:

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

ioctl(TIOCSTI)

\n\n

另一个技巧是redraw-current-line像往常一样绑定一些未使用的密钥,然后使用 ioctl 模拟该密钥(它仍然可以在 Linux 中的当前TIOCSTItty上运行,无需额外的特权)。但你需要 C、perl、python 等:

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

最后一个技巧仅适用于 Linux;TIOCSTI可能支持它的其他系统上的ioctl 编号是不同的。

\n\n
\n\n

注意:如果有人认为我应该require "sys/ioctl.h"而不是硬连线 ioctl 数字:不,我不应该即使在这种情况下偶然起作用,perl 的h2ph也是 b\xc3\xb8rked,并且不应使用这些.ph文件:

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

注意真实事物上的额外位:80045430!=80005430

\n