心理准备(学习曲线)
学习Vim的核心原因:
1))跨平台。诸如Gitbash中会启动Vi,不会操作。linux|Mac中也常用
2)vim小巧强大
3)本身技能已经足够理解vim的功能 (使用过notepad++,VS,VSCode,Idea,Eclipse)
4)其他如notepad++是tai独,故不再支持
概念(基础的基础):
A)Vim有6种modes,(normal, visual, insert, command-line, select, and ex) ,其中红色4种最常用。
B)
a) Vim 多文件编辑:Vim 多文件编辑:窗口,Vim 多文件编辑:标签页和缓冲区 . 这里要明白缓冲区是基础,它的内容就是读入的文本,用户不可见,它服务于窗口window和标签页tab。关闭tab或window不代表就unload了buffer,只是人看不见了而已。
b) 一个tab可以包含N个window , 一个window可以显示一个buffer的内容,多个window可以显示同一个buffer的内容。
c) register是什么或更多解释. register是为了编辑文本时记录各种临时信息:比如用过命令,copy的内容,编辑过的内容。
注意为了和系统剪切板交互要用到'+'寄存器,并且Vim当前版本必须支持剪切板(目前我用的gVim8.2默认支持)。
了解下'0'寄存器和黑洞寄存器'_'
基本操作1:(打开关闭文件,单Window)
:e 文件名 | 打开一个文件 |
:enew | 创建一个无名新文件 |
:sp 文件名 | 在最上方新增一个window加载文件 |
拖文件到vim上 | 1. :sp 拖文件到vim自动输入文件名 , 这样打开新window加载file. 2. 在command mode即普通模式直接拖放到vim,则原window内容会被拖拽的文件内容替代。 (高度常用) |
tabe (拖)文件名 | 新开tab加载文件。(高度常用) |
Ctrl+w c | 关闭当前Window,如果被修改过,会有提示不能关闭。得用:q!或:close! 强制不写入关闭,否则就:wq (高度常用) |
:w [filename] | 将编辑的数据储存成另一个档案(类似另存新档) (低度常用) |
:r [filename] | 在编辑的数据中,读入另一个档案的数据。亦即将 『filename』 这个档案内容加到游标所在行后面 (低度常用) |
基本操作2:(一个窗口Window内的光标移动,copy/cut/paste/select)
3种模式与基本操作 ,可视化块情况下的copy/paste , Vim中,copy被叫做yank,所以缩写键是y。
h | Move cursor to left by one position。可以是{count}h,比如10h,表示左移cursor 10个char距离。 |
l | Move cursor to right by one position |
k | Move cursor to upward direction by one line |
j | Move cursor to downward direction by one line。之所以j表示下移cursor,是因为我们下移比上移更频繁。 |
w | Move cursor to the beginning of the next word (高度常用) 。 也可以{count}w,比如10w,右移cursor 10个word位置 |
b | Move cursor to the beginning of the previous wor (高度常用) |
[Ctrl] + [f] | 屏幕『向下』移动一页,相当于 [Page Down]按键 (高度常用) |
[Ctrl] + [b] | 屏幕『向上』移动一页,相当于 [Page Up] 按键 (高度常用) |
[Ctrl] + [d] | 屏幕『向下』移动半页 (高度常用) |
[Ctrl] + [u] | 屏幕『向上』移动半页 (高度常用) |
0 或功能键[Home] | 这是数字『 0 』:移动到这一行的最前面字符处 (高度常用) |
$ 或功能键[End] | 移动到这一行的最后面字符处 (高度常用) |
H | 光标移动到这个屏幕的最上方那一行的第一个字符 (高度常用) |
M | 光标移动到这个屏幕的中央那一行的第一个字符 (高度常用) |
L | 光标移动到这个屏幕的最下方那一行的第一个字符 (高度常用) |
G | 移动到这个档案的最后一行 (高度常用) |
nG | n 为数字。移动到这个档案的第 n 行。例如 20G 则会移动到这个档案的第 20 行(可配合 :set nu)。 这种用法也适用于hjkl,比如10h表示cursor向左移动10个字符位置。(高度常用) |
gg | 移动到这个档案的第一行,相当于 1G 啊! (高度常用) |
n<Enter> | n 为数字。光标向下移动 n 行 (高度常用) |
[Ctrl]+[End] | 跳到文件尾部 |
ggvG$ 或ggv[Ctrl]+[End] |
全选文档。很多post提示用ggvG,但这样在Win10的gVim8.2中只选择到最后一行的开头,最后一行后面的字符没选中。 (高度常用) |
d1G | 删除光标所在到第一行的所有数据 |
dG | 删除光标所在到最后一行的所有数据 |
d$ | 删除游标所在处,到该行的最后一个字符(中度常用) |
d0 | 那个是数字的 0 ,删除游标所在处,到该行的最前面一个字符 |
dd或D | 删除cursor所处一行 . 要删除连续3行就用3dd或d3d或3D (高度常用) |
r或R | 从普通模式command mode/normal mode进入取代模式(Replace mode): r 只会取代光标所在的那一个字符一次;R会一直取代光标所在的文字,直到按下 ESC 为止;(高度常用) |
s或S | normal/command mode删除cursor下一个字符,或一行字符,并立即进入insert mode。可以前面跟数字,比如3S,删除当前及后面两行。(中度常用) |
. | 不要怀疑!这就是小数点!意思是重复前一个动作的意思。 如果你想要重复删除、重复贴上等等动作,按下小数点『.』就好了! (高度常用) |
:set nu | 显示行号,设定之后,会在每一行的前缀显示该行的行号 (高度常用) |
o或O | 插入空行 . 如果要在cursor后插入,就要在_vimrc文件中指定nnoremap 了 |
zz | 会使当前光标所在的行显示在窗口中部,且保持光标所在列的位置不变 (低度常用) |
基本操作3(格式化文本)
> | 视图模式下当前行右缩进,反之<减少缩进 |
= | 视图模式下选中多行内容进行代码格式的自动排版 |
== | indent the current line |
3== | 连续多行indent . indent that many lines, starting from the cursor (高度常用) |
:12,20>>> | |
gg=G |
所以可以在visual mode选择部分行,然后执行=命令。 (高度常用) |
:set autoindent或smartindent或cindent | 在insert mode时,vim如果识别到内容是coding内容就自动做indentation。 Generally, |
:filetype plugin indent on |
根据文件后缀自动管理indentation. |
基本操作4:(跨Window,Tab操作)
Window相关:如果你现在编辑的文件中含有另外一个文件的名字,你可以将光标移动文江名上,然后按gf去编辑那个文件。使用Ctrl-W gf会让该文件显示在一个新的tab中。
Ctrl-w或W | 切换window (高度常用) |
Ctrl-w Shift-T | 把一个window内容放到一个新tab里,原window close (高度常用) |
:args :tab all |
vim内置 :tabe 文件名 只打开一个文件。要打开多个文件(可以拖进去),比如 :tabe 文件路径1 文件路径2 就用左边的方法。 (高度常用) |
gt或gT | 切换tab (高度常用) |
查看:help tab-page-intro
进阶操作:寄存器register
使用方法 "寄存器名{motion}
""p | Vim 缺省使用无名寄存器。无名寄存器用引号表示,例如,Vim 命令 ""p 完全等同于 p 命令。(不需要我们介入) |
"+y | 把Visual mode中选择的内容copy到系统剪切板,可以被OS paste到其他APP中 (高度常用) |
"+p | 把从其他APP或OS中copy的内容粘贴到Vim中 (高度常用) |
"_d | Vim 黑洞寄存器是个有去无回的黑洞,可用下划线显式引用。例如, Vim 命令 "_d{motion} 会删除文本内容且不保存任何副本。 (不知使用价值) |
<C-r>{register} |
不离开插入模式或者在command line mode中. 粘贴寄存器中的文本. ({register}是我们想要插入的寄存器的名字) (高度常用) |
|
insert mode或command line mode中使用表达式。 (这是使用了Vim表达式寄存器 "= ) |
:shell 可以在不关闭vi的情况下打开新的、独立的shell Window,它不能像:ter一样具有normal mode。新开的shell Window只能像普通windows cmd窗口一样操作。
(应用)Windows下如何copy与paste , 如何在Commond mode里paste (Ctr-r同样适用于insert mode)
(应用)如何像普通编辑器delete而不是cut?因为Vim中delete就是cut ()
(应用)Vim中希望能同时打开shell窗口(command mode输入terminal),把部分内容从Vim中copy到shell(shell必须是insert mode,Ctrl-w"指定寄存器),得到命令结果后把部分内容copy到Vim(Ctrl-w+N进入normal mode,像普通Vim一样操作)
进阶操作:用command
进入command line mode后用上下键 | 列出上/下一个已执行过的command. type |
his | :his lists the command history, and :his / lists the search history. |
q: 或 q/ | 打开command-line window 。好处是you can use all Vim's editing power, including searching with '/' in normal mode, or using whole-line completion (:help compl-whole-line) in insert mode。这个whole-line completion会绘制一个窗口,显示与输入的字符串匹配的命令,可以用上下左右选择。
|
关闭command-line window | After editing a command, you can:
|
根据文档,command history是被保存到vimrc里,没有命令清理。 |
应用(直接通过unicode或ascii码,输入文字或特殊字符,比如符号)
根据实验,在Windows上必须要先设置好正确的encoding和guifont,通过Ctrl+v才能正确显示输入的字符。
显示和杨。
打开gVim=>进入command line mode=>:set encoding=utf-8=>:set guifont=*,选择COURT NEW字体=>打开文件=>进入insert mode=>Ctrl+v=>u2713得到=>Ctrl+v=>u6768得到‘杨’ . 可以在vimrc文件中直接指定COURT NEW字体。
进阶(缓冲buffer,跨buffer)
buffers are memory portion loaded with the file content
ls 或 files 或 buffers | 查看加载的buffer。加载<>显示到Window里 (高度常用) |
e 不跟任何文件名 | 在一个Window中用e 将手工reload这个文件。 e! 将强制reload这个文件。 (高度常用) |
bd buffer号 | 关闭一个buffer(即bufferdelete吧),比如buffer 4。如果已经修改过可以用bd! buffer号 来关闭 (高度常用) |
buffer buffer号 | 当前Window加载指定的buffer。 (高度常用) |
drag & drop 多个文件到vim上 | vim目前默认不会同时打开多个tab或Window显示拖拽的files。 drag & drop完成后,这些files被记录到buffer里。可以通过:tab ball ,每个tab加载一个buffer。 (高度常用) |
:bufdo bd | 关闭所有加载的buffer,如果某个buffer被修改了,又没使用:bufdo bd! ,这个命令算失败并停止。 特别使用于打开多个文件(拖拽或:args 文件组)后想用新tab打开所有buffer前使用 (高度常用) |
:bufdo e | 手工reload所有文件。 bufdo e!,放弃所有修改,手工reload所有文件 (高度常用) |
3Ctrl-^或 3Ctrl-6 |
normal mode跳到buffer号为3的buffer。 通用命令是{count}Ctrl-^ (低度常用) 等效于:e #{count} |
Ctrl-^或Ctrl-6 | 载入上一次编辑过的文件,即使是bd关闭了。Edit the alternate file. Mostly the alternate file is the previously edited file. (中度常用) 等效于:e # |
进阶(搜索)在command mode中输入/ 进入搜索(高度常用)
使用正则搜索与替换 , 统计搜索到的匹配数量()
默认的搜索模式只在一个buffer中搜索,要想跨buffer或多个文件,就要用其他命令,见下。
/word | 向光标之下寻找一个名称为 word 的字符串。例如要在档案内搜寻 vbird 这个字符串,就输入 /vbird 即可! (高度常用) |
/\cword | 大小写不敏感的方式搜索,如果用\C,则指定大小写敏感 (高度常用) |
?word | 向光标之上寻找一个字符串名称为 word 的字符串。(高度常用) |
n | 这个 n 是英文按键。代表重复前一个搜寻的动作。举例来说, 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字符串,则按下 n 后,会向下继续搜寻下一个名称为 vbird 的字符串。如果是执行 ?vbird 的话,那么按下 n 则会向上继续搜寻名称为 vbird 的字符串! (高度常用) |
N | 这个 N 是英文按键。与 n 刚好相反,为『反向』进行前一个搜寻动作。 例如 /vbird 后,按下 N 则表示『向上』搜寻 vbird 。 (高度常用) |
u | 复原前一个动作。(常用) |
[Ctrl]+r | 重做上一个动作。(常用) |
:vimgrep /搜索内容/g 文件名 | 用Vim内部grep机制,从多个文件中搜索 |
:grep 搜索内容 | 用外部grep,从多个文件中搜索。Win10上用了findstr完成的功能。 |
bufdo vimgrepadd % | co | 跨buffer搜索文字。理解Quickfixlist ,但每次用的是global的,所以下次再使用里面内容会累加,会影响判断。 |
:cex[] | bufdo vimgrepadd /要搜索的内容/g % | 跨buffer搜索文字。比上一个好些,因为它用的是全新的quickfixlist,每次使用很干净。 |
cexpr[] | clear quickfixlist |
:helpgrep <phrase> | 不知道命令,只知道部分关键字,在帮助中搜索,Search help phrase in manual (高度常用) |
:help <topic-name> | 已知某个命令,查找帮助 |
:nohighlight " 等效于 :nohl |
有木有觉得每次查找替换后 Vim 仍然高亮着搜索结果? 可以手动让它停止高亮,在normal/command模式下输入 |
|
统计符合搜索条件的次数,shows the number of times that 这个必须在command line mode执行. (高度常用) |
|
统计符合搜索条件的行数,display the number of lines where the pattern matches。 这个必须在command line mode执行. (高度常用) |
|
指定行数范围内搜索,比如从第10到50行内搜索。 restrict the count to a region of the text, specify a range instead of 这个必须在command line mode执行. (中度常用) |
|
在visual mode中,选中区域内搜索。选中后按:进入command line mode,会自动带出'<,'>前缀。 (高度常用) |
进阶操作(正则搜索)(高度常用)
例如,使用 \v
模式开关查找上述匹配十六进制颜色代码的正则表达式可简化为:/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})
。
:%s/foo/bar/g | 本buffer内全文替换foo为bar (高度常用) |
:s/foo/bar/g | 本行替换foo为bar |
:%s/foo/bar/gc | 本buffer内全文替换foo为bar,但替换前会提示确认 (高度常用) |
:%s/foo/bar/gi | 本buffer内全文替换foo为bar,大小写敏感。用大写I则大小写不敏感 (高度常用) |
:5,12s/foo/bar/g | 在5~12行内替换foo为bar (高度常用) |
:'<,'>s/foo/bar/g | visual mode中选中一片区域,进入command line mode,可以在此区域内搜索foo替换为bar (高度常用) |
:.,$s/foo/bar/g | 从当前行到文档结尾范围搜索替换 |
:.,+2s/foo/bar/g | 从当前行起与之后2行内搜索替换 (中度常用) |
:%s/\vfoo/bar/g | 普通情况下,Vim默认使用magic搜索模式,即不是完整的正则表达式。 magic 搜索模式下,字符转义的规则制定得比较混乱,容易混淆。 使用 very magic 搜索模式下,除下划线 |
进阶操作:
查看Vim当前打开文件的文件名、位置信息和状态等:<Ctrl-g>
(同时按下Ctrl键和g键)
重选上一次由可视模式所选择的文本范围:gv
进阶(文件对比)(高度常用)
:vert diffsplit <filename> |
与指定未打开的1个文件进行diff,水平开另一个window (高度常用) |
:windo diffthis | 同一个tab中已经打开了两个Window即不同文件,两者之间diff (高度常用) |
:windo diffof | 对比完成后关闭highlight (高度常用) |
进阶(jumplist)
不推荐这个功能,感觉价值很低!stackflow上推荐当希望回到上一个位置用bookmark就好。
因为只有下面的command才会记录jump。或者某行发生了change。
Ctrl-o 或Ctrl-l | 根据jumplist ,跳到older或newer (很少用) |
进阶操作(bookmark,特殊的jump。低度常用)
Using this feature we can make navigation within file really faster. 普通模式(即命令模式)输入。我在Win10的Vim8.2上验证,bookmark只支持1个字符,任何可见字符,比如a-Z,特殊符号逗号,句号等。
|
create bookmark. 比如ma 创建了一个叫a的bookmark。又或者m1,则创建名字是1的bookmark。(常用) |
`{bookmark-name} | 比如 `1 就会自动跳到名字是1的bookmark处 (常用) |
‘{bookmark-name} | 跳到名字是1的bookmark那行的开头 |
|
列出所有bookmarks (常用) |
|
删除bookmark (常用) |
m{BOOKMARK-NAME} | global bookmark,使用的名字是大写字母,就能跨文件跳转 |
保存创建的bookmark | 根据stackoverflow和使用命令vimgrep File marks,看到确实默认保存bookmark,实验也通过。但通过:set vi,看到默认保存100个文件的a-z,0-9 bookmarks |
进阶操作(Folding) 用于code或json或xml文件
程序员常用的方式是 :set foldmethod=syntax |
|
|
|
|
|
fold可以通过view机制save/restore当前fold | |
:folddoc <command> | 在每个fold上执行特定command |
help使用
:h 需要弄明白的指令 | 直接跳转到指令说明处 (高度常用) |
:h 需要弄明白的指令 [Ctrl]+D | list all topics that contain "指令". (高度常用) |
:h 需要弄明白的指令 [Tab键] | scroll through the topics that start with "指令" (高度常用) |
|
如果搜索到的有多条match,用这些往前/后跳转 (高度常用) |
:copen | 执行help中的搜索后,这个指令才可用。list out all the matches in a separate window. |
:h CTRL-R |
同一条指令在4种mode中意义不同。不加前缀的,即搜索针对normal mode/command mode的意义. Ctrl-R in normal mode |
:h i_CTRL-R |
同一条指令在4种mode中意义不同。不加前缀的,即搜索针对normal mode/command mode的意义. Ctrl-R in insert mode |
:h c_CTRL-R |
Ctrl-R in command mode |
:h v_CTRL-V |
Ctrl-V in visual mode |
进阶(无插件Vim配置文件vimrc推荐)
(应用)如果寄存器中的字符串存在 <Esc>
字符或 <CR>
字符,则会时 Vim 回到 normal 模式, 并继续执行寄存器中的命令。为了防范 剪切板劫持,可以添加下列的 Vim 配置:
inoremap <C-r>+ <C-g>u<C-\><C-o>"+gP
进阶(Marco): 有哪些场合必须用marco?
function其实可以提供更灵活的方式,但有学习curve。只是当场景简单时,用marco更容易被初学者接受。
q{一个字母作为宏名} | 普通模式q开始与停止录制宏 |
N@{宏名} | 执行录制的宏,N代表执行次数,可以没有。 |
|
Jumping to a tag |
|
Returning after a tag jump |
|
How do I list the contents of the tag stack? |
|
preview a tag |
|
browse through the tag list in a preview window |
|
highlight all the tags in the current file |
Plugin管理:
Vim8提供了buildin的包管理机制。老的vim对于plugin可能管理不够优秀,所以市面上有第三方的plugin manager,比如Vundle, Pathogon , Vim-Plug 。就github的star来看,vim-plug的风头大过Pathogon 和 Vundle 。而Pahogon的官方github页面也提到vim8提供的包管理机制类似Pathogon(Vim 8 includes support for package management in a manner similar to pathogen.vim),所以是否用内置机制就足够了,连vim-plug都不需要了???
内置机制,根据实践和老文章对比 ,查询过:help runtimepath后,了解到:vim会自动搜索c:\users\当前用户名\vimfiles\plugin。所以我把vim plugin用git clone到这个folder后,gVim下次会自动应用. 但不同Plugin可能会有丰富用法,可能还需要设置_vimrc或在command line mode中set。
后续可以了解1. autoload folder的作用,为什么用Pathogon或Vundule都要求copy它。 2. 通过 :help packages了解package与plugin的关系。
高阶操作:
1. tags ,即:help 文件中提到的|xxx| .
2. 可以使用vim script提供更好的fucntion
好的Vim教程参考:
1. runoob.com/linux/linux-vim.html
2. https://w3cschool.cn/vim/
3. https://vim.fandom.com/wiki/Vim_Tips_Wiki
4. https://harttle.land/vim-practice.html
5. https://www.tutorialspoint.com/vim/vim_markers.htm (不太好的教程。部分内容描述错误,比如0是跳到行首而不是文件头,$是跳到行尾,而不是文件尾)
6. https://www.w3cschool.cn/vim/tqd11hss.html
7. Vim命令行模式下输入 :help
会自动打开Vim自带的帮助文档首页,这里列出了help的目录列表,可以根据需要查看对应主题的详细帮助文档说明。
普通模式下,将光标移动到某个带有下划线的主题或者关键字上,按下 <ctrl>-]
,会进入该关键字tag的详细介绍页面,按下组合键 <ctrl>-t
会重新返回到原来的位置。
可以通过关键字的方式直接打开对应内容的帮助文档。例如。在Vim命令行模式输入 :help R
可以看到触发进入替换模式的Vim命令 R
的详细内容。
vimrc应用(vim在编辑时,文档被其他编辑器如notepad修改保存,自动提示文档已被修改,是否要reload)
:set autoread | 默认安装gVim后,此值默认未开启。可以通过:set all查看是否是noautoread。 只要设置过,就会有弹窗提示要不要reload。 |
vimrc+script应用(正确显示ar或cs语言)
Win10默认情况下,gVim默认是latin-1,即使通过_vimrc设置了utf-8,显示的ar还是一片黑块,cs有个别char也是黑块。需要做一下2步就能正确显示。(知识,There really isn't a common way to determine the encoding of a plaintext file, as that information isn't saved in the file itself - except UTF-8 Files where you've got a so called BOM which indicates the Encoding. This is why xml and html files have charset metatags.)
1. 默认在Windows上gVim的_vimrc里没有设置UTF-8,需加入set encoding=utf-8
2. 需要在_vimrc中加入一段代码,在edit ar或cs文本就正常了。另一个post的code也是类似,也可以。
if has("gui_running") " only the GUI can set the font
if has("gui_gtk2") " GTK2 only, not GTK1
set gfn=Courier\ New\ 10
elseif has("gui_photon")
set gfn=Courier\ New:s10
elseif has("gui_kde") " the obsolete kvim
set gfn=Courier\ New/10/-1/5/50/0/0/0/1/0
elseif has("x11") " other X11 GUIs, including GTK1
set gfn=*-courier-medium-r-normal-*-*-100-*-*-m-*-*
else " non-X11 GUIs
set gfn=Courier_New:h10:cDEFAULT
endif
endif
(应用)vim的word completion功能
添加我们自己常用的word,vim会读取出来。但是中文字典加入后vim带不出来,不知道用什么方法。