vim

学会一个软技能,总结一篇文章就够了。
剩下要做的就是不停的练习,不停的尝试,本文是在学习这个仓库 (opens new window)之后的极简总结中。 主要作为一个备忘录使用。

长期更新。。。

# 一、Vim基础介绍

  1. vim 看到一个介绍页面
  2. i 进入编辑模式
  3. : 光标将移动到屏幕底部,在这里您可以输入命令
  4. Esc 切回普通模式
  5. :quit 退出编辑模式,简写为:q
  6. :write 保存模式,简写为:w
  7. :w f.md 如果是新建的一个没有名字的文件,以f为名字保存文件
  8. :wq 保存退出
  9. :q! 不保存修改而强制退出
  10. :h 在冒号模式下,输入 :h quit 然后按Tab键就会自动打出命令。
  11. :vim f1 f2 通过vim命令在不同的buffers中打开多个文件
  12. vim --version '+'表示支持的特性,'-'表示不支持的特性
  13. vim +%s hello/liugezhou/g file 这条命令的意思是 打开file文件将文档中所有的hello改为liugezhou
  14. vim -o2 水平打开n个窗口
  15. vim -O2 垂直打开n个窗口
  16. Ctrl + z(:stop :suspend) 使用vim打开的文件进行挂起 输入fg恢复。

# 二、Buffers、Windows、Tabs

创建一个.vimrc,添加配置set hidden(切换buffer且当前buffer没有保存,不会进行提示)

# 2.1 buffers

  1. vim file1.js file2.js,实际创建了两个buffers,执行完该命令后展示的是file1.js的buffers 运行:buffers命令可以查看所有的buffers,或者使用 :ls OR :files命令查看。
  2. 切换到下一个buffer :bnext:buffer fileNamebuffer n
  3. 切换到下一个buffer的快捷键:Ctrl + I,切换到原来buffer的快捷键:Ctrl + O
  4. 一旦buffer创建成功,即进入了buffers列表,这个时候想在buffers列表中删除某一个buffer,直接:bdelete n即可
  5. 退出vim
  • 关闭所有buffer :qall
  • 关闭所有buffer但是不保存 qall!
  • 关闭所有buffer且保存 wqall

# 2.2 Windows

  1. vim file1.txt打开file1文件,有一个buffer,有一个窗口 此时在vim中使用:split file2.txt 会看到此刻有两个窗口,两个buffer,file2.txt的窗口在上
    如果想垂直打开file2窗口 :vsplit file2.txt 如果想垂直打开一个新命名文件的窗口 :vsplit filename
  2. 如果要在窗口直接导航
    Ctrl+ W h 左移窗口 Ctrl+ W l 右移窗口 Ctrl+ W j 下移窗口 Ctrl+ W k 上移窗口
  3. 继续输入 :split file3.txt,此时有三个窗口、三个buffer
  4. 如果想在显示file2.txt的窗口中显示file3.txt,只需要在当前buffer为2下输入:buffer file3.txt即可
  5. 要关闭当前窗口 Ctrl+W c
  6. 普通模式下关于窗口的命令: Ctrl + W c 打开一个垂直分割的窗口 Ctrl + W s 打开一个水平分割的窗口 Ctrl + W c 关闭当前所在窗口 Ctrl + W o 除了当前窗口,关闭其它所有窗口

# 2.3 Tabs

  1. vim tabs.md 这个时候打开一个新tab,使用命令 :tabnew readme.md
  2. 切换下一个tab,使用命令 :tabnext
  3. 关闭当前tab,使用命令:tabclose
  4. 切换上一个tab,使用命令:tabprevious
  5. 切换至最后一个tab,使用命令:tablast
  6. 切换至第一个tab,使用命令:tabfirst
  7. 如果想让vim启动时就包含多个tabs,可以使用命令 vim -p file1.txt file2.txt

# 三、打开和搜索文件

