本文学习和讨论bash的键绑定。

默认键绑定

bash manual学习了一下bash默认的emacs格式的键绑定:

  • 字符操作
    • 前进一个字符:c-f
    • 后退一个字符:c-b
    • 删除一个字符:DEL or BACKSPACE
    • 撤销一个操作:C-_ or C-X C-u
  • 词操作 (M代表Meta键,现在的键盘上很少有Meta键,通常用ALT键代替)
    • 前进一个单词:M-f
    • 后退一个单词:M-b
  • 行操作:
    • 移动到行首:C-a
    • 移动到行尾:C-b
  • 屏幕操作
    • 清除屏幕,只保留当前行:C-l
  • Kill/Yang(复制粘贴)
    • 消除至行尾:C-k
    • 前向消除一个单词:M-d (删除到M-f的位置)
    • 后向消除一个单词:M-DEL (删除到M-b的位置)
    • 向后消除一个单词即相应的空格:C-w
    • 拽回之前消除的内容:C-y
    • 在之前消除的内容链中做选择:M-y
      • M-0 3 l
      • M– C-k 消除至行首
      • M-0 9 C-d 向前消除9个字符
      • M– 9 C-d 向后消除9个字符
  • 搜索命令
    • 后向搜索历史 C-r
    • 前向搜索历史 C-s
    • 终止搜索历史 C-j
    • 推出搜索历史 C-g
  • 其他命令
    • 重新加载配置文件 C-x C-r

默认的键绑定难用的地方是很多操作需要辅助键(CTRL,META)的配合,但是这些辅助键在不同的键盘上有所区别,导致其不够通用。

下面关于Meta键的表述

The text M-k is read as ‘Meta-K’ and describes the character produced when the Meta key (if you have one) isdepressed, and the k key is pressed. The Meta key is labeled ALT on many keyboards. On keyboards with two keyslabeled ALT (usually to either side of the space bar), the ALT on the left side is generally set to work as a Metakey. The ALT key on the right may also be configured to work as a Meta key or may be configured as some othermodifier, such as a Compose key for typing accented characters.

If you do not have a Meta or ALT key, or another key working as a Meta key, the identical keystroke can be generatedby typing ESC first, and then typing k. Either process is known as metafying the k key.

The text M-C-k is read as ‘Meta-Control-k’ and describes the character produced by metafying C-k.

使用vi键绑定

vi键绑定或许是更通用的键绑定,因为它涉及到的辅助键比较少,主要使用不同的编辑模式来提供不同的功能。

在bash里面,可以使用set -o vi来切换到vi键绑定。如果在bash里面获取更多的关于键绑定的信息,可以使用bind -l或者bind -p命令。

下面是bind --help的输出

bind: bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
    Set Readline key bindings and variables.
    
    Bind a key sequence to a Readline function or a macro, or set a
    Readline variable.  The non-option argument syntax is equivalent to
    that found in ~/.inputrc, but must be passed as a single argument:
    e.g., bind '"\C-x\C-r": re-read-init-file'.
    
    Options:
      -m  keymap         Use KEYMAP as the keymap for the duration of this
                         command.  Acceptable keymap names are emacs,
                         emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
                         vi-command, and vi-insert.
      -l                 List names of functions.
      -P                 List function names and bindings.
      -p                 List functions and bindings in a form that can be
                         reused as input.
      -S                 List key sequences that invoke macros and their values
      -s                 List key sequences that invoke macros and their values
                         in a form that can be reused as input.
      -V                 List variable names and values
      -v                 List variable names and values in a form that can
                         be reused as input.
      -q  function-name  Query about which keys invoke the named function.
      -u  function-name  Unbind all keys which are bound to the named function.
      -r  keyseq         Remove the binding for KEYSEQ.
      -f  filename       Read key bindings from FILENAME.
      -x  keyseq:shell-command	Cause SHELL-COMMAND to be executed when
    				KEYSEQ is entered.
      -X                 List key sequences bound with -x and associated commands
                         in a form that can be reused as input.
    
    Exit Status:
    bind returns 0 unless an unrecognized option is given or an error occurs.

readline

bash使用的是readline这个库来进行命令行编辑。除了bash之外,还有其他程序使用到了readline这个库,如果想修改所有使用readline的程序的键绑定,可以修改readline的配置文件.inputrc,比如在里面把编辑模式修改成vi模式:

set editing-mode vi

更多关于readline配置的文档,可以参考

转义字符

字符终端一般使用转义字符序列来对终端做一些控制。像我们常用的ESC,TAB键等等都可以用转义字符的方式发给终端。下面是一段参考信息:

In addition, several keys have their own names. Specifically, DEL, ESC, LFD, SPC, RET, and TAB all stand for themselves when seen in this text, or in an init file (see Readline Init File). If your keyboard lacks a LFD key, typing C-j will produce the desired character. The RET key may be labeled Return or Enter on some keyboards.

命令行的infocmp或者tput之类的命令可以查看转义字符映射表。

不同的终端有不同的转义字符映射表,ANSI的有ANSI Escape sequences (ANSI Escape codes),XTERM的有XtermControlSequence等等。

其他

bash的搜索分为Incremental和Non-incremental两种,可以参考

后记

2019-08-07

发现一款工具hstr可以用来方便查阅命令行历史,支持bash和zsh。