赞
踩
vim被公认为最强的编辑器,自然有其独到之处。对于新手而言,模式、寄存器和缓冲区是有别于其他编辑器的三个核心概念。
vim有别于其他编辑器的最典型特征就在于它有不同的工作模式。有趣的是,对于vim有几种模式这个问题,答案却是众说纷纭。我个人认同vim有下列3种模式的说法。
所谓正常模式就是vim处于等待用户操作指令的状态。vim启动后默认进入正常模式。任何情况下,用户都可以通过按Esc键返回正常模式。如果Esc键失效,可以尝试Ctrl+c键或者Ctrl+[键——为避免歧义,后面带有Ctrl的组合键使用^代替Ctrl键。在正常模式下,用户可浏览内容、移动光标,并在需要的时候输入操作指令。
正常模式下输入i即可进入插入模式——当然,除了i还有另外几个指令也可以切换插入模式,后面会有详述。插入模式下,vim可以像普通编辑器那样输入文本,可以退格、删除、回车,可以使用上下左右四个方向键移动光标以改变插入位置,也可以随时按Esc键退回到正常模式。
正常模式下输入v即可进入选取模式,如果输入^v则进入块选取模式。选取模式下使用上下左右四个方向键或者hjkl四个键移动光标,以选取操作目标,之后可对操作目标实施删除、复制等操作,并自动返回正常模式。
很多应用程序都有复制粘帖的操作,并且都是通过系统剪贴板来实现这个功能。vim自然也不例外,稍有不同的是,vim不仅支持系统剪贴板,还另外提供了多个不同的剪贴板,所有这些剪贴板统称为寄存器。
vim 中有9类寄存器:
使用:reg命令可以查看当前所有寄存器的内容。
vim的缓冲区是一个奇怪的存在,要理解它,需要结合窗口、标签页等概念一起解释。
对于大多数编辑器来说,打开一个文档,就意味着打开了一个标签页,一个标签页通常就是一个窗口。对于vim而言,打开一个文档,就意味着建立了一个缓冲区,同时将缓冲区的内容显示在当前的标签页的活动窗口上。用户可以创建、关闭标签页,可以切换当前标签页,可以在当前标签新建窗口、切换活动窗口、更换与活动窗口对应的缓冲区。
命令 | 说明 |
---|---|
$ vim ~/MyCode/PyCode/demo.py | 打开文件 |
$ vim -R ~/MyCode/PyCode/demo.py | 以只读方式打开文件 |
$ vim MyCode/PyCode/demo.py MyCode/CCode/hello.c | 打开多个文件,显示第一个文件 |
$ vim -O2 MyCode/PyCode/demo.py MyCode/CCode/hello.c | 打开多个文件,水平排列窗口 |
$ vim -o2 MyCode/PyCode/demo.py MyCode/CCode/hello.c | 打开多个文件,垂直排列窗口 |
命令 | 说明 |
---|---|
:e ~/MyCode/PyCode/demo.py | 在vim中打开文件 |
:tabnew ~/MyCode/CCode/hello.c | 在vim中新建标签页打开文件 |
:w | 保存文件 |
:w! | 强制保存文件 |
:w ~/MyCode/PyCode/demo.py | 以输入的文件名另存文件 |
:q | 退出 |
:q! | 放弃当前文件的修改,强制退出 |
:qa! | 放弃全部文件的修改,强制退出 |
:wq | 保存文件并退出 |
:wq! | 强制保存文件并退出 |
:e! | 放弃所有修改,回退到最后一次保存文件的状态 |
:x | 保存文件并退出 |
无论何时、无论什么状态,都可以使用上下左右四个方向键移动光标。不过,这不是vim的方式,vim使用hjkl四个键完成光标的左下上右的光标移动——当然,前提是在非插入模式下。
明明有光标键,却还要再定义hjkl四个键来移动光标——虽然可以用“避免手指离开主键盘区”来解释,但总是有点古怪。这就是vim的哲学,没有体验就无法理解。
除了hjkl四个键,vim还提供了其他光标定位方式,其数量之多、功能之繁杂,令人叹为观止。
命令 | 说明 |
---|---|
0 | 移动光标至行首,注意是数字0不是字母o |
$ | 移动光标至行尾 |
^ | 移动光标至第一个非空字符 |
g_ | 移动光标至最后一个非空字符首 |
w | 移动光标至下一个单词的开头 |
e | 移动光标至下一个单词的结尾 |
9l | 光标向后移动9个字符 |
fa | 移动光标至下一个字符a |
Fa | 移动光标至前一个字符a |
2fa | 向后移动光标至第2个字符a |
2Fa | 向前移动光标至第2个字符a |
ta | 移动光标至下一个字符a之前 |
Ta | 移动光标至前一个字符a之前 |
2ta | 向后移动光标至第2个字符a之前 |
2Ta | 向前移动光标至第2个字符a之前 |
命令 | 说明 |
---|---|
G | 移动光标至尾行行首 |
gg | 移动光标至首行行首 |
9G | 移动光标至第9行行首 |
9gg | 移动光标至第9行行首 |
:9 | 移动光标至第9行行首(需要按回车键) |
H | 移动光标至可视区域首行行首 |
M | 移动光标至可视区域中间行行首 |
L | 移动光标至可视区域尾行行首 |
zt | 把当前行移动到可视区域首行 |
zz | 把当前行移动到可视区域中间行 |
zb | 把当前行移动到可视区域尾行 |
% | 移动光标至匹配的括号(前提是光标位于括号处) |
命令 | 说明 |
---|---|
^f | 下一页,光标位于可视区域首行首个非空字符 |
^b | 上一页,光标位于可视区域尾行首个非空字符 |
^e | 向下滚动一行,光标不变或位于可视区域首行 |
^y | 向上滚动一行,光标不变或位于可视区域尾行 |
命令 | 说明 |
---|---|
m{a-z} | 标记光标所在位置(局部标记,仅限于当前文件跳转) |
m{A-Z} | 标记光标所在位置(全句标记,可用于跨文件跳转 |
'{m} | 移动光标至标记m所在行首个非空字符 |
`{m} | 移动光标至标记m所标记的位置 |
:marks | 显示所有标记 |
:delmarks {m} | 删除标记m |
:delmarks! | 删除所有标记 |
在文件中输入内容,需要切换到插入模式。
命令 | 说明 |
---|---|
i | 在光标所在字符之前插入 |
I | 在光标所在行行首插入 |
a | 在光标所在字符之后插入 |
A | 在光标所在行行尾插入 |
o | 在光标所在行的下一行行首插入 |
O | 在光标所在行的上一行行首插入 |
s | 删除光标所在字符,然后插入 |
S | 删除光标所在行内容,然后插入 |
cw | 删除从光标处开始到该单词结束的字符,然后插入 |
撤销和重做只能在正常模式下执行。
命令 | 说明 |
---|---|
u | 撤销最近的修改 |
3u | 撤销最近的3次修改 |
^r | 重做最近撤销的修改 |
3^r | 重做最近撤销的3次修改 |
U | 恢复光标所在行至初始状态 |
选取操作的流程可分为3步:
例如,全选操作ggvG$,其中gg是移动光标至文件起始位置,v是进入选取模式,G是移动光标至文件尾行开始位置,$是移动光标至行尾。选取之后,通常接续删除或复制的操作。
命令 | 说明 |
---|---|
v | 切换至正常选取模式 |
^v | 切换至块选取模式 |
类似于很多应用程序中Ctrl+x、Ctrl+c和Ctrl+v分别对应剪切、复制和粘帖操作,vim提供了d、y和p命令与之相对应。不过vim不区分删除和剪切,删除操作也会将删除的内容存入寄存器。
正常模式下,删除的内容保存在默认寄存器(‘’)中。
命令 | 说明 |
---|---|
dd | 删除当前行 |
d0 | 删除行首至光标位置前的内容 |
d$ | 删除光标位置至行尾的内容 |
3dd | 删除自当前行开始的3行内容 |
x | 删除光标所在字符 |
X | 删除光标之前的字符 |
dw | 删除到光标所在单词的下一个单词开头 |
dW | 删除到光标所在单词(包括标点符号)的下一个单词开头 |
de | 删除到光标所在单词末尾 |
dE | 删除到光标所在单词(包括标点符号)末尾 |
db | 删除光标所在单词的光标前的内容 |
dB | 删除光标所在单词(包括标点符号)的光标前的内容 |
J | 删除当前行回车符 |
3J | 删除自当前行开始的3行回车符 |
选取模式下,可以指定保存删除内容的寄存器,同时默认寄存器也会保存删除的内容。
命令 | 说明 |
---|---|
d | 删除选取内容,保存到默认寄存器(") |
""d | 删除选取内容,保存到默认寄存器(") |
"+d | 删除选取内容,保存到系统剪贴板寄存器(+) |
"{0-9}d | 删除选取内容,保存到数字寄存器(0-9) |
"{a-z}d | 删除选取内容,保存到数字寄存器(a-z) |
使用正则表达式删除空行,也是常用的命令。
命令 | 说明 |
---|---|
:g/^$/d | 删除空行 |
:g/^\s*$/d | 删除包含空格的空行 |
正常模式下,复制的内容保存在默认寄存器(‘’)中。
命令 | 说明 |
---|---|
yy | 复制当前行 |
y0 | 复制行首至光标位置前的内容 |
y$ | 复制光标位置至行尾的内容 |
3yy | 复制自当前行开始的3行内容 |
yw | 复制到光标所在单词的下一个单词开头 |
yW | 复制到光标所在单词(包括标点符号)的下一个单词开头 |
ye | 复制到光标所在单词末尾 |
yE | 复制到光标所在单词(包括标点符号)末尾 |
yb | 复制光标所在单词的光标前的内容 |
yB | 复制光标所在单词(包括标点符号)的光标前的内容 |
选取模式下,可以指定保存复制内容的寄存器,同时默认寄存器也会保存复制的内容。
命令 | 说明 |
---|---|
y | 复制选取内容,保存到默认寄存器(") |
""y | 复制选取内容,保存到默认寄存器(") |
"+y | 复制选取内容,保存到系统剪贴板寄存器(+) |
"{a-z}y | 复制选取内容,保存到字母寄存器(a-z) |
"{0-9}y | 复制选取内容,保存到数字寄存器(0-9) |
粘帖只能在正常模式下执行。
命令 | 说明 |
---|---|
P | 在光标之后粘帖默认寄存器(")的内容 |
p | 在光标之前粘帖默认寄存器(")的内容 |
"+P | 在光标之后粘帖系统剪贴板寄存器(+)的内容 |
"+p | 在光标之前粘帖系统剪贴板寄存器(+)的内容 |
"{a-z}P | 在光标之后粘帖字母寄存器(a-z)的内容 |
"{a-z}p | 在光标之前粘帖字母寄存器(a-z)的内容 |
"{0-9}P | 在光标之后粘帖数字寄存器(0-9)的内容 |
"{0-9}p | 在光标之前粘帖数字寄存器(0-9)的内容 |
查找只能在正常模式下执行。vim使用/和?区分正向和反向查找,使用封闭的尖括号(需要反斜杠转义)表示全词匹配,支持正则表达式,可以实现复杂的查找功能。
命令 | 说明 |
---|---|
* | 正向搜索光标所在单词并高亮显示,光标下移至搜索目标 |
# | 反向搜索光标所在单词并高亮显示,光标上移至搜索目标 |
/str | 正向搜索str并高亮显示,光标下移至搜索目标 |
/str\c | 正向搜索str(大小写不敏感)并高亮显示,光标下移至搜索目标 |
/str\C | 正向搜索str(大小写敏感)并高亮显示,光标下移至搜索目标 |
/\<str\> | 正向搜索str(全词匹配)并高亮显示,光标下移至搜索目标 |
/^str | 正向搜索以str开头的行并高亮显示,光标下移至搜索目标 |
/str$ | 正向搜索以str结尾的行并高亮显示,光标下移至搜索目标 |
/str_1|str_2 | 正向搜索str_1或str_2并高亮显示,光标下移至搜索目标 |
上面的命令以/开头表示正向查找,如果将/替换为?,即可实现反向查找。查找命令执行后,使用下面的命令可以在搜索结果中前后移动光标。对于正向搜索,向前即光标上移,向后即光标下移;反向搜索则与之相反。如果不再需要查找结果了,可以使用下表中的命令取消高亮,也可以在vim的配置文件中使用非递归键盘映射,为Esc键增加取消高亮功能。
命令 | 说明 |
---|---|
n | 光标后移至另一个搜索目标 |
N | 光标前移至另一个搜索目标 |
:noh | 取消高亮 |
如果想要统计查找目标出现的次数,简单的查找是无法实现的,需要用下面的查找替换来实现。
查找替换只能在正常模式下执行。查找替换的命令是s,其后是查找目标的正则表达式,紧接着是替换的内容,三者之间使用/连接。
命令 | 说明 |
---|---|
:s /str_old/str_new | 将光标所在行的首个str_old替换为str_new |
:s /str_old/str_new/g | 将光标所在行的全部str_old替换为str_new |
:s /\<str_old\>/str_new/g | 将光标所在行的全部str_old替换为str_new |
:2,9s/str_old/str_new/g | 将2-9行的全部str_old替换为str_new |
:2,$s/str_old/str_new/g | 将第2行至结尾的全部str_old替换为str_new |
:%s/str_old/str_new/g | 将全文的str_old替换为str_new |
:%s/str//gn | 统计str在全文出现的次数 |
将文件中形如2022-09-30的日期两侧加上单引号。命令如下:
:%s/\(\d\{4\}-\d\{2\}-\d\{4\}\)/'\1'/g
熟悉正则表达式的话,很容易理解下面这几点:
执行块选取(^v)操作,移动光标选取删除目标,再按d键删除。
执行块选取(^v)操作,移动光标选取插入位置,使用I键(shift+i)切换至块插入,输入插入内容。此时仅块的首行显示插入内容,退出插入模式后方会显示块插入的结果。
每打开一个文件,就会创建一个新的缓冲区,每个缓冲区对应一个数字编号。
命令 | 说明 |
---|---|
:ls | 列出全部缓冲区 |
:bn | 当前窗口显示下一个缓冲区内容 |
:bp | 当前窗口显示上一个缓冲区内容 |
:b2 | 当前窗口显示2号缓冲区内容 |
:bw | 删除当前窗口缓冲区,若当前窗口不是最后一个窗口则同时关闭窗口 |
Vim 自7.0版本引入了多标签页(Tabs)概念,使得vim终于可以像其他编辑器那样同时编辑多个文件了。
命令 | 说明 |
---|---|
:tabnew | 新建“未命名”标签页 |
:tabnew hello | 新建名为“hello”标签页 |
:tabnew ~/MyCode/CCode/hello.c | 新建标签页打开文件 |
:tabs | 列出全部标签页 |
:tabn | 切换至下一个标签页 |
:tabp | 切换至上一个标签页 |
:tabc | 关闭当前标签页 |
gt | 顺序切换标签页 |
在一个标签页可以创建多个窗口,每个窗口的显示内容可以通过缓冲区操作实现切换,缓冲区操作仅对当前窗口有效。
命令 | 说明 |
---|---|
^ws | 将当前窗口分为上下两个窗口,指向同一个缓冲区 |
^wv | 将当前窗口分为左右两个窗口,指向同一个缓冲区 |
:sp ~/MyCode/CCode/hello.c | 将当前窗口分为上下两个窗口,打开文件显示在上面窗口 |
:vsp ~/MyCode/CCode/hello.c | 将当前窗口分为左右两个窗口,打开文件显示在左侧窗口 |
^wh | 移动光标至左侧窗口 |
^wl | 移动光标至右侧窗口 |
^wk | 移动光标至上方窗口 |
^wj | 移动光标至下方窗口 |
^wH | 当前窗口左移 |
^wL | 当前窗口右移 |
^wK | 当前窗口上移 |
^wJ | 当前窗口下移 |
^wq | 关闭当前窗口 |
vim生态圈有海量的插件可选,插件的安装和管理方法也是五花八门。这里我推荐几款vim的必备插件,只需要从GitHub上clone到指定路径下,再将配置文件粘帖进去,瞬间即可将vim配置成适合C和Python的集成开发工具。下面操作基于以Linux Mint 21,适用于Unbuntu及其他衍生操作系统。
大纲视图插件依赖ctags包,安装命令如下。
sudo apt-get install universal-ctags
YCM被认为是安装最复杂的自动补全插件,不过用vam安装的话,简单到连配置都免了。
sudo apt-get install vim-youcompleteme
sudo apt-get install vim-addon-manager
sudo vam install youcompleteme
创建插件目录:
$ cd ~
$ mkdir .vim
$ cd .vim
$ mkdir bundle
$ cd bundle
从GitHub克隆插件管理器、树形目录插件、状态栏插件、缩进线插件、大纲视图插件、git插件,以及我喜欢的一款vim配色主题插件。
$ git clone https://github.com/VundleVim/Vundle.vim.git
$ git clone https://github.com/Lokaltog/vim-powerline.git
$ git clone https://github.com/scrooloose/nerdtree.git
$ git clone https://github.com/Yggdroot/indentLine.git
$ git clone https://github.com/majutsushi/tagbar.git
$ git clone https://github.com/tpope/vim-fugitive.git
$ git clone https://github.com/tomasr/molokai.git
复制以下内容到系统剪贴板。
set nocompatible "关闭vi兼容模式" "" filetype off set rtp+=~/.vim/bundle/Vundle.vim call vundle#begin() Plugin 'VundleVim/Vundle.vim' "插件管理器" Plugin 'Lokaltog/vim-powerline' "状态栏插件" Plugin 'scrooloose/nerdtree' "树形目录插件" Plugin 'Yggdroot/indentLine' "缩进线插件" Plugin 'majutsushi/tagbar' "类视图插件" Plugin 'tpope/vim-fugitive' "git插件" Plugin 'tomasr/molokai' "vim配色主题插件" call vundle#end() filetype plugin on "" set shortmess=atI "启动的时候不显示援助乌干达儿童的提示" set lines=999 columns=999 "窗口最大化" set fileformat=unix "设置以unix的格式保存文件" set fenc=utf-8 "文件编码" set autoread "文件在Vim之外被更改时自动更新" "" set guifont=FreeMono\ Regular\ 14 "字体" set background=dark "背景色" colorscheme molokai "配色方案" "" set guioptions-=r "隐藏右侧滚动条" set guioptions-=L "隐藏左侧滚动条" set guioptions-=b "隐藏底部滚动条" "" set number "显示行号" set nowrap "设置不折行" set cursorline "当前行高亮" set laststatus=2 "命令行为两行" "" set smartindent "智能缩进" set shiftwidth=4 "自动缩进宽度" set tabstop=4 "table宽度" autocmd FileType python set expandtab "针对python脚本,table替换为空格" "" set ignorecase smartcase "搜索时忽略大小写(模式包含大写字母时例外)" set incsearch "输入搜索内容过程中即时显示搜索结果" set hlsearch "高亮搜索项" set whichwrap+=<,>,h,l "允许光标跨行移动" "" "目录树" let NERDTreeChDirMode=1 "改变tree目录的同时改变工程的目录 " let NERDTreeIgnore=['\~$', '\.pyc$', '\.pyo$', '\.obj$', '\.o$', '\.so$', '\.egg$', '\.swp$', '^\.git$', '^\.svn$', '^\.hg$'] "忽略的文件类型" let NERDTreeWinSize=25 "窗口大小" "" "类视图" let tagbar_width = 35 "窗口大小" "" "缩进线" let indentLine_char='┆' let indentLine_enabled = 1 "" function! Run() execute "w" if &filetype == 'c' execute "!mkdir -p %:p:h/build" execute "!gcc %:p -o %:p:h/build/%:t:r.out" execute "!time %:p:h/build/%:t:r.out" elseif &filetype == 'python' execute ":cd %:p:h" execute "!time python3 %" elseif &filetype == 'html' execute "!firefox % &" endif endfunction "" "F2开启/关闭树" map <F2> :NERDTreeToggle<CR> "" "F5开启/关闭类视图" map <F5> :TagbarToggle<CR> "" "F8运行源码" map <F8> :call Run()<CR> "" "r运行源码" noremap r :call Run()<CR> "" "<Esc>增加取消高亮" noremap <Esc> :noh<return><Esc> "" "Go to last file(s) if invoked without arguments." autocmd VimLeave * nested if (!isdirectory($HOME . "/.vim")) | \ call mkdir($HOME . "/.vim") | \ endif | \ execute "mksession! " . $HOME . "/.vim/Session.vim" autocmd VimEnter * nested if argc() == 0 && filereadable($HOME . "/.vim/Session.vim") | \ execute "source " . $HOME . "/.vim/Session.vim"
在shell中使用vi打开配置文件:
$ vi ~/.vimrc
输入"+p命令(+也是命令的内容,共3个字符)将系统剪贴板的内容粘帖进来,再使用:wq命令保存文件并关闭编辑器。
至此,大功告成。打开vim或者gvim,一个全新的IDE呈现在眼前。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。