cmdline

cmdline.txt 适用于 Vim 9.0 版本。 最近更新: 2022年7月 VIM 参考手册 by Bram Moolenaar 译者: Dasn、tocer Cmdline-mode Command-line-mode 命令行模式 Cmdline Command-line mode-cmdline : 命令行模式可以用来输入 Ex 命令 (":"),搜索符合模式的字符串 ("/" 和 "?"),和过 滤命令 ("!")。 一些基本的、与命令行编辑相关的内容在用户手册的第 20 章里有所描述,见: usr_20.txt 。 1. 命令行编辑 cmdline-editing 2. 命令行补全 cmdline-completion 3. Ex 命令行 cmdline-lines 4. Ex 命令行的范围 cmdline-ranges 5. Ex 命令行的标志位 ex-flags 6. Ex 特殊字符 cmdline-special 7. 命令行窗口 cmdline-window

1. 命令行编辑 cmdline-editing

通常,字符会在光标位置前插入。你可以用键盘上的左右键来移动光标的位置。还可以通 过 <Insert> 键,在 "插入" 和 "替换" 两种模式之间切换。 注意,如果你的键盘上没有可以移动光标的键或其它特殊键,你可以用 ":cnoremap" 定 义另外一个键来代替它们。例如,定义一组 tcsh 风格的键: tcsh-style :cnoremap <C-A> <Home> :cnoremap <C-F> <Right> :cnoremap <C-B> <Left> :cnoremap <Esc>b <S-Left> :cnoremap <Esc>f <S-Right> (<> 记法,见 <> ;上面的例子要一字不落地输入) cmdline-too-long 当命令行指令长度大于屏幕的宽度时,只有合适的部分被显示出来。光标只能在命令的 可视部分移动,所以你不能编辑其他部分。 cmdline-history history 在命令行里输入的命令会存储在历史记录中,你可以使用上下箭头键来翻阅它们。有五个 历史表: - 一个是为 ':' 命令准备的 - 一个是为搜索字符串准备的 - 一个是为表达式准备的 - 一个是为输入行准备的,用来输入 input() 函数。 - 一个是为调试模式下的命令准备的 这些记录是完全分开的。每一种输入模式只能访问与之相关的一个记录。 选项 'history' 用来设定保存历史记录的行数 (默认值: 50 ) 。 注意: - 如果你输入了一条命令与历史记录中已有的命令完全相同,那么历史记录中的这条旧命 令会被删除 (这样做是为了避免历史列表被大量的重复指令占据)。 - 只有键入的命令才会记录下来。完全来自映射的命令不会。 - 所有的搜索操作都会放到与搜索相关的历史记录中,包括通过 "*" 和 "#" 进行的搜 索。但是对于映射,只有最近一次的搜索会被记录下来 (这样是为了避免很长的映射把 历史记录搞乱) 。 {仅当编译的时候加入 +cmdline_hist 特性才可用} 命令行的自动匹配功能;见 cmdline-completion c_CTRL-V CTRL-V 下一个字符如果是非数字字符,按本义插入。不然,不超过三个的数字 字符可用于输入单个字节的十进制编码。这里的非数字和三个数字字符 不经过映射。与插入模式下该键的工作方式相同 (见 i_CTRL-V )。 注意: 由于在 MS-Windows 系统上,CTRL-V 被映射为 "粘贴文本",这 时我们要用 CTRL-Q 代替 CTRL-V。 如果打开 modifyOtherKeys ,特殊转义序列被转换回没有 modifyOtherKeys 时的样子,除非同时按住 Shift 键。 c_CTRL-Q CTRL-QCTRL-V 相同。但是有些终端把它定义为控制字符,那样就无法使用 了。 CTRL-SHIFT-V c_CTRL-SHIFT-V c_CTRL-SHIFT-Q CTRL-SHIFT-Q 与 CTRL-V 类似,除非激活了 modifyOtherKeys ,此时插入带修饰符 的键的转义序列。 GUI 里插入 key-notation ,不经简化。 c_<Left> c_Left <Left> 光标左移 c_<Right> c_Right <Right> 光标右移 c_<S-Left> <S-Left><C-Left> c_<C-Left> 光标左移一个字串 (WORD) c_<S-Right> <S-Right><C-Right> c_<C-Right> 光标右移一个字串 (WORD) CTRL-B<Home> c_CTRL-B c_<Home> c_Home 光标移动至命令的起始 CTRL-E<End> c_CTRL-E c_<End> c_End 光标移动至命令的末尾 c_<LeftMouse> <LeftMouse> 将光标置于点击鼠标的地方。 c_<MiddleMouse> <MiddleMouse> 粘贴剪贴板的内容 (X11 而言是 PRIMARY 选择区)。和 CTRL-R * 类 似,但行间不插入 CR 字符。 CTRL-H c_<BS> c_CTRL-H c_BS <BS> 删除光标前面的字符 (如果你的 <BS> 键不能正常工作,请参阅 :fixdel )。 c_<Del> c_Del <Del> 删除光标下的字符 (如果光标处于行的末尾,则删除光标前的字符) (如果你的 <Del> 键不能正常工作,请参阅 :fixdel )。 c_CTRL-W CTRL-W 删除光标前的单词 ( word )。单词范围受 'iskeyword' 选项影响。 c_CTRL-U CTRL-U 删除光标所在位置与行首之间的所有字符。先前一些版本的 vim 删 除整行的所有字符。如果你喜欢原先的这种方式,可以把下面的命令 加入到你的 .vimrc : :cnoremap <C-U> <C-E><C-U> c_<Insert> c_Insert <Insert> 在插入和替换之间切换。 {char1} <BS> {char2} c_digraph CTRL-K {char1} {char2} c_CTRL-K 输入二合字母 (见 digraphs )。如果 {char1} 是一个特殊键,插入 该键 <> 形式的编码。 CTRL-R {register} c_CTRL-R c_<C-R> 插入寄存器里的内容。当按下 CTRL-R 时,屏幕会显示一个 '"' 字 符,提示你输入一个寄存器的名字。 插入的文字就像是你自己输入的,但是映射和缩写不会生效。同样也不 会触发 'wildchar' 的补全功能。并且那些可以结束命令的字符会被按 字面插入 (<Esc><CR><NL><C-C>)。但 <BS>CTRL-W 仍旧可 能结束命令行模式,并使剩余的字符被接下来其他的模式解释,这可能 并非你的本意。 特殊寄存器: '"' 无名寄存器,包含最近一次删除或复制的内容 '%' 当前文件名 '#' 轮换文件名 '*' 剪贴板的内容 (X11: 主选择区) '+' 剪贴板的内容 '/' 最近一次的查找模式 ':' 最近一次在命令行输入的命令 '-' 最近一次小的 (少于一行) 删除 '.' 最近插入的文本 c_CTRL-R_= '=' 表达式寄存器: 会提示你输入一个表达式。 (见 expression ) (在表达式提示中无效;不允许改变缓冲区或者当前 窗口这样的操作,以避免副作用) 如果结果为 List 列表,其中的每一项当作一行。 当然其中内容也可包含换行符。 如果结果为浮点数,自动转换为字符串。 注意 如果只想要移动光标而不插入内容,要确保表 达式计算为空串。例如: <C-R><C-R>=setcmdpos(2)[-1]<CR> 与寄存器相关的内容请参见 registers 。 实现细节: 如果使用 expression 寄存器并且调用 setcmdpos(),那 么在插入返回的文本之前设置光标位置。使用 CTRL-R CTRL-R 在插入 返回的文本之后设置光标位置。 CTRL-R CTRL-F c_CTRL-R_CTRL-F c_<C-R>_<C-F> CTRL-R CTRL-P c_CTRL-R_CTRL-P c_<C-R>_<C-P> CTRL-R CTRL-W c_CTRL-R_CTRL-W c_<C-R>_<C-W> CTRL-R CTRL-A c_CTRL-R_CTRL-A c_<C-R>_<C-A> CTRL-R CTRL-L c_CTRL-R_CTRL-L c_<C-R>_<C-L> 插入光标下的对象: CTRL-F 光标下的文件名 CTRL-P'path' 扩展的光标下的文件名。与 gf 中的类似。 CTRL-W 光标下的单词 CTRL-A 光标下的字串;参见: WORD CTRL-L 光标下的文本行 如果置位 'incsearch',使用当前显示匹配文本的末尾作为光标位置。 使用 CTRL-W 时,已经录入的单词部分不再重复插入。 CTRL-FCTRL-P: {仅当包含 +file_in_path 特性才可用} c_CTRL-R_CTRL-R c_<C-R>_<C-R> c_CTRL-R_CTRL-O c_<C-R>_<C-O> CTRL-R CTRL-R {register CTRL-F CTRL-P CTRL-W CTRL-A CTRL-L} CTRL-R CTRL-O {register CTRL-F CTRL-P CTRL-W CTRL-A CTRL-L} 插入寄存器或光标下的对象。类似于 c_CTRL-R ,但是该命令按本义 插入文本。例如,如果寄存器 a 的内容为 "xy^Hz" (^H 是退格键), 那么 "CTRL-R a" 会插入 "xz",而 "CTRL-R CTRL-R a" 会插入 "xy^Hz"。 CTRL-\ e {expr} c_CTRL-\_e 计算表达式 {expr} 并用结果替换整个命令行。程序会提示你输入表达 式,用 <Enter> 键提交表达式。这项功能在映射里十分有用。参见 expression 。 欲了解插入表达式结果的相关信息,请参阅 c_CTRL-R_=getcmdline()getcmdline()getcmdpos() 函数在这里很有 用。 缺省,光标的位置不会改变,除非光标正位于行末,那么它还会停留在 行末。 不过,可以用 setcmdpos() 来自行设置光标的位置。 使用沙盘 sandbox 计算表达式以避免讨厌的副作用。 例如: :cmap <F7> <C-\>eAppendSome()<CR> :func AppendSome() :let cmd = getcmdline() .. " Some()" :" place the cursor on the ) :call setcmdpos(strlen(cmd)) :return cmd :endfunc 它无法递归操作,所以如果正在编辑一个表达式,它将无效。但可在映 射中使用。 c_CTRL-Y CTRL-Y 当存在无模式选择时,复制该选择区域的内容至剪贴板。 参考 无模式选择 modeless-selection 。 如果没有选择,那么 CTRL-Y 会被当作字符直接插入。 CTRL-MCTRL-J c_CTRL-M c_CTRL-J c_<NL> c_<CR> c_CR <CR><NL> 执行输入的命令 CTRL-[ c_CTRL-[ c_<Esc> c_Esc <Esc> 如果 'cpoptions' 选项中不包括 'x',那么输入该键会退出命令行模 式,而不执行命令。若 'cpoptions' 里包含 'x',或者该键出现在宏 命令里,则执行输入的命令。 注意: 如果键盘上输入 <Esc> 不方便,请训练一下用 CTRL-[ 吧。 c_CTRL-C CTRL-C 不执行命令,退出命令行模式 c_<Up> c_Up <Up> 在历史记录中查找开始部分与当前输入匹配的前一条命令。(见下面) {仅当编译时加入 +cmdline_hist 特性才可用} c_<Down> c_Down <Down> 在历史记录中查找开始部分与当前输入匹配的下一条命令。(见下面) {仅当编译时加入 +cmdline_hist 特性才可用} c_<S-Up> c_<PageUp> <S-Up><PageUp> 取回历史记录中的上一条命令 {仅当编译时加入 +cmdline_hist 特性才可用} c_<S-Down> c_<PageDown> <S-Down><PageDown> 取回历史记录中的下一条命令 {仅当编译时加入 +cmdline_hist 特性才可用} CTRL-D 命令行补全 (见 cmdline-completion ) 'wildchar' 选项 命令行补全 (见 cmdline-completion ) CTRL-N 命令行补全 (见 cmdline-completion ) CTRL-P 命令行补全 (见 cmdline-completion ) CTRL-A 命令行补全 (见 cmdline-completion ) CTRL-L 命令行补全 (见 cmdline-completion ) c_CTRL-_ CTRL-_ a - 在希伯来语和英语的键盘模式之间切换,这只是针对命令行模式, 与 hkmap 无关。如果命令行、搜索、缩写,等等需要输入希伯来文的 话,这一功能就很有用了。只有在 Vim 编译时加入了 +rightleft , 并且置位了 'allowrevins' 选项后,该功能才可用。 参见 rileft.txt 。 b - 在波斯语和英语的键盘模式之间切换,这只是针对命令行模式,与 fkmap 无关。在波斯语键盘模式下,字符的插入方式与平时相反 (即从 右至左)。如果命令行、搜索、缩写,等等需要输入波斯语的话,这一 功能就很有用了。只有在 Vim 编译时加入了 +farsi ,该功能才可 用。 参见 farsi.txt c_CTRL-^ CTRL-^ 语言映射 :lmap 和/或 输入法的开关。 如果输入搜索模式且 'imsearch' 的值不是 -1 ,VAL 是 'imsearch' 的值,否则,VAL 是 'iminsert' 的值。 如果定义了语言映射: - VAL 为 1 (使用 langmap 映射) 时变成 0 (不使用 langmap 映 射)。 - VAL 不为 1 时变成 1,从而打开 langmap 映射。 如果没有定义语言映射: - VAL 为 2 (使用输入法) 时变成 0 (不使用输入法) - VAL 为其它值时变成 2,从而打开输入法。 这些语言映射通常用来输入键盘上不能直接产生的字符。'keymap' 选 项用来安装若干完整的这样的映射表。 命令行输入时,langmap 映射关闭,因为假定你想输入命令。即使你用 CTRL-^ 打开了映射,新的状态也不会被下一条命令或搜索模式再次使 用。 (译者注: 此处的语言映射或 langmap 映射与 'langmap' 选项是不 同的概念,后者只适用于普通模式。) c_CTRL-] CTRL-] 激活缩写,但不插入任何字符。 对于 Emacs 风格的命令行编辑请参阅 emacs-keys<Up><Down> 键使用当前的命令行作为搜索的字符串。前面或后面的命令的起始部分 与该字符串做比较。最先匹配的作为新的命令。若连续重复这两个键,则使用同一字符串 进行再次匹配。例如,寻找前一个替换命令: 输入 ":s" 然后 <Up>。同样的效果也可以 用重复输入一连串 <S-Up> 直至找到你需要的命令为止达成。(注意: Shift+箭头键在某 些终端里不可用) :his :history :his[tory] 列出最近执行的命令。 {仅当编译时加入 +cmdline_hist 特性才可用} :his[tory] [{name}] [{first}][, [{last}]] 列出 {name} 历史记录的内容,{name} 可以是: c[md] 或 : 命令行的历史记录 s[earch] 或 / 或 ? 查找字符串的历史记录 e[xpr] 或 = 表达式寄存器的历史记录 i[nput] 或 @ 输入行的历史记录 d[ebug] 或 > 调试命令的历史记录 a[ll] 所有上述记录 如果给定了数字 {first}{last},那么就会列出指定范围内的历史 记录条目。这些数字可以是下面的格式: :history-indexing 正数表示历史记录的绝对索引,也就是 :history 命令列出的第一列数 字。即使历史记录中的其它条目被删除了,该数字也会保持不变。 负数表示与某一记录的相对位置。以最新的一条记录 (索引号为 -1) 为基准向后算起。 例子: 列出搜索历史记录中的第 6 到第 12 条记录: :history / 6,12 列出所有历史记录中倒数第二条记录录: :history all -2 列出所有历史记录中最近的两条记录: :history all -2, :keepp[atterns] {command} :keepp :keeppatterns 执行 {command},不加入搜索历史

