文章目录
- Vim script
- 打印输出和字符串
- 变量
- 数字
- 复杂数据结构
- 表达式
- 控制结构
- 函数和匿名函数
- 重要命令
- 事件
- 内置函数
- 四种模式
- 正常(normal)模式
- 插入(insert)模式
- 可视(visual)模式:v/V
- 命令行(command-line)模式
- vim的键描述
- Vim脚本语言
- 备份和撤销文件
- 鼠标支持
- 中文支持
- 图形界面的字体配置
- 光标移动
- 文本修改
- 文本对象选择d/y/c
- 演示 a、i 和 w、双引号、圆括号搭配使用
- 其他搭配
- 对多个(层)文件对象进行操作
- 更快地移动
- 重复
- vim的运行支持文件
- syntax:Vim 的语法加亮文件
- doc:Vim 的帮助文件
- colors:Vim 的配色方案
- plugin:Vim 的“插件”,即用来增强 Vim 功能的工具
- 用户的vim配置目录
- vim软件包
- 安装minpac包管理器
- 多文件打开与缓冲区:复制粘贴的正确姿势
- 复制粘贴
- 多文件的打开方式
- 工作流
- 缓冲区的管理和切换
- 窗口和标签页:修改、对比多个文件的正确姿势
- 多窗口编辑
- 双窗口比较
- 多标签页编辑
- 正则表达式
- 正则表达式搜索
- 最长匹配和最短匹配
- 正则表达式替换
- 编程支持
- 查看文档
- 自动完成
- 记录
Vim script
打印输出和字符串
- Vim 里使用 "或’ 来引起一个字符串。
- 可以在 ’ 括起的字符里把 ’ 重复一次来得到这个字符本身,即 ‘It’‘s’ 相当于 “It’s”。
- 字符串可以用 . 运算符来拼接。字典访问也可以用 .
- 可以使用 . 或 … 进行字符串拼接。
echo 'Hello world!'
变量
# 变量可以用 let 命令来赋值
# Vim 的变量可以手工取消,需要的命令是 unlet。
let answer = 42
echo 'The meaning of life, the universe and everything is ' . answer
数字
复杂数据结构
Vim 脚本内置支持的复杂数据结构是列表(list)和字典(dictionary)。
- 列表(list)
let primes = [2, 3, 5, 7, 11, 13, 17, 19]
# 可以用下标访问,比如用 primes[0] 就可以得到 2。
- 字典(dictionary)
# Vim 脚本的续行——下一行的第一个非空白字符如果是 \,则表示这一行跟上一行在逻辑上是同一行
let int_squares = {
\0: 0,
\1: 1,
\2: 4,
\3: 9,
\4: 16,
\}
# 键会自动转换成字符串,而值会保留其类型。
# 访问字典里的某一个元素可以用方括号,如 int_squares['2'];或使用 .,如 int_squares.2。
表达式
- Vim 脚本的表达式里可以使用括号,可以调用函数(形如 func(…))
- 支持加(+)、减(-)、乘(*)、除(/)和取模(%)
- 支持逻辑操作(&&、|| 和 !)
- 还支持三元条件表达式(a ? b : c)
- == 和 != 运算符对所有类型都有效
- 而 <、>= 等运算符对整数、浮点数和字符串都有效
- 对于文本处理,常见的情况是我们使用 =~ 和 !~ 进行正则表达式匹配,前者表示匹配的判断,后者表示不匹配的判断。比较操作符可以后面添加 # 或 ? 来强制进行大小写敏感或不敏感的匹配(缺省受 Vim 选项 ignorecase 影响)。表达式的左侧是待匹配的字符串,右侧则是用来匹配的正则表达式
- 在表达式的左侧,需要有 echo 这样的命令
- 如果你只想调用一个函数,而不需要使用其返回的结果,则应使用 call func(…) 这样的写法
- 我们在插入模式和命令行模式下都可以使用按键 =(两个键)后面跟一个表达式来使用表达式的结果
- 在替换命令中,我们在 = 后面也同样可以跟一个表达式,来表示使用该表达式的结果。
- 当前编辑文件的每一行前面插入行号和空格:
:%s/^/\=line('.') . ' '/
- line 是 Vim 的一个内置函数,line(‘.’) 表示“当前”行的行号
控制结构
- 在 while 和 for 循环语句里,你可以使用 break 来退出循环,也可以使用 continue 来跳过循环体内的其他语句。
# 每种结构都要用一个对应的 endif、endwhile 和 endfor 来结束
" 简单条件语句
if 表达式
语句
endif
" 有 else 分支的条件语句
if 表达式
语句
else
语句
endif
" 更复杂的条件语句
if 表达式
语句
elseif 表达式
语句
else
语句
endif
" 循环语句
while 表达式
语句
endwhile
" for循环
for var in object
这儿可以使用 var
endfor
函数和匿名函数
function 函数名(参数1, 参数2, ...)
函数内容
endfunction
# 匿名函数
echo map(range(1, 5), {idx, val -> val * val})
重要命令
- execute(缩写 exe):它能用来把后面跟的字符串当成命令来解释。
- source(缩写 so)命令:它用来载入一个 Vim 脚本文件,并执行其中的内容。
- map 系列键映射命令:
- set
- noremap、inoremap
- let
事件
内置函数
四种模式
正常(normal)模式
插入(insert)模式
- i(insert):在光标前面进入插入模式;
- I 则相当于 ^i,把光标移到行首非空白字符前然后进入插入模式。
- a(append):在光标后面进入插入模式
- A:在光标所在的行尾进行插入
- o:在光标的下一行 进行输入
- O:在光标的上一行 进行输入
可视(visual)模式:v/V
用于选定文本块
V:进入可视行模式
命令行(command-line)模式
用于执行较长、较复杂的命令;
- 进入命令行模式 ::
- 搜索:/ ?
vim的键描述
- 表示 Esc 键;显示为“⎋”
- 表示回车键;显示为“↩”
- 表示空格键;显示为“␣”
- 表示 Tab 键;显示为“⇥”
- 表示退格键;显示为“⌫”
表示删除键;显示为“⌦”- 表示光标上移键;显示为“⇡”
- 表示光标下移键;显示为“⇣”
- 表示光标左移键;显示为“⇠”
- 表示光标右移键;显示为“⇢”
- 表示 Page Up 键;显示为“⇞”
- 表示 Page Down 键;显示为“⇟”
- 表示 Home 键;显示为“↖”
- 表示 End 键;显示为“↘”
- <S-…> Shift 组合键;显示为“⇧”
- <C-…> Control 组合键;显示为“⌃”
- <M-…> Alt 组合键;显示为“⌥”
- <D-…> Command 组合键;显示为“⌘”(Mac 键盘)
Vim脚本语言
syntax on:打开语法高亮
let mapleader=" "
set enc=utf-8:配置语言
set number:显示行号
set cursorline:设置游标线
set wrap:设置文字区间不超过当前屏幕
set showcmd:在底下显示输入的命令
set wildmenu:命令补全,按Tap
set mouse=a
noremap n h:在键盘上按n时输入的是h键
noremap u k
noremap e j
noremap i l
noremap k i
noremap K I
noremap l u
noremap <LEADER><CR> :nohlsearch<CR> # nohlsearch:no high light search
方便搜索时上下查找:
noremap = nzz
noremap - Nzz
map s <nop>:让在正常模式下的s键无效
map S :w<CR>:映射,当按下S键时,输入的是:w<CR>,即保存
map Q :q<CR>:设置按下Q退出vim
map R :source $MYVIMRC<CR>:按下R即刷新配置文件
source $VIMRUNTIME/vimrc_example.vim:导入 Vim 的示例配置(这会打开一些有用的选项,如语法加亮、搜索加亮、命令历史、记住上次的文件位置,等等)
正常模式下:
<operation><motion>:操作,加一个动作
命令行模式下:
:color blue/darkblue/default:选择主题
备份和撤销文件
set nobackup
set undodir=~/.vim/undodir
if !isdirectory(&undodir)
call mkdir(&undodir, 'p', 0700)
endif
鼠标支持
if has('mouse')
if has('gui_running') || (&term =~ 'xterm' && !has('mac'))
set mouse=a
else
set mouse=nvi
endif
endif
中文支持
set fileencodings=ucs-bom,utf-8,gb18030,latin1
图形界面的字体配置
- windows
if has('gui_running')
set guifont=Courier_New:h10
endif
- 在 Ubuntu 下把字体设成 10 磅的 DejaVu Sans Mono
" Linux 和 Windows 不同,不能用 '_' 取代空格
set guifont=DejaVu\ Sans\ Mono\ 10
- 宽字符字体配置
set guifontwide=Noto\ Sans\ Mono\ CJK\ SC\ 11
光标移动
- w(word):向后跳转一个单词。小写的跟编程语言里的标识符的规则相似,认为一个单词是由字母、数字、下划线组成的(不严格的说法)。
- W:向后跳转一个单词。大写的命令则认为非空格字符都是单词。
- b(back):向前跳转一个单词。小写的跟编程语言里的标识符的规则相似,认为一个单词是由字母、数字、下划线组成的(不严格的说法)。
- B:向前跳转一个单词。大写的命令则认为非空格字符都是单词。
- f(find)和 t(till):寻找字符
它们的作用都是找到下一个(如果在输入它们之前先输入数字 n 的话,那就是下面第 n 个)紧接着输入的字符。两者的区别是,f 会包含这个字符,而 t 不会包含这个字符。
This is vim: the best editor out there.
当光标在T的上面时:使用于d/y/c,即删除、复制、剪切
df:(f:表示从光标寻找到最近的一个:):从光标一直删除到冒号
dt:(t:表示从光标寻找到最近的一个:):从光标一直删除到冒号前,即不包括冒号本身
- ( 和 ) 移到上一句和下一句
- { 和 } 移到上一段和下一段
- gg、:跳转到文件的开头
- :跳转到文件的结尾
- G:跳转到最后一行的第一个字符,而不是最后一个字符
文本修改
- d(delete) 加动作来进行删除(dd 删除整行);D 则相当于 d$,删除到行尾。
d<数字><方向键>:往相应的方向删除对应的数字
- c (cut)加动作来进行修改(cc 修改整行);C 则相当于 c$,删除到行尾然后进入插入模式。
- i 在当前字符前面进入插入模式;I 则相当于 ^i,把光标移到行首非空白字符上然后进入插入模式。
- a 在当前字符后面进入插入模式;A 相当于 $a,把光标移到行尾然后进入插入模式。
- o 在当前行下方插入一个新行,然后在这行进入插入模式;O 在当前行上方插入一个新行,然后在这行进入插入模式。
- u 撤销最近的一个修改动作;U 撤销当前行上的所有修改。
文本对象选择d/y/c
演示 a、i 和 w、双引号、圆括号搭配使用
假设有下面的文本内容:
if (message == "sesame open")
我们进一步假设光标停在“sesame”的“a”上,那么:
d:delete
a:all
i:inner内部的
w:word
- ‘dw’(理解为 delete word)会删除“ame␣”,结果是“if (message == “sesopen”)”
- ‘dW’
- ‘diw’(理解为 delete inside word)会删除“sesame”,结果是“if (message == " open")”
- ‘daw’(理解为 delete a word)会删除“sesame␣”,结果是“if (message == “open”)”
- ‘diW’会删除““sesame”,结果是“if (message == open”)”
- ‘daW’会删除““sesame␣”,结果是“if (message == open”)”
- ‘di"’会删除“sesame open”,结果是“if (message == “”)”
- ‘da"’会删除““sesame open””,结果是“if (message ==)”
- ‘di(’或‘di)’会删除“message == “sesame open””,结果是“if ()”
- ‘da(’或‘da)’会删除“(message == “sesame open”)”,结果是“if␣”
其他搭配
- 搭配 s(sentence)对句子进行操作——适合西文文本编辑
- 搭配 p(paragraph) 对段落进行操作——适合西文文本编辑,及带空行的代码编辑
- 搭配 t(tag)对 HTML/XML 标签进行操作——适合 HTML、XML 等语言的代码编辑
- 搭配 ` 和 ’ 对这两种引号里的内容进行操作——适合使用这些引号的代码,如 shell 和 Python
- 搭配方括号(“[”和“]”)对方括号里的内容进行操作——适合各种语言(大部分都会用到方括号吧)
- 搭配花括号(“{”和“}”)对花括号里的内容进行操作——适合类 C 的语言
- 搭配角括号(“<”和“>”)对角括号里的内容进行操作——适合 C++ 的模板代码
对多个(层)文件对象进行操作
在a和i前加上数字
更快地移动
- 我们仍然可以使用 和 来翻页,但 Vim 更传统的用法是 和 ,分别代表 Backward 和 Forward。
- 除了翻页,Vim 里还能翻半页,有时也许这种方式更方便,需要的键是 和 ,Up 和 Down。
- 如果你知道出错位置的行号,那你可以用数字加 G 来跳转到指定行。类似地,你可以用数字加 | 来跳转到指定列。
- 你只关心当前屏幕的话,可以快速移动光标到屏幕的顶部、中间和底部:用 H(High)、M(Middle)和 L(Low)就可以做到。
- 只要光标还在屏幕上,你也可以滚动屏幕而不移动光标。需要的按键是 和 。
- 另外一种可能更实用的滚动屏幕方式是,把当前行“滚动”到屏幕的顶部、中部或底部。Vim 里的对应按键是 zt、zz 和 zb。
- [[:跳转到上一个函数;
- ]]:跳转到下一个函数;
重复
- ; 重复最近的字符查找(f、t 等)操作
- , 重复最近的字符查找操作,反方向
- n 重复最近的字符串查找操作(/ 和 ?),已替换成=
- N 重复最近的字符串查找操作(/ 和 ?),反方向,已替换成-
- . 重复执行最近的修改操作
vim的运行支持文件
linux: /usr/share/vim/vim82
syntax:Vim 的语法加亮文件
里面的文件去掉“.vim”后缀后,就是文件类型的名字,你可以用类似 :setfiletype java 这样的命令来设置文件的类型,从而进行语法加亮。
let do_syntax_sel_menu = 1
let do_no_lazyload_menus = 1
doc:Vim 的帮助文件
我们用“:help”命令查看的帮助文件就放在 doc 目录下。
colors:Vim 的配色方案
plugin:Vim 的“插件”,即用来增强 Vim 功能的工具
除了 rrhelper 和 spellfile 属于功能支持插件,没有自己的帮助页面,其他功能都可以使用“:help”命令来查看帮助。查看帮助时,插件名称中的“Plugin”后缀需要去掉。如:help zip
- gzip:编辑 .gz 压缩文件(能在编辑后缀为 .gz 的文件时自动解压和压缩,你会感觉不到这个文件是压缩的)
- logiPat:模式匹配的逻辑运算符(允许以逻辑运算、而非标准正则表达式的方式来写模式匹配表达式)
- manpager:使用 Vim 来查看 man 帮助(强烈建议试一下,记得使用 Vim 的跳转键 C-] 和 C-T)
- matchparen:对括号进行高亮匹配(现代编辑器基本都有类似的功能)
- netrwPlugin:从网络上编辑文件和浏览(远程)目录(支持多种常见协议如 ftp 和 scp,可直接打开目录来选择文件)
- rrhelper:用于支持 --remote-wait 编辑(Vim 的多服务器会用到这一功能)
- spellfile:在拼写文件缺失时自动下载(Vim 一般只安装了英文的拼写文件)
- tarPlugin:编辑(压缩的)tar 文件(注意,和 gzip 情况不同,这儿不支持写入)
- tohtml:把语法加亮的结果转成 HTML(自己打开个文件,输入命令“:TOhtml”就知道效果了)
- zipPlugin:编辑 zip 文件(和 tar 文件不同,zip 文件可支持写入)
用户的vim配置目录
修改 Vim 行为最简单的一种方式,就是把一个系统的运行支持文件复制到自己的 Vim 配置目录下的相同位置,然后修改其内容。
这种方式的缺点(在适当的时候也是优点)是,如果 Vim 的运行支持文件后来被修改 / 更新了,你也会继续使用你自己目录下的老版本修改版。如果你的修改不只是你自己的临时方案、同时也适合他人的话,最佳做法还是给 Vim 项目提交补丁,让其他所有人都能用上你的修改,这样才是开源的最佳使用方式。
- Vim 软件包的支持(“:help packages”)
- 异步任务支持(“:help channel”、“:help job”和“:help timers”)
- 终端支持(“:help terminal”)
vim软件包
- 一个 Vim 的插件(严格来讲,应该叫包)通常也会分散在多个目录下:
- 插件的主体通常在 plugin 目录下
- 插件的帮助文件在 doc 目录下
- 有些插件只对某些文件类型有效,会有文件放在 ftplugin 目录下
- 有些插件有自己的文件类型检测规则,会有文件放在 ftdetect 目录下
- 有些插件有特殊的语法加亮,会有文件放在 syntax 目录下
- vim包管理器:
每个包有自己的目录,然后这些目录会被加到 Vim 的运行时路径(runtimepath)选项里。
有了包管理器之后,runtimepath 就会非常复杂,每个包都会增加一个自己的目录进去。
Vim 会在用户的配置目录(Unix 下是 $HOME/.vim ,Windows 下是 $HOME/vimfiles )下识别名字叫 pack 的目录,并在这个目录的子目录的 start 和 opt 目录下寻找包的目录。
Vim 8 在启动时会加载所有 pack/*/start 下面的包,而用户可以用 :packadd 命令来加载某个 opt 目录下的包,如 :packadd vimcdoc 命令可加载 vimcdoc 包,来显示中文帮助信息。
安装minpac包管理器
安装minpac之后,我们就有了三个新的命令,可以用来更新(安装)包、清理包和检查当前包的状态。
# 下载安装包
git clone https://github.com/k-takata/minpac.git ~/.vim/pack/minpac/opt/minpac
# 在.vimrc配置文件添加内容:
if exists('g:loaded_minpac')
" Minpac is loaded.
call minpac#init()
call minpac#add('k-takata/minpac', {'type': 'opt'})
" Other plugins
endif
if has('eval')
" Minpac commands
command! PackUpdate packadd minpac | source $MYVIMRC | call minpac#update()
command! PackClean packadd minpac | source $MYVIMRC | call minpac#clean()
command! PackStatus packadd minpac | source $MYVIMRC | call minpac#status()
endif
- 通过 minpac 安装扩展包
在“Other plugins”那行下面加入以下内容:
call minpac#add(‘tpope/vim-eunuch’)
保存文件,然后我们使用 :PackUpdate 命令。
- 最近使用的文件
安装 yegappan/mru 包
if !has('gui_running')
" 设置文本菜单
if has('wildmenu')
set wildmenu
set cpoptions-=<
set wildcharm=<C-Z>
nnoremap <F10> :emenu <C-Z>
inoremap <F10> <C-O>:emenu <C-Z>
endif
endif
# 在增加上面的配置之后,你就可以使用键 <F10>(当然你也可以换用其他键)加 <Tab> 来唤起 Vim 的文本菜单。
多文件打开与缓冲区:复制粘贴的正确姿势
复制粘贴
- :粘贴内容
多文件的打开方式
Vim 支持一次性打开多个文件,你只需要在命令行上写出多个文件即可,或者使用通配符。
在上面的命令后,Vim 建立了一个文件列表,并且暂时只打开其中的第一个文件。接下来,用户可以决定,要编辑哪个文件,或者查看列表,或者提前退出,等等。
- :args:可以显示“参数”,即需要编辑的多个文件的列表
- :args 文件名:使用新的文件名替换参数列表
- :next(可缩写为 :n):打开下一个文件;如当前文件修改(未存盘)则会报错中止,但如果命令后面加 ! 则会放弃修改内容,其他命令也类似
- :Next(缩写 :N)或 :previous(缩写 :prev):打开上一个文件
- :first 或 :rewind:回到列表中的第一个文件
- :last:打开列表中的最后一个文件
工作流
- 在终端里进入到目标目录下;
- 使用 vim *.cpp *.h 或 gvim *.cpp *.h 来打开需要编辑的文件;
要编辑的文件除了当前目录下的,还有所有子目录下的:
“**”也包含了当前目录,键入 vim 进入 Vim,然后使用 :args **/*.cpp **/*.h 来打开需要编辑的文件
- 对于第一个文件,使用之前的方法贴入所需的文本;
- 使用 V 进入行选择的可视模式,移动光标选中所需的文本,然后使用 y 复制选中的各行;
- 执行命令 :set autowrite,告诉 Vim 在切换文件时自动存盘;
- 执行命令 :n|normal ggP,切换到下一个文件并执行正常模式命令 ggP,跳转到文件开头并贴入文本;
可以拆成 :n 和 ggP 两步,但文件数量较多时,反复手工敲 ggP 也挺累的。因此,可以使用了 normal 命令,在命令行模式下执行正常模式命令,下面就可以直接重复切换命令加粘贴命令,我们的编辑效率也得以大大提升。
- 确认修改无误后,键入 :、上箭头和回车,重复执行上面的命令;
- 待 Vim 报错说已经在最后一个文件里,使用 :w 存盘,或 :wq(抑或更快的 ZZ)存盘退出;
缓冲区的管理和切换
Vim 里会对每一个已打开或要打开的文件创建一个缓冲区,这个缓冲区就是文件在 Vim 中的映射。
- 缓冲区显示的信息:
- 文件名前面有编号;
- 除了当前活跃文件的标记“%a”,还有个文件被标成了“#”,这表示最近的缓冲区;缓冲区列表里还可能有其他标记,如“+”表示缓冲区已经被修改。
- 文件名后面有行号,表示光标在文件中的位置。
- 缓冲区命令:
- :buffers 或 :ls:可以显示缓冲区的列表
- :buffer 缓冲区列表里的编号(:buffer 可缩写为 :b):跳转到编号对应的缓冲区;如当前缓冲区已被修改(未存盘)则会报错中止,但如果命令后面加 ! 则会放弃修改内容;其他命令也类似
- :bdelete 缓冲区列表里的编号(:bdelete 可缩写为 :bd):删除编号对应的缓冲区;编号省略的话删除当前缓冲区
- :bnext(缩写 :bn):跳转到下一个缓冲区
- :bNext(缩写 :bN)或 :bprevious(缩写 :bp):跳转到上一个缓冲区
- :bfirst 或 :brewind:跳转到缓冲区列表中的第一个文件
- :blast:跳转到缓冲区列表中的最后一个文件
- 两个文件之间切换
Vim 对最近编辑的文件(上面提到的列表里标有“#”的文件)有特殊的支持,使用快捷键 <C-^> 可以在最近的两个缓冲区之间来回切换。这个快捷键还有一个用法是在前面输入缓冲区的编号:比如,用 1<C-^> 可以跳转到第一个缓冲区(跟命令行模式的命令 :bfirst 或 :b1 效果相同)。
缓冲区是文件在某个 Vim 会话里的映射。这意味着,如果某个 Vim 会话里不同的窗口或标签页(下一讲里会讨论)编辑的是同一个文件,它们对应到的也会是同一个缓冲区。更重要的是,文件 / 缓冲区的修改在同一个 Vim 会话里是完全同步的——这就不会像在多会话编辑时那样发生冲突和产生错误了。
窗口和标签页:修改、对比多个文件的正确姿势
多窗口编辑
- 水平分割::split(缩写 :sp)
命令后面如果有文件名,表示分割窗口并打开指定的文件;如果没有文件名,那就表示仅仅把当前窗口分割开,当前编辑的文件在两个窗口里都显示。
- 竖直分割: :vsplit(缩写 :vs)
键盘命令:
- 加方向键(h、j、k、l、 等等)可以在窗口之间跳转
- w 跳转到下一个(往右和往下)窗口,如果已经是右下角的窗口,则跳转到左上角的窗口
- W 跳转到上一个(往左和往上)窗口,如果已经是左上角的窗口,则跳转到右下角的窗口
- n 或 :new 打开一个新窗口
- c 或 :close 关闭当前窗口;当前窗口如果已经是最后一个则无效
- o 或 :only 只保留当前窗口,关闭其他所有窗口
- s 和 :split 作用相同,把当前窗口横向一分为二
- v 和 :vsplit 作用相同,把当前窗口纵向一分为二
- = 使得所有窗口大小相同(当调整过终端或图形界面 Vim 的窗口大小后特别有用)
- _ 设置窗口高度,命令前的数字表示高度行数,默认为纵向占满(想专心编辑某个文件时很有用)
- | 设置窗口宽度,命令前的数字表示宽度列数,默认为横向占满
- + 增加窗口的高度,命令前的数字表示需要增加的行数,默认为 1
- - 减少窗口的高度,命令前的数字表示需要减少的行数,默认为 1
- > 增加窗口的宽度,命令前的数字表示需要增加的列数,默认为 1
- (提醒,我们用 表示“<”键)减少窗口的宽度,命令前的数字表示需要增加的列数,默认为 1
快捷键映射:
nnoremap 命令映射正常模式下的键盘,inoremap 命令映射插入模式下的键盘;正常模式的映射简单直白,应该不需要解释,插入模式的映射使用了临时模式切换键 ,在正常模式下执行相应的窗口命令,然后返回插入模式。使用这样的键盘映射之后,这两个快捷键在正常模式和插入模式下就都可以使用了。
由于切换窗口是一个非常常见的操作,我通常会映射一下快捷键。为了跟一般的图形界面程序一致,我使用了 Ctrl-Tab 和 Ctrl-Shift-Tab:
nnoremap <C-Tab> <C-W>w
inoremap <C-Tab> <C-O><C-W>w
nnoremap <C-S-Tab> <C-W>W
inoremap <C-S-Tab> <C-O><C-W>W
双窗口比较
使用 vimdiff 或 gvimdiff 命令,后面跟两个文件名,我们就可以对这两个文件进行比较。
也可以打开第一个文件,然后使用命令 :vert diffsplit 第二个文件。
多标签页编辑
单窗口多文件编辑最适合的场景是批量修改具有相似性质的文件,
多窗口编辑最适合的场景是需要对多个文件进行对比编辑,
而其他的一些同时编辑多个文件的场景,就可以考虑多标签页的编辑方式。
- 多标签页编辑允许在编辑器里同时修改多个(未存盘的)文件;
- 多标签页编辑一次只展示一个文件
- 通过选择标签页(或使用键盘)可以方便地在多个标签页中进行切换
键盘命令:
如果某个 Vim 会话里不同的窗口(或标签页;以下略)编辑的是同一个文件,它们对应到的也会是同一个缓冲区。
- 在已有命令行模式命令前加 tab␣ 可以在新标签页中展示命令的结果,如 :tab help 可以在新标签页中打开帮助,:tab split 可以在新标签页中打开当前缓冲区;
- :tabs 展示所有标签页的列表;
- :tabnew 或 :tabedit 可以打开一个空白的新标签页,后面有文件名的话则打开该文件;
- :tabclose 可以关闭当前标签页(如果标签页里只有一个窗口,使用窗口关闭命令 c 应该更快);
- :tabnext、gt 或 可以切换到下一个标签页
- :tabNext、:tabprevious 、gT 或 可以切换到上一个标签页
- :tabfirst 或 :tabrewind 切换到第一个标签页
- :tablast 切换到最后一个标签页
正则表达式
正则表达式搜索
- . 可以匹配除换行符外的任何字符:如 a. 可以匹配“aa”、“ab”、“ac”等,但不能匹配“a”、“b”或“ba”。如果需要匹配换行符(跨行匹配)的话,则需要使用 _.。
- *表示之前的匹配原(最普通的情况为单个字符)重复零次或多次:如 aa* 可以匹配“a”、“aa”或“aaa”,a.* 可以匹配“a”、“aa”、“abc”等等,但两者均不能匹配“b”。
- ^ 匹配一行的开头,如果出现在模式的开头的话;在其他位置代表字符本身。
- $ 匹配一行的结尾,如果出现在模式的结尾的话;在其他位置代表字符本身。
- ~ 匹配上一次替换的字符串,即如果上一次你把“foo”替换成了“bar”,那 ~ 就匹配“bar”。
- […] 匹配方括号内的任一字符;方括号内如果第一个字符是 ^,表示对结果取反;除开头之外的 - 表示范围:如 [A-Za-z] 表示任意一个拉丁字母,[^-+/] 表示除了“+”、“-”、“”、“/”外的任意字符。
- \ 的含义取决于下一个字符,在大部分的情况下,包括上面的这几个(.、*、\、^、$、~、[ 和 ]),代表后面这个字符本身;在跟某些字符时则有特殊含义(后面我们会讨论最重要的那些)。
6个特殊模式项:
- ? 表示之前的匹配原重复零次或一次:如 aa? 可以匹配“a”、“aa”,但不能完整匹配“aaa”(可以匹配其前两个字符、后两个或最后一个字符)。
- + 表示之前的匹配原重复一次或多次:如 aa+ 可以匹配“aa”、“aaa”,但不能匹配“a”或“b”。
- {n,m} 表示之前的匹配原重复 n 到 m 遍之间,两个数字可以省略部分或全部:如 a{3}(可读作:3 个“a”)可以匹配“aaa” ,a{,3}(可读作:最多 3 个“a”)可以匹配“”、“a”、“aa”和“aaa”;两个数字都省略时等价于 *,也就是之前的匹配原可以重复零次或多次。
- ( 和 ) 括起一个模式,将其组成为单个匹配原:如 (foo)? 可以表示单词“foo”出现零次或一次。( 和 ) 还有一个附加作用,是捕获匹配的内容,按 ( 出现的先后顺序,可以用 \1、\2 到 \9 来引用。如果你不需要捕获匹配内容的话,用 %( 和 ) 的性能更高。
- & 是分支内多个邻接(concat)的分隔符,概念上可以和与操作相比,表示每一项都需要匹配成功,然后取最后一项的结果返回:如 .foo.&.bar. 匹配同时出现了“foo”和“bar”的完整行。相对来讲,& 没那么常用。
- | 是多个分支的分隔符,概念上可以和或操作相比,表示任意一项匹配成功即可:如 foo|bar 可匹配“foo”或“bar”两单词之一。
13 个特殊模式项:
- < 匹配单词的开头
- > 匹配单词的结尾
- \s 匹配空白字符 和
- \S 匹配非空白字符
- \d 匹配数字,相当于 [0-9]
- \D 匹配非数字,相当于 [^0-9]
- \x 匹配十六进制数字,相当于 [0-9A-Fa-f]
- \X 匹配非十六进制数字,相当于 [^0-9A-Fa-f]
- \w 匹配单词字符,相当于 [0-9A-Za-z_]
- \W 匹配非单词字符,相当于 [^0-9A-Za-z_]
- \h 匹配单词首字符,相当于 [A-Za-z_]
- \c 忽略大小写进行匹配
搜索实例:
- 搜索函数名:在前后加上匹配单词头尾的标记,如,\<begin\>。
- 被誉为最有用的 Vim 提示,是把光标移到希望搜索的关键字上,然后按下 * 键。Vim 会提取光标下的关键字,并自动添加 < 和 > 进行搜索。
- 搜索 begin 或 end:/\<\(begin\|end\)\>
- HTML 标签匹配:<.\{-1,}>
最长匹配和最短匹配
- *、?、+ 和 {} 都属于最长匹配(也叫贪婪匹配)
- 在 Vim 里,最短匹配只有一种形式,{-n,m},其意义和之前说的 {n,m} 基本相同,但结果是较短而非较长的字符串。
正则表达式替换
编程支持
查看文档
Vim 里快捷键 K 可以用来查看光标下关键字的相关文档。
" 启用 man 插件
source $VIMRUNTIME/ftplugin/man.vim
set keywordprg=:Man
自动完成
- 当光标下的文件名可以在 path 选项标识的目录下找到时,我们可以很方便地跳转过去。你需要的是正常模式命令 gf(goto file) 和 f(会打开一个新窗口)。
记录
- 按键是 KeyCastr,录屏是 GIF Brewery。Screenkey
- vim如何离线安装插件?如何配置网络?
- :e Tab:查看当前目录下的文件?
- vim打开一个项目如何在文件和目录之间跳转?
- 可视模式怎么使用?
- 配置python完全支持:如何使用指定路径的解释器?、如何进行引用跳转和查看方法的说明?如何运行和debug?如何在项目中使用git?如何更好地使用代码补全?