我像这样定义了一个 shell 键绑定~/.bashrc
:
bind -x '"\e\C-w":"/usr/bin/reset"'
这确实使可执行文件Ctrl-Alt-w
启动reset
。但是,它会使终端处于类似于按 进入的状态Ctrl-v
。因此,例如,如果在以这种方式重置后立即按Ctrl-p
,而不是调用该快捷方式的操作(重复上一个命令),我会得到^P
打印。
知道是什么导致了这个问题以及如何解决它吗?
编辑:我附加了一个 Python 程序,它重现了我试图用reset
.我在调试多线程应用程序时经常遇到这种情况:
import pdb, thread, time
def interrupt():
time.sleep(2)
pdb.set_trace()
thread.start_new_thread(interrupt, ())
raw_input('? ')
pdb.set_trace()
要重现混乱的状态,只需运行上面的代码,然后在看到调用调试器时按 Enter(在运行程序并出现初始提示后大约两秒,它将打印一堆文本,以 结尾)。
答案1
运行reset
会清除终端显示并将所有输入设置重置为默认值。特别是,它将输入模式设置为煮熟的,即终端一次读取一行,然后将整行发送到应用程序(这里,应用程序是 bash)。终端的行编辑器是一种极其原始的编辑器,只能理解退格键,没有什么新奇的。 Bash 提供了一个复杂的行编辑器;它将终端切换到原始模式,每个字符在键入后立即发送到应用程序。
如果您发现自己的终端混乱(没有行版本或 bash 提示符下没有回显),最简单的恢复方法是运行命令reset
或stty sane
.通常您可以盲打它们并按Return。如果这不起作用(例如,因为终端处于熟模式并且行提交字符不是默认字符),您可以运行reset 2>/dev/pts/42
(终端重新初始化)或stty sane </dev/pts/42
(输入配置重新初始化)(注意不同的重定向),/dev/pts/42
其中运行 shell 的终端。如果无法在其中运行命令,则查找终端名称可能需要一些猜测。在终端内,该命令tty
将显示它。如果您可以在输出中找到正确的 bash 进程ps
,则您需要该TTY
列,/dev
前面带有。
通过在 bash 提示符下键入这些命令来运行这些命令是正确的,但将它们作为 readline 宏的一部分运行则不然。 Bash 每次打印新提示时都会重置终端设置,因此您在编辑一行期间所做的操作不会持续到后续命令为止。
此外,如果您在行reset
编辑期间运行,这会弄乱 bash 所依赖的参数:特别是,它将终端模式设置为“cooked”,而 bash 行编辑要求行编辑器逐字符接收输入。比较stty
bash 命令行版本期间和不在 bash 提示符下的输出,我认为这些是您需要的设置:
bind -x '"\e\C-w": "reset; stty -icrnl -icanon -echo </dev/tty"'
如果您reset
只是为了清除显示而调用,请调用而不是。tput rs1 rs2 rs3 rf
reset
正如我上面所写,重置终端设置的正确方法是reset
在 bash 提示符下运行。将其作为键绑定的一部分运行是行不通的,因为 bash 在显示下一个提示时会恢复上一个应用程序(导致终端设置混乱的应用程序)留下的设置。我不认为 bash 有任何内置功能可以将终端设置重置为正常的默认值,但如果需要,您可以通过用户配置来做到这一点,并在您的 中使用以下行.bashrc
:
PROMPT_COMMAND="$PROMPT_COMMAND
stty sane"
如果您确实希望有一个在行编辑期间重置终端设置的键绑定,那么您需要更复杂的东西。使 bashreset
在提示符下运行命令(而不是作为编辑命令的一部分),然后恢复当前编辑。这在 bash 中并不容易做到,因为绑定只能是 readline 宏或 bash 函数,但不能混合使用两者。以下代码将Ctrl+ Meta+绑定W到 readline 宏,该宏通过绑定调用 bash 函数,然后accept-line
通过其\C-m
绑定调用 readline 函数,然后通过另一个绑定调用另一个 bash 函数。这bind -x
绑定只能分配给长度为 1 或 2 的按键序列C-x LETTER
,所以我对辅助宏使用很少使用的组合。
run_command_during_line_edition () {
saved_READLINE_LINE=$READLINE_LINE saved_READLINE_POINT=$READLINE_POINT
READLINE_POINT=0 READLINE_LINE=" $1"
unset run_command_first
}
restore_saved_command () {
READLINE_LINE=$saved_READLINE_LINE READLINE_POINT=$saved_READLINE_POINT
unset saved_READLINE_LINE saved_READLINE_POINT
}
bind -x '"\C-xZ": "restore_saved_command"'
bind -x '"\C-xR": "reset; stty sane -icrnl -icanon -echo; run_command_during_line_edition reset"'
bind '"\e\C-w": "\C-xR\r\C-xZ"'
同样,您可能不需要所有这些复杂的操作 -reset
在提示符处盲目键入,或者包含stty sane
在您的 中PROMPT_COMMAND
,应该可以解决您的问题。哦,或者您可以切换到 zsh,这一切都会变得轻而易举。