Используя rlwrap с Node.js REPL, как узел '.break' (Ctrl-C) не может быть интерпретирован rlwrap как SIGINT?
После этого обсуждения о том, как сохранить историю командной строки между сессиями, я определил следующий псевдоним:
alias node='env NODE_NO_READLINE=1 rlwrap node'
Он отлично работает для сохранения истории, но теперь, каждый раз, когда я делаю Ctrl-C, чтобы отправить команду узла.break, rlwrap принимает ее тоже, но как SIGINT: он очищает все и самоубийства (как описано на его man-странице), таким образом вынуждая меня перезапустить сессию узла (вызывая мои var, funcs, require и т. д.), в то время как я просто хотел ".break"...
Есть ли способ вернуть классическое поведение узла?
- Ctrl-C: разрывы
- Ctrl-C снова (или на пустой строке): выход
1 ответ
Избегая SIGINT
node
изменяет значение CTRL-C, сбрасывая его символ прерывания VINTR
(обычно CTRL-C), чтобы избежать сигнала прерывания, который он получил бы в противном случае.
После запуска rlwrap
спит все время, пока что-то не происходит на вашем терминале или на псевдотерминале (pty
) используется, например, node
, Это "что-то" может быть нажатием клавиши вами или выводом из 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
может напрямую переадресовывать специальные ключи даже в режиме readline, связывая такой ключ с rlwrap-direct-keypress
в ~/.inputrc
:
$if node
"\C-c": rlwrap-direct-keypress
$endif
Тем не мение, node
CTRL+C предоставляет специальную обработку только тогда, когда он сам использует readline (попробуйте NODE_NO_READLINE=1 node
а затем наберите CTRL-C), чтобы увидеть, что я имею в виду)
В таких случаях (т. Е. Когда команда выполняет собственное редактирование строки), необходимо rlwrap
в режиме readline:
$ rlwrap --always-readline node
Это имеет неприятный и неизбежный недостаток, когда команда запрашивает одиночные нажатия клавиш (Continue? Y/N
) нужно ввести дополнительный Enter.
И еще есть проблема, набросанная выше: если символ прерывания терминала не изменился, 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 для одиночных нажатий клавиш