# 3.1 打开和编辑文件

  • 要在vim中打开一个文件,直接使用命令 :edit newFile
  • edit接收通配符*,比如使用 :edit *.md然后按tab键,就会依次显示md文件,还可以是*/*.js这种格式
  • :edit 路径URL也可以直接打开一个文件

# 3.2 使用find命令搜索文件

  • 比如:我试了一下:find readme.md就直接跳转到那个文件了,但是这里只是找之前buffers中存在的
  • 通过 find的命令会直接跳转到找到的那个文件,且在当前窗口打开

# 3.3 find和Path的区别

  • :find命令根据path选项配置的路径去找文件

  • :edit命令则不会。 在我们开始牛逼的使用find命令前,我们需要对path到底是什么进行一个学习

  • :set path?这个命令,可以让我们看一下我们的path是什么,在当前这个文件(使用vim写),输入此命令,显示内容为:path=.,/usr/include,,

# 3.4 使用grep命令在文件中搜索

内置grep

  • grep是指在文件内容进行内容的查找, :vim /pattern/ file pattern为正则表达式
  • 搜索出来后默认显示出第一条匹配内容
  • 查看所有搜索内容::copen
  • 关闭窗口::cclose
  • 跳到下一个列表: cnext
  • 跳到上一个列表: cprevious

外置grep

  • 在命令行终端搜索
  • grep -R "搜索的内容" fileUrl

用Netrw浏览文件

  • Netrw是vim内置的文件浏览器、查看项目的目录结构时很有用。
  • 要运行Netrw,需要在.vimrc中配置
set nocp
filetype plugin on
  • 这个时候 vim直接给一个地址就可以了
  • 要从内部运行Netrw,则需要给:edit一个目录地址

# 3.5 vim中文件内容搜索

  • normal模式(即Esc模式)
  • 直接输入/或者?,然后输入要搜索的字符进行搜索
  • 注意区别是:
    • /是从光标处向下查找,这个时候输入n 是继续查找下一个,输入N是查找上一个
    • ?是从光标处向上查找,这个时候输入n是继续向上查找,输入N是向下开始查找

彩蛋:item2的光标样式设置为Profiles -> Colors -> Cursor colors -> Cursor进行设置 然后在vim搜索中还是不明显,这个时候将Profiles -> Colors -> Cursor colors ->Cursor guide勾选上就好很多了。

# 四、Vim语法

# 4.1 ⭐️ vim语言的语法规则 动词 + 名词

动词是动作

  • y 复制
  • p 粘贴到光标后
  • P 粘贴到光标前
  • d 删除文本
  • D 从光标处,删除改行的末尾
  • c 删除文本,与d不同的是--将删除的文本保存在寄存器中,从普通模式进入到插入模式
  • C 直接删除一行,并进入插入模式

名词是位置

  • h
  • l
  • j
  • k
  • 0 当前行的开始
  • $ 当前行的末尾
  • w 下一个单词的开头
  • } 跳转到下一个段落

# 4.2 结合

  • y$:复制当前位置到行尾的所有内容
  • dw:删除当前位置到下一个单词开头的内容
  • c}:修改当前位置到段落结尾的内容。

# 4.3 更多名词

  • 如何更快的把括号中内容删除:I want say (hello vim)?
  • 文本对象:小括号中、中括号、大括号、引号
  • 文本对象可以被操作符operations使用,两类文本对象分别为:i + object a + object
  • di( 删除()内的内容
  • 删除整个被{}包裹的内容:di{
  • 删除hello这个单词:在h这个字母上,使用命令:diw
<div>
  <h1>Header1</h1>
  <p>Paragraph1</p>
  <p>Paragraph2</p>
</div>
  1. 若此时光标在Header1上
  2. 删除Header1这个单词:dit
  3. 删除<h1>Header1</h1>:dat

# 4.4 常用到的文本对象

  • w: 一个单词
  • p: 一个段落
  • s: 一个句子
  • (或者):指的是()
  • {或者}:指的是{}
  • <或者>:指的是一对<>
  • t: XML标签

# 4.5 针对性复习

  • w or W: 跳转到下一个单词

  • 0: 跳转到本行的开始

  • $: 跳转到本行的行尾

  • {: 跳转到打开文件光标所在位置的段落最开始

  • }: 跳转到打开文件光标所在位置的段落最末尾

  • gg:跳转到打开文件的第一行文字开始位置

  • G: 跳转到打开文件的最后一行的开始位置

  • ]]:同G

  • [[:跳转到打开文件的第一行

  • nG: 跳转到第n行

  • nj: 光标处开始,向下n行

  • nk: 光标处开始,向上n行

  • d: 删除操作符

  • y: 复制操作符

  • c: 删除插入操作符

  • p: 粘贴到光标后操作符

  • gU: 小写变大写操作符

# 五、在文件中移动

# 5.1 ⭐️ 字符导航

普通模式下:

  • hjkl: 字符导航
  • n + hjkl: 向左下上右移动n个行或者字符
  • 0: 跳转到本行开始
  • $: 跳转到本行结尾
  • ^: 跳转到本行第一个非空字符 g_跳转到本行最后一个非空字符串($的使用于g_的区别,还是$在使用中普遍)
  • n|: 跳转到本行第n列
  • fs: focusOn string 在本行内光标之后开始搜索,光标停留在字符s
  • Fs: focusOn string 在本行内光标之前开始搜索,光标停留在字符s
  • ts : focusOn string 在本行内光标之后开始搜索,光标停留在字符s之前
  • Ts : focusOn string 在本行内光标之前开始搜索,光标停留在字符s之前
    • ;: 表示继续 在本行向下搜索下一个
    • ,: 表示继续 在本行向上搜索上一个

# 5.2 句子和段落导航

  • 句子定义:指以 .?!这三个字符 跟着一个换行符或者空格、tab结尾的,就算一个句子。

  • (跳到前一个句子

  • )跳到下一个句子

  • 段落:可以从一个空行之后开始,也可以从段落选项中字符对所指定的段落宏的每个集合开始。

  • {跳到上一个段落

  • }跳到下一个段落

# 5.3 ⭐️ 行号导航

  • nG:跳转到第n行
  • gg:跳转到第一行
  • G:跳转到最后一行
  • n%:跳转到文件的百分比
  • ctrl + g:可以看到总行数以及当前所在行数

# 5.4 窗格导航

  • H:Head 跳转到屏幕的顶部
  • M:Middle 跳转到屏幕的中部
  • L:Line 跳转到屏幕的底部
  • nH:跳转到距离顶部n行的位置
  • nL:跳转到距离底部n行的位置

# 5.5 ⭐️ 屏幕滚动

普通模式下:

  • ctrl + e:向下滚动一行-> e,中文一,就是向下一行

  • ctrl + y:向上滚动一行-> yu,骑驴的时候让驴听一下,回大喊一声yu,也就是退一步

  • ctrl + f:向下滚动一屏-> full screen

  • ctrl + b:向上滚动一屏-> back screen

  • ctrl + u:向上滚动半屏->up,up半屏。

  • ctrl + d:向下滚动半屏-> down,down半屏

# 5.6 当前行位置指定

  • zt:将当前行 指定到窗格的顶部
  • zz:将当前行 指定到窗格的中间
  • zb:将当前行 指定搭配窗格的底部

# 5.7 位置标记(暂了解即可)

  • ma:标记当前位置
  • ``a`:回到标记的位置(行与列)
  • 'a:回到标记的行

# 5.8 跳转

在普通模式下:

  • nG:跳转到第n行
  • /:向后搜索跳转
  • ?:向前搜索跳转
  • n 重复上一次搜索,相同方向
  • N 重复上一次搜索,相反方向
  • % 查找匹配
  • ( 跳转上一个句子
  • ) 跳转下一个句子
  • { 跳转上一个段落
  • } 跳转下一个段落
  • L 跳转到当前屏幕的最后一行
  • M 跳转到当前屏幕的中间
  • H 跳转到当前屏幕的第一行
  • [[ 跳转到上一个小节
  • ]] 跳转到下一个小节
  • 'a:跳转到标记的行
  • ``a`:跳转到标记的行和列

# 六、输入模式

这一节通过输入模式来提升输入效率。

# 6.1 ⭐️ 进入输入模式的方法

  • i: 从光标位置的前面开始输入内容
  • I: 从光标所在行的第一个非空字符开始输入内容
  • a: 与i是相对应的,从光标位置的后面开始输入内容
  • A: 与I是相对应的,从当前行的末尾非空文本后追加文本
  • o: 这个小o是非常的有用,在当前光标位置的下方自己给新起一行开始输入文本
  • O: 这个是与小o对应,在当前行的上一行开始新加一行并开始输入文本
  • s: 删除当前光标处字符,并开始输入内容
  • S: 删除光标所在当前行内容,并开始输入内容

# 6.2 退出输入模式的方法

除了Esc外,还可以直接使用Ctrl + c的方式退出输入模式

# 6.3 删除模式

输入过程出现错误的合理做法是切换到普通模式,使用d来删除错误

在输入模式中也是可以删除的:

  • Ctrl + h是删除一个字符
  • ctrl + w是删除一个单词
  • ctrl + u是删除一行

# 6.4 寄存器输入

寄存器是说在a-z这个标识直接对一个单词在普通模式下进行保存操作"ayiw,然后在输入模式中使用ctrl + r a的方式进行保存
这里在使用寄存器输入之前先用好y$ yw,结合p、P,再考虑使用寄存器。

# 6.5 输入模式下的翻页

输入模式下也是可以翻页的

  • ctrl + x ctrl + y: 向上滚动页面
  • ctrl + x ctrl + e: 向下滚动页面

# 6.6 ⭐️ 执行普通模式下的命令

在输入模式下,可以使用普通模式下的命令。

  • 输入模式下,键入ctrl + o就进入了普通模式(左下角的模拟指示器显示 --insert--),这个时候就可以使用普通模式下的命令
  • ctrl + o zz 剧中窗口显示光标所在位置
  • ctrl + o H/M/L 光标跳转到窗口的顶部、中部、底部
  • ctrl +o D 从光标处删除到行尾

# 七、点命令

使用点命令来重放上一个修改动作,点命令是最简单的命令,也是减少重复操作最有用的命令。

# 7.1 用法

想把下面的代码中let替换成const

let one = '1'
let two = '2'
let three ='3'
  1. 使用/let进行匹配
  2. 使用cwconst<esc> 将匹配到的第一个替换成了 const
  3. 使用n找到下一个匹配的位置
  4. 使用.命令,重复之前的匹配的操作
  5. 持续 n.n.将每一个词进行替换

# 7.2 怎么算是修改操作

使用普通模式下的命令来更新(添加、修改、删除)当前缓冲区内容时,就是执行一个修改操作。

first, second, third,

删除从开始到第一个逗号出现的位置:df,使用.重复两次直到整个句子删除。

将下面中的逗号删除,不删除文本

liugezhou,is,a,Cool,boy

根据5.1我们知道fs命令是搜索到字符s所在的位置,因此这里只删除,的操作,我们使用:f,x;.;.的方式
之所以加;是因为在vim中,操作是不包括移动的,这里是使用;移动到下一个目标点,执行删除操作。

再看一个例子

my 
name
is 
liugezhou

目的是要在每一行结尾加上逗号:

  • 首先根据6.1我们知道A是在当前行结尾追加内容
  • 然后根据vim中的点操作不包括移动,我们这样:
  • A, <ESC> j .<ESC> j .<ESC> j . 从按下命令A开始,到退出模式之间的所有输入都算是一整个修改操作。

# 7.3 重复多行修改操作

1  Hello World!
2 Hello World!
3 Hello World!
4 Hello World!
5 Hello World!
6 Hello World!
7 Hello World!

有7行数据,要删除的是除了第5行。我们这里使用简单的删除方法:先删除前四行,再删除第6、7行。
命令位:d4jjd2j 解析:其中d为操作删除,4j类比于5.3节nG,即要删除的范围为:当前光标处下移动4行。j表示下。

点命令非常简单且功能强大,这里先记录这三个。

# 八、寄存器

# 8.1 10种寄存器类型

  1. 匿名寄存器("")
  2. 编号寄存器("0-9)
  3. 小删除寄存器("-)
  4. 命名寄存器("a-z)
  5. 只读寄存器(:,:.,"%)
  6. Buffer交替文件寄存器("#)
  7. 表达式寄存器("=)
  8. 选取和拖放寄存器("*,"+)
  9. 黑洞寄存器("_)
  10. 探索模式寄存器("/)

# 8.2 寄存器命令

从存值和取值两个方面了解哪些命令与寄存器有关。

存值到寄存器中的操作:

  • y: 复制
  • c: 删除并进入插入模式 [需要跟名词]
  • d: 删除 [需要跟名词]
  • s: 直接删除光标处字符并进入插入模式
  • S: 直接删除光标所在行内容并进入插入模式
  • x: 直接删除处于光标处字符,与s不同为仍然处于普通模式
  • x: 直接删除处于光标处上一个字符,且仍然处于普通模式

从寄存器中取出文本操作

  • p:在光标位置之后粘贴文本

  • P:在光标位置之前粘贴文本

  • pP都可以接受计数和一个寄存器标志作为参数。

  • 10p表示:当前光标之后,将上一次存值到寄存器中的内容,复制100遍。

  • 10"ap表示:将寄存器a中的文本粘贴10次。(关于寄存器a是寄存标志,8.4内容介绍)

# 8.3 在输入模式中使用寄存器

输入模式下使用寄存器的命令为:
ctrl + r a
这里的a是指寄存器的标志(关于标签a如何添加,下面内容介绍)。

# 8.4 ⭐️ 不同类型寄存器标志说明

1.匿名寄存器""
说明:匿名寄存器存储的是最近的一次复制、修改或者删除的文本,和电脑上的粘贴功能一个意思。
语法:p || P

2.编号寄存器("0-9) 说明:编号寄存器自动以升序进行填充,按0-9分为复制寄存器(0)和其他编号寄存器(1-9)

复制寄存器(0):是指若是复制操作(yy复制一行),Vim会将文本存放在两个寄存器中->匿名寄存器p和复制寄存器0中去,这里的操作只能是复制,删除不管用,好处是最新复制的内容一直会在复制寄存器中。
语法:普通模式下->"0p,插入模式下->ctrl + r 0

编号寄存器(1-9):当修改或者删除至少一整行的文本时,这部分文本会按时间顺序被存储在1-9号编号寄存器中(编号越小,距离时间越近)。
语法:普通模式下->"np,插入模式下->ctrl + r n 注意:小型的单词删除(dwORvw)不会被储存在编号寄存器中,会被储存在小删除寄存器中"-

3.小删除寄存器("-) 说明:不足一行的修改或者删除都不会被存储到0-9的编号寄存器中去,而是会被存储在小删除寄存器("-)中去。 语法:普通模式下->"-p,插入模式下->ctrl + r -

4.命名寄存器("a-z) 说明:命名寄存器是Vim中用法最丰富的寄存器。a-z命名寄存器可以存储复制、修改和删除的文本。
语法:"ayiw 表示复制一个单词,且存储在寄存器中以a命名。

5.只读寄存器(":,".,"%) 说明:vim只要三个只读寄存器,.存储上一个输入的文本,:存储上一次执行的命令,%存储当前文件的文件名
举例:在vim中处于插入模式下,想看本文件目录:ctrl + r %,直接打出文件名字。

6.buffer交替文件寄存器("#) 说明:vim中,#通常代表交替文件,交替文件是上一个打开的文件,使用命令"#p, 只是打印出文件名,貌似没有什么大用。

7.表达寄存器("=) 说明:Vim有一个表达式寄存器,"=用于计算表达式的结果。 语法:普通模式下-> "=100+100 Enter p,插入模式下->ctrl + r =100+100 enter

扩展:可以使用表达寄存器方法结合@符号从其他寄存器中直接拿出值->ctrl + r =@a OR ctrl + r =@1

8.选取和拖放寄存器("*,"+) 可以用"*"+来访问从外部程序中复制的文本。
语法:当在外部复制了一段文本后,要在vim中复制文本,普通模式下->"*p | "+p,在插入模式下-> ctrl + r * | ctrl + r * 反向:在vim文件内,普通模式下复制一行代码->"*yy,这个时候在外部直接粘贴即可。

扩展:为了vim仅使用p就能从外部粘贴文本,可以在vimrc配置文件中->set clipboard=unnamed

9.黑洞寄存器("_) 说明:每次修改或者删除文本时,默认会存入到寄存器中,如果不想存,就可以使用黑洞寄存器。 语法: "_dd 删除一行且不放入到寄存器中去。

10.探索模式寄存器("/) 说明: 之前使用了?或者/进行了搜索,这个搜索文本可以通过 "/p的方式快速打印。

查看所有的寄存器 语法:使用:register的方式查看所有寄存器,可跟参数,比如:register a 1 - 扩展:使用寄存器插件vim-peekaboo可查看所有寄存器内容(且分类的),普通模式下直接输入"或者@即可,插入模式下ctrl + r即可。

tips:到这里的时候,根据这篇文章先去安装了vim的包管理器Vim-plug (opens new window)
并安装了插件preservim/NERDTree(图形界面),以及junegunn/vim-peekaboo插件。

清除寄存器
从技术上来说没必要清理寄存器,但是通过:register或者插件看到的寄存器可能就是不得劲。
这里记录一个清除寄存器的命令::let @1 =''->将编号寄存器0清除。

获取寄存器中的内容 语法:使用:put a打印出寄存器a的内容。 :putap的区别在于,前者是新起一行插入寄存器内容,后者在光标位置之后插入。

# 九、宏命令

背景:编辑文件的时候,有时候我们会反复的做一些相同动作,通过vim的宏命令,可以将一些动作记录到Vim寄存器。

# 9.1 基本宏命令

  • 基本语法:qa:开始记录动作到寄存器a, q: 停止记录
  • 注意:使用小写字母a-z去存储宏命令,通过@a命令去调用。

Practice:有以下文本,需要将每一行的字母变成大写

my 
name
is
liugezhou

普通模式下:qa0gU$jq 命令分解:

  • qa: 开始记录一个宏定义并存储在a寄存器中
  • 0: 移动到改首
  • gU$:从光标处到行尾字母变成大写
  • j:向下移动一行
  • q: 停止记录
  • 最后通过@a去执行改宏命令,3@a会执行三次宏命令。

# 9.2 增添、修改、拷贝宏

在普通模式下:

  • 增添一个宏:: let @a ='something'
  • 修改一个宏:: let @a ='输入新的' 即可。
  • 拷贝一个宏:: let @z = @a

# 十、撤销

撤销是一个基本功能,本节记录撤销、取消撤销、浏览撤销分支、反复撤销、浏览改动时间线。

# 10.1 撤销(undo),重做和行撤销(UNDO)

在每次进入插入模式和退出模式之间的任何修改都被定义为一次修改。

  • 基本撤销:u (undo),可以连续执行。
  • 撤销基本撤销: ctrl + r,可以连续执行。
  • 跳过中间修改:U(使用较少)

tips:在.vimrc中设置 set undolevels =500可以执行500次的undo操作

# 10.2 断点插入操作

上面的撤销是从插入模式到退出模式作为一次修改,而我们在输入模式中,由于输入大量文本,也有撤销的要求,也就是在输入模式下记录一下撤销点。
插入模式下,当执行完一个操作后,键入ctrl + g u,这个时候就记录了一个断点。

# 10.3 撤销树

语法:g+ g-

# 10.4 保存撤销记录

操作步骤

  • 新建一个空的test.md文件
  • i 输入"one"
  • ctrl + g u
  • 回车,继续输入"two"
  • ctrl + g u
  • 回车,继续输入"three"
  • esc
  • : wundo test.undo
  • 退出vim

再次打开test.md的时候,我们执行u命令发现,下方提示:Already at oldest change,即不能撤销。 这个时候执行:rundo test.undo,在执行u命令就可以撤销了。

语法::wundo file.undo:rundo file.undo

tips:真正开发的时候,应该没人去自己创建一个undo的文件,我们为了默认每次进入文件后都是可以执行u的,可以在~/.vim目录下新建一个默认目录undo_dir,然后在.vimrc文件中设置

set undodir=~/.vim/undo_dir
set undofile

这个时候,无论何时保存,Vim都会自动创建和保存撤销的历史记录。

# 10.5 时间旅行

时间旅行真的是太Cool了。
打开一个文件,如果你想看之前某个时刻的显示:

  • :earlier 10s 恢复到10秒之前的状态
  • :earlier 10m 恢复到10分钟之前的状态
  • :earlier 10h 恢复到10小时之前的状态
  • :earlier 10d 恢复到10天前的状态
  • :earlier 2 恢复到2次修改前的状态
  • :earlier 2f 恢复到2次保存前的状态

:earlier对应的版本:later,语法同上。

# 十一、可视化模式

# 11.1 三种可视化模式

  • v: 逐字可视化模式
  • V: 逐行可视化模式
  • ctrl + v:逐块可视化模式

可在三种模式下切换,切合hjkl体验效果。

# 11.2 可视模式导航

可视化导航指的是,在向某一个方向进行可视化的时候,这个时候有向相反方向进行可视化的需求,这个时候使用o来切换光标位置。

# 11.3 可视模式语法

使用三种模式的一种,将某一段文本、代码为可视化后,按d直接将其删除。
与普通模式语法规则不同的是,(动词 + 名词)的不适用于可视模式,可适模式下没有名词。

# 十二、搜索和替换

  1. 智能区分大小写
  • 设置搜索不区分大小写->.vimrc->set ignorecase
  • 设置全小写不区分大小写,有一个大写字母就区分->.vimrc-> set ignorecase smartcase
  1. 一行中的第一个字符和最后一个字符
  • 使用^匹配行中的第一个字符,$匹配最后一个字符
  1. 重复搜索|候选词搜索
  • //重复上一个搜索/
  • /up|down:遍历搜索历史
  • :history /:查看所有历史记录
  • /s1\|s2:同时搜索字符s1和s2,重点是转义符
  • \vs1|s2: 同上使用\v
  1. 搜索字符组 与正则表达式相通:\v[^0-9a-zA-Z]{m,n}

  2. 基本替换:
    将good单词替换为awesome::s/good/awesome 全局将good单词替换为awesome::s/good/awesome/g

# 十三、全局命令

# 13.1 全局命令概述

  • :h ex-cmd-index查看完整列表
  • 全局命令语法::g/pattern/command

举例:

const one = 1;
console.log("one: ", one);

const two = 2;
console.log("two: ", two);

要删除所有包含console的行,可以运行 :g/console/d

# 13.2 逆向匹配

:v/console/d:它将删除所有不包含console的行。

# 十四、外部命令

# 14.1 读取外部文件

  • :r是Vim的读命令,如果不带!使用它,则可以使用它来获取文件内容,若当前目录有文件 test.md , 运行 :r test.md. Vim就会将test.md的内容放入到当前缓冲区。
  • :r !ls,语法结构为 :r + ! + 外部命令,该命令的输出将插入到当前缓冲区。eg :r !ls ,这个命令会将当前目录下执行ls列出的文件列表,插入到当前编辑的文件中。
  • :r !ctrl -s 'url':这个命令会将接口url返回的内容插入到当前编辑的文件中。

# 14.2 将缓冲区内容写入外部命令

console.log('liugezhou')
console.log('vim')

当上面内容在缓冲区内时,在普通模式下,执行:w !node,Vim将使用node执行JavaScript表达式来打印出liugezhouvim

# 14.3 执行外部命令

可以在不离开Vim的情况下运行任何外部命令。

  • 语法::!cmd
  • :!ls -ls
  • :kill -9 3466

# 十五、命令行模式

切记本章内容是在命令行模式下。

# 15.1 进入和退出命令行模式

进入命令行模式:/?:!
离开命令行模式:ESCctrl + cctrl + [

# 15.2 命令行模式快捷键

  • 如果要移动一个单词:shift + leftshift + right
  • 如果要移动到该行开始:ctrl + b,移动到该行结尾:ctrl + e
  • 删除字符:ctrl + h(删除一个字符),ctrl + w 删除一个单词, ctrl + u删除一行 、
  • 编辑文件一样编辑命令 ctrl + f,比如使用/或者?进入命令行模式后,键入ctrl + f 可以查看历史记录以及编辑新的内容,:!同理,按下enter执行。

# 15.3 寄存器和自动补全

  • 在命令行模式下,可以像插入模式那样使用 ctrl + r从Vim寄存器中插入文本。
  • 命令行模式下,ctrl + r ctrl + w 获取当前光标下的字母
  • 命令行模式下,ctrl + r ctrl + A 获取当前光标下的词组
  • 命令行模式下,ctrl + r ctrl + l 获取当前光标所在行内容

# 十六、标签

暂时略过

# 十七、折叠

# 17.1 手动折叠

  • 折叠操作符是z
  • zfj: 从光标所在行到下一行内容折叠
  • zo: 在光标处、打开已折叠文本
  • zc: 关闭/收缩文本
  • 折叠操作符,符合语法规则(动词 + 名词)
  • zR:展开所有折叠
  • zM:收缩所有折叠
  • za: 切换折叠状态

命令行模式下,使用:fold命令执行一次折叠

  • ,+1fold 折叠当前行及紧随其后的第二行
  • 16,20fold kjj第16到20行

# 17.2 不同的折叠方法

  • 通过:set foldmethod查看折叠方式,默认是手动折叠manual

  • 手动折叠

  • 缩进折叠

  • 表达式折叠

  • 语法折叠

  • 差异折叠

  • 标志折叠

# 十八、Git

# 18.1 差异比较

  • 查看两个文件的差异: vimdiff f1.md f2.md OR vim -d f1.md f2.md
  • 使用]c跳转到下一处差异,[c跳转到上一处差异
  • :diffput 将左侧内容同步到右侧
  • :diffget 将右侧内容同步到左侧

# 18.2 使用Vim作为合并工具

  1. 首先运行以下命令来将默认合并工具更改为 vimdiff
git config merge.tool vimdiff 
git config merge.conflictstyle diff3
git config mergetool.prompt false

或者通过修改~/.gitconfig

[core]
  editor = vim 
[merge]
  tool = vimdiff 
  conflictstyle = diff3 
[difftool]
  prompt = false

# 18.2 在Vim中使用Git

使用!可以运行任何Git命令

:!git status
:!git commit 'add something'
:!git diff
:!git push origin master
:!git add `%` (%-当前缓冲区) 
:!git checkout `#` (`#`其他缓冲区)

# 十九、编译

Vim有运行makefile的:make命令,当运行它时,Vim会在当前目录寻找makefile并执行它。

# 19.1 Make命令

新建一个makefile文件,内容保存如下:

all:
	echo "Hello all"
foo:
	echo "Hello foo"
list_pls:
	ls

vim命令后模式运行::make :make all :make foo :make list_pls 查看打印内容

# 19.2 使用Make编译

  • 创建一个make.js文件
function make(){
  console.log('使用makefile中的node命令进行编译')
}
make()
  • 在该目录下创建一个makefile文件,内容如下
node:
    node ./make.js
  • 运行 :make node 即可查看结果。

# 19.3 不同的make程序

  • 当运行:make的时候,实际上会执行makeprg选项设置的命令
  • 通过运行 :set makeprg?来查看,默认的设置为:makeprg=make
  • 修改命令为::set makeprg=node\ %,\为对空格的转义,%符号表示当前文件。

# 二十、视图、会话和Viminfo

当项目的一些设置、布局、缓冲区在开始设置后,关闭Vim再次进入后原先设置会丢失,这节来学习如何使用视图、会话和 Viminfo 来保存项目'快照'

本节内容暂时跳过

# 二十一、多文件操作

# 21.1 多文件中执行命令的方法

  • 参数列表(argdo)
  • 缓冲区列表(bufdo)
  • 窗口列表(windo)
  • tab列表(tabdo)
  • 快速修复列表(cdo)
  • 文件方式的快速修复列表(cfdo)
  • 位置列表(ldo)
  • 文件方式的位置列表(lfdo)

# 21.2 参数列表

通过参数将一些文件创建一个列表:

  • :args file1 file2 file3
  • :args *.js
  • :args a*.js
  • :args **/*.js