2. 命令行补全 cmdline-completion

在编辑命令行的时候,有一些命令可以用来补全光标前面的单词。此功能可用于下述情 况: - 命令名称: 在命令行的起始处。 - 标签: 只在 ":tag" 命令后。 - 文件名: 只在可以接受文件名的命令或可以接受文件名的选项之后。也被称作文件名补 全。 - 外壳命令名: 在 ":!cmd"、":r !cmd" 和 ":w !cmd" 之后。使用 $PATH。 - 选项: 仅在 ":set" 命令之后。 - 映射: 仅在 ":map" 或与之类似的命令之后。 - 变量和函数名: 仅在 ":if",":call" 或类似的命令之后。 帮助条目的匹配数目有上限 (目前是 300 个),以避免过多匹配造成的延迟问题。 以下是可以使用的命令: c_CTRL-D CTRL-D 列出与光标前面的模式所匹配的名字。 在列文件名的时候,目录名会被高亮 (见 'highlight' 选项)。扩展名 与 'suffixes' 匹配的文件名放到列表的最后。 要列出匹配标签所在的文件,可以设置选项 'wildoptions' 为 "tagfile"。 c_CTRL-I c_wildchar c_<Tab> 'wildchar' 选项 用光标前的模式完成匹配。匹配的项目 (如果有多项匹配,则选第一 项) 会插入并取代模式。(注意: 该功能不能用于宏,因为在大多数情 况下 <Tab><Esc> 被用做 'wildchar',而这些键在某些宏里面有 特殊的意义。) 如果再次输入,并且有多项匹配时,则插入下一项匹 配。在最后一项匹配之后,会再次匹配第一项 (循环使用)。 该行为可以通过设置 'wildmode' 选项来改变。 c_<S-Tab> <S-Tab>'wildchar'<Tab> 类似,但从最末匹配开始,依次选择前一项 匹配。 <S-Tab> 不是所有系统都可用。 c_CTRL-N CTRL-N 在使用 'wildchar' 之后,如果得到了多项匹配,则选择下一项匹配。 否则选择命令历史列表中的下一条命令。 c_CTRL-P CTRL-P 在使用 'wildchar' 之后,如果得到了多项匹配,则选择前一项匹配。 否则选择命令历史列表中的上一条命令。 c_CTRL-A CTRL-A 将所有与模式匹配的项全部插入到光标前面。 c_CTRL-L CTRL-L 用光标前的模式完成匹配。如果有匹配的项目,则插入并取代当前的模 式。如果有多个项目匹配,那么取这些项目中尽可能长的共同部分插 入以取代模式。若结果比模式短,则匹配不成功。 /_CTRL-L 如果置位 'incsearch',用 "/" 或 "?" 录入搜索模式而显示当前的匹 配时,CTRL-L 会从当前匹配的末尾一次加一个字符。如果置位了 'ignorecase''smartcase' 而命令行没有大写字符,加入的字符会 转换为小写。 c_CTRL-G /_CTRL-G CTRL-G 如果置位 'incsearch',用 "/" 或 "?" 录入搜索模式而显示当前的匹 配时, CTRL-G 会移动到下一个匹配 (不考虑 search-offset )。 CTRL-T 移动到前一个匹配。提示: 在常规键盘上 T 在 G 上方。 c_CTRL-T /_CTRL-T CTRL-T 如果置位 'incsearch',用 "/" 或 "?" 录入搜索模式而显示当前的匹 配时, CTRL-T 会移动到前一个匹配 (不考虑 search-offset )。 CTRL-G 移动到下一个匹配。提示: 在常规键盘上 T 在 G 上方。 选项 'wildchar' 的默认值是 <Tab> (在 Vi 兼容模式里用的是 CTRL-E;在以前的版本 里用的是 <Esc>)。 如果用来匹配文件名,在匹配模式里可以使用标准的通配符 '*' 和 '?'。'*' 匹配任意字符串,'?' 匹配一个字符。 重复使用 'wildchar'CTRL-N 会循环选择匹配,并最终转回到正在输入的内容。如果 首个匹配不如所愿,可以用 <S-Tab>CTRL-P 直接回到刚输入的内容。 置位选项 'wildignorecase' 可用于忽略文件名的大小写。 'wildmenu' 选项可用于设置在命令行正上方显示可能的匹配。 如果你喜欢 tcsh 的自动列表匹配,可以使用这个映射: :cnoremap X <C-L><C-D> (X 是命令键,<C-L>CTRL-L<C-D>CTRL-D) 这样就可以找到最长的匹配并列出 所有匹配的文件。 如果你喜欢 tcsh 的自动列表匹配,你可以使用 'wildmode' 选项来模拟它。例如,这与 autolist=ambiguous 极其类似: :set wildmode=longest,list 这将在你输入第一个 'wildchar' 之后,找到最长的匹配,接着列出所有匹配的文件。 complete-script-local-functions 补全用户函数名时,可在之前加上 "s:" 来找到局部于脚本的函数。 suffixes 对于文件名的匹配你可以用 'suffixes' 选项在相似的文件名之间设定优先级。如果有多 个文件匹配,并且 'suffixes' 选项中包含这些文件的扩展名,那么这些文件会被忽略。 'suffixes' 的默认值是 ".bak,~,.o,.h,.info,.swp,.obj"。其含义是: 以 ".bak","~",".o",".h",".info",".swp" 和 ".obj" 结尾的文件名有时被忽略。 空项目,即两个连续的逗号,匹配不包含 "." 的文件名,因为它们没有扩展名。可用来 忽略 "prog" 而选择 "prog.c"。 例如: 模式: 文件: 匹配: test* test.c test.h test.o test.c test* test.h test.o test.h and test.o test* test.i test.h test.c test.i and test.c 无法忽略包括两个句号的后缀名。 如果有多个文件匹配 (在忽略了与 'suffixes' 匹配的扩展名之后),则第一个匹配的文 件名被插入。当你按两次 'wildchar' 时,你可以看到只有一个匹配并且完整的匹配保持 不变。你可以再输入一次 'wildchar'CTRL-N,或 CTRL-P 得到另一个匹配。包括所有 的文件,也包括扩展名与 'suffixes' 匹配的文件。 要完全忽略有某些扩展名的文件,请使用 'wildignore' 选项。 要只匹配以输入文本结尾的文件,附加 "$" 即可。例如,要匹配 ".c" 结尾的文件: :e *.c$ 这样就不会匹配 ".cpp" 结尾的文件。如果没有 "$" 就会。 一个选项的旧值可以通过在 '=' 后面输入 'wildchar' 来获得。例如,在 ":set dir=" 后输入 'wildchar',就会插入当前 'dir' 的值。对于选项值是文件名的选项,这一行为 优先于文件名匹配。 若你喜欢在 xterm 里使用 <S-Tab> 代替 CTRL-P,把这条命令放到你的 .cshrc 里: xmodmap -e "keysym Tab = Tab Find" 把这条命令放到你的 .vimrc 里: :cmap <Esc>[1~ <C-P>

3. Ex 命令行 cmdline-lines

Ex 命令有几个特别的地方: :quote :comment 如果 '"' 出现在一行的开始,那么该行被忽略。如果 '"' 出现在命令之后,则使得该行 的剩余部分被忽略。这可以被用于添加注释。例如: :set ai "set 'autoindent' option 不能给外壳命令 (":!cmd") 或 ":map" 和其它的一些的命令 (主要是期待表达式的命令) 添加注释,因为它们把 '"' 视为命令的一部分。 :argdo :autocmd :bufdo :cexpr (诸如此类) :cdo (诸如此类) :command :cscope (诸如此类) :debug :display :echo (诸如此类) :elseif :execute :folddoopen :folddoclosed :for :grep (诸如此类) :help (诸如此类) :if :let :make :map (诸如此类,包括 :abbrev 等命令) :menu (诸如此类) :mkspell :normal :ownsyntax :popup :promptfind (诸如此类) :registers :return :sort :syntax :tabdo :tearoff :vimgrep (诸如此类) :while :windo :bar :\bar '|' 可以用来分割命令,所以你可以在一行里输入多个命令。如果你想在参数里使用 '|' ,应该在前面加上 '\'。 下面这些命令把 '|' 当作它们的参数,所以后面不能跟别的 Vim 命令: :argdo :autocmd :bufdo :cdo :cfdo :command :cscope :debug :eval :folddoopen :folddoclosed :function :global :help :helpfind :helpgrep :lcscope :ldo :lfdo :lhelpgrep :make :normal :perl :perldo :promptfind :promptrepl :pyfile :python :registers :read ! :scscope :sign :tcl :tcldo :tclfile :terminal :vglobal :windo :write ! :[range]! 没有参数 "-bar" 的用户自定义命令 :command 注意: 在 ":g" 中 '|' 包含在命令里 (作为参数),但 ":s" 却不是。这的确有点乱 (继承于 Vi)。 为确保总能执行另一个命令,请使用 ":execute" 命令。 例如 (读入 "ls" 的输出,并且跳到第一行): :execute 'r !ls' | '[ 有一个例外: 如果 'b' 出现在 'cpoptions' 选项中,那么在 ":map" 和 ":abbr" 之类 的命令里需要用 CTRL-V 代替 '\'。你也可以用 "<Bar>" 来代替。参见 map_bar 。 例如: :!ls | wc 查看两个命令的输出 :r !ls | wc 将相同的输出插入文本 :%g/foo/p|> 将所有匹配的行移动一个 shiftwidth :%s/foo/bar/|> 将一行移动一个 shiftwidth :map q 10^V| 将 "q" 映射为 "10|" :map q 10\| map \ l 将 "q" 映射为 "10\" 和将 "\" 映射为 "l" (如果 'cpoptions' 选项中包含 'b') 用与 '|' 相同的方法,你也可以用 <NL> 分割多个命令。用 CTRL-V CTRL-J 插入一个 <NL>。Vim 会显示一个 "^@"。应该说,使用 '|' 是一个更好的方法。但是对于外部命 令,就必须使用 <NL>,因为外部命令会包含 '|'。如果要避免 <NL> 的特殊含义,就必 须在它前面加反斜杠。例如: :r !date<NL>-join 将当前时间读入文件,并且与上一行文本衔接。 注意: 如果 '|' 前面的命令产生了错误,那么其后面的命令不会执行。 为了兼容 Vi,下面几个奇怪的命令 Vim 也支持: :| 打印当前行 (同 ":p") :3| 打印第 3 行 (同 ":3p") :3 前进至第 3 行 在范围与命令之间允许有一个冒号。这个冒号被忽略 (与 Vi 兼容)。例如: :1,$:s/pat/string 当字符 '%' 或 '#' 被用在一个需要文件名的地方时,会被扩展为当前的文件名或轮换文 件名 (参见 "编辑文件" 的章节 :_% :_# )。 在 Amiga 系统上,如果文件名要作为参数使用,那么文件名里是允许包含空格符的。通 常末尾的空格符会被忽略,除非使用转义字符反斜杠或 CTRL-V 使它转义。注意, ":next" 命令使用空格符分割文件名。所以要在该命令里使用带空格符的文件名,就需要 将空格符转义。例如: :next foo\ bar goes\ to school\ 开始编辑 "foo bar","goes to" 和 "school " 三个文件。 当你想在命令里使用特殊字符 '"' 或 '|',或者想在文件名里使用 '%' 或 '#',就需要 在这些字符前加一个反斜杠。在范围和 ":substitute" 命令里不需要使用反斜杠。 另见 `= :_! 在 Ex 命令之后的 '!' (叹号) 使得命令以不同的方式执行。'!' 应该紧跟在命令之后, 中间没有任何空白字符。如果插入了空白字符,'!' 则被视为该命令的参数,其含义是不 同的。例如: :w! name 将当前缓冲区内容写入文件 "name"。若该文件存在,则覆盖 之。 :w !name 将当前缓冲区内容作为标准输入发送给 "name" 命令。

4. Ex 命令行的范围 cmdline-ranges [range] E16

有些 Ex 命令前面可以接受一个范围限定,这被称作 [range] (范围)。它由一个或多个 被 ',' 或 ';' 分割的行限定符组成。 一些基本的内容在用户手册的 10.3 里解释过。 Vim9 脚本里要表示范围,必须在前加上冒号,以免和续行起歧义。例如,"+" 可以用 作范围,也可以是表达式的继续: var result = start + print 如果 "+" 用作范围,须在前加上冒号: var result = start :+ print :, :; 当范围被 ';' 分割时,在解释下一个行限定符之前,光标的位置会被设置为前一个行限 定符确定的行值。这种情况不会发生在 ',' 上。例如: 4,/this line/ 从第 4 行到匹配当前光标后的一个 "this line" 为止的范围。 5;/that line/ 从第 5 行到匹配第 5 行之后的一个 "that line" 为止的范围。 对大多数命令而言,默认的行限定符就是光标的位置,但是 ":write" 和 ":global" 命 令的默认值是整个文件 (1,$)。 若行限定符的个数多于命令需要的数量,则第一个 (或前几个) 限定符被忽略。 行号可以用下列符号限定: :range {address} {number} 行号 E1247 . 当前行 :. $ 文件的最后一行 :$ % 相当于 1,$ (整个文件) :% 't 标记 t 的位置 (小写) :' 'T 标记 T 的位置 (大写);如果标记存在于另一个文件中,则不 能在范围里应用。 /{pattern}[/] 下一个匹配 {pattern} 的行 :/ ?{pattern}[?] 前一个匹配 {pattern} 的行 :? \/ 下一个与前次搜索模式匹配的行 \? 前一个与前次搜索模式匹配的行 \& 下一个与前次替代模式匹配的行 这些符号后面可以跟 (一个或多个) '+' 或 '-' 和一个可选的数字。该数字会与前面的 行号相加或相减。若该数字省略,则认为是 1。如果 '+' 或 '-' 前为空,使用当前行。 在 {pattern} 之后需要由 "/" 或 "?" 来分隔匹配模式与其之后的内容。 "/" 和 "?" 前面可能有另一个地址。查找就从那里开始。和使用分号的方式不同之处 是: 光标不会被移动。例如: /pat1//pat2/ 从包含 "pat1" 的行开始,向后寻找直至找到包含 "pat2" 的 行为止,不移动光标位置。 7;/pat2/ 从第 7 行开始,向后寻找直至找到包含 "pat2" 的行为止。 光标留在第 7 行。 {number} 必须在 0 和文件的总行数之间。当使用 0 (零) 的时候,大多数命令会把它解 释成 1 。把它用作计数器的命令会将它解释为零 ( :tag:pop 等)。有些命令会把 零解释为 "在第一行之前" ( :read ,搜索模式等)。 例如: .+3 光标下面三行 /that/+1 下一个包含 "that" 的行的下一行 .,$ 从当前行直至文件末尾 0;/that 第一个包含 "that" 的行,也能匹配第一行 1;/that 第一行之后 (从第二行开始) 包含 "that" 的那一行 有些命令后面可以跟一个数量。这个数量被用作从上一个行限定符 (默认值是当前光标所 在的行) 开始计算的行数。可以使用范围但是不使用文件名作为参数的命令可以接受这种 数量参数 (因为文件名也可能是一个数字)。此数量不能为负。 例如: :s/x/X/g 5 用 'X' 替换当前行和下面四行里的 'x'。 :23d 4 删除 23,24,25 和 26 行。 折叠和范围 如果激活了折叠功能,行号会被取整以包括整个折叠。见 fold-behavior 。 反向范围 E493 在范围里,小的数字应该出现在前面。如果不是这样,Vim 会询问你是否交换。 Backwards range given, OK to swap 但全局命令 ":g" 里不会这么做。 在命令前用 ":silent" 可以避免此问题,这时范围总是进行交换。 计数和范围 N: 如果在进入 ":" 之前输入了计数前缀,这种情况会被解释成: :.,.+(count - 1) 简单来说就是: 包括当前行,向后共计 'count' 行。例如,删除三行: 3:d<CR> 被翻译成: .,.+2d<CR> 可视模式和范围 v_: {Visual}: 将可视模式中选择的区域用作命令行模式的范围。 :'<,'> 被用来表 示这种范围。这样就可以在不同的选择区域上,从命令历史列表里选择 相似的命令来重复执行操作。 :* :star :star-visual-range 如果已经退出可视模式,更简短的方法是用 :* 来得到可视区域的范 围。需要 'cpo' 里不出现 "*",参见 cpo-star 。否则,只能通过输 入 :'<,'> 得到。 关于 "*" 何时会出现在 'cpo' 里,可见 :star-compatible

5. Ex 命令行的标志位 ex-flags

部分 Ex 命令支持以下标志位。它们显示光标在执行完命令之后所在的行: l 像 :list 那样输出 # 加上行号 p 像 :print 那样输出 可以联合使用这些标志位,这样 "l#" 表示使用行号并且使用 :list 风格输出。

6. Ex 里的特殊字符 cmdline-special

注意: 这些是要执行的 Ex 命令行中的特殊字符。如果你想要在录入时插入特殊的内容, 可以使用 CTRL-R 命令。例如,"%" 表示当前文件名,而 CTRL-R % 则立即插入当前文件 名。见 c_CTRL-R备注: 在 Vim 脚本中要避免特殊字符的效果,可用 fnameescape() 。另见 `= 。 在 Ex 命令中,下列字符在可以使用文件名的地方有特殊的意义。它们同样可以用到表达 式函数 expand() 中。 % 被当前文件名取代。 :_% c_% # 被轮换文件名取代。 :_# c_# 每个窗口都会分别记住。 #n (n 是一个数字) 被第 n 个缓冲区的文件名取代。 :_#0 :_#n "#0" 与 "#" 相同。 c_#n ## 被参数列表里的所有文件名 (使用空格符分隔) 取代。 :_## c_## 文件名中的空格符前面会加一个反斜杠。 #<n (n 是一个正数) 被第 n 个旧文件名取代。 :_#< c_#< 要得到这个数值,见 :oldfilesv:oldfiles E809 {仅当编译时加入 +eval+viminfo 特性才可用} Vim9-script 中 # 用于注释开始,需用 %% 来代表轮换文件名: % 被当前文件名取代。 %% 被轮换文件名取代。 :_%% c_%% %%n (n 是一个数字) 被第 n 个缓冲区的文件名取代。 :_%%0 :_%%n "%%0" 与 "%%" 相同。 c_%%n %%% 被参数列表里的所有文件名 (使用空格符分隔) 取代。 :_%%% c_%%%# %%<n (n 是一个正数) 被第 n 个旧文件名取代。 :_%%< c_%%< 注意: 除了 "#<n" 以外,它们只给出输入时使用的文件名。如果需要绝对路径 (当从另 一个目录使用文件名的时候),你需要加 ":p"。见 filename-modifiers 。 "#<n" 项返回绝对路径,但在主目录下的文件名会以 "~/" 开始。 注意: 空格符前面会插入反斜杠,以便 Vim 命令会正确地解释文件名。但是外壳命令不 会如此。为此,你可以使用引号 (但对包含引号和通配符的文件名会有问题): :!ls "%" :r !spell "%" 要避免 '%' 和 '#' 的特殊含义,可以在它前面插入一个反斜杠。细节: 只要有反斜杠在 这些字符前面,它们就不具备特殊含义,不管有多少个反斜杠。 你输入: 结果 # 轮换文件名 \# # \\# \# 另见 `= E499 E500 注意: 下面这些不是特殊键,需要逐个字符输入! :<cword> <cword> <cword> 被当前光标下的单词代替 (类似于 star ) :<cWORD> <cWORD> <cWORD> 被当前光标下的字串代替 (见 WORD ) :<cexpr> <cexpr> <cexpr> 被当前光标下的单词,必要时包含更多内容以构成的完整 C 表达式 所代替。如,当光标在 "ptr->arg" 的 "arg" 上,结果是 "ptr->arg";如光标在 "list[idx]" 的 "]" 上,则结果是 "list[idx]"。用于 v:beval_text :<cfile> <cfile> <cfile> 被当前光标下的路径名代替 (类似于 gf 用的方法) :<afile> <afile> <afile> 在执行自动命令时,被所操作的缓冲区或用来读或写的文件的文件 名取代。 E495 :<abuf> <abuf> <abuf> 在执行自动命令时,被当前有效的缓冲区序号取代 (对于 ":r file" 和 ":so file" 来说是当前的缓冲区,因为被读取/执行 的文件不在缓冲区里)。 E496 :<amatch> <amatch> <amatch> 在执行自动命令时,被激发自动命令的实际匹配代替。 E497 文件名不用于匹配 (对于 FileType、Syntax 和 SpellFileMissing 事件) 时,与 <afile> 不同。 文件名用于匹配时,被扩展为完整路径。 :<sfile> <sfile> <sfile> 执行 :source 命令时,替换为正在被 "source" 执行的文件名。 E498 执行老式函数时,替换为调用堆栈,如同 <stack>。(后向兼容,建 议使用 <stack><script>)。 Vim9 脚本里,函数中使用 <sfile> 会报错 E1245 注意,如果 <sfile> 用在函数里,那么文件名修饰符 (filename-modifiers) 就没用了。 :<stack> <stack> <stack> 替换为调用堆栈,函数行用 "function {function-name}[{lnum}]" 而脚本行用 "script {file-name}[{lnum}]",项目间以 ".." 区 隔。例如: "function {function-name1}[{lnum}]..{function-name2}[{lnum}]" 无调用堆栈时会报错 E489 :<script> <script> <script> 执行 :source 命令时,替换为执行文件的文件名。执行函数时, 替换为函数定义所在的脚本的文件名。 不能确定文件名时会报错 E1274 :<slnum> <slnum> <slnum> 执行 :source 命令时,替换为行号。 E842 执行函数时,这是相对函数开始处的行号。 :<sflnum> <sflnum> <sflnum> 执行脚本时,替换为行号。 和 <slnum> 不同在于不管什么情况,<sflnum> 都会被替换为脚本 的行号。 E961 :<client> <client> <client> server2client() 中替换为最近收到信息的 {clientid} filename-modifiers :_%: ::8 ::p ::. ::~ ::h ::t ::r ::e ::s ::gs ::S %:8 %:p %:. %:~ %:h %:t %:r %:e %:s %:gs %:S 可以在 "%","#","#n","<cfile>","<sfile>","<afile>" 或 "<abuf>" 之后使用文 件名修饰符。这些修饰符也可以和 fnamemodify() 函数一起用。 此类修饰符必须按如下顺序给出: :p 给出文件名的全路径。必须是第一个修饰符。也会将 "~/" (Unix 和 VMS 系统里的 "~user/") 变成指向用户主目录的路径。若被修饰的名 字是一个目录,则在后面加一个路径分隔符。如果文件名不存在,或 其绝对路径不存在,那么结果不可预料。MS-Windows 上 8.3 文件名被 扩展为长文件名。 :8 将路径转换为 8.3 短格式 (目前仅适用于 MS-Windows)。转换的结果 尽可能与现存路径一致。 :~ 如果可能,路径名缩减为基于主目录的相对路径。若文件不在主目录 下,则文件名不会被改变。 :. 如果可能,路径名缩减为基于当前目录的相对路径。若文件不在当前目 录下,则文件名不会被改变。 要想尽可能缩减,可使用 ":~:." 。 :h 文件名的头部 (除去文件名的最后一部分以及路径分隔符)。 不能与 :e,:r 或 :t 一起使用。 可以被重复使用来删除后面的多个部分。 如果文件名以一个路径分隔符结尾,仅删除该分隔符。这样一个目录 名的 ":p:h" 结果是目录名本身 (没有后面的斜杠)。 如果文件名是一个绝对路径 (Unix 上以 "/" 开始;Win32 以 "x:\" 开始;Amiga 以 "drive:" 开始),这些部分不会被删除。如果没有文 件头 (路径是相对于当前目录的),则结果为空。 :t 文件名的尾部 (文件名的最后一部分)。必须在 :r 或 :e 之前。 :r 文件名的根部 (除去最后的扩展名)。如果只有扩展名 (文件名以 '.' 开始,例如,".vimrc"),则不会被删除。可以重复使用,以删除多个 扩展名 (最后一个先被删除)。 :e 扩展名。只有单独使用时才有意义。 如果没有扩展名,那结果为空。 如果文件名只是一个扩展名 (以 '.' 开始的文件名),则结果为空。 可以重复使用来包含更多的扩展名。如果没有足够的扩展名 (但是至少 有一个),那么就尽可能多的包含。 :s?pat?sub? 用 "sub" 代替第一次出现的 "pat"。这类似于 :s 命令。"pat" 是 一个正则表达式。 可以用其它字符代替 '?',只要该字符不出现在 "pat" 或 "sub" 里。 在此之后,上述的修饰符可以再次使用。例如 ":p",是替换之后的完 整路径。 :gs?pat?sub? 用 "sub" 替换所有的 "pat"。其余和 ":s" 一样。 :S 转义所有外壳命令使用的特殊字符 (见 shellescape() )。必须是最 后一个修饰符。示例: :!dir <cfile>:S :call system('chmod +w -- ' . expand('%:S')) 例如,如果文件名是 "src/version.c",当前目录是 "/home/mool/vim": :p /home/mool/vim/src/version.c :p:. src/version.c :p:~ ~/vim/src/version.c :h src :p:h /home/mool/vim/src :p:h:h /home/mool/vim :t version.c :p:t version.c :r src/version :p:r /home/mool/vim/src/version :t:r version :e c :s?version?main? src/main.c :s?version?main?:p /home/mool/vim/src/main.c :p:gs?/?\\? \home\mool\vim\src\version.c 又例,如果文件名是 "src/version.c.gz": :p /home/mool/vim/src/version.c.gz :e gz :e:e c.gz :e:e:e c.gz :e:e:r c :r src/version.c :r:e c :r:r src/version :r:r:r src/version extension-removal :_%< 如果 "<" 跟在 "%","#","#n" 或 "CTRL-V p" 后面,那么文件的扩展名 ('.' 之后的 内容,包括 '.') 会被删除。包含这样的功能是为了与 3.0 版本兼容,现在推荐使用 ":r" 的形式。例如: % 当前文件名 %< 当前主文件名 (无扩展名) # 当前窗口的轮换文件名 #< 同上,但无扩展名 #31 序号为 31 的轮换文件名 #31< 同上,但无扩展名 <cword> 光标下的单词 <cWORD> 光标下的字串 (见 |WORD|) <cfile> 光标下的路径名 <cfile>< 同上,但无扩展名 注意: 在需要文件名的地方,就会完成文件名的通配符扩展。在 Unix 上,除非可以在内 部实现 (为了运行速度考虑),此功能会通过外壳来完成。 除非在 restricted-mode 中,也可以使用反引号,比如在 :n `echo *.c` 但是扩展仅在 '%','#' 等字符扩展之前就出现通配符的时候发生。这可以避免对文件名 中的通配符字符进行扩展。如果你想扩展 <cfile> 的结果,可以给它加一个通配字符。 例如: (轮换文件名是 "?readme?") 命令 扩展为 :e # :e ?readme? :e `ls #` :e {匹配 "?readme?" 的文件} :e #.* :e {匹配 "?readme?.*" 的文件} :cd <cfile> :cd {光标下的文件} :cd <cfile>* :cd {光标下的文件名加上 "*" 然后进行扩展} 另见 `= 。 当被扩展的参数包含一个 "!" 并且在外壳命令里 (":!cmd",":r !cmd" 或 ":w !cmd") 使用时,"!" 被反斜杠转义,以免扩展为前次使用的命令。如果 'shell' 选项包含 "sh",会执行两次转义,以避免外壳扩展 "!"。 filename-backslash 对于文件系统使用反斜杠作为目录分隔符的操作系统 (MS-Windows) 来说,确认反斜杠是 否为转义字符就有点儿困难了。一般来说: 如果反斜杠后面跟一个普通的字符,那么就没 有特殊意义。因此 "\file\foo" 是合法文件名,没有必要输入两次反斜杠。 一个例外是 '$' 符号。在文件名里它是一个合法的字符。但是为了避免像 "$home" 这 样的文件名被当作环境变量解释,则需要在前面加一个反斜杠。因此你需要用 "/\$home" 表示根目录下的 "$home" 文件。几个例子: 文件名 被解释为 $home 扩展为环境变量 $home 的值 \$home 当前目录里的 "$home" 文件 /\$home 根目录下的 "$home" 文件 \\$home 名为 "\\" 加上扩展后的 $home 的文件 另见 `=

7. 命令行窗口 cmdline-window cmdwin

command-line-window 在命令行窗口里,可以像编辑文本一样来编辑命令。这是一类特殊的窗口,你不能把它当 作普通窗口使用。 {仅当编译时加入 +cmdwin 特性才可用} 开 启 c_CTRL-F q: q/ q? 有两种方法可以打开命令行窗口: 1. 在命令行模式里,用 'cedit' 选项所指定的键。 在没有置位 'compatible' 的情况下,默认值是 CTRL-F 。 2. 在普通模式里,用 "q:","q/" 或 "q?" 命令。 它们分别开始编辑 Ex 命令 ("q:") 或搜索字符串 ("q/" 或 "q?")。 注意,处于记 录状态时不能使用 ("q" 会结束记录)。 窗口里的内容是命令行的历史记录。最后一行是最近输入的命令。左面一列字符表示命令 行的类型。见: cmdwin-char 。 如果没有置位 'insertmode' 选项,Vim 在打开之后会进入普通模式。 窗口的高度可以通过 'cmdwinheight' 选项设定 (如果没有足够的空间,窗口会缩小一 点)。窗口永远都是以最大宽度出现,并且被放在命令行的上面 (紧靠命令行)。 编 辑 现在你可以在窗口里移动或者编辑里面的文本了。可以在普通模式和插入模式中进行这些 操作。 可以用 ":","/" 和其他命令使用命令行,但却不能再打开另一个命令行窗口。这里不允 许嵌套。 E11 E1188 命令行窗口不是普通的窗口。你不能移动到别的窗口或编辑别的缓冲区。在命令行窗口 里,所有此类操作都被禁止。当然你 可以 执行在命令行窗口里输入的任何命令。关闭窗 口时,其它的文本编辑都被舍弃。 关 闭 E199 有很多方法可以退出命令行窗口: <CR> 执行光标下的命令。插入和普通模式里都可以。 CTRL-C 继续回到命令行模式。光标下的命令被用做命令行的命令。插入和普通 模式里都可以。不会重画窗口,这样命令行窗口仍然可见。 :quit 放弃命令行,回到普通模式。也可以使用 ":close"、CTRL-W c、 ":exit",":xit" 和 CTRL-\ CTRL-N 命令。 :qall 除非改动了某些缓冲区,否则退出 Vim。 :qall! 退出 Vim,放弃所做的改动。 一旦命令行窗口关闭,旧的窗口就会立刻恢复原先的大小。待执行的命令会作用于调用该 命令行窗口或缓冲区,就好像没有没有用过命令行窗口一样 (除了会有一次额外的屏幕刷 新以外)。命令行窗口用过的缓冲区会被删除。对其中的命令所做的改动 (如果没有用 <CR> 执行过) 会全部丢失。 如果你想执行光标所在的命令后再次打开命令行窗口,可用以下映射: :autocmd CmdwinEnter * map <buffer> <F5> <CR>q: 其 它 命令行窗口不能用在: - 已经存在一个命令行窗口的时候 (不能嵌套) - 输入密钥或使用 inputsecret() 函数的时候 打开命令行窗口的时候,会自动设置下面的选项: 'filetype' 当编辑 Ex 命令时,会设置为 "vim";如果打开高亮的话,这样就会启 用对 Vim 脚本的语法高亮。 'rightleft''modifiable''buftype' "nofile" 'swapfile' 关 将命令窗口缓冲区的内容写到文件是允许的。这也是一个保存命令历史记录以便日后取回 的好办法。 如果 'wildchar' 选项设置为 <Tab>,并且命令行窗口用于 Ex 命令,那么会在命令行窗 口里加入两个映射用于命令补全,如下: :inoremap <buffer> <Tab> <C-X><C-V> :nnoremap <buffer> <Tab> a<C-X><C-V> 注意,在普通模式里敲 <Tab> 键会在下一个字符上补全。这样的话,就可以在行尾进行 补全了。 如果你不想要这些映射,可用下面的命令将它们禁用: au CmdwinEnter [:>] iunmap <Tab> au CmdwinEnter [:>] nunmap <Tab> 你可以把这几行命令放到你的 vimrc 文件中。 在命令行窗口里,你不能用鼠标把光标放到另一个窗口里,或者拽动其它窗口的状态栏。 你可以拽动命令行窗口自己的状态栏以及命令行窗口之上的状态栏来改变命令行窗口的大 小,但对其它窗口无效。 getcmdwintype() 函数返回正在编辑的命令行的种类,其值见 cmdwin-char 。 自 动 命 令 使用两种自动命令事件: CmdwinEnterCmdwinLeave 。你可以使用这些 Cmdwin 事 件对命令行窗口进行特殊的设置。小心不要引起副作用! 例如: :au CmdwinEnter : let b:cpt_save = &cpt | set cpt=. :au CmdwinLeave : let &cpt = b:cpt_save 设置 'complete' 选项,以便在当前窗口用 i_CTRL-N 进行匹配。 另一个例子: :au CmdwinEnter [/?] startinsert 将使 Vim 在打开命令行窗口时切换到插入模式。 cmdwin-char 模式使用的下列字符用于指示命令行的种类: : 普通的 Ex 命令 > 调试模式的命令 debug-mode / 正向查找字符串 ? 反向查找字符串 = "= 表达式 expr-register @ input() 字符串 - :insert:append 的文本 vim:tw=78:ts=8:noet:ft=help:norl: