8.3 Readline 初始化文件(Readline Init File)

尽管 Readline 库默认安装的是类 Emacs 按键绑定集合,但其也可以使用不同的按键绑定集合。任何用户可以将命令放入“inputrc”文件对 Readline 的使用进行定制化编程。按照惯例,该文件放在该用户的家目录中。该文件的的文件名是从 shell 变量 INPUTRC 中获得的。如果该变量是未设置的,则默认文件名是“~/.inputrc”。如果该文件不存在或无法读取,最终会使用默认文件“/etc/inputrc”。内建命令 bind 也可用于设置 Readline 按键绑定和变量。参见 4.2《Bash 内建命令》。

当一个程序使用 Readline 库启动时,会读取该初始化文件,并且设置按键绑定。

还有,“C-x C-r”命令会重新读取该文件,因此可以使用该命令重新加载已变更的初始化文件。

8.3.1 Readline 初始化文件语法(Readline Init File Syntax)

在 Readline 初始化文件中只有很少的基本结构是允许使用的。空白行是会被忽略的。以“#”开头的行是注释行。以“$”开头的行代表条件结构(参见 8.3.2《条件初始结构》)。其它行用于表示变量设置和按键绑定。

变量设置

你可以在初始化文件中使用 set 命令来改变 Readline 中的变量值来修改 Readline 的运行时行为。其语法为:

set variable value

例如,如何将默认的类 Emacs 按键绑定变更到使用 vi 行编辑命令:“set editing-mode vi

正确的变量名和其值是可以被识别的,并且大小写不敏感。未被识别的变量名会被忽略。

布尔型变量(其可以设置为 on 或 off 的)如果其值是空(null)或空值(empty),或为大小写不敏感的“on”,或为 1,则被认为设置为“on”。任何其它值则被认为是设置成“off”。

“bind -V”命令列出了所有当前 Readline 的变量名和其值。参见 4.2《Bash 内建命令》。

改变运行时行为的一个很好的方法是改变下面的变量。

bell-style

控制在Readline想要敲响终端响铃时会发生什么。如果设置为“none”,Readline从来不会敲响铃。如果设置为“visible”,如果某个响铃可用,则使用该可见的响铃。如果设置为“audible”(默认值),Readline会试图敲响终端响铃。

bind-tty-special-chars

如果设置为“on”(默认值),Readline试图用由内核终端驱动特殊处理控制字符绑定到其等价Readline上。

blink-matching-paren

如果设置为“on”,Readline会试图在后半个小括号插入时将光标暂时移动到前半个小括号的位置。默认值为“off”。

colored-completion-prefix

如果设置为“on”,当列出补全时,Readline会使用不同颜色显示出可行补全集合的公共前缀。颜色的定义是来自于环境变量LS_COLORS的值。默认值为“off”。

colored-stats

如果设置为“on”,Readline在显示可行补全时使用不同的颜色来指明其文件类型。颜色的定义是来自于环境变量LS_COLORS的值。默认值为“off”。

comment-begin

当“insert-comment”命令执行时,该字符串会插入到一行的开始位置。其默认值为“#”。

completion-display-width

当执行这补全时,用于显示可行匹配的屏幕列宽的数量。如果该值小于零或大于终端屏幕的宽度,则忽略该值。设置为0会用每行显示一个匹配。默认值为“-1”。

completion-ignore-case

如果设置为“on”,Readline会使用大小写不敏感的方式来执行文件名匹配和补全。默认值为“off”。

completion-map-case

如果设置为“on”,并且“completion-ignore-case”也开启了,Readline会在执行大小写不敏感的文件名匹配和补全时视中横线“-”和下划线“_”相同。默认值为“off”。

completion-prefix-display-length

不带有修改的显示可行补全列表中公共前缀字符的长度。当该值设置为大于零时,在显示可行补全时公共前缀长度大于该值的字符会被替换为省略号。

completion-query-items

当询问用户是否要显示可行列表时,用于确定的可行补全数量。如果可行补全数量大于或等于该值,Readline会询问用户是否愿意查看它们;否则,就直接列出。该值必须设置为一个大于或等于0的整数。负数意味着Readline不会询问。默认值为100。

comvert-meta

