Vim
[count]<C-a> 从当前光标处正向查找一个数字进行自增[count]<C-x> 从当前光标处正向查找一个数字进行自减. 重复命令, 会重复进入插入模式那一刻起(包括进入插入模式的按键本身),直到返回普通模式为止的输入或上一个普通模式下的操作(daw这样的命令会被视作一个操作),
可以被看作一个微型的宏命令.
j. 在下一行里重复之前的操作n. 在下一个匹配里重复之前的操作在为
. 范式预备插入模式命令时, 使用方向键(<Up> <Down> <Left> <Right>)会产生撤销块,导致连续的命令被中断(可以想象成是用
<Esc> 退出了插入模式, 然后用 hjkl 做了移动). 范式优于使用count的命令, 例如 dw. 要优于 d2w, 原因在于估计count的值很不直观, 多按几次 . 反而好控制.i 进入插入模式gi 在上一次退出插入模式的位置进入插入模式<C-u> 删除至行首(此快捷键在Bash也可使用)<C-w> 删除上一个单次(此快捷键在Bash也可使用)<C-r>{register} 插入寄存器内容(插入模式下)<C-r>={expression}<CR> 插入表达式寄存器, 将输出表达式的计算结果<C-r><C-p>{register} 插入寄存器内容(paste模式)Vim使用基于树而不是队列的历史记录, 撤销前的内容会作为一个分支保留.
按分支操作是把树当作一般的文本编辑器里的队列, 因此无法访问其他分支.
u 按分支撤销 undoU 按分支撤销对整行的操作<C-r> 按分支重做 redo按时间操作是按时间顺序访问树.
g- 按时间回退改动g+ 按时间前进改动在输入前几个字之后按
按
<C-n> 将出现自动补全窗口(如果只有一个, 则直接补全),按
<C-n> 切换到下一个补全项, 按 <C-p> 切换到上一个补全项.<C-x><C-i> 补全整行<C-x><C-j> 补全标签<C-x><C-f> 补全文件名gd 跳转到下一个当前光标处的内容定义的位置gD 跳转到下一个当前光标处的内容定义的位置(从文件开头查找)使用
ctags -R 生成标签文件tags.每次保存ts文件时自动生成标签文件(autocmd自动命令):
autocmd BufWritePost *.ts silent! !ctags -R &以下命令需要标签文件tags才能使用
<C-]> 跳转到定义 在VSCode里可直接使用<C-t> 跳转回原文件 在VSCode里可直接使用:tn 下一个标签 tag next:tp 上一个标签 tag previous:ts 打开标签列表菜单 tag select<C-o> 在插入模式下进入插入-普通模式, 在该模式下可以完成一个普通模式动作,然后自动回到插入模式, 该模式的优点在于可以省去一个进入插入模式的按键
<C-o>:w<CR> 快速保存<C-[> 切换到普通模式, 跟用<Esc>退回普通模式似乎没有区别插入模式
插入模式
插入模式
插入模式
<C-v>{code} 插入非常用字符(三位数的十进制字符编码)插入模式
<C-v>u{code} 插入Unicode字符(四位十六进制字符编码)插入模式
<C-v>{nondigit} 按照原义插入字符, 例如 <C-v><Tab> 插入制表符(无视expandtab设置)插入模式
<C-k>{char1}{char2} 插入二合字符, 例如 <C-k>12 插入 ½, <C-k><< 插入 «ga 显示当前光标字符的编码vi时代的缓冲区列表, vim时代用于批量执行命令.
由于vim不会将打开的文件自动填入参数列表, 因此避免将不必要的文件卷入命令执行.
由于vim不会将打开的文件自动填入参数列表, 因此避免将不必要的文件卷入命令执行.
:args {arglist} 填充参数列表, 例如 :args index.html app.js 即可打开两个文件,参数列表可使用glob模式批量添加, 甚至执行命令
:args `cat .chapters` 以文件内容作为参数:first:next:previous:last:arg {file1} {file2} 定义参数列表:arg **/*.ts 递归定义参数列表(将所有ts文件放进参数列表):argdo {ex-command} 对参数列表中的所有文件执行一条命令:argdo %s/\<animal\>/creature/ge | update 将参数列表内的文件执行替换, 并保存(update, 等价于 :write):args 显示参数列表vim时代的参数列表的替代品, vim多文件编辑的本质是一次将多个文件内容读入多个缓冲区, 保存则为将缓冲区内容写入文件.
:b[uffer] n 切换到第n个文件:bfirst 列表中第一个文件:blast 列表中最后一个文件:bn[ext] 切换到下一个文件:bp[rev] 切换到上一个文件:b file 按文件名切换:ls 或 :buffers 或 :files 列出打开的文件, 这是vim引入的功能, vi只有 :args<C-^> 在当前文件和轮换文件之间快速切换:bufdo 类似argdo, 在打开的缓冲区上执行Ex命令:bd[elete] N1 N2 N3 删除缓冲区(即退出编辑), 也可用 :n1,n2bd 批量删除, 按Tab可自动补全文件名:qa[ll] 关闭所有缓冲区:wa[ll] 写入所有缓冲区:wn[ext] 写入当前缓冲区并切换到下一个缓冲区内置文件浏览器, 支持sftp, scp等协议.
:Ex 或 :Explore 打开Netrw:e {directory} 指定目录打开Netrw:Vex 左右分割打开Netrw:Sex 上下分割打开Netrw:Lex 左右分割打开Netrw, 并将Netrw窗口置于最左侧Enter 打开文件- 上级目录D 删除文件或目录R 重命名文件或目录知名的侧边文件浏览器插件, 支持鼠标.
:NERDTree 打开NERDTree:NERDTreeToggle 开关NERDTreeEnter 或 o 打开文件vim -On file1 file2 左右分屏打开多文件 openvim -on file1 file2 上下分屏打开多文件vim + file 打开文件并跳转至最后一行<C-w>s 或 :sp[lit] 水平分屏当前文件 split:sp[lit] {file} 水平分屏当前文件 or 新文件<C-w>v 或 :vsp[lit] 垂直分屏当前文件 vertical:vsp[lit] {file} 垂直分屏当前文件 or 新文件<C-w>h 切到左窗口<C-w>l 切到右窗口(以此类推上 k 下 j)<C-w>H 移动至左侧窗口<C-w>L 移动至右侧窗口(以此类推上 K 下 J)<C-w>w 循环切换窗口, 也可以直接 <C-w><C-w><C-w>+ 加大窗口<C-w>- 减小窗口<C-w>= 所有窗口等高等宽<C-w>_ 最大化当前窗口高度<C-w>| 最大化当前窗口宽度[N]<C-w>_ 设置当前窗口高度为N行[N]<C-w>| 设置当前窗口宽度为N列<C-w>c 关闭当前窗口 close<C-w>q 关闭当前窗口并退出 quit<C-w>o 或 :on[ly] 关闭当前窗口以外的所有窗口:lcd {path}为当前窗口设置工作目录:pwd查看工作目录:windo lcd {path}为所有窗口设置工作目录:edit {filename}相对当前工作目录打开文件:edit!放弃修改重新载入当前文件, 通常用于录制宏时对操作过的文件进行撤销,
以便将宏应用于所有缓冲区文件时不会重复运行:e[dit] %<Tab>用%<Tab>补全当前缓冲区文件(即当前文件)的路径, 便于相对当前文件路径打开其他文件:e[dit] %:h<Tab>上一补全命令的相对路径版本,:h是一种文件名修饰符(用:h ::h查看说明文件):e[dit] .打开目录, 空格可以省略:find {filename}不使用完整路径打开文件文件,
例如:find Main.js输入文件名后也可以用<Tab>补全文件路径
(建议补全路径, 否则在有同名文件的情况下只会打开第一个):set path+=app/**添加find的查找路径:set path?查看当前path路径gf打开当前光标处的文件(受path和suffxiesadd影响):set suffixesadd+=.js为gf功能添加.js扩展名:!mkdir -p %:h在写入不存在目录的文件时, 创建那个目录:w !sudo tee % >/dev/null以root权限写入
原理为将当前缓冲区(文件)内容作为输入重定向给具有root权限的tee, 再由tee写入到对应文件,
用/dev/null屏蔽掉多余的打印内容:clo[se]关闭当前窗口(只剩一个窗口时不能关闭, 这是与:quit的主要区别):on[ly]只保留当前窗口, 关闭其他窗口
vimdiff {filename1} {filename2}]c 跳转到上一个冲突[c 跳转到下一个冲突do 将文件修改应用于当前窗口中的文件 diff obtaindp 将当前窗口中的文件修改推送给另一个文件 diff put:diffg[et] {file} 相当于do, 在同时比较3个文件以上时, 需要后接文件名:diffp[ut] {file} 相当于dp, 在同时比较3个文件以上时, 需要后接文件名在git处理合并冲突时使用vimdiff
左上角的窗口为本地修改(当前分支)
中上的窗口为共同祖先
右上角的窗口为远程修改(合并进来的分支)
下方的窗口为合并结果(需要通过编辑解决冲突的文件)
删除
git mergetool左上角的窗口为本地修改(当前分支)
中上的窗口为共同祖先
右上角的窗口为远程修改(合并进来的分支)
下方的窗口为合并结果(需要通过编辑解决冲突的文件)
:diffg L 使用本修改 LOCAL:diffg B 使用共同祖先 BASE:diffg R 使用远程修改 REMOTE:wqa 保存并退出删除
.orig 文件(合并冲突的备份):w `date` 使用Shell命令的输出作为文件名保存:set foldmethod=indent 启用基于缩进的折叠功能:set foldmethod=syntax 启用基于语法的折叠功能(需要Vim能够识别该语法):set foldmethod=diff 处于diff时采用的折叠方式zo 打开折叠 openzc 关闭折叠 closeza 切换折叠状态zR 打开所有折叠zM 关闭所有折叠::tabnew 或 tabe[dit] {filename} 打开一个新的标签页<C-w>T 把当前窗口移到一个新标签页:tabc[lose] 关闭当前标签页及其所有窗口:tabo[nly] 只保留当前标签页,关闭其他所有标签页:tabn[ext] {N} 或 {N}gt 切换到标签页Ngt 或 :tabn[ext] 切换到下一标签页gT 或 :tabp[revious] 切换到上一标签页:tabmove [N] 将标签页移动至N, 0为第一个标签页, 若省略N, 则移到最后一个标签页:x 保存退出(相当于 :wq?):qa! 强制退出所有文件 quit all:e file 打开另一个文件:e! 放弃对文件的所有修改, 恢复原样ZZ 保存当前文件并退出(:wq 的别名)Ctrl+G 显示当前编辑文件状态信息(文件名, 当前行, 总行数, 百分比等)<C-O> (在查找等操作之后)返回上一次光标所处的位置, 可重复使用<C-I> 反向的 <C-O>r 修改单个字符, 在可视模式下, 将以单个字符填充所有选中的字符 replaces 删除当前字符并进入插入模式S 删除当前行并进入插入模式(会保持缩进, 功能与cc一样)c{motion} 删除并进入插入模式cc 删除整行并进入插入模式(会保持缩进)cw 删除单词并进入插入模式C 删除至行尾(和 D 不同, 不会回退到上一个字符)D 剪切至行尾(会回退到上一个字符, 相当于 d$)gj 根据屏幕行向下移动gk 根据屏幕行向上移动g^ 移动到屏幕行的第一个非空字符g$ 移动到屏幕行的行尾v <motion> :w filename 将选区内容保存为新文件:h index 查看Vim默认的按键绑定:map {key} 查看以对应按键key开头的映射:unmap {key} 取消对应的重映射:mapclear 清除所有重映射:map ^M I#<ESC> 设置递归快捷键映射, 例子意为Ctrl+M映射为I#<ESC>(在行首插入#然后退出插入模式):noremap ^M I#<ESC> 设置非递归映射:nnoremap ^M I#<ESC> 设置正常模式下的非递归映射:vnoremap ^M I#<ESC> 设置可视模式下的非递归映射:inoremap ^M I#<ESC> 设置插入模式下的非递归映射:ab email user@example.com 设置字符宏, 输入email(需要追加一个空白字符)会被自动替换为 user@example.com:ce 居中 center:le 靠左 left:ri 靠右 right进入块视图模式, 选中多行文本, 用
I 在选中内容前批量插入字符 //.进入块视图模式, 选中需要删除的内容, 用
d 命令删除.0行首^或_非空白字符行首$行尾g_非空白字符行尾w移动光标到下一个"狭义单词(以符号为分隔符)的开头" wordW移动光标到下一个"广义单词(以空格为分隔符)的开头"b移动光标到上一个"狭义单词(以符号为分隔符)的开头 backwardB移动光标到上一个"广义单词(以空格为分隔符)的开头"e移动光标到下一个"狭义单词(以符号为分隔符)的结尾"
(如果当前光标在一个单词的非结尾处, 那么下一个"单词的结尾"即是当前单词的结尾处, 而非"下一个单词"的结尾)E移动光标到下一个"广义单词(以空格为分隔符)的结尾"ge移动光标到上一个"单词的结尾"fa移动光标到本行下一个字符为a的位置 findFa移动光标到本行上一个字符为a的位置ta移动光标到a前的一个字符, till, 这个命令通常用于dt.(删除至下一个句号前)这样的动作Ta移动光标到a后的一个字符(移动至句首(以". "作为一句, 注意句号后的空格))移动至句尾(以". "作为一句, 注意句号后的空格){移动到上一个段落(空白行)}移动到下一个段落(空白行);向后重复f,t操作,向前重复f,t操作d/something删除至something, 这提供了正则删除能力gg或H或1G或[[或``文件首行G或]]文件末行H光标移动至编辑区(window)首行 head line of windowM光标移动至编辑区(window)中间 middle line of windowL光标移动至编辑区(window)末尾 last line of windownG移动光标到第n行nH移动光标到第n行(ngg同理)%在配对的括号字符上来回移动, 有效字符为()[]{}*查找当前光标处的单词#反向查找当前光标处的单词(这两个命令实际上是为了快捷使用而创建出来的宏命令)g*查找当前光标处的单词, 但不使用单词界定符g#反向查找当前光标处的单词, 但不适用单词界定符n%到文件n%的位置
可视范围
zz 当前行置于屏幕中间zt 当前行置于屏幕顶端 topzb 当前行置于屏幕底端 bottom<C-f> 下一页 forward<C-b> 上一页 back<C-u> 上半页 up<C-d> 下半页 down<C-e> 向下一行<C-y> 向上一行dfa 删除至下一个字符 adnfa 删除至第n个字符 adH 删除至文本首dG 删除至文本尾daw 删除光标位置所处的单词至下一个单词的第一个字符(dw只删除当前光标位置到下一个单词的第一个字符)yw 复制单词yfa 复制至下一个字符aynfa 复制至第n个字符ay$ 复制至行尾yH 复制至文本首yG 复制至文本尾J 合并下一行内容至本行(删除两行之间的换行符和其他空白符) 两行中间会有一个空格gJ 两行中间没有空格的 J:1,10m20 将1到10行的内容移动到20行后 movei inside,不包括文本对象边界,只针对内容a around,包括文本对象边界s 句子 sentencew 狭义单词 wordW 广义单词p 段落t HTML标签" 双引号' 单引号( 括号< 尖括号[ 方括号{ 花括号可以用
v{i|a}{文本对象} 方式直接框选相关内容P 复制至光标前 paste插件
<Leader><Leader>w 开启基于单词的EasyMotion, 最常用(同理, 还有 W, b, B, e, E, ge, gE)<Leader><Leader>f 开启正向查找字符的EasyMotion(同理, 还有 F, t, T)<Leader><Leader>{方向键} 朝对应的文本方向开启EasyMotion在搜索时
<Leader><Leader>n 开启用于跳转到搜索结果的EasyMotion(同理, 还有 N)<Leader> 先导键, 默认为 \let mapleader = "\<space>" 将先导键修改为空格(于 .vimrc 中设置)u 转小写字母 等于普通模式下的 gu{motion} 例如 guitU 转大写字母 等于普通模式下的 gU{motion} 例如 gUit注意可视模式下的命令用
. 重复执行时,选取和动作会被视为两条命令,将导致一些问题(例如选区长度被固定为一定数量的字符).
正确的方法是使用
g 开头的命令一次完成选取和动作, 这样 . 命令就可以正确执行.o 光标跳转至选区另一端, 该命令用于调整选区范围gv 重选中上次选区{number}| 跳转到指定列{number}gg 或 :{number} 跳转到指定行:+{number} 向下相对跳转到指定行:-{number} 向上相对跳转到指定行ma 标记此处为a'a 跳转至a标记:marks 查看所有标记:delm! 删除所有标记m{a-z} 缓冲区范围内的位置标记m{A-Z} (多文件)全局范围内的位置标记'{a-zA-Z} 跳转到标记所在行`{a-zA-Z} 跳转到标记所在行和列`` 跳转到上次跳转之前的位置, 常见用法是配合 % 跳转修改成对括号, %r{w}``r{w}`< 上次高亮选区的起始位置`> 上次高亮选区的结束位置同理也存在
' 相应的跳转, 只不过 ' 跳转到对应行不常用的跳转:
`. 上次修改(即跳转到改变列表的最后一位)`^ 上次插入gi 跳转到上次插入位置并进入插入模式(相当于 `^i)`[ 上次修改或复制的起始位置`] 上次修改或复制的结束位置Vim 8.1开始提供的模式, 可在Vim内打开一个终端窗口.
:term[inal] 打开终端:term {command} 打开终端并执行命令r (进入单字符替换模式)替换光标当前字符 replaceR (进入替换模式)替换光标后的所有字符(用 <ESC> 停止)Vr{char} 替换整行字符为char~ 改变当前字符的大小写n~ 改变n个字符的大小写g~~ 改变整行的大小写gUU 改变整行至大写guu 改变整行至小写3gUU 改变三行至大写gUw 改变单词至大写guw 改变单词至小写<C-v> 块可视化模式(可以无视行的长度选中文本块, 但在Terminus里无法使用, 疑似因为 <C-v> 被屏蔽)在块可视化模式内用
I 或 A, 可以实现在选中的文本块的行前或后添加文本(将批量作用到选中文本块的每一行)va"在""文本块内部, 可用此命令选中该文本块的所有内容,"可替换为其他文本块字符,
例如(,',{,[vi"同上, 但不选中"本身
<C-n> 或 <C-p> 代码提示(编辑模式下)qa 开始录制宏并保存到寄存器aaA 开始录制宏并追加到寄存器aq 停止宏录制@a 应用位于寄存器a的宏@@ 应用上一个宏n@a 应用a宏n次:'<,'>normal @a 进入V模式后批量运行宏a, 在这种运行方式里宏a在一行中运行失败不会中断其他行的运行:argdo normal @a 批量运行宏a至参数列表中的文件, 有必要对录制文件执行 :edit! 撤销修改, 避免重复运行:argdo execute ":normal @a" | update 批量运行宏a至参数列表中的文件并保存:new 打开新的缓冲区"ap 输出宏a的内容_"ay$ 将新缓冲区的内容复制回宏a:reg 查看所有寄存器:reg {register} 查看寄存器:put a 输出寄存器a的内容到下一行"add 或 :d a 将行内容写回寄存器a, 用 "ay$ 写回寄存器时可以免去行尾的换行符"" 无名寄存器 即 d, s, x, y, c 命令默认使用的寄存器"_ 黑洞寄存器, "_d{motion}, 删除的内容不会进入任何寄存器"0 复制专用寄存器, 当使用 y 命令时, 相关内容不仅会进入无名寄存器, 也会进入此寄存器,此寄存器被用于解决
d 等命令覆盖无名寄存器以至复制内容消失的问题;但实际上也可以用
v 选中需要被替换的文本, 直接用 p 命令覆盖, 就不需要使用此寄存器"{a-z} 寄存器, "ad{motion} 可将内容输入进寄存器a, "ap 粘贴寄存器a信息"{A-Z} 追加寄存器, 将寄存器名从小写改为大写字母时, 新内容不会覆盖原寄存器, 而是追加到原内容之后"+ 系统剪贴板"* X11窗口系统的主剪贴板(primary), 与鼠标中间有关, Windows和macOS无此概念,该功能可在编译Vim时被禁用(xterm_clipboard)
"= 表达式寄存器, 可用来计算只读寄存器
"% 当前文件名"# 轮换文件名". 上次插入的文本": 上次执行的Ex命令"/ 上次查找的模式Vim的copy使用y(yank)而不是c是历史原因, 在添加复制命令时, c键已经被用于change命令, 而y键还未被使用
- 命令行模式按下
<c-d>, 显示所有补全项 - 命令行模式按下
<Tab>, 自动补全 - 命令行模式
<C-r><C-w>复制光标单词(word)插入至命令行,
在使用s命令进行文本替换时比较有用, 在开启insearch的情况下, 也可以用来直接补全匹配词 - 命令行模式
<C-r><C-a>复制光标字串(WORD)插入至命令行
单词(word)的定义: 符合英文语法的单词(单词可以被符号隔开, 比如
字串(WORD)的定义: 任何以空格字符分隔开的非空白字符
we're 算两个单词)字串(WORD)的定义: 任何以空格字符分隔开的非空白字符
>> 缩进行:[range]> {count} 缩进行的ex命令形式<< 反缩进行:[range]< {count} 反缩进行的ex命令形式>G 缩进至文件末尾<G 反缩进至文件末尾:1 首行:$ 尾行:0 虚拟行(位于首行上方):. 当前行:'m 包含位置标记m的行:'< 高亮选区起始:'> 高亮选取结束:% 整个文件, 相当于 :1,$:.,.+3 选取当前行(.)和后三行:/<html>/,/<\/html>/ 正则选区:/<html>/+1,/<\/html>/-1 正则选区(偏移n行, +1 可省略为 +):copy 复制选区, 详见 :h :copy:move 移动选区, 详见 :h :move:normal 执行普通模式命令, 详见 :h :normal, 例如 :'<,'>normal . 意为对高亮选区里的每一行使用 . 命令:@: 或直接在普通模式下 @: 或 @@ 重复上一条Ex命令:shell 打开一个新的shell, exit后即可回到Vim窗口(如果不想打开新的shell, 也可以用
<C-z> 暂停Vim, 回到原来的shell里, 做完其他事后再用fg回到Vim):term 以分屏的形式打开一个shell, 常用:sil[ent] 屏蔽输出n1,n2d 删除n1到n2(等同于sed的 d 命令)同理存在
:#,#s 在范围内查找g标志位指一整行范围(来源于行编辑器ed), 而不是全局(
% 才是全局):%s/find/replace/i 大小写不敏感的替换 ignoreCases:%s/find/replace/gc 需要人工确认的全局替换 check- magic
此为默认模式, 只有极少数符号不需要转义 - no magic
所有符号都需要用反斜线\转义 - very magic
数字, 字母, 下划线以外的字符都是特殊字符, 通过在正则表达式首加入\v启用此模式
:%s/\(\w\)/\1/g 捕获并替换, 括号在very magic模式以外的情况下必须转义\c 此元字符在正则中强制忽略大小写敏感\C 此元字符在正则中强制大小写敏感\v 此元字符在正则中开启very magic模式(符合Python, Perl, Ruby语法的正则模式),
该模式下
_, 数字, 字母以外的字符都被当作特殊字符, 避免大量使用转义, 有效节省字符数和增强可读性/\<word\> 搜索整个单词 /\bword\b 搜索整个单词(Vim for VSCode)\< 单词开始\> 单词结尾<\w+> very magic模式下的单词边界零宽度元字符(单词定界符),用
< 和 > 包裹字符部分(在一般模式下需要对 < 和 > 转义)%(a|b) very magic模式下的非储存匹配, 在圆括号前加上 %,匹配内容不会被存入寄存器
\1, 类似于正则的 (?:pattern)\V 此元字符在正则中强制只有 \ 带有特殊含义(实际上在正向查找时有 / 作为结束符,反向查找时有
? 作为结束符, 所以是三个, 在查找URL时非常容易碰到此情况), 在只想按照原义匹配时很有用\x 此元字符代表 [0-9a-fA-F], 即十六进制数\zs 零宽度元字符 匹配边界开始 功能类似于正则的断言 (assert) (?=pattern) (?!pattern) (?<=pattern)\zs 零宽度元字符 匹配边界结束 功能类似于正则的断言 (assert) (?=pattern) (?!pattern) (?<=pattern)例子: 假设有一段文本
Goodbye World, Hello World,需要匹配World, 但只匹配前面是Hello的World, 使用
/Hello \zsWorld<CR> 即可完成匹配(高亮项目为World)在查找时使用寄存器的方法:
在查找时使用寄存器并转义的方法:
(光标不在最后一个字符时将选中匹配项的剩余字符, 光标在最后一个字符时将选中至下一个匹配项的第一个字符)
衍生:
/\V<C-r>a<CR> 其中 <C-r>a 即输出寄存器a的值在查找时使用寄存器并转义的方法:
/\V<C-r>=escape(@a, getcmdtype().'\') 其中escape是内置转义函数,getcmdtype 自动识别当前查找是正向还是反向并返回对应字符, . 是Vim脚本的字符串连接操作符/<CR> 正向查找上一次匹配?<CR> 反向查找上一次匹配gn 匹配状态下的可视模式, 正向选中内容(光标不在最后一个字符时将选中匹配项的剩余字符, 光标在最后一个字符时将选中至下一个匹配项的第一个字符)
gN 匹配状态下的可视模式, 反向选中内容衍生:
gUgn 匹配内容转大写dgn 删除匹配内容cgn 修改匹配内容/pattern/e 设置匹配搜索结果时光标的位置在匹配内容的末尾, 可用 :h search-offset 查看更多值:%s//{string}/g 重复上一次匹配并替换(查找内容为空时会使用上一次匹配的模式),用于分步完成替换操作(先用
/ 完成匹配):%s///gn 统计上一匹配的匹配数量, 标志位n抑制替换操作<C-r>/ 输入上一次的查找模式~ 在替换域中使用此符号, 则意味着使用上一次替换的替换域标志位
e 屏蔽错误提示(例如"找不到匹配的模式")标志位
& 重复上一次substitute命令的标志位\={script} 执行表达式脚本, 可在substitute命令中使用\=@{register} 调用寄存器内容, 可在substitute命令中使用\=submatch(0)-1 匹配项数字 -1, 可用于HTML标签的h2替换为h1, h3替换为h2g&相当于:%s//~/g意为在当前文件里重复执行上一次替换(在忘记输入%或g的情况下使用)&重复上一次替换命令:'<,'>&&在选区中重复上一次替换命令
(第一个&是重复上一次替换命令, 第二个&是重复替换标志位,
需要两个&是因为第一个&并不会记住标志位)
:%s/\v(<man>|<dog>)/\={"dog":"man","man":"dog"}[submatch(1)]/g交换替换
The dog bit the man 的 dog 和 man, 其中 {} 是Vim脚本里的字典数据类型局限于一个窗口版本的快速恢复列表, 大多数快速恢复列表命令前加上
l 即可:lgrep:lmake:lopen:lclose:lnext:lprev:lwindow一个Vim会话中只有一个快速恢复列表
:vimgrep //g % 将当前文件里上一次的匹配放进quickfix列表, % 为当前文本路径:grep 也可直接在Vim里调用外部grep程序, 运行结果会保存在quickfix列表里, 性能更好, 但支持不如vimgrep:copen 打开quickfix列表, 像Vim一样编辑:cclose 关闭quickfix列表, 像Vim一样编辑:cp[rev] 跳转到quickfix列表的上一项:cn[ext] 跳转到quickfix列表的下一项:vimgrep /{pattern} **/*.txt 查找当前目录下的所有txt文件:cfdo 对quickfix列表项目运行批处理, 有必要先 :set hidden:set hidden 忽略未保存退出(切换缓冲区):cfdo update 保存所有quickfix列表文件(如果有更新的话):cfdo %s//{string}/g | update 替换保存二合一命令(| 是Vim的命令分隔符, 不是管道符号):[range] g[lobal] /{pattern}/ [cmd]在整个文件(global命令的范围默认即为
%)里对匹配到的行执行命令, 缺省的 cmd 为 print;需要注意的是, 命令仍然支持指定范围, 所以
[cmd] 也可以看作 [range][cmd]:v[global]和:g[lobal]!是:g[lobal]的非匹配版本, 不匹配的行将执行cmd,v指invert:g//d删除所有匹配文本, 比如:g/\v\<\/?\w+\>/d可删除所有HTML标签:g/TODO收集TODO行qaq:g/TODO/yank A清空寄存器a, 将所有TOOD收集进寄存器a
(使用大写A是为了让每一行都能被追加进寄存器, 而不是覆盖):g/TODO/t$收集TODO并复制到文件尾:g/{/ .+1,/}/-1 sort排序CSS属性, 请注意.+1,/}/-1 sort是此条命令的cmd部分
这条命令符合如下模式::g/{start}/ .,{finish} [cmd]只将global用作匹配起点, 用.,{finish}模式框选需要用cmd处理的部分:[range]copy {address}复制内容到指定位置, 别名:t copyTo:[range]move {address}移动内容到指定位置, 别名:m:'<,'>sort排序选中行
grep的来历即为
:g/re/p g是global, re是正则表达式, p是打印:[range]!{command} 执行Linux命令, 如果存在range, 则将以命令输出替换相关内容(过滤):r[ead] filename 将文本文件的内容输入到当前光标处:r[ead] !{command} 执行Linux命令并输入到当前光标处(空格可以省略):w[rite] !cat 这是read的相反命令, 将缓冲区写入shell命令, 注意空格不可省略, :w! 将改变语义为强制写入w | !node % 用 | 合并两条命令, 其中 % 会被替换为当前文件名jumps 查看跳转列表(jump list)<C-o> 反向遍历跳转列表<C-i> 或 <Tab> 正向遍历跳转列表changes 查看改变列表(change list)g; 反向遍历改变列表g, 正向遍历改变列表普通模式下
普通模式下
输入Ex命令时, 可用
q: 调出历史Ex命令行窗口, 回车执行当前行命令普通模式下
q/ 调出历史查找命令行窗口, 回车执行当前行命令输入Ex命令时, 可用
<C-f> 将当前输入的内容切换到命令行窗口编辑创建
.vim 文件, 可以用于Ex命令的批处理, 在批处理中不需要在语句首使用::source batch.vim 在打开的文件中执行批处理=:args 显示参数列表(当 vim *.txt 一次性打开多个文件时, 可以看到参数列表里有多个文件):n[ext] 移动到下一个文件:pre[vious] 移动到上一个文件:first 移动到首个文件:argdo source batch.vim 对参数列表里的每一个文件执行batch.vim批处理Vim脚本(用于宏)
:let i=0 赋值:echo i 打印:let i+=1 递增<C-r>=i<CR> 在插入模式下用表达式寄存器输入i的值:echo @a 打印宏内容:let @a=substitute(@a, 'old', 'new', 'g') 赋值替换宏内文本:set 或 :se 显示所有修改过的配置:set all 显示所有配置项:set option? 显示option的值:set option! 取消option的值:set option& 重置option的值为默认值:set nooptions 取消option的值:ver 显示 vim 的信息:setlocal 只对当前缓冲区生效的配置:bufdo setlocal 对当前打开的所有缓冲区生效的配置:windo setlocal 对当前打开的所有窗口生效的配置:set nu 显示绝对行号 number:set nonu 取消显示绝对行号 number:set relativenumber 显示相对行号(会覆盖绝对行号):n 前往第n行(相当于 nG, ngg, nH):set ic 或 :set ignorecase 使查找命令不区分大小写:set noic 使查找命令区分大小写 no ignore cases:set smartcase 智能大小写敏感性(当出现大写字符时, 自动敏感):set hls[earch] 高亮匹配内容:set nohls[earch] 关闭高亮:noh[lsearch] 临时关闭高亮(至下一次搜索):set incsearch 在搜索输入关键字时, 就匹配第一个结果:set nowrapscan 关闭搜索时找不到内容就自动从文件头部继续搜索的特性:set ft=html 设置文件类型为html(file type):set history=200 将历史命令保存上限设置为200条:set paste 进入paste模式, 该模式下autoindent等妨碍粘贴的选项将被关闭(在gVim等GUI版本里, 无需设置paste, 粘贴会被自动识别, 不会打乱文本)
:set nopaste 退出paste模式:set pastetoggle=<f5> 将paste模式的开关设置为F5:so[urce] {file} 执行Vim脚本, 一般用来更新.vimrc的修改:so[urce] $MYVIMRC 跨平台的vimrc更新命令:so% 执行当前编辑的Vim脚本:edit $MYVIMRC 跨平台的vimrc文件编辑命令:set directory=$HOME/.vim/swap// 设置交互文件的保存路径(默认为当前文件的位置):set noswapfile 关闭交互文件功能:set undofile 启动持久性撤销(退出文件后仍然保留编辑历史记录)在
.vimrc 里启动持久性撤销并设置撤销文件的保存路径set undofileif !isdirectory("$HOME/.vim/undodir") call mkdir("$HOME/.vim/undodir", "p")endifset undodir="$HOME/.vim/undodir":h[elp] {keyword} 在帮助文件里查找关键字:h[elp] {keyword} <C-d> 输入一个不完整的关键字, 显示帮助文件里所有包含此关键字的标签.