Vim键盘映射

发布时间:2016-7-5 16:30
分类名称:Linux


最简单的形式是将一个键输入序列映射到一个键上。由于那些除了 <F1> 外的功能键
都没有预先定义的功能,选择它们作为映射对象是很有效的。例如: >

    :map <F2> GoDate: <Esc>:read !date<CR>kJ

这显示了如何使用三种不同的运行模式。在用 "G" 移动到最后一行后,"o" 命令开始一
个新行并开始插入模式。然后文本 "Date: " 被输入并用 <Esc> 离开插入模式。
注意在 <> 内使用的特殊键。这叫尖括号记法。你要分别地输入这些字符,而不是键
入要表示的键本身。这使得映射更具可读性,而且你也可以方便地拷贝,粘贴文本。
":" 使得 Vim 回到命令行。":read !date" 命令读取 "date" 命令的输出并添加到当
前行之下。<CR> 是用来执行该命令的。
到此为止,文本看起来像:

    Date: ~
    Fri Jun 15 12:54:34 CEST 2001 ~

然后 "kJ" 将光标上移并将两行连接起来。


映 射 与 运 行 模 式

":map" 命令定义普通模式的键映射。你也可以为其它运行模式定义映射。例如,":imap"
用来定义插入模式的映射。你可以用它来定义一个插入日期的映射: >

    :imap <F2> <CR>Date: <Esc>:read !date<CR>kJ

看起来很象前面为普通模式定义的 <F2> 映射。只是开始的地方有所不同。普通模式下的
<F2> 映射依然有效。这样你就可以在各种模式下为同一映射键定义不同的映射。
应该注意的是,虽然这个映射以插入模式开始,但它却以普通模式结束。如果你希望
继续插入模式,可以在最后加上 "a"。

下面是一个映射命令及其生效模式的总览:

    :map        普通,可视模式及操作符等待模式
    :vmap        可视模式
    :nmap        普通模式
    :omap        操作符等待模式
    :map!        插入和命令行模式
    :imap        插入模式
    :cmap        命令行模式


操作符等待模式是当你键入一个操作符 (比如 "d" 或 "y") 之后,Vim 期待你键入一个
动作命令或者文本对象时的状态。比如,当你键入命令 "dw", 那个 "w" 就是在操作符
等待模式下键入的。