如果设置为“on”,Readline会将带有第八位的字符剥去第八位转换为一个ASCII键序列,并在前面加入ESC字符为前缀将其转换为Meta为前缀的键序列。默认值为“on”,但如果本地区域语言是包含第八位字符的,该值将会设置为“off”。

disable-completion

如果设置为“on”,Readline会禁用单词补全。补全字符会被插入到行,就像其已映射到“self-insert”一样。默认值为“off”。

echo-control-characters

如果设置为“on”,表示在操作系统上支持该项,Readline会依据从键盘产生的信号对字符进行回显。默认值为“on”。

editing-mode

“editing-mode”变量控制着使用哪一个按键绑定的默认集。默认情况下,Readline会启动Emacs编辑模式,键盘输入习惯类似于Emacs。该变量可以设置为“emacs”或“vi”。

emacs-mode-string

如果开启了“show-mode-in-prompt”变量,当emacs编辑模式激活,在主提示符最后一行之前会立即显示该字符串。该值的扩展就像按键绑定一样,因此“meta-”的标准集、控制前缀和反斜线转义序列都是可用的。使用“\1”和“\2”转义为非打印字符的开头和结尾序列。该序列常用于将终端控制序列嵌入到模式字符串中。默认值为“@”。

enable-bracketed-paste

当该值设置为“on”,Readline将会配置终端,使其每一次粘贴插入到编辑缓冲中的字符作为一个字符串,而不是像从键盘读取每一个字符那样进行处理。这样能防止这些粘贴的字符翻译为编辑命令。默认值为“on”。

enable-keypad

如果该值设置为“on”,当调用小键盘应用程序时,Readline会试图开启它。一些系统需要开启该项来开启方向键。默认值为“off”。

enable-meta-key

如果该值设置为“on”,当调用终端声明支持的Meta修饰符键时,Readline会试图开启它。在多数终端上,Meta键一般发送八位的字符。默认值为“on”。

expand-tilde

如果该值设置为“on”,当Readline试图进行单词扩展时,可执行波浪号扩展。默认值为“off”。

history-preserve-point

如果该值设置为“on”,历史命令代码试图将当前光标位置放到由“previous-history”按键或“next-history”按键取回的历史命令行相同的位置。默认值是“off”。

history-size

设置能存储到历史命令列表中最大的历史条目数量。如果设置为零,任何现存的历史条目都会被删除并且不会有新条目存储。如果该值设置为小于零,则不会限制存储条目的数量。默认情况下,存储的条目数量是不限制的。如果将其设置为一个非数字型的值,历史条目的数量会被设为500。

horizontal-scroll-mode

该变量可以设置为“on”或“off”。设置为“on”,意味着当编辑的行文本的长度长于屏幕的宽度时,可以在屏幕单一行上进行水滚动,而不是折返到屏幕上新的一行上。该变量会自动为高度为1的终端设置为“on”。默认该变量为“off”。

input-meta

如果设置为“on”,Readline将会开启八位输入(其不会清除读取的字符中的第八位),而不管终端声明能否支持。默认值为“off”,但如果本地区域语言包含八位字符,Readline将会设置为“on”。该变量的代名词为“meta-flag”。

isearch-terminators

该字符串中的字符可终止增量搜索,并且不会将该字符作为后继命令执行(参见8.2.5《在历史中搜索命令》)。如果该变量没有给出值,按键“ESC”和“C-J”可终止增量搜索。

keymap

设置Readline用于按键绑定命令的当前按键映射方式。内建的按键映射名称有“emacs”、“emacs-standard”、“emacs-meta”、“emacs-ctlx”、“vi”、“vi-move”、“vi-command”和“vi-insert”。“vi”等同于“vi-command”(“vi-move”也是其代名词);“emacs”等同于“emacs-standard”。应用程序可添加额外的名称。默认值是“emacs”。变量“editing-mode”的值也会影响默认的按键映射。

keyseq-timeout

当Readline读取一个未确定的键序时,其所指定的持续等待的时间(其一是从输入到现在为止所形成的完整键序,或其间再输入更长键序)。如果在超时之前没有接收到输入,Readline将使用更短的但完整的键序。Readline使用该值来确定在当前输入源(默认是rl_instream)中的输入是否可用。该值是以毫秒为单位,所以值1000代表Readline将额外等待1秒的输入时间。如果该变量值设置为小于等于零,或为一个非数字值,Readline将会等待到另一个键按下后来决定补全哪个键序。默认值为500。

