# Pratical Vim 整理 本文档内容基于Drew Neil著作Pratical Vim中译本整理。 ## 模式(Mode) ### 普通模式(Normal mode) * 能够前往其他任一Vim模式 * 字符命令形式:`[{count}=1]{operator}`,对光标下起的count个字符执行操作并后移光标。 * 动作命令形式:`[{count}=1]{operator}{motion}`,表示执行operator操作,作用于当前光标+motion指定的范围,并执行count次。 * 行命令形式:对于动作命令,`{operator}{operator}`表示将该操作作用于当前行;`guu`和`gUU`是作用于当前行的简化版。 * 操作符和动作命令均可以自定义,也可与已有的操作符和动作命令组合使用。 #### 操作符 名称|含义 ----|--- `[{count}]`|当前光标**之上或之后**的数字自增count `[{count}]`|当前光标**之上或之后**的数字自减count `c{motion}`|修改(删除并进入插入模式) `d{motion}`|删除(剪切到寄存器) `y{motion}`|复制到寄存器 `p`|粘贴到光标之后/下一行,光标在新内容开头 `P`|粘贴到光标之前/上一行,光标在新内容开头 `gp` `gP`|粘贴但光标在新内容结尾 `~`|变换当前光标下字符大小写并前进光标 `g~{motion}`|反转大小写 `gu{motion}`|转换为小写 `gU{motion}`|转换为大写 `>{motion}`|缩进下一级 `<{motion}`|缩进上一级 `={motion}`|自动缩进 `!{motion}`|外部程序过滤 #### 动作命令 ##### 光标移动 实际(文件)行是真实文件中的一行,它需要一个或多个虚拟(屏幕)行来显示。如果要以屏幕实际显示位置为基准移动,需要用以`g`引导的移动命令:`gk` `gj` `g0` `g^` `g$`。 命令|功能 ----|---- `h`|← `l`|→ `k`|实际行↑ `j`|实际行↓ `0`|移动到实际行首 `^`|移动到实际行的第一个非空白字符 `$`|移动到实际行尾 ##### 单词(word)/字串(WORD)移动 单词边界是非字母字符,而字串边界是空白字符。例如`set-up`中有3个单词,且是1个字串。 命令|功能 ----|---- `w` `W`|下一个单词/字串的首字母 `b` `B`|当前或上一个单词/字串的首字母 `e` `E`|当前或下一个单词/字串的末字母 `ge` `gE`|上一个单词/字串的末字母 ##### 行内查找字符 找不到所要的字符时,则没有任何动作 命令|功能 ----|---- `f{char}`|正向查找char,光标char之上 `F{char}`|反向查找char,光标char之上 `t{char}`|正向查找char,光标char之前 `T{char}`|反向查找char,光标char之后 #### 文本对象 某些成对的文本。由两个字符组成,第一个字符是`i`表示分隔符内部的文本(inside),`a`表示分隔符在内的整体文本(around/all)。第二个字符表示对象类型。 名称|含义 ----|--- `iw`|当前单词(不含前后空格边界) `aw`|当前单词(包含单个空格边界) `W`|当前字串 `s`|当前句子 `ip`|当前段落 `ap`|当前段落和一个空行 i/a `)`或`b`|圆括号 i/a `}`或`B`|花括号 i/a `]`|方括号 i/a `>`|尖括号 i/a `'`|单引号 i/a `"`|双引号 i/a `` ` ``|反引号 i/a `t`|XML标签 #### 标记与跳转 命令|功能 ----|---- `m{a-z}`|用相应的字母标记当前光标位置,作用于当前缓冲区 `m{A-Z}`|用相应的字母标记当前光标位置,作用于全局 `` `{mark} ``|跳转到标记mark处 `` `` ``|当前文件上次跳转之前位置 `` `. ``|上次修改的位置 `` `^ ``|上次插入的位置 `` `[ ``|上次修改或复制的起始位置 `` `] ``|上次修改或复制的结束位置 `` `< ``|上次可视模式选区起始位置 `` `> ``|上次可视模式选区结束位置 `%`|首尾括号间跳转或配对关键词(matchit插件) `{line}G`|行号跳转 `G`|跳到最后一行 `(`和`)`|上一句/下一句的首字符 `{`和`}`|上一段/下一段的首字符 `H` `M` `L`|屏幕的第一行/中间行/最末行的行首 `gf`|跳转到光标下的文件名(需配置) ``|跳转到光标下的关键词定义 命令|功能 ----|---- ``|下一页 ``|上一页 ``|上一个光标位置(后退) ``|前进光标位置,也是``的替代键 #### 寄存器 Vim中的删除命令本质是剪切命令。修改、删除、复制、粘贴命令之前可以指定要使用的寄存器。 即为`"{register}c/x/d/y/p`,不指定时使用无名寄存器 Vim中有下列寄存器: 名称|标识符|用途 ---|----|---- 无名寄存器|`"`|缺省的寄存器 复制专用寄存器|`0`|`y{motion}`复制操作时自动赋值 命名寄存器|`a`-`z`|用户使用的寄存器,用大写字母引用时可以追加内容到寄存器中 黑洞寄存器|`_`|丢弃内容 系统剪贴板|`+`|系统剪贴板的内容 主剪贴板|`*`|X11系统中上次高亮显示的文本 表达式|`=`|进入命令行输入表达式并求值 只读寄存器|`%`|当前文件名 只读寄存器|`#`|轮换文件名 只读寄存器|`.`|上次插入的文本 只读寄存器|`:`|上次执行的Ex命令 只读寄存器|`/`|上次查找的模式(可用`:let`赋值) #### 拼写检查 使用`:set spell`启用。 使用`:set spelllang={ISO639}`设置拼写检查语言 `:h spell-remarks` 使用`:set spellfile={files}`设置自定义拼写文件,根据加入顺序编号 `:h 'spellfile'` 命令|功能 ----|---- `]s`|下一处拼写错误 `[s`|上一处拼写错误 `z=`|获取当前单词建议 `{n}zg`|将当前单词添加到拼写文件n中 `zw`|将当前单词从拼写文件中删除 `zug`|撤销对当前单词的`zg`或`zw`命令 #### 常用的组合命令 命令|功能 ----|---- `xp`|调换两个字符的顺序 `ddp`|调换两行的顺序 `yyp`|在下方复制当前行 `ea`|在单词结尾插入文本 #### 其他 命令|功能 ----|---- `ga`|显示光标处字符的编码值 `g&`|整个文件上重复上一次替换,同`:%&&` `:h g&` `*`|正向查找光标处单词并高亮 `#`|反向查找光标处单词并高亮 `zz`|重绘屏幕 ``|显示文件名和状态,标记空白缓冲区为新文件 ### 操作符待决模式 (Operator pending mode) 普通模式下,输入了操作符,只接受动作命令,或者被``终止操作回到普通模式的状态。 ### 插入模式/替换模式 `-INSERT-`/`-REPLACE-` 插入或替换文本。 普通模式进入插入或替换模式的基本命令为: 命令|功能 ----|---- `i`|在当前光标前插入 `a`|在当前光标后插入 `R`|从当前光标起替换 `gR`|进入虚拟替换模式,按屏幕显示文本宽度替换 `r`|单次替换光标下字符,随即返回普通模式 `gr`|单次虚拟替换光标下字符 以及与动作命令组合的复合命令: 复合命令|等效命令|意义 -------|-------|--- `C`|`c$`|修改当前光标至行尾 `s`|`cl`|修改光标下的字符 `S`|`0c$`|修改整行 `I`|`^i`|行首插入 `A`|`$a`|行尾插入 `o`|`A`|在下方插入新行 `O`|`ko`|在上方插入新行 插入模式下可用的控制键 按键|功能 ----|---- ``|删除前一个字符(即``,终端功能) ``|删除前一个单词(空格为止,终端功能) ``|删除到行首(终端功能) ``|返回普通模式,终端下等同`` `{cmd}`|执行普通模式命令cmd,重新回到插入模式 `{reg}`|插入寄存器reg的内容,用于粘贴、运算等 `{reg}`|原样插入寄存器reg的内容,防止自动换行或缩进 `{DDD}`|插入ASCII码为十进制DDD的字符 `u{HHHH}`|插入Unicode码为十六进制HHHH的字符 `{char}`|插入键盘按键表示的原始字符,如`` `{char1}{char2}`|插入二合字符,参考`:h digraph-table` ``|切换`-INSERT-`与`-REPLACE-` #### 自动补全 触发补全的按键与关键字来源,普通补全默认来源为缓冲区+包含文件+标签文件,可以修改配置`:h 'complete'`。 按键|功能 ----|---- ``|普通 ``|当前缓冲区文本 ``|包含文件中文本 ``|标签文件 ``|字典 ``|整行 ``|文件名 ``|全能Omni补全 ``|拼写自动补全 触发补全后显示一个补全菜单 `:h popupmenu-completion` ``与``将遍历补全列表并更新文档,对应的``、``并不更新,需要按``或``确认选择。``退出自动补全。 ### 可视模式/选择模式 `-VISUAL-`/`-SELECT-` 可视模式是先通过动作命令定义操作作用范围,再用操作命令执行操作的操作方式。首先选定一个起点,激活面向字符、行或者列的可视模式,调整终点后执行相应的操作。 选择模式与可视模式不同之处在于确定选区后只能进行替换被选中文本的操作,输入任何字符将删除被选中文本并进入插入模式。 普通模式进入可视模式的命令为: 命令|功能 ----|---- `v`|进入面向字符的可视模式 `V`|进入面向行的可视模式 ``|进入面向列的可视模式 `gv`|重选上次的选区(如果删除了上次的选区,可能不是想要的结果) 进入可视模式后,可用上面除`gv`外的命令切换可视模式,以及用``返回普通模式。 可视模式下的命令为: 命令|功能 ----|---- ``|在可视模式和选择模式之间切换 `o`|切换高亮选区的活动端,用于调整选区开始点 `u`|将选区文本转为小写 `U`|将选区文本转为大写 ### 命令行模式 进入方式|后续命令|用途 ------|----|---- `:`|`{command}`|执行Ex命令 command `/`|`{pattern}`|正向正则查找 pattern `?`|`{pattern}`|反向正则查找 pattern `=`|`{experssion}`|访问表达式寄存器,提供表达式 在Ex命令输入过程中可用的按键: 按键|功能 ----|---- ``|显示可用的命令补全列表 ``|正向遍历补全列表 ``|反向遍历补全列表 ``|插入缓冲区光标下单词 ``|插入缓冲区光标下字串 ``|上一次执行的Ex命令,根据当前已输入命令过滤 ``|``的回滚命令 ``|上一次执行的Ex命令,但不过滤 ``|``的回滚命令 ``|将当前命令行的内容复制到命令行窗口中 #### 命令行窗口 可以编辑Ex命令的缓冲区历史,进行命令行的编辑。但不能切换到其他窗口,直到运行了一个Ex命令或关闭缓冲区(`:q`)。 按键|功能 ----|---- `q:`|进入Ex命令历史的命令行窗口 `q/`|进入查找命令历史的命令行窗口 ``|在活动窗口执行当前行上的Ex命令 ## 重复与撤销 ### 撤销块 * 普通命令(操作符+动作命令) * 插入模式输入或移动光标 ### 重复和回退命令 操作类型 | 首次执行 | 重复 | 回退 --------|---------|-----|------ 普通模式修改|`{edit}`|`.`|`u` 行内查找|`f/t/F/T{char}`|`;`|`,` 全文查找|`/`/`?` `pattern`|`n`|`N` 全文替换|`:s/pattern/replacement`|`&`|`u` 宏|`q{reg}{edit}q`|`@{reg}`|`u` Ex命令|`:{command}`|`@:`|`u` ### 宏 宏是存储在寄存器中的命令序列,因此也可以修改寄存器来编辑宏。 当宏正在录制中,左下角将显示`recording`。 录制宏时,应当加入规范光标位置的动作命令。当动作命令失败时宏将终止退出。 命令|功能 ----|---- `q{reg}{operations}q`|录制宏到寄存器reg `[count]@{reg}`|回放宏reg,以串行方式执行count次 `:[range]normal @{reg}`|以并行方式在range上执行宏reg `:argdo normal @{reg}`|以并行方式在所有缓冲区上执行宏reg `@@`|回放上次调用的宏 ## Ex命令 ### 配置相关 命令格式|功能 -------|---- `:set {config}`|打开配置项 `:set no{config}`|关闭配置项 `:set {config}!`|反转配置项 `:set {config}?`|获取配置项设置 `:set {config}&`|恢复配置项默认值 `:set {config}={value}`|设置需要参数的配置项 `:set {config}+={value}`|追加需要参数的配置项 `:set {config}-={value}`|移除需要参数的配置项 ### 操作缓冲区文本 Ex命令可以对整个缓冲区的文本进行操作,并且使用共通的范围表示方法,称为地址(address)或范围(range)。 表示方法|含义 -------|---- `{address1},{address2}`|起止地址表示的范围 `{address}+/-{n}`|地址偏移前后n行 `0`|第一行上方的虚拟行 `1`|首行 `{line}`|指定行号的单行 `.`|当前行 `$`|末尾行 `%`|所有行 `'<`|选区开始(可视模式) `'>`|选区结束(可视模式) `'{mark}`|位置标记mark所在行 `/{pattern}/`|匹配模式 命令格式|功能 -------|---- `:[range]p[rint]`|显示指定行的内容 `:[range]d[elete] [register]`|剪切指定行到寄存器 `:[range]yank [register]`|复制指定行到寄存器 `:[line]put [register]`|将寄存器的内容粘贴到行line的下方 `:[range]m[ove] {address}`|剪切指定行到地址address的下方 `:[range]co[py] {address}`|复制指定行到地址address的下方,简写`t` `:[range]join`|连接指定行 `:[range]normal {commands}`|指定行上执行普通模式命令 `:[range]sort`|对指定行进行字母排序`:h :sort` ### 寄存器相关 命令格式|功能 -------|---- `:let`|对寄存器赋值 `:register {reg}`|查看寄存器reg的内容 ### 缓冲区相关 缓冲区列表中`%`表示当前缓冲区,`#`表示轮换缓冲区,用``在当前与轮换缓冲区之间切换。 若缓冲区被修改过,列表中会以`+`表示,默认情况下不允许切换、退出缓冲区,除非使用了叹号后缀。一个不活动的未保存修改的缓冲区为隐藏缓存区,用`h`表示。 命令格式|功能 -------|---- `:ls`|显示缓冲区列表 `:bfirst`|移动到首个缓冲区 `:bp[revious]`|移动到上一个缓冲区 `:buffer {bufname}`|移动到指定缓冲区 `:bn[ext]`|移动到下一个缓冲区 `:blast`|移动到最后缓冲区 `:[range]bdelete [bufname]`|删除缓冲区 `:bufdo [cmd]`|所有缓冲区上执行Ex命令 ### 文件系统相关 `%:h`相当于`dirname(%)`获得活动缓冲区中文件所在的目录。 命令格式|功能 -------|---- `:lcd {path}`|设置当前窗口工作目录 `:pwd`|输出当前工作目录 `:e[dit] {filename}`|将文件读入缓冲区 `:find {filename}`|从path配置中查找文件并打开 `:edit!`|重新从文件读取,丢弃缓冲区修改 `:update`|文件发生改动时保存文件 `:write`|保存缓冲区 `:quit`|关闭缓冲区 ### 参数列表相关 参数(argument)即为启动Vim时传入的命令参数,即为文件列表。但在Vim中参数列表是可变的。 命令格式|功能 -------|---- `:args`|显示参数列表 `:args {arglist}`|用文件名、通配符、Shell命令输出填充参数列表 `:next`|向后遍历参数列表中的文件 `:prev`|向前遍历参数列表中的文件 `:argdo [cmd]`|对参数列表中的各缓冲区执行Ex命令 ### 窗口相关 命令格式|功能 -------|---- `s`|水平分割窗口,缓冲区不变 `v`|垂直分割窗口,缓冲区不变 `:sp[lit] {file}`|水平分割窗口,新窗口载入file `:vsp[lit] {file}`|垂直分割窗口,新窗口载入file `w`或``|窗口循环切换 `kjhl`|切换到上下左右的窗口 `c`或`clo[se]`|关闭活动窗口 `o`或`on[ly]`|关闭所有非活动窗口 `=`|所有窗口等宽、等高 `_`|最大化活动窗口的高度 `|`|最大化活动窗口的宽度 `{N}_`|活动窗口的高度设为N行 `{N}|`|活动窗口的宽度设为N行 `T`|将当前窗口移动到新的标签页 `:windo {cmd}`|对每个窗口的缓冲区执行命令cmd ### 标签页相关 标签页可包含一个或多个窗口,可以理解为工作区或多个虚拟桌面。 命令格式|功能 -------|---- `:tabe[dit] [file]`|创建标签页,包含指定文件的缓冲区 `:tabc[lose]`|关闭标签页和所有的窗口 `:tabo[nly]`|关闭所有非活动标签页 `:tabmove [N]`|移动标签页,0为开头,缺省为最后 Ex命令|普通模式命令|功能 -------|----|--- `:tabn[ext] {N}`|`{N}gt`|切换到N号标签页 `:tabn[ext]`|`gt`|切换到下个标签页 `:tabp[revious]`|`gT`|切换到上个标签页 ### Shell相关 可用`%`表示当前文件名用于Shell命令中。 命令格式|功能 -------|---- `:shell`|启动Shell,用`exit`返回Vim `:!{command}`|执行Shell命令 command,回显输出 `:read !{cmd}`|把Shell命令cmd的stdout导入缓冲区 `:[range]write !{cmd}`|把缓冲区内容作为Shell命令cmd的stdin执行 `:[range]!{cmd}`|把指定范围的内容用外部命令进行过滤 ## 模式 ### 模式开关 `\c`不区分大小写,`\C`区分大小写,它会覆盖`'ignorecase'`的设置,且可以位于模式的任意位置。 Vim正则模式类似POSIX。且三类括号的默认(magic)行为并不一致。 可以在模式前使用very magic开关`\v`与very nomagic开关`\V`更改。 符号|`magic`|`very magic`|`very nomagic` -------|----|----|---- 圆括号()|总是字面|子模式|字面 方括号[]|字符类|字符类|字面 花括号{}|字面/仅开括号转义|量词|字面 尖括号<>|总是字面|单词边界|字面 `\v`假定除`_`、大小写字母和数字之外的字符都具有特殊含义(如果有的话)。 `\v`使得除`\`以外的字符均不具有特殊含义,所有元字符都必须用反斜杠转义。 无论何种模式,正向查找时需要转义正斜杠,反向查找时需要转义问号。 `escape({string},{chars})`函数可以在表达式转义string的字符chars。 ### 匹配边界 元字符`\zs`和`\ze`用于界定模式中匹配的边界,可以由此减少子模式的使用频率。 ### 标志位 `:h s_flags` 修饰符|功能 -------|---- `e`|查找:将光标置于匹配模式的结尾 `e`|替换:屏蔽找不到匹配的错误提示 `g`|替换所有匹配项 `c`|替换前确认,用`:h :s_c`操作 `n`|不执行替换,而是报告匹配个数 `&`|重用上次的标志位 ### 替换域元字符 `:h sub-replace-special` 符号|功能 ---|---- `\0`或`&`|插入完整匹配 `\1`-`\9`|插入子匹配 `~`|上次替换使用的替换域 `\={vim script}`|执行表达式并作为替换的结果 在表达式中用函数`submatch({n})`获得完整匹配或子匹配。 ### 查找相关Ex命令 命令格式|功能 -------|---- `[range]s[ubstitue]/{pattern}/{string}/[flags]`|指定范围内替换字符串 `[range]g[lobal]/{pattern}/[cmd]`|对指定范围内的匹配行(缺省为`%`,每行执行Ex命令cmd(默认为`print`) `[range]v[global]/{pattern}/[cmd]`|类似`global`,但仅在不匹配的行上执行 `grep {pattern} {wildchar}`|使用外部`grep`在多个文件中查找模式pattern,使用grep语法 `vimgrep {pattern} {wildchar}`|在多个文件中查找模式pattern `nohlsearch`|暂时关闭查找高亮,直到执行下一个查找命令 `&`|重复上一次的替换操作,且忽略标志位。保留标志位需要`:&&`。 * `:g/re/d` 删除所有的匹配行 * `:v/re/d` 只保留匹配行 * `:g/re/p` 所谓的`grep`命令 ### 查找相关配置项 项目|说明 ----|---- `ignorecase`|查找模式不区分大小写 `smartcase`|模式有大写字母则大小写敏感,否则不敏感 `hlsearch`|高亮匹配文本 `incsearch`|增量查找 ## 配置项 项目|说明 ----|---- `hidden`|自动将含有未保存修改的缓冲区设为隐藏 `history={number}`|保存Ex命令历史记录的条数 `suffixesadd`|使用`gf`搜寻文件时尝试使用的扩展名列表 `path={paths}`|查找文件的路径列表,`**`为递归匹配 `tags={tag_files}`|查找ctags标签文件的路径 `makeprg={cmd}`|`:make`包装程序目标 `include={pattern}`|查找包含文件的模式 `complete={sources}`|普通关键词补全使用的来源 `wildmode={modes}`|自动补全模式,见`:h 'wildmode'` `wildmenu`|使用补全菜单 `spell`|启动拼写检查 ## 插件与工具 ### matchit用于关键词配对 ``` set nocompatible filetype plugin on runtime macros/matchit.vim ``` ### netrw对本地、远程文件进行读写 #### 配置 ``` set nocompatible filetype plugin on ``` #### 使用 * 以目录作为路径启动Vim * 用`:edit {path}`打开文件管理窗口 * 用`:e[dit ].`显示当前工作目录 * 用`:E[xplore]`显示活动缓冲区所在目录 * 利用`scp`、`ftp`、`curl`、`wget`来读写网络文件 ### ctags建立索引实现标签跳转和自动补全 建立ctags索引过程略,更新思路有:`:!ctags -R`、设置映射和git hook。 命令|说明 ----|---- ``|跳转到匹配当前光标关键词的首个标签 `g`|跳转到匹配当前光标关键词的唯一标签或提示列表 `:tag {keyword}`|跳转到首个keyword处 `:tjump {keyword}`|类似`g` `:pop`或``|反向遍历标签历史 `:tag`|正向遍历标签历史 `:tnext`|下一个匹配标签 `:tprev`|上一个匹配标签 `:tfirst`|第一个匹配标签 `:tlast`|最后一个匹配标签 `:tselect`|提示标签匹配列表 ### Quickfix列表 `:h quickfix` Quickfix列表:一组由文件名、行号、列号(可选)和消息组成的可定位注释信息。 Vim可以对外部`make`进行包装,用`:make`执行编译返回的错误信息进行处理后加入Quickfix列表。