运行以上命令后,当前buffer会切换到列表中的第一个文件,运行:args可以查看当前创建的文件列表。

  • :first:跳转至列表中的第一个文件
  • :last:跳转到最后一个文件
  • :next:跳转到下一个文件
  • :prev:跳转到上一个文件
  • :wnext:保存当前文件跳转到下一个文件
  • :wprev:保存当前文件跳转到上一个文件

# 二十二、Vimrc

# 22.1 Vim如何找到Vimrc

根据操作系统,文件路径名可能不同,一般的使用路径是 ~/.vimrc

# 22.2 Vimrc基础内容

绝大部分的使用场景包含一下五个内容集合:

  • 插件
  • 设置
  • 自定义函数
  • 自定义命令
  • 键盘映射

插件

我的插件管理器使用的是vim-plug

  1. 添加插件方法,在.vimrc中:
call plug#begin
  Plug 'mattn/emmet-vim'
  Plug 'preservim/nerdtree'
call plug#end()
  1. 保存退出
  2. 在vim命令后模式中运行:PlugInstall
  3. 如果想删除不使用的插件,只要将插件名从call代码块之前删除,保存后执行:PlugClean即可。

设置 在任意一个vimrc文件中会发现有大量的set设置。
而在命令行模式下执行set命令,只是暂时的,关闭vim后设置就会丢失。

  • set number:显示行号
  • set hidden:允许在有未保存的修改时切换缓冲区,此时的修改由 vim 负责保存
  • set hlsearch: 搜索时高亮显示被找到的文本
  • set clipboard=unnamed:仅使用p就能从外部粘贴文本
  • set undolevels =500可以执行500次的undo操作
  • set undodir=~/.vim/undo_dirset undofile:为了默认每次进入文件后都是可以执行u的,在~/.vim目录下新建一个默认目录undo_dir
  • set ignorecase smartcase:设置全小写不区分大小写,有一个大写字母就区分->.vimrc-> set ignorecase smartcase …… 更多设置参考 (opens new window)

自定义函数 vimrc是一个很好的用来放置自定义函数的地方,后面的章节继续学习写vimscript函数

自定义命令 可以使用command创建一个自定义命令 eg:创建一个显示今天日期的基本命令 Today(首字母大写) :command! Today echo call("strftime",["%F"])

键盘映射 略过

# 22.3 组织管理Vimrc

.vimrc文件变得大且复杂时,有两种方法可以使文件保持整洁:

  1. 将vimrc文件划分为几个文件
  • ~/.vim下创建一个子文件settings
  • 在该子文件下创建多个文件(plugins.vimconfigs.vimfunctions.vimmappings.vim)
  • .vimrc中添加 source $HOME/.vim/settings/.....
  • 然后分别在四个文件中设置setcall plug等等,即可
  1. 折叠vimrc文件 在.vimrc文件顶部添加如下内容
" setup folds {{{
augroup filetype_vim
  autocmd!
  autocmd FileType vim setlocal foldmethod=marker
augroup END
" }}}
" plugins {{{
call plug#begin('~/.vim/plugged')
  Plug 'mattn/emmet-vim'
  Plug 'preservim/nerdtree'
call plug#end()
" }}}
" configs {{{
set nocompatible
set relativenumber
set number
" }}}

# 22.4 启动Vim时加载/不加载vimrc和插件

  • 启动Vim时,既不加载vimrc,也不加载插件:vim -u NONE
  • 启动Vim时,不加载vimrc,但加载插件:vim -u NORC
  • 启动Vim时,加载vimrc,但不加载插件:vim --noplugin
  • 启动Vim时加载其他的vimrc配置文件:vim -u ~/.vimrc-backup

# 二十三 Vim软件包

待更新

上次更新: 10/18/2022, 5:58:40 PM