mark-directories

如果设置为“on”,完整的目录名会追加一个斜线。默认值为“on”。

mark-modified-lines

如果该变量设置为“on”,会使Readline在显示历史行时在已修改过的行首加入一个星号“*”。默认值为“off”。

mark-symlinked-directories

如果设置为“on”,链接到目录的软链接的完整名称会追加一个斜线(受限于“mark-directories”的值)。默认值为“off”。

match-hidden-files

该变量设置为“on”时,会在Readline执行文件名补全时匹配以“.”开头的文件名(即隐藏文件)。如果设置为“off”,文件名开头的“.”必须由用户显式提供才能进行文件名补全。默认值为“on”。

menu-complete-display-prefix

如果设置为“on”,在循环遍历可行补全列表之前,菜单补全会显示该列表的公共前缀(可能是空的)。默认值是“off”。

output-meta

如果设置为“on”,Readline会直接显示带有第八位设置的字符,而不是作为一个meta前缀转义字符显示。默认值是“off”。但如果本地区域语言包含八位字符,则Readline会将其设置为“on”。

page-completions

如果设置为“on”,Readline使用像内部命令more一样的分页一次显示一屏的可行补全。该变量默认值为“on”。

print-completions-horizontally

如果设置为“on”,Readline会水平显示按字母顺序排序的匹配补全,而不是从屏幕自上而下的。默认值为“off”。

revert-all-at-newline

如果设置为“on”,当执行“accept-line”(参见8.4.2《操纵历史命令》)时Readline将在返回之前撤消所有历史行的变更。默认情况下,历史行可以被修改并且保留在readline调用之间的单个撤消列表。默认值为“off”。

show-all-if-ambiguous

该项会改变补全函数的默认行为。如果设置为“on”,多于一个可行补全的单词可使匹配项立即列出,而不是进行响铃警告。默认值为“off”。

show-all-if-unmodified

该项会改变补全函数的默认行为,就像“show-all-if-ambiguous”的一样。如果设置为“on”,不带有部分可行补全(不共享公共前缀的可行补全)的多于一个可行补全的单词会使匹配项立即列出,而不是进行响铃警告。默认值为“off”。

show-mode-in-prompt

如果设置为“on”,则在提示符前加入一个字符串来指示编辑模式是“emacs”、“vi command”或是“vi insertion”。该模式字符串是用户可设置的(例如,在“emacs-mode-string”中)。默认值为“off”。

skip-completed-text

如果设置为“on”,当向行中插入一个单一匹配时,其会改变默认补全行为。其只会在单词中部执行补全时才会被激活。如果开启了该项,readline是不会在正在补全的单词中的光标点之后向匹配字符插入补全,所以跟在光标后的后半部分单词是不会重复的。例如,如果开启了该项后,当光标处于“Makefile”字符串中间的“e”的位置时试图进行补全,其只假设这是一个单一可行补全,则结果匹配为“Makefile”而不是“Makefilefile”。默认值为“off”。

vi-cmd-mode-string

如果变量“show-mode-in-prompt”开启了,当vi编辑模式激活并处于命令模式下,该字符串会立即显示在主提示符的最后一行之前。该值的扩展类似于一个按键绑定,所以“meta-”和“control”前缀的标准集和反斜线转义序列是可用的。使用“\1”和“\2”转义作为非打印字符的序列的开始和结尾,其常用于内嵌到模式字符串的终端控制序列中。默认值为“(cmd)”。

vi-ins-mode-string

如果变量“show-mode-in-prompt”开启了,当vi编辑模式激活并处于插入模式下,该字符串会立即显示在主提示符的最后一行之前。该值的扩展类似于一个按键绑定,所以“meta-”和“control”前缀的标准集和反斜线转义序列是可用的。使用“\1”和“\2”转义作为非打印字符的序列的开始和结尾,其常用于内嵌到模式字符串的终端控制序列中。默认值为“(ins)”。

visible-stats

如果设置为“on”,当列出可行补全时,表示文件类型的字符会追加到文件名后面。默认值为“off”。

按键绑定

在初始化文件中用于控制按键绑定的语法是比较简单的。首先你要找到你想要变更的命令名。下面的表包含命令名、默认按键绑定(如果有的话)和该命令是干什么用的简短说明。

一旦你知道了命令名,可以简单地将你要绑定到命令的按键名、一个冒号和命令名放入到初始化文件的一行里。在按键名和冒号之间可以没有空格,其会翻译为按键名的一部分。按键名可以使用不同的方式表示,这取决于你的习惯。

除此之外还有命令名。当按键按下之后(即一个宏命令),readline 会插入一个按键绑定的字符串。

“bind -p”(参见 4.2《Bash 内建命令》)命令会使用一种格式显示 Readline 函数名和其绑定。该格式可直接放入到初始化文件中。

keyname: function-name or macro

“*keyname*”是用英语拼写的按键名。例如:
    Control-u: universal-argument
    Meta-Rubout: backward-kill-word
    Control-o: "> output"
在上面的例子中,“C-u”绑定到“universal-argument”函数,“M-DEL”绑定到“backward-kill-word”函数,和“C-o”绑定到运行右侧宏表达式(即,将“> output”插入到行中)。
当处理按键绑定语法时,一些符号化字符名是可用的:DEL、ESC、ESCAPE、LFD、NEWLINE、RET、RETURN、RUBOUT、SPACE、SPC和TAB。

keyseq”: function-name or macro

“*keyseq*”不同于上面的“*keyname*”。其代表的是可指定的按键序列,由双引号括起来。下面例子中使用了一些GNU Emacs风格的按键转义,但特殊字符名是不会被识别的。
    "\C-u": universal-argument
    "\C-x\C-r": re-read-init-file
    "\e[11~": "Function Key 1"