假定你想定义映射 <F7> 使得命令 d<F7> 删除一个 C 程序块 ({} 包括的文本)。类似的
y<F7> 会将程序块拷贝到匿名的寄存器。因此,你所要做的就是定义 <F7> 来选择当前的
语法块。你可以用下面的命令做到: >

    :omap <F7> a{

这使得 <F7> 在操作符等待模式下选择一个块,就像是你键入了 "a{" 一样。这个映射在
你不容易键入 { 时比较有用。


映 射 列 表

要查看当前定义的映射,使用不带参数的 ":map" 命令。或者其它运行模式的变体。输出
应该类似于:

     _g         :call MyGrep(1)<CR> ~
    v <F2>         :s/^/> /<CR>:noh<CR>`` ~
    n <F2>         :.,$s/^/> /<CR>:noh<CR>`` ~
     <xHome>     <Home>
     <xEnd>     <End>


第一列显示该映射有效的运行模式。"n" 表示普通模式,"i" 表示插入模式,等等。空白
表示用 ":map" 命令定义的映射,也就是对普通和可视模式有效。
列出映射的一个比较实用的目的是检查 <> 表示的特殊键是否被识别了 (仅当支持多
色彩是有效)。例如,当 <Esc> 被用彩色显示时,它表示转义字符。否则,只是 5 个不
同的字符。


重 映 射

映射的结果会检查其中包括的其他映射。例如,上面对 <F2> 的映射可以减短为: >

    :map <F2> G<F3>
    :imap <F2> <Esc><F3>
    :map <F3> oDate: <Esc>:read !date<CR>kJ

在普通模式下 <F2> 被映射为: 行进至最后一行,然后输入 <F3>;在插入模式下先键入
<Esc> 后也输入 <F3>。接下来 <F3> 也被映射,执行真正的工作。

假设你几乎不使用 Ex 模式,并想用 "Q" 命令来排版文本 (就像旧版本的 Vim 那样)。
下面的映射就能做到: >

    :map Q gq

但是,你总有需要用到 Ex 模式的时候。我们来将 "gQ" 映射为 Q,这样你仍然可以进入
Ex 模式: >

    :map gQ Q

这样一来当你键入 "gQ" 时它被映射为 "Q"。到现在为止一切顺利。但由于 "Q" 被映射
为 "gq", 输入的 "gQ" 被解释成为 "gq", 你根本就没进入 Ex 模式。
要避免键被再次映射,使用 ":noremap" 命令: >

    :noremap gQ Q

现在 Vim 就知道了对 "Q" 不需要检查与之相关的映射。对于每个模式都有一个类似的命
令:

    :noremap    普通,可视和操作符等待模式
    :vnoremap    可视模式
    :nnoremap    普通模式
    :onoremap    操作符等待模式
    :noremap!    插入和命令行模式
    :inoremap    插入模式
    :cnoremap    命令行模式



递 归 映 射

当一个映射调用它本身的时候,会无限制的运行下去。这可以被用来无限次重复一个操
作。
例如,你有一组文件,每个的第一行都包括一个版本号。你用 "vim *.txt" 来编辑它
们。你现在正在编辑第一个文件。定义下面的映射: >

    :map ,, :s/5.1/5.2/<CR>:wnext<CR>,,

现在当你键入 ",," 时,上面的映射被触发。它把第一行的 "5.1" 替换为 "5.2"。接着
执行 ":wnext" 来写入文件并开始编辑下一个。映射以 ",," 结束。这又触发了同一个映
射,再次执行替换操作,依此类推。
这个映射会一直进行下去,直至遇到错误为止。在这里可能是查找命令无法匹配到
"5.1" 。你可以自行插入 "5.1" 然后再次键入 ",,"。或者 ":wnext" 因为遇到最后一个
文件而失败。
当映射在中途遇到错误时,映射的剩余部分会被放弃。你可用 CTRL-C 中断映射。(在
MS-Windows 上用 CTRL-Break)。


删 除 映 射

要删除一个映射,使用 ":unmap" 命令。同样,删除映射的命令也和运行模式相关:

    :unmap        普通,可视和操作符等待模式
    :vunmap        可视模式
    :nunmap        普通模式
    :ounmap        操作符等待模式
    :unmap!        插入和命令行模式
    :iunmap        插入模式
    :cunmap        命令行模式


这里有个小技巧可以定义一个对普通模式和操作符等待模式有效而对可视模式无效的映
射: 先对三个模式都定义映射,然后将可视模式的那个删除: >

    :map <C-A> /---><CR>
    :vunmap <C-A>

注意那 5 个字符 "<C-A>" 表示一个键组合 CTRL-A。

要清除所有的映射,使用 |:mapclear| 命令。现在你应该可以猜到各种模式下的变体了
吧。要当心使用这个命令,它不可能被撤销。


特 殊 字 符

在 ":map" 命令后面可以追加另一个命令。需要用 | 字符来将两个命令分开。这也就意
味着一个映射中不能直接使用该字符。需要时,可以用 <Bar> (五个字符)。例如:
>
    :map <F8> :write <Bar> !checkin %<CR>

":unmap" 命令有同样的问题,而且你得留意后缀的空白字符。下面两个命令是不同的:
>
    :unmap a | unmap b
    :unmap a| unmap b

第一个命令试图删除映射 "a ",后面带有一个空格。

当要在一个映射内使用空格时,应该用 <Space> (七个字符): >

    :map <Space> W

这使得空格键移动到下一个空白字符分割的单词。

在一个映射后不能直接加注释,因为 " 字符也被当作是映射的一部分。你可以用 |" 绕
过这一限制。这实际上是开始一个新的空命令。例如: >

    :map <Space> W| " Use spacebar to move forward a word


映 射 与 缩 写

缩写和插入模式的映射很象。对参数的处理它们是一样的。它们主要的不同在于触发的方
式。缩写是由单词之后的非单词字符触发的。而映射由其最后一个字符触发。
另一个区别是你键入的缩写的字符会在你键入的同时被插入到文本内。当缩写被触发
时,这些字符会被删除并替换成缩写所对应的字符。当你键入一个映射时,直到你完成所
有的映射键而映射被触发时,映射所对应的内容才会被插入。如果你置位 'showcmd' 选
项,键入的字符会显示在 Vim 窗口的最后一行。
有一个例外是当映射有歧义的时候。假定你有两个映射: >

    :imap aa foo
    :imap aaa bar

现在,当你键入 "aa" 时,Vim 不知道是否要使用第一个映射。它会等待另一个键输入。
如果是 "a",第二个映射被执行,结果是 "bar"。如果是其它字符,例如空格,第一个映
射被执行,结果是 "foo", 而且空格字符也会被插入。


另 外 ...

<script> 关键字可以被用来使一个映射仅对当前脚本有效。参见 |:map-<script>|。

<buffer> 关键字可以被用来使一个映射仅对当前缓冲区有效。参见 |:map-<buffer>|。

<unique> 关键字可以被用来当一个映射已经存在时不允许重新定义。否则的话新的映射
会简单的覆盖旧的。参见 |:map-<unique>|。

如果要使一个键无效,将之映射至 <Nop> (五个字符)。下面的映射会使 <F7> 什么也干
不了: >

    :map <F7> <Nop>| map! <F7> <Nop>

注意 <Nop> 之后一定不能有空格。
===============================================
标识符        含义             等价于    十进制数值    ~
-----------------------------------------------------------------------
<Nul>        零            CTRL-@     0 (存储为 10) *<Nul>*
<BS>        退格键            CTRL-H     8    *backspace*
<Tab>        制表符            CTRL-I     9    *tab* *Tab*
                            *linefeed*
<NL>        换行符            CTRL-J     10 (用作 <Nul>)
<FF>        换页符            CTRL-L     12    *formfeed*
<CR>        回车符            CTRL-M     13    *carriage-return*
<Return>    同 <CR>                    *<Return>*
<Enter>        同 <CR>                    *<Enter>*
<Esc>        转义            CTRL-[     27    *escape* *<Esc>*
<Space>        空格                 32    *space*
<lt>        小于号            <     60    *<lt>*
<Bslash>    反斜杠            \     92    *backslash* *<Bslash>*
<Bar>        竖杠            |    124    *<Bar>*
<Del>        删除                127
<CSI>        命令序列引入        ALT-Esc    155    *<CSI>*
<xCSI>        图形界面的 CSI                 *<xCSI>*

<EOL>        行尾 (可以是 <CR>、<LF> 或 <CR><LF>,
        根据不同的系统和 'fileformat' 而定)    *<EOL>*

<Up>        光标上移键            *cursor-up* *cursor_up*
<Down>        光标下移键            *cursor-down* *cursor_down*
<Left>        光标左移键            *cursor-left* *cursor_left*
<Right>        光标右移键            *cursor-right* *cursor_right*
<S-Up>        Shift+光标上移键
<S-Down>    Shift+光标下移键
<S-Left>    Shift+光标左移键
<S-Right>    Shift+光标右移键
<C-Left>    Control+光标左移键
<C-Right>    Control+光标右移键
<F1> - <F12>    功能键 1 到 12            *function_key* *function-key*
<S-F1> - <S-F12> Shift+功能键 1 到 12        *<S-F1>*
<Help>        帮助键
<Undo>        撤销键
<Insert>    Insert 键
<Home>        Home                *home*
<End>        End                *end*
<PageUp>    Page-up                *page_up* *page-up*
<PageDown>    Page-down            *page_down* *page-down*
<kHome>        小键盘 Home (左上)        *keypad-home*
<kEnd>        小键盘 End (左下)        *keypad-end*
<kPageUp>    小键盘 Page-up (右上)        *keypad-page-up*
<kPageDown>    小键盘 Page-down (右下)        *keypad-page-down*
<kPlus>        小键盘 +            *keypad-plus*
<kMinus>    小键盘 -            *keypad-minus*
<kMultiply>    小键盘 *            *keypad-multiply*
<kDivide>    小键盘 /            *keypad-divide*
<kEnter>    小键盘 enter            *keypad-enter*
<kPoint>    小键盘 小数点            *keypad-point*
<k0> - <k9>    小键盘 0 到 9            *keypad-0* *keypad-9*
<S-...>        Shift+键            *shift* *<S-*
<C-...>        Control+键            *control* *ctrl* *<C-*
<M-...>        Alt+键 或 meta+键        *meta* *alt* *<M-*
<A-...>        同 <m-...>            *<A-*
<D-...>        Command+键 (只用于苹果机)    *<D-*
<t_xx>        termcap 里的 "xx" 入口键
-----------------------------------------------------------------------

备注: Shift+方向键,帮助键和撤销键只在少数终端里有效。在 Amiga 机器上,Shift
+功能键 10 生成命令序列引入码 (CSI),也用于键序列。只有再按一个键,该代码才能
被识别出来。

备注: Delete 键有两个键码。一般是十进制的 ASCII 码 127,这个总能认出来。但有些
delete 键会发送 termcap 入口项 "kD" 的值。这两个值有同样的效果。
参见 |:fixdel|。

备注: 小键盘上的按键与其对应的 "正常" 按键一样。例如,<kHome> 与 <Home> 有同样
的效果。如果小键盘上的键发送的原始键码与 "正常" 键相同,那么将被认为是按下了
"正常" 键。例如,如果 <kHome> 发送的键码与 <Home> 相同,当按下 <khome> 的时
候,Vim 会认为你按下了 <Home>。<kHome> 的映射此时不会有效。

                                *<>*
例子中经常使用 <> 记法。有时这只是用来说明你需要输入什么,但经常它需要照本义键
入,例如在 ":map" 命令里。规则是:
1. 任何可显示的字符都可以直接键入,反斜杠和 '<' 除外。
2. 反斜杠用两个反斜杠表示 "\\",或者用 "<Bslash>"。
3. 真正的 '<' 用 "\<" 或 "<lt>" 表示。只有在没有歧义的时候才可以直接用 '<'
表示。
4. "<key>" 的意思是特殊键。其含义上面的表格都有介绍,下面是一些例子:
     <Esc>        Escape 键
     <C-G>        CTRL-G
     <Up>            光标上移键
     <C-LeftMouse>    Control+鼠标左键点击
     <S-F11>        Shift+功能键 11
     <M-a>        Meta- a (第 8 位置位的 'a')
     <M-A>        Meta- A (第 8 位置位的 'A')
     <t_kd>        termcap 的 "kd" 入口 (光标下移键)

如果你想在 Vim 里使用 <> 的完整记法,必须确定 'cpoptions' 里不包括 '<' 标志位
(如果没有置位 'compatible',默认值就是这样)。 >
    :set cpo-=<
这里,<> 记法使用 <lt> 来抵消键名的特殊含义。使用反斜杠也可以,但是需要去掉
'cpoptions' 里的 'b' 标志位。

下面的例子是把 CTRL-H 映射成六个字符 "<Home>":
    :imap <C-H> \<Home>
    :imap <C-H> <lt>Home>
第一种方法只有在 'cpoptions' 里没有 'B' 标志位才好用。第二种总成立。
要在映射中得到按本义出现的 "<lt>" 这几个字符: >
    :map <c-l> <lt>lt>

对于映射,缩写和菜单命令你可以用复制-粘贴直接使用手册里的例子。你也可以手动键
入它们,包括 '<' 和 '>'。但是在其它命令里,比如 ":set" 和 "autocmd",这是_不_
行的!