将 rlwrap 与 Node.js REPL 一起使用,节点 '.break' (Ctrl-C) 怎么可能不被 rlwrap 解释为 SIGINT?



在讨论了如何在会话之间保留命令行历史记录之后,我定义了以下别名:

alias node='env NODE_NO_READLINE=1 rlwrap node'

它非常适合历史持久性,但现在,每次我用Ctrl-C发送节点的".break"命令时,rlwrap也会接受它,但作为一个SIGINT:它会清除所有内容和自杀(如其手册页中所述),从而迫使我重新启动节点会话(必须调用我的var、funcs、requires等),而我只想".breach"…

有什么方法可以恢复经典的节点行为吗?

  • Ctrl-C:中断
  • 再次按Ctrl-C(或在空行上):退出

避免SIGINT

node通过取消设置其中断字符VINTR(通常为CTRL-C)来改变CTRL-C的含义,以避免它本来会得到的中断信号。

启动后,rlwrap一直处于睡眠状态,直到您的终端或node使用的伪终端(pty)上发生了一些事情。这个"某物"可以是您的按键,也可以是node的输出。

每次发生这种情况时,rlwrap都会将nodes的终端设置(包括VINTR))复制到自己的tty中。

然而,如果node更改其终端设置,则这本身不会唤醒rlwrap,从而将旧设置保留在自己的tty上。透明度将被破坏:当您按下CTRL-C时,rlwrap仍将其解释为SIGINT,而node将理解.break命令。

有一种特殊的、非常模糊的pty模式(EXTPROC),它允许pty主机(rlwrap)被从机在终端设置中的更改唤醒,但这是非常不可移植的。这就是为什么,自0.41版本以来,rlwrap有一个不那么优雅的--polling选项,它每40毫秒唤醒一次,并复制从属设备的终端设置。

转发CTRL-C

从0.43版本开始,rlwrap即使在读线模式下也可以通过绑定直接转发特殊密钥CCD_ 22中的CCD_ 21的这样一个密钥:

$if node
"C-c": rlwrap-direct-keypress
$endif

然而,当node本身使用readline(尝试NODE_NO_READLINE=1 node,然后键入CTRL-C)时,仅给予CTRL+C特殊处理

在这种情况下(即,当命令进行自己的行编辑时),必须强制rlwrap进入读行模式:

$ rlwrap --always-readline node

这有一个不幸而不可避免的缺点,那就是从来没有命令要求单一按键(Continue? Y/N)必须键入extra输入

然后仍然是上面概述的问题:如果终端的中断字符没有改变,node将永远看不到CTRL-C(而是得到SIGINT)

有两种解决方案。任一:

stty intr undef # disable interrupt character
rlwrap --always-readline node
stty intr '^c'  # re-enable CTRL-C

或:

rlwrap --polling --always-readline node # --polling means: continually wake up and wacth  node's interrupt character

包装

长话短说:

  • "C-c": rlwrap-direct-keypress添加到您的inputc
  • 暂时取消设置终端的中断字符,或如上所述使用rlwrap --polling --always-readline
  • 试着使用额外的Enter来实现单按键

相关内容

最新更新