在上面的例子中,“C-u”再一次绑定到“universal-argument”函数(就像在第一个例子中一样),“C-x C-r”绑定到“re-read-init-file”函数,“ESC[11~”绑定为插入文本“Function Key 1”。

在指定按键序列时,下列 GNU Emacs 风格的转义序列是可用的:

转义序列说明
\C-control 键前缀
\M-meta 键前缀
\e一个 ESC 键字符
\\反斜线
一个双引号
一个单引号

除了 GNU Emacs 风格的转义序列,另外还有一组反斜线转义是可用的:

转义序列说明
\a报警(响铃)
\b退格
\d删除
\f换页符
\n换行
\r回车
\t水平制表符
\v垂直制表符
\nnn八进制值 nnn(一到三位数字)代表的 8 位字符
\xHH十六进制值 HH(一到两位十六进制数字)代表的 8 位字符

当输入一个宏文本时,宏定义必须使用单引号或双引号指定。未被引起来的文本会被认为是函数名。在宏主体中,上面描述的反斜线转义是会被扩展的。在宏文本中反斜线会转义所有其它字符,包括双引号和单引号。例如,下面的绑定“C-x \”会将一个单反斜线“\”插入到行中:

"\C-x\\": "\\"

8.3.2 条件初始化结构(Conditional Init Constructs)

Readline 会执行一个在思想上与 C 预处理程序的条件编译特性类似的特殊功能,其允许按键绑定与变量设置作为条件测试结果执行。这里有四种解析指令可直接使用。

$if

“$if”语句结构可以基于编辑模式、终端使用或使用 Readline 的应用程序来对绑定进行设置。在任意比较操作符之后的测试条件文本可扩展到该行的末尾;除非有其它注解,无需用字符来隔离测试文本。

mode
“$if”指令的“mode=”形式用于测试Readline是处于emacs模式还是vi模式。其可以用于和“set keymap”命令连接。例如,只有在Readline启动于emacs模式时才可在“emacs-standard”和“emacs-ctlx”中设置绑定。

term
“term=”形式可用于包含终端特定的按键绑定,也可由终端功能键绑定按键序列输出。在等号“=”右边的单词是条件测试对象,即可以是终端的全名,也可以是终端名称中第一个“-”线前面的部分名称。例如,“sun”和“sun-cmd”两个都可以使用“sun”匹配。

version
“version”条件测试可用于执行特定Readline版本的比较。“version”扩展为当前Readline的版本。比较操作符包括“=”(和“==”)、“!=”、“<=”、“>=”、“<”和“>”。在操作符右侧的版本号由主版本号、一个可选的小数点和一个可选的小版本号(例如,7.1)组成。如果省略了小版本号,则假设其值为“0”。可以用空格将操作符与字符串“version”和版本号参数分隔开。下面的例子是为大于等于7.0版本的Readline设置一个变量:
    $if version >= 7.0
    set show-mode-in-prompt on
    $endif

application
“application”结构用于包含应用程序特定的设置。每一个程序都使用Readline库设置“application name”,并且可以为特定值进行条件测试。这可以用于为特定程序绑定按键序列以实现有用的功能。例如,下面的例子会在Bash中为当前或上一个单词添加引号绑定一个按键序列:
    $if Bash
    # Quote the current or previous word
    "\C-xq": "\eb\"\ef\""
    $endif

variable
“variable”结构为Readline变量和值提供了简单的等式测试。其只允许使用比较操作符“=”、“==”和“!=”。变量名必须使用空格与比较操作符分隔;可以使用空格将操作符与右侧的值进行分隔。字符串与布尔型变量都可以进行条件测试。布尔型变量必须与“on”或“off”值进行条件测试。下面的例子等同于上面的“mode=emacs”的条件测试:
    $if editing-mode == emacs
    set show-mode-in-prompt on
    $endif

$endif

在上面的各个例子中出现的“$endif”是用于终止“$if”命令。

$else

该命令是“$if”指令的分支,是在条件测试失败后执行的。

$include

该指令是拿一个文件名作为参数,并从该文件中读取命令和绑定。例如,下面的指令是读取“/etc/inputrc”: $include /etc/inputrc

8.3.3 初始化文件实例(Sample Init Constructs)

这是一个 inputrc 文件的例子。其展示了按键绑定、变量赋值和条件判断语句。

# This file controls the behaviour of line input editing for
# programs that use the GNU Readline library. Existing
# programs include FTP, Bash, and GDB.
#
# You can re-read the inputrc file with C-x C-r.
# Lines beginning with ’#’ are comments.
#
# First, include any system-wide bindings and variable
# assignments from /etc/Inputrc
$include /etc/Inputrc
#
# Set various bindings for emacs mode.
set editing-mode emacs
$if mode=emacs
Meta-Control-h: backward-kill-word Text after the function name is ignored
#
# Arrow keys in keypad mode
#
#"\M-OD": backward-char
#"\M-OC": forward-char
#"\M-OA": previous-history
#"\M-OB": next-history
#
# Arrow keys in ANSI mode
#
"\M-[D": backward-char
"\M-[C": forward-char
"\M-[A": previous-history
"\M-[B": next-history
#
# Arrow keys in 8 bit keypad mode
#
#"\M-\C-OD": backward-char
#"\M-\C-OC": forward-char
#"\M-\C-OA": previous-history
#"\M-\C-OB": next-history
#
# Arrow keys in 8 bit ANSI mode
#
#"\M-\C-[D": backward-char
#"\M-\C-[C": forward-char
#"\M-\C-[A": previous-history
#"\M-\C-[B": next-history
C-q: quoted-insert
$endif
# An old-style binding. This happens to be the default.
TAB: complete
# Macros that are convenient for shell interaction
$if Bash
# edit the path
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
# prepare to type a quoted word --
# insert open and close double quotes
# and move to just after the open quote
"\C-x\"": "\"\"\C-b"
# insert a backslash (testing backslash escapes
# in sequences and macros)
"\C-x\\": "\\"
# Quote the current or previous word
"\C-xq": "\eb\"\ef\""
# Add a binding to refresh the line, which is unbound
"\C-xr": redraw-current-line
# Edit variable on current line.
"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
$endif
# use a visible bell if one is available
set bell-style visible
# don’t strip characters to 7 bits when reading
set input-meta on
# allow iso-latin1 characters to be inserted rather
# than converted to prefix-meta sequences
set convert-meta off
# display characters with the eighth bit set directly
# rather than as meta-prefixed characters
set output-meta on
# if there are 150 or more possible completions for a word,
# ask whether or not the user wants to see all of them
set completion-query-items 150
Chapter 8: Command Line Editing 128
# For FTP
$if Ftp
"\C-xg": "get \M-?"
"\C-xt": "put \M-?"
"\M-.": yank-last-arg
$endif