《Vim实用技巧(第2版)》学习笔记

第1章 Vim解决问题的方式


第一部分 模式

第2章 普通模式


第3章 插入模式


第4章 可视模式


第5章 命令行模式

  • 技巧30- 在指定范围上执行普通模式命令
    • 如果想在一系列连续行上执行一条普通模式命令,可以用:normal命令。
    • :normal命令与.命令结合能完成大量重复性任务。
    • :%normal A; Vim在文件每行的结尾都添加一个分号。
    • :%normal i// 注释整个文件。
  • 技巧31-重复上次的Ex命令
    • .命令可以重复上次的普通模式命令。
    • @:重复上次的Ex命令。
    • :bn在列表中逐项正向移动。
    • :bp在列表中逐项反向移动。
  • 技巧32-自动补全Ex命令
    • Vim显示可用的补全列表。
    • Tab 依次遍历剩余的补全项。
  • 技巧33-把当前单词插入命令行
  • 技巧34-回溯历史命令
  • 技巧35-运行Shell命令
  • 技巧36-批处理运行Ex命令

第二部分 文件

第6章 管理多个文件


第7章 打开及保存文件


第三部分 更快地移动及跳转

第8章 用动作命令在文档中移动


第9章 在文件间跳转


第四部分 寄存器

第10章 复制与粘贴


第11章 宏


第五部分 模式

第12章 按模式匹配以及按原义匹配


第13章 查找


第14章 替换


第15章 global命令


第六部分 工具

第16章 通过ctags建立索引,并用其浏览源代码


第17章 编译代码,并通过Quickfix列表浏览错误信息


第18章 通过grep、vimgrep以及其他工具对整个工程进行查找


第19章 自动补全


第20章 利用Vim的拼写检查器,查找并更正拼写错误


第21章 接下来干什么

  • 21.1 继续练习
  • 21.2 定制你自己的Vim
  • 12.3 欲善其事,先利其器

附录 A 根据个人喜好定制Vim

  • A.1 动态改变Vim的设置项
  • A.2 将配置信息存至vimrc文件
  • A.3 为特定类型的文件应用个性化设置

未完待续…

第1章 Vim解决问题的方式

《Vim实用技巧(第2版)》技巧1-认识.命令

1. 什么是.命令?

  • 命令(点命令) 可以重复上次的修改
  • 命令是Vim中的瑞士军刀
  • 点命令是一个微型的宏

2. 点命令说的重复的“修改”指的是什么?

  • x 删除一个字符
  • dd 删掉一行
  • >G 缩进

3. 举例

  • 输入daw删除1个单词后,可以按键盘中的.来重复删除后面一个单词(. == daw) 。

4. 点命令有什么优点?

  • 点命令让可以重复的修改变得简单快捷,大大提高了输入效率。

5. 点命令有什么优点?

  • 哪些情况需要使用点命令,这个问题还需要平时练习中多思考总结。
  • 如果你发现自己要在几个地方同样的小修改,就可以尝试构造你的修改,让它能够被 点命令执行。

相关视频

《Vim实用技巧(第2版)》技巧2-不要自我重复

1. 减少无关的移动

  • 在行尾添加内容:使用A而不是$a(A == $a)
    • 用A替换$a 如果是多行操作,大大提升了.命令的效率

2. 一箭双雕的操作

  • C == c$:删除当前位置到行尾的字符并进入插入模式
  • s == cl: 删除当前字符并进入插入模式
  • S == ^C:删除当前行并进入插入模式
  • I == ^i:在行首进入插入模式
  • A == $a:在行尾进入插入模式
  • o == A<CR>:向上插入一行
  • O == ko:向下插入一行

3. 总结

  • 在平时使用vim的过程中可以总结一下,哪些命令可以简化,用更简单的方式操作。
  • 上诉命令是作者给我们总结的一些常用快捷键,理解以后,在平时的练习中多加运用,效率定会大大提高。

技巧3-以退为进

1. 在一个字符前后各添加一个空格,这样可以事半功倍地完成任务。

  • 操作符左右添加空格,例如:用a = b + c; 替代 a=b+c;

2. 使修改可重复

  • 把a = b+c;改成a = b + c;按下面的方法好处是可以重复操作,这样可以用.命令来重复,提高了效率。
f+s + <Esc>

3. 使移动可重复

  • 使用;可以重复上次f命令查找的字符

4. 合二为一

  • 修改a = b+c+d+e; 为a = b + c + d + e;的方法为
f+s + <Esc>;.;.

5. 总结

  • 技巧3主要是给了一个以退为进来构造重复操作的方法;
  • 使用;可以重复上次f命令查找的字符;
  • ;.结合起来能够重复查找替换的操作,能够极大提高效率;
  • 点命令的威力在这里又体现出来了。

《Vim实用技巧(第2版)》技巧4-执行、重复、回退

1. Vim可以重复执行的每个操作以及如何回退这些命令

序号目的操作重复回退
1做出一个修改{edit}.u
2在行内查找下一指定字符f{char}/t{char};,
3在行内查找上一指定字符F{char}/T{char};,
4在文档中查找下一匹配项/patternnN
5在文档中查找上一匹配项?patternnN
6执行替换:s/target/replacement&u
7执行一系列修改qx{changes} q@xu

2. 总结

  • 这一个技巧记录了vim中可以执行的命令,如何重复和回退,记住并在平时多加练习即可。

《Vim实用技巧(第2版)》技巧5-查找并手动替换

1. 偷懒的办法:无需输入就可以进行查找

  • * 选中,n查找下一个,N查找上一个

2. 使修改可重复

  • 进入插入模式然后退出的整个过程都是一个修改,可以用.命令进行重复

3. 合而为一

  • 1和2的组合就可以实现查找替换:n.n.n.
  • 可以是用:%s/a/b/gc 进行询问替换

4. 总结

  • 平时要批量替换时,用:%s/a/b/gc 进行询问替换比较多,以后可以多尝试一下用.命令试试。
  • 如果你有更好的操作方法,欢迎留言一起讨论一下~

《Vim实用技巧(第2版)》技巧6-认识.范式

1. 回归三个 .命令编辑任务

A;<Esc>
j.
f+
s + 
;.
* 
cwcopy
n.

2. .范式(理想模式)

  • 用一次按键移动,另一次按键执行,我们把它叫做“. 范式

3. 总结

  • 构造“.范式”, 用一次按键移动,另一次按键执行,构造重复动作,累积效率就提高了。

第2章 普通模式

技巧7-停顿时请移开画笔

普通模式

  • 把普通模式是Vim的自然放松状态。
  • 普通模式是一种常态。
  • 许多普通模式命令可以再执行时指定执行的次数,这样他们就可以被执行多次。
  • 简单地重复执行一条命令,要比花时间去计算想要执行多少次更好。

停顿时请移开画笔

  • 画家再休息时不会吧画笔放在画布上。

总结

  • 技巧7 告诉我们使用vim记住不要习惯待着插入模式,上一个操作结束后马上回到普通模式。这是个习惯问题。也是提高vim输入效率必须做到的。

技巧8-把撤销单元切成块

1.在vim中我们可以自己控制撤销的粒度

  • 撤销命令:u
  • u会撤销一次修改
  • 一次修改:什么是一次修改呢?前面的技巧里提到了,进入插入模式到,退出插入模式的过程是一次修改。
  • 我们能够控制什么时候进入插入模式,什么时候退出,进而可以控制撤销的粒度
  • 退出插入模式:<Esc> 或Ctrl+[

2. 让每次“可撤销块” 对应一次思考过程

  • 每次修改最好是一个完整的操作,这样撤销也是完整的。

3. 在插入模式中移动光标会重置修改状态

  • 在插入模式中移动光标会重置修改状态,所有不建议在插入模式移动光标,就是说,不用在插入模式耍上下左右键了。老老实实用hjkl吧。

4. 总结

  • 这个技巧就是告诉我们再每次退出插入模式前的修改最好是一个完整修改:一个单词,一个语句,或者一个代码块等等。

技巧9-构造可重复的修改

VimGolf: 整个操作的Vim高尔夫得分

  • 在高尔夫得分相同的情况下,选择可重复的修改作为最优方案。

  • 如下面的例子:光标在h初 需要删除nigh

The end is nigh
  1. 可以用dbx
  2. 可以用bdw
  3. 可以用daw
  • 高尔夫得分相同,但是 daw 可以发挥.命令的重复作用,是最优方案。

结论

  • 想要利用.命令,事先常常需要进行一番周详的考虑。
  • 如果你防线自己要几个地方做同样的修改,就可以尝试构造你的修改,让他们能够被.命令重复执行。
  • 要识别出这类机会需要进行一定的实践,不过一旦养成了使修改可重复的习惯,你就回从Vim这里得到“奖赏”。

技巧10-用次数做简单的算术运算

  1. 大多数普通模式命令可以再执行时指定次数,可以利用这个功能来做简单的算术运算。
  2. <C-a>和<C-x>命令分别对数字执行加和减操作。
  3. 光标移到字符5上,执行10<C-a>就会变成15。
  4. 查看<C-a>Vim帮助文档:h ctrl-a
  5. 想要做如下操作该怎么办呢? 把"background-position:0px 0px" 前面的0px改为-180px。
  • 方案1:先f0查找第一个0,再i-18<Esc>
  • 方案2:180<C-x>
  • 方案1和方案2中,方案2里ctrl-x有查找并修改值的功能,所以可以省了f0的步骤。但是如果是要改后面的0px那么就省不了了。
  1. 008 <C-a>后是多少?
  • 答案是:9
  • 原因:Vim默认吧0开头的数字解释为八进制。
  • 可以在vimrc里面修改为十进制 set nrformats=

技巧11-能够重复,就别用次数

1. 能够重复,就别用次数

  1. 使用次数可以使按键次数变得最少,但是缺点也很明显,我们需要认真考虑次数与重复各自的优缺点。
  2. 例如删掉“Delete more than one word” 想把这段文字改为“Delete one word”
    1. 方案1:d2w或2dw
    2. 方案2:dw.
    3. 方案1与方案2相比,方案2具有更细的粒度。
    4. 如果要删除7个单词是用哪个方案呢? 显然方案1需要先在脑子里面计算,数一数,再按键,方案2就不需要操心。

2. 只在必要时使用数字

1. 例如:I have a couple of questions 改为 I have some more questions 可以使用c3wsome more这个时候个人觉得用数字会更方便一些。

3. 总结

1. 个人觉得使用重复还是次数还是仁者见仁智者见智,具体情况具体分析。
2. 使用重复的好处可以将修改更加细粒度化,方便后面的变更。使用数字的好处是更加快捷,简洁。
3. 当你不知道是该用重复还是次数的时候,只要不是敲的手抖的话,可以优先考虑用重复咯^ v ^

《Vim实用技巧(第2版)》学习笔记:技巧12-双剑合璧,天下无敌

1. 操作符 + 动作命令 = 操作

  • d{motion}命令可以对一个字符、一个完整单词或一整个段落进行操作,它作用的范围是由动作命令决定的。
  • c{motion},y{motion}等被统称为操作符(operator)
  • g、gu、gU命令要用两次按键来调用,g被当做前缀字符,用以改变其后面的按键行为。
  • Vim的语法只有一条额外规则,即:当一个操作符命令被连续调用2次时,他会作用于当前行。例如:
序号命令用途
1dd删除当前行
2cc删除当前行并进入插入模式
3yy复制当前行
4>>缩进当前行
5= =当前行自动缩进
6gUgU(gUU)当前行全转大写
7gugu(guu)当前行全转小写
8g~ g~(g ~ ~)当前行大小写反转
  • Vim的操作符
命令用途
c修改
d删除
y复制到寄存器
g~反转大小写
gu转换为小写
gU转换为大写
>增加缩进
<减少缩进
=自动缩进
!使用外部程序过滤{motion}所跨越的行

2. 自定义操作符与已有动作命令协同工作

  • Tim Pope的commentary.vim,此插件为Vim支持的编程语言增添了注释以及取消注释的命令 命令 | 含义 :-- | :-- gc{motion} | 切换指定行的注释状态 gcap | 切换当前段落的注释状态 gcG | 注释当前行到文件结尾 gcc | 注释当前行

3. 自定义动作命令与已有操作符协同工作

  • Kana Natsuno 的textobj-entire插件,新增2种文本对象:ie和ae。那么gg=G 就可以用=ae替换了

4. 操作符待决模式

  • 在命令dw中,输入d但没有输入w的短暂时间间隔就是操作符待决模式。
  • Esc结束操作符待觉模式

5. 总结

  • 认清Vim一个操作的组成可以帮助我们理解Vim的操作原理,方便我们扩展我们的命令。
  • Vim的操作符要多练习。
  • commentary.vim插件很好用,推荐安装~~
  • 欢迎留言一起学习讨论!

第3章 插入模式

技巧13-在插入模式中可即时更正错误

1. 在插入模式中除了用退格键还可以用下面的命令删除光标下的字符。

按键操作用途
C-h删除前一个字符(同退格键)
C-w删除前一个单词
C-u删除到行首

2. 上面的快捷键在Shell中同样适用。

3. 总结

  • 个人觉得用C-h,C-w,C-u 比用退格键更方便高效。

技巧14-返回普通模式

  • 插入模式只专注于做一件事,那就是输入文字。
  • 普通模式却是我们大部分时间所适用的模式。

1. 插入模式返回普通模式的几种方式

按键操作用途
Esc切换到普通模式
C-[切换到普通模式
C-o切换到插入-普通模式

2. 结识插入-普通模式

  • 插入-普通模式是普通模式的一个特例,他能让我们执行一次普通模式命令,在此模式中,可以执行一个普通模式命令,执行完后,马上又返回到插入模式。
  • 要从插入模式切到插入-普通模式,可以按C-o
  • 插入模式中,让当前行显示在窗口正中间:C-ozz

技巧15-不离开插入模式,粘贴寄存器中的文本

不离开插入模式,粘贴寄存器中的文本

  • yt,复制文本到专用寄存器中
  • C-r0 把复制的文本粘贴到光标所在的位置

对面向字符的寄存器使用C-r{register}命令

  • 如果寄存器中包含了大量的文本,屏幕的更新有些轻微的延时。
  • C-rC-p{register}命令会更智能一些,会修正任何不必要的缩进。
  • 文本内容多的话,不建议使用寄存器了。

总结

  • 技巧15主要是告诉我们,在插入模式中,可以使用寄存器进行复制和粘贴。
  • 具体寄存器用法再后面的技巧中会有更具体的展现。

技巧16-随时随地地做运算

1. 表达式寄存器

  • 可以使用=符合知名使用表达式寄存器
  • 在插入模式中使用<C-r>= 就可以访问表达式寄存器

2. 表达式寄存器的作用

  • 表达式寄存器可以做简单的算术运算
  • 更高级的应用见技巧71(笔记后续添加)

技巧17-用字符编码插入非常用字符

  • Vim可以用字符编码插入任意字符。可以很方便地输入键盘上找不到的符号。
  • 插入模式输入:C-v{code} 其中{code}是要插入字符的编码。
  • Vim接受的字符编码共包含3位数字。 例如A 编码:065 输入:C-v065
  • 插入编码超过3位数的字符 C-vu{code},其中code是16进制的,例如:C-vu00bf
  • 查看字符编码快捷键:光标放在字符上按ga
  • 文本中没有的字符如何知道字符的编码,查unicode表这里有一份
  • C-v字符:插入当前按的字符
按键操作用途
C-v{code}以十进制字符编码插入字符
C-vu{code}以十六进制字符编码插入字符
C-v{nondigit}原义插入非数字字符
C-k{char1}{char2}插入以二合字母{char1}{char2}表示的字符

技巧18-用二合字母插入非常用字符

二合字母(digraph)

  • 插入模式输入<C-k>{char1}{char2}

如何选择组成二合字母的两个字符

  • :h digraphs-default 查看帮助

查看二合字母列表

  • :digraphs 查看可用的二合字母列表
  • :h digraph-table 查看另一个更为有用的列表

技巧19-用替换模式替换已有文本

1. 替换模式

  • 按 R 由普通模式进入替换模式
  • 按 Esc由替换模式回普通模式

2. 用虚拟替换模式替换制表符

  • gR 进入虚拟替换模式
  • 在虚拟替换模式,制表符被当成一组空格进行处理
  • 在可能的情况下,尽量使用虚拟替换模式
  • 单次模式的替换模式以及虚拟替换模式, r{char}和gr{char}命令允许覆盖一个字符,之后马上又回到普通模式。
  • 查看帮助输入:h r

第4章 可视模式

技巧20-深入理解可视模式

深入理解可视模式

  • 你已经熟悉的很多普通模式命令,在可视模式中也能完成相同的功能。
  • 某些可视模式命令执行的基本功能与普通模式相同,但操作上有些细微的变化。
    1. 例如c命令的功能是一样的,都是删除指定的文本并切入到插入模式。但是,指定其操作的范围,二者的方式却不相同。
    2. 在普通模式中,先触发修改命令,然后使用动作命令指定其作用范围。
    3. 在可视模式中,要先选中选区,然后再触发命令。

技巧21-选择高亮选区

激活可视模式

命令用途
v激活面向字符的可视模式
V激活面向行的可视模式
Ctrl-v激活面向列块的可视模式
gv选中上次的高亮选区

在可视模式间切换

按键操作用途
Esc /回到普通模式
Ctrl-[回到普通模式
v / V /切换到普通模式
Ctrl-v切换到普通模式
v切换面向字符的可视模式
V切换面向行的可视模式
Ctrl-v切换面向列块的可视模式
o切换高亮选区的活动端

切换选区的活动端

  • 高亮选区的范围由其两个端点界定。
  • 其中一端固定,另一端可以随光标自由移动,可以用o键来切换其活动的端点。

总结

  • o键的切换选区的活动端使用起来非常方便,之前没有注意到有这个用法,使用起来发现会方便很多。

技巧22-重复执行面向行的可视命令

  • 修改一个面向行的高亮选区,然后使用.命令重复此修改。
  • 当使用.命令重复对高亮选区所做的修改时,此修改会重复作用于相同范围的文本。

技巧23-只要可能,最好用操作符命令,而不是可视命令

  • 可视模式可能比Vim的普通模式操作起来更自然一些,但是有一个缺点:.命令有时候会有一些异常的表现。
  • vit: visually select inside the tag
  • 把括号内的字符都转为大写:
  • step1: vi{
  • step2: U
  • step3: j.
   <html>aaaaaaaaaaaaaaaaaaaaa</html>
   <html>bbbbbbbbbbbb</html>
  • vi{,vi(,vi[ 把括号内的字符都转为大写:
  • step1: vi{
  • step2: U
{Aaaaaaaaaaaaaaaa}
{bbbbbbbbbbbbbbbbbbbb}
(aaaaaaaaaaaaaaa)
[bbbbbbbbbbbbbbbbbbbb]

使用普通模式下的操作符命令

  • gUit,gUi{,gUi[,gUi(

总结

  • 在做一系列可重复的修改时,最好首选操作符命令,而不是可视模式命令。

技巧24-面向列面向列块的可视模式编辑表格数据

  • 使用CTRL-v进入列模式
  • 使用.命令重复
  • 使用x删除列

技巧25-修改列文本

  • jje:选中要操作的选区。
  • c:删除选中选区的文字并进入插入模式。
  • :返回普通模式。

技巧26-在长短不一的高亮块后添加文本

列块可视模式不仅限于操作方形的文本区域。

在长短不一的文本后面添加分号:

var foo = 1
var bar ='a'
var foobar = foo + bar
  • jj$:选中需要修改的区域
  • A;:在选中区域后面加分号";"
  • :退出插入模式返回普通模式

Vim对“i”以及“a”键的约定

  • Vim对于从普通模式切换到插入模式有几个约定。
  • i:插入字符之前
  • a:插入字符之后
  • A:插入行开头
  • A:插入行尾

第5章 命令行模式

  • 技巧30- 在指定范围上执行普通模式命令
    • 如果想在一系列连续行上执行一条普通模式命令,可以用:normal命令。
    • :normal命令与.命令结合能完成大量重复性任务。
    • :%normal A; Vim在文件每行的结尾都添加一个分号。
    • :%normal i// 注释整个文件。
  • 技巧31-重复上次的Ex命令
    • .命令可以重复上次的普通模式命令。
    • @:重复上次的Ex命令。
    • :bn在列表中逐项正向移动。
    • :bp在列表中逐项反向移动。
  • 技巧32-自动补全Ex命令
    • Vim显示可用的补全列表。
    • Tab 依次遍历剩余的补全项。
  • 技巧33-把当前单词插入命令行
  • 技巧34-回溯历史命令
  • 技巧35-运行Shell命令

技巧27-认识Vim的命令行模式

1. 命令行模式

  • 命令行模式提示我们输入一条 Ex 命令、一个查找模式或一个表达式。
  • 按下: 键时,Vim会切换到命令行模式。
  • 按<Esc> 退回到普通模式。
  • 在命令行模式中执行的命令被称为 Ex 命令。
  • 可以用Ex命令读写文件(:edit 和:write)
    • 创建新标签页(:tabnew)
    • 分隔窗口(:split)
    • 操作参数列表(:prev/:next)
    • 操作缓冲器列表(:brev/:bnext)
    • Vim为几乎所有功能都提供了相应的Ex命令(参见:h ex-cmd-index)

2. 操作缓冲区文本的Ex命令

命令用途
:[range]delete [x]删除指定范围的行[到寄存器x中]
:[range]yank [x]复制指定范围的行[到寄存器x中]
:[line]put [x]在指定行后粘贴寄存器x中的内容
:[range]copy {address}把指定范围内的行拷贝到{address}指定的行之下
:[range]move {address}把指定范围内的行移动到{address}指定的行之下
:[range]join连接指定范围内的行
:[range]normal {command}对指定范围内的每一行执行普通模式命令{command}
:[range]substitute/{pattern}/{string}/[flags]把指定范围内出现{pattern}的地方替换为{string}
:[range]global/{pattern}/[cmd}对指定范围内匹配{pattern}的所有行执行Ex命令{cmd}

3. Vim命令行模式中的特殊按键

  • 有些命令在插入模式和命令行模式可以通用
命令含义
C-w删除到上一个单词
C-u删除到行首
C-v键入字符
C-k键入字符
C-r{register}把任意寄存器的内容插入到命令行

4. Ex 命令影响范围广且距离远

  • Ex 命令拥有能够在多行上同时执行的能力。

技巧28-在一行或多个连续行上执行命令

  1. 用行号作为地址
  2. 用地址指定一个范围
  3. 用高亮选区指定范围
  4. 用模式指定范围
  5. 用偏移对地址进行修正

技巧-29 ‘:t’和‘:m’复制和移动行

:[range]copy {address}
  • :copy命令简写为:co或:t。
  • :move可以把一行或多行移到文档的其他地方。

:t的一些实例

  • :6t. 把第6行复制到当前行下。
  • :t6 把当前行复制到第6行下。
  • :t. 为当前行创建一个副本。
  • :t$ 把当前行复制到文本结尾。
  • :'<,'>t0 把高亮选中的行复制到文件开头。

用‘:m’ 命令移动行

:[range]move {address}
  • :move 简写为:m。
  • :'<,'>m$ 把高亮选中的文本移动到文件末尾。

技巧33-把当前单词插入命令行

  • 在Vim的命令行下,复制光标下的单词并插入命令行。
  • :%s//linux/g 把光标下的单词换成linux
  • :%s//linux/g 把光标下的字串换成linux

技巧34 回溯历史命令

  • Vim会记录命令行模式中执行过的命令。
  • Vim提供了2种方式回溯这些命令。用光标键回滚之前的命令或调出命令行窗口查看先前的命令。
  • 来回溯历史命令。
  • Vim缺省会记录最后20条命令。
  • 在.vimrc中添加相关配置修改记录历史命令行数
set history=200
  • q: 打开Ex命令行窗口
  • q/ 打开查询命令行窗口
  • 命令行从命令行模式切换到命令行窗口

技巧35-运行Shell命令

  • 不用离开Vim就能方便的调用外部程序。
  • 还可以吧缓冲区的内容作为标准输入发送给一个外部命令,或者吧外部命令的标准输出倒入缓冲区里。

执行Shell中的程序

  • 在Vim的命令行模式中,给命令加一个感叹号前缀就可以调用外部程序。

    • 例如查看当前目录的内容:
    :!ls
    
    • 执行一次性命令:!{cmd}
    • :shell 启动一个交互的shell会话。
    :shell
    
    • exit退出交互shell返回Vim.
    $exit
    
    • 把Vim置于后台
    Ctrl-z
    
    • fg命令返回挂起前的状态。
    $fg
    
    • jobs查看挂起进程。
    $ jobs
    [1]  + suspended  vim README.md
    
    

把缓冲区内容作为标准输入或输出

  • :read !{cmd} 命令把命令的标准输出读入到当前缓冲区中。
  • :write !{cmd} 命令把缓冲区内容作为指定{cmd}的标准输入。

技巧36-批处理运行Ex命令

  • 将需要批量执行的Ex命令保存到文件batch.vim
cat batch.vim
global/href/join
vglobal/href/delete
%normal A: http://vimcasts.org
  • 使用:source 命令执行batch.vim
:source batch.vim
  • args 命令查看vim的参数
:args
  • 使用argdo批量执行命令
:argdo source batch.vim

第6章 管理多个文件

技巧37-用缓冲区列表管理打开的文件

1. 了解文件与缓冲区的区别

  • 文件存储在磁盘上,而缓冲区存在于内存中。
  • 绝大多数Vim命令都是用来操作缓冲区,不过也有一些命令针对文件进行操作。

2. 结识缓冲区列表

  • Vim允许同时在多个缓冲区上工作。
  • :ls 查看缓冲区列表。
  • :bnext 切换到下一个缓冲区。
  • % 符号指明哪个缓冲区在当前窗口中可见。
  • # 符号则代表轮换文件 <C-^>可以在当前文件和轮换文件之间快速切换。

3. 使用缓冲区列表

命令含义
:bprev/bp在列表中反向移动
:bnext /bn在列表中正向移动
:bfirst跳到列表的开头
:blast跳到列表的结尾
:buffer N跳转到编号为N的缓冲区
:ls查看所有缓冲区
:bufdo在所有缓冲区执行 Ex 命令(参见:h bufdo)
:bdelete/bd N1 N2 N3删除缓冲区N1 N2 N3
:N,M bdelete/bd删除N到M编号的缓冲区

删除缓冲区

  • bdelete

技巧38-用参数列表将缓冲区分组

  • 用:argdo命令可以在参数列表中的每个文件上执行一条Ex命令。
  • :args 查看参数列表。
:args {arglist}
  • 用文件名指定文件
:args index.html app.js
:args
[index.html] app.js
  • 用Glob模式指定文件
:args *.*     匹配index.html app.js
:args **/*.js 匹配app.js lib/framework.js
:args **/*.js 匹配index.html app.js lib/framework.js
  • 构造个之包含.js和.css文件,但不包含其他文件类型的参数列表。
:args **/*.js **/*.css
  • 用反引号结构指定文件
cat .chapters
a.pml
b.pml
c.pml
d.pml
:args `cat .chapters`
  • 使用参数列表
:args {arglist} 清空重置参数列表
:next,:prev 命令遍历参数列表中的文件。
:argdo 命令在列表中的每个缓冲区上执行同一条命令。

技巧39-管理隐藏缓冲区

  • 查看缓冲区列表
:ls
1 #a + "README.md"                    line 2 
4 %a   "inject_test.lua"              line 6 
  • 缓冲区列表前有一个+号,表示这个缓冲区被修改过了。
:ls 
1 %a + "README.md"                    line 2 
  • :bnext!强制切换缓冲区(README.md切换到inject_test.lua)
  • inject_test.lua被标记为a,表示它是活动缓冲区(active)
  • README.md别标记为h,表示它是一个隐藏缓冲区(hidden)
:bnext!
:ls
1 #h + "README.md"                    line 2
4 %a   "inject_test.lua"              line 7 

在退出时处理隐藏缓冲区

  • quit退出时会提示
:quit
E37: No write since last change 
E162: No write since last change for buffer "README.md"       
Press ENTER or type command to continue
  • 按任意键后会加载第一个有改动的隐藏缓冲区。这里会加载README.md
  • :write 可以保存缓冲区,:edit!可丢弃修改,没有隐藏缓冲区时:q关闭Vim。
:write
:edit!
:q
  • 退出Vim不检查未保存的修改
qall!
  • 保存所有改动的缓冲区,无需逐个检查
:wall

运行‘:*do’命令前,启用‘hidden’设置

  • 启用了'hidden'选项就可以不带末尾的感叹号来执行:next、:bnext、:cnext。
:argdo
:bufdo
:cfdo

技巧40-将工作区切分成窗口

创建分割窗口

<C-w>s 水平切分当前窗口
<C-w>v 垂直切分当前窗口
:sp[lit] 水平切分当前窗口
:vsp[lit] 垂直切分当前窗口
  • 将缓冲区载入活动窗口中
:edit {filename}

在窗口间切换

<C-w>w 在窗口间循环切换
<C-w>h 切换到左边的窗口
<C-w>j 切换到下面的窗口
<C-w>k 切换到上面的窗口
<C-w>l 切换到右边的窗口
<C-w><C-w> 同<C-w>w

关闭窗口

:clo[se] 或 <C-w>c  关闭活动窗口
:on[ly] 或 <C-w>o  只保留活动窗口

改变窗口大小及重新排列窗口

<C-w>= 使用所有窗口等宽、等高
<C-w>_ 最大化活动窗口的高度
<C-w>| 最大化活动窗口的宽度
[N]<C-w>_ 把活动窗口的高度设为[N]行
[N]<C-w>| 把活动窗口的宽度设为[N]列

技巧41-用标签页将窗口分组

如何使用标签页

  • lcd
:lcd {path}
  • lcd 命令设置当前窗口的本地工作目录。
  • windo lcd {path} 为所有窗口设置本地工作目录。
:windo lcd {path}

打开及关闭标签页

  • tabedit 命令可以打开一个新的标签页
:tabedit {filename} 或 :tabe {filename}
  • 把当前窗口移到一个新标签页中
<C-w>T
  • 查看帮助
:h CTRL-W_T
  • 关闭此窗口以及包含此窗口的标签页
:close
  • 关闭当前标签页
:tabclose 或 :tabc
  • 只保留活动标签页
:tabo[only]
  • 在标签页间切换,标号从1开始
{N}gt
:tabn[ext] {N}
  • 切换到下一个标签页
gt
:tabn[ext]
  • 切换到上一个标签页
gT
:tabp[revious]

重排标签页

  • 用:tabmove [N] 命令可以重新排列标签页。
  • 当[N]为0时,当前标签页会被移动到开头。
  • 如果省略了[N],当前标签页会被移动到结尾。
  • 如果终端支持鼠标,或是正在使用GVim,那么也可以通过鼠标拖拽来进行重排操作(不推荐)。

总结

  • 标签页平时使用的不多。
  • 如果遇到多个项目需要使用vim的情况,我通常是:
  • 使用tmux开启多个pannel或session。
  • 或者使用i3分屏解决。
  • 开启多个terminal。
  • 在i3和tmux都没有的情况,标签页是可以起到很大作用的。虽然用得不多,但是需要的时候还是可以减少不少不必要的麻烦的。

返回《Vim实用技巧(第2版)》学习笔记:汇总

  • 扫描下方二维码,关注我的公众号,获取更多技术方面的知识 在这里插入图片描述

第7章 打开及保存文件

技巧42-用:edit命令打开及保存文件

1. 相对于当前工作目录打开一个文件

  • :edit {file} 命令可以接受相对于工作目录的文件路径

2. 相对于活动文件目录打开一个文件

  • :edit %:h <Tab> M <Tab><Tab>
  • %符号代表活动缓冲区的完整文件路径。
  • :h 修饰符会去掉文件名,但保留路径中的其他部分(参见 :h ::h)

技巧43-使用:find打开文件

配置'path'选项

:set path+=app/**
  • ** 通配符会匹配app/目录下的所有子目录。
  • 使用rails.vim进行只能路径管理。

使用:find命令,通过文件名查找文件。

:find Navigation.js
  • 使用Tab
:find Main.js<Tab>

技巧44-使用netw管理文件系统

结识netrw--Vim原生的文件管理器

  • Vim打开当前目录
vim .
  • vim返回上一级目录
-
或光标移动到..上按<CR>
  • 使用 :edit {path}命令打开文件管理器窗口
:edit . 或 e . 在文件管理器里打开工程的根目录。
  • 在文件管理器里打开当前目录
:edit %:h
  • 打开文件管理器并显示活动缓冲区所在目录
:Explore 或:E
  • 在一个水平切分窗口及打开文件管理器
:Sexplore
  • 在一个垂直切分窗口打开文件管理器
:Vexplore

与分割窗口协同工作

  • 调出文件管理器后想返回原来正在编辑的文件
<C-^>

技巧45-把文件保存到不存在的目录中

  • 创建了一个缓冲区 a/test.md
:edit a/test.md
  • 如果目录a不存在保存会报错
:write 无法保存
  • 使用下面命令可以解决问题
:!mkdir -p %:h 其中%代表活动缓冲区的完整文件路径,:h修饰符会去除文件名 -p是创建不存在的中间目录。

技巧46-以超级用户权限保存文件

  • 修改一个需要sudo文件权限的文件时是无法保存的,保存的方法是:
vim /etc/host
:w !sudo tee % > /dev/null
  • 只有学会让手不离开本位行就可以移动光标,才能更快地操作Vim。
  • 用hjkl来移动光标。
h 左移一列
l 右移一列
j 下移一行
k 上移一行

让右手待在它该在的位置上

  • 在Qwerty键盘上,j、k、和l键刚好在右手的食指、中指和无名指下方。
  • 戒掉使用光标键的习惯。
  • 可以把光标键映射为什么都不做。
noremap <Up>  <Nop>
noremap <Down>  <Nop>
noremap <Left>  <Nop>
noremap <Right>  <Nop>

技巧48-区分实际行与屏幕行

wrap设置开启

  • wrap设置开启时,每个超出窗口宽度的文本行都会被会绕显示,以爆炸呢个没有文本现实不出来。

启用number来查看实际行与屏幕行之间的不同。

实际行与屏幕行的移动

  • jk在实际行之间移动。
  • 0移动到实际行的行首。
  • ^移动到实际行的第一个非空白字符。
  • gj和gk在屏幕行间移动。
  • g0移动到屏幕行的行首。
  • g$移动到屏幕行的行尾。
  • g^移动到屏幕行的第一个非空白字符。

技巧49-基于单词移动

  • 一组基于单词的动作命令
w 正向移动到下一单词的开头(forword)
b 反向移动到当前单词/上一单词的开头(back-word)
e 政协移动到当前单词/下一单词的结尾
ge 反向移动到上一单词的结尾
  • ea命令连在一起可以解读为在当前单词结尾添加。
  • gea命令连在一起可以解读为在上一个单词结尾添加。

理解单词与字串

  • 单词word :h word查看帮助
  • 字串WORD :h WORD查看帮助
  • 下面一行有10个单词5个字串
e.g. we're going to slow
  • 上面的句子如果是基于单词的移动就很慢了。w命名显得很吃力。
  • 如果是基于字串的移动,用更少的按键就可以达到同样的效果。
  • 光标在行手WW将跳转到going的首字母。
  • 光标在we的w上,想把we're改为it's的操作是
cWit's
  • 如果想更快地移动用基于字串的移动:W
  • 如果想更细力度地移动用基于单词的移动:w

技巧50-对字符进行查找

  • f{char} 命令是在Vim中移动的最快的方式之一。

  • 如果找到了,就会把光标移动到此字符上。

  • 如果未找到,则保持光标不动。

  • 参考:h 。

  • ; 重复之前的查找。

  • ,退回上次查找。

  • F{char} 反向查找上一个{char}

  • t{char} 正向查找下一个{char}之前

  • T{char} 反向查找上一个{char}之后

想Scrabble玩家那样思考

  • 下面的例子,光标在一行开头I处,想要找到excellent并删除,怎么做更好?
Improve your writing by deleting excellent adjectives.
  • 方法1:
fe;;dw
  • 方法2:
fxdaw
  • 把x作为目标查找字符更佳。

总结

  • 在使用字符查找命令时,最好是选择出现频率比较低的字母作为目标字符。

技巧51-通过查找进行移动

  • f{char}可以移动但是具有局限性。
  • 一次查找一个字符。
  • 只能在一行。
  • 使用/查找tasks这个单词。
  • n命令重复上次查找,N命令反向查找。
/tasks<CR>
  • 启用hlsearch功能,以便高亮匹配项。

查找动作操作文本

  • 在可视模式将选区扩大到到get
v/get<CR>
  • 删除到查找的文本get:d/get
hello cfanzp.
get cfanzp and me.
d/get<CR>
删除后的文本:
hello get cfanzp and me.

技巧52-用精确的文本对象选择区域

  • 文本对象允许操作括号、被引用的文本、XML标签以及其它文本中常见结构。
  • 光标在{}内,想高亮{}内的内容:
vi}
  • 选中由双引号括起来的字符范围:
va"
  • 选中由双引号括起来的字符范围:
vi"
  • vi"和va"的区别是前者不包含分隔符后者包含。
  • 类似操作还有:
a) ab
a} aB
a]
a>
a'
a"
a` 一对反引号
at 一对XML标签

i) ib
i} iB
i]
i>
i'
i"
i` 一对反引号
it 一对XML标签

用文本对象执行操作

  • 只有操作符待决模式中使用文本对象,才能真正展现出他们的能力。
  • 可以在可视模式以及操作符待决模式中使用文本对象。
  • 每当在命令语法里看到{motion}时,也可以在这个地方使用文本对象。常见的例子:
d{motion}
c{motion}
y{motion}
  • c{motion}:删除指定文本,然后切换到插入模式。
  • 例如把abcd换成hello的操作为:ci"hello
text::
like "abcd"
opt:
ci"hello<Esc>

结论

  • 这些命令都只需要3次按键。都采用了技巧12中提到的简单语法规则。

技巧53-删除周边,修改内部

文本对象分为2类:

    1. 操作分隔符的文本对象:i),i",it 称为:分隔符文本对象,Vim文档称:块对象
    1. 操作文本块,入单词,句子和段落 称为:范围文本对象,Vim文档称:非块对象
  • 范围文本对象,i:可理解为inside,a可理解为around,iw:inside the word,aw:around the word
iw 当前单词
aw 当前单词及一个空格
iW 当前字串
aW 当前字串及一个空格
is 当前句子
as 当前句子及一个空格
ip 当前段落
ap 当前段落及一个空格

总结

  • daw,ciw,d{motion}与aw,as和ap配合,c{motion}与iw及类似文本对象一起用效果会更好。

技巧54-设置位置标记,以便快速跳回

  • m{a-zA-z} 命令会用选定的字母标记当前光标所在位置。(参见:h m)
    • '{mark} 命令跳转到位置标记所在行,并把光标置于该行第一个非空白字符上。
    • `{mark} 命令跳转到位置标记所在处。
    • mm和`m:设置标记m和跳转到标记m。

自动位置标记

```
`` 当前文件中上次跳转动作之前的位置
`. 上次修改的地方
`^ 上次插入的地方
`[ 上次修改或复制的起始位置
`] 上次修改或复制的结束位置
`< 上次高亮选区的起始位置
`> 上次高亮选区的结束位置
```

技巧55-在匹配括号间跳转

  • % 命令允许在一组开、闭括号间跳转(参见:h %),可作用于:(),{},[]。
  • matchit 插件增强%
  • vimrc开启matchit
set nocompatible
filetype plugin on
runtime macros/matchit.vim

surround.vim插件

  • S" 命令用一对双引号报选中的文本括起来
S"
s)
s}
  • cs]} 命令把] 修改为}

技巧56-遍历跳转列表

跳转列表

  • 动作命令在一个文件内移动,跳转则可以在文件间移动。
  • jumps查看
:jumps
  • 每次上下移动一行不算跳转。
  • 任何改变当前窗口中活动文件的命令,都可以被陈伟跳转命令。
  • 正在使用分割窗口或多标签页,那么命令会始终在当前活动窗口的跳转列表范围内进行跳转。

技巧57-遍历改变列表

  • 查看改变列表
:changes
  • changes列表中的change id 为0的为当前修改的位置。
  • 正向遍历changes列表列表(changes列表向下)
g,
  • 反向遍历changes列表,从最近一次修改开始遍历。(changes列表向上)
g;
  • 跳到上次更改过的地方
g;

标识上次修改方位的位置标记

  • . 标记总是指向上次修改的位置 (:h .)
  • ^ 标记则会记录上次退出插入模式时光标所在的位置(:h ^)
  • gi 如果先退出插入模式,接着有在文档中四处移动,然后又想快速回到退出的地方继续编辑时,用gi命令就行了,此命令会用`^标记恢复光标位置,并切换到插入模式,这是省时省力的好办法。(:h gi)
  • Vim会为编辑会话中的每个单独缓冲区维护一个改变列表,而与之不同的是,每个窗口都会创建一个单独的跳转列表。

总结

  • 下面这些技巧有必要记住,省时省力
  • g; 跳转到上一个修改过的地方
  • g,跳转到下一个修改过的地方
  • `^ 标记上次插入的位置
  • gi:跳转到上次插入的位置,并且进入插入模式

技巧58-跳转到光标下的文件

  • Vim会吧文档中的文件名当成一个超连接。正确配置后,就可以用gf命令跳转到光标下的文件了。
  • gf 可以想成 go to file (:h gf)

指定文件扩展名

  • 添加.lua扩展名支持
:set suffixesadd+=.lua

指定要搜寻的目录

  • 查看path的值
set path?
  • 目录含义
. 代表当前文件所在目录
,, 空字符串(由2个连着的逗号界定):代表工作目录
  • 与gf类似命令Ctrl+]
  • Ctrl+] 是基于ctags在文件间跳转,需要确保tags文件是最新的。
  • 具体介绍ctags和Ctrl+] 可以看技巧103,和技巧104。

总结

  • 使用gf在当前窗口跳转,或CTRL-M CTRL-F分屏打开
  • 使用CTRL-o跳转回来,CTRL-^来回跳转,CTRL-i往后跳。

技巧59-用全局位置标记在文件间快速

  • 全局位置标记是一种书签,让我们可以在文件间跳转。
  • m{letter} 在当前光标位置创建一个位置标记(:h m查看帮助)。
  • {letter}命令使光标快速回到标记所在之处(:h 查看帮助)。
  • 默认情况下,全局标记在2次编辑会话之间仍然会保留(这个是可以配置的:h 'viminfo'查看)。

在浏览代码前先设置一个全局标记

  • 当需要浏览一些文件,然后再快速跳回到原处时,全局标记会显得特别有用。

  • eg:

  • 我们正在编码,想找到代码中所有出现DLOG函数的地方,用:vimgrep(安装了ag插件可以用Ag)。

  • 默认情况下,:vimgrep会直接跳到它所找到的第一处匹配上,可能会切换到另外一个文件。可以用Ctrol-o命令回到执行:vimgrep之前的位置。

  • 假如已经遍历了几个查找项,想回到之前的位置,怎么做呢?多按几次Ctrl-o反向遍历。但是会比较麻烦。

  • 更好的选择是:在调用vimgrep之前,先执行mM,在想回来的时候执行`M。

  • 标记当前位置为M

mM
  • 跳转到标记M
`M

需要养成习惯:

  • 在使用与quickfix列表有关的命令前,如:grep、vimgrep、make、Ag等,先设置全局标记。
  • 在执行与缓冲区列表或参数列表有关的命令前,如:args {arglist},argdo,也要设置全局标记。
  • 总共可以设置26个全局位置标记,足够用了,可以毫无顾及地用。

技巧60-用无名寄存器实现删除、复制与粘贴操作

1. 调换字符

  • 将“Practica lvim”改为“Practical vim”,操作如下,其中xp:吧空格字符剪切下来,放入无名寄存器,最后p将无名寄存器的内容贴到光标后面。
f空格
xp
  • xp: 调换光标之后的两个字符。

2. 调换文本行

  • ddp:调换当前行和它的下一行。

3 . 创建文本行的副本

  • yyp:复制当前行粘贴到下一行。

4. diw 会删除当前单词,放入无名寄存器中

技巧61-深入理解Vim寄存器

  • 引用一个寄存器
  • Vim的删除、复制与粘贴命令都会用到众多寄存器中的某一个。
  • 可以同时给命令加"{register}前缀的方式指定要用的寄存器。若不指明,Vim将缺省使用无名寄存器。
  • Vim 剪切复制与粘贴对应的术语:delete,yank与put。

一些寄存器的例子

  • 把当前单词复制到a寄存器中
"ayiw
  • 把当前整行文本剪切至寄存器b中。
"bdd
  • 把b寄存器的内容粘贴出来
"bp

无名寄存器("")

  • 倘若没有指定要使用的寄存器,Vim将缺省使用无名寄存器。

  • 无名寄存器用双引号表示(:h quote_quote)。

  • ""p等同于p

  • x、s、d{mition}、c{motion}、与y{motion}命令(以及它们对应的大些命令)都会覆盖无名寄存器中的内容。

  • x和d{motion}应该被理解为剪切命令更合适,它们会覆盖无名寄存器的内容。

复制专用寄存器("0)

  • 当使用y{motion}寄存器时,要复制的文本不仅会被拷贝到无名寄存器中,而且也被拷贝到了复制专用寄存器中,后者可以用数字0加以引用。(:h quote0)
  • 复制专用寄存器,仅当使用y{motion}命令时才会被赋值。
  • 使用 "0P 复制出复制专用寄存器中的内容。

查看寄存器的内容

  • 查看所有寄存器的内容
:reg
  • 查看复制专用寄存器的内容
:reg "0

有名寄存器("a-"z)

  • 查看a寄存器内容
reg a

黑洞寄存器

  • 黑洞寄存器可以用下划线引动它。
  • 如果只想删除文本却不想覆盖无名寄存器中的内容时,此命令很官用。

系统剪贴板("+) 与选择专用寄存器("*)

  • Vim的加号寄存器与系统剪贴板等效,可用+号引用。
  • "+p命令将其粘贴到Vim内部。
  • 插入模式下用Ctrl-r+将其粘贴到Vim内部。
  • 如果在Vim的复制或删除命令之前加入"+,相应的文本将被捕获至系统剪切板。
  • X11视窗系统支持另一种被叫做主剪切板(primary)的剪贴板,它保存着上次被高亮选中的文本,可以用鼠标中键把他们粘贴出来。
  • Vim的星好寄存器对应主剪贴板,可以用*号加以引用。
  • "+ X11剪贴板,用剪切、复制与粘贴命令操作。
  • "* X11主剪贴板,用鼠标中键操作。
  • X11剪贴板的功能可在编译Vim时被激活或禁用。
  • 运行:version命令,然后找到xterm_clipboard关键字,如果前面有个减号,就表示不支持。

其它寄存器

  • 可以显式地使用删除与复制命令来设置有名、无名以及复制专用寄存器的内容。
  • 只读寄存器:Vim还提供了几组可被隐式赋值的寄存器。
"% 当前文件名
"# 轮换文件名
". 上次插入的文本
": 上次执行的Ex命令
"/ 上次查找的模式
  • 以技术上讲,"/寄存器并非只读,可以用:let命令对其进行显式赋值。

技巧62-用寄存器中的内容替换高亮选区的内容

  • 在可视模式下使用p命令时,Vim将用指定的寄存器内容来替换高亮选区中的文本。
  • 可以解决弄丢了复制内容的问题
  • 把删除和粘贴合成了一步,不需要先删除高亮选区的内容再粘贴。
  • 无名寄存器的内容和高亮选区的内容通过p命令交换了。

交换2个词

  • eg:光标在I处将chips and fish 换成:fish and chips
  • m{char}负责设置标记,{char}负责跳转到该标记。更多信息可以参考技巧54
{start} I like chips and fish
fc: 光标跳到chips的c处
de: 剪切chips
mm: 当前位置标记为m
ww(或ff):光标跳到fish的f处
ve:选中可视模式选中fish
p:交换选中的词与无名寄存器中的chips,选中部分变成chips,无名寄存器中变成fish
`m:跳到标记m处
p:粘贴无名寄存器的内容fish

技巧63-把寄存器的内容粘贴出来

  • p命令将寄存器中的文本粘贴到光标之后。
  • P命令奖寄存器中的文本粘贴到光标之前。

粘贴面向字符的区域

  • 在普通模式用p或P。
  • 在插入模式用Ctrl-r{register}
  • 这种方式,寄存器中的文本总会被插入光标之前,就像我们在插入模式下手动输入一样。
  • Ctrl-r0 插入复制专用寄存器的内容
  • Ctrl-r" 插入无名寄存器的内容

粘贴面向行的区域

  • 当要粘贴的内容来自于面向行的寄存器时,p和P命令会把他们粘贴至当前行的上衣行或下一行。
  • gp,和gP作用同p,P,区别:将光标移动到粘贴出来的文本结尾而不是开头。
  • 当复制多行文本时,gP命令尤其管用。

结论

  • p与P命令对于粘贴多行文本区域非常重要。
  • 对于小段的面向字符的文本来讲,使用Ctrl-r{register}映射项的方式会更直观。

技巧64-与系统剪贴板进行交换

了解你所用系统的剪贴命令

  • 在OS X中,Cmd-v映射会触发系统粘贴命令。
  • 在Windows,Linux中比较复杂。
  • Ctrl-v是系统粘贴命令的标准映射项。
  • 普通模式下Ctrl-v会激活Visual-Block模式。
  • 在插入模式下,它允许插入字符本身或字符编码。

在插入模式下使用系统粘贴命令。

  • 'autoindent'选项被启用,当创建新行时,Vim都会保持同级缩进。这样剪贴板复制过来会导致一行比一行往右偏。
  • paste选项允许手动通知Vim要使用系统粘贴命令了。
  • paste选项启用后,Vim将禁用所有插入模式下的映射项和缩写,并重置很多选项,其中就包括autoindent。
  • 关闭paste:
:set paste!
  • paste选项启用后,在Vim插入模式下创建自定义映射项的方法都失效了。作为替代方案,可以把pastetoggle选项映射成一个功能键。
:set pastetoggle=<f5>
  • 请试着在命令行窗口执行以上命令,用f5来切换paste,在插入模式和普通模式下都能用。
  • 可以把上面的配置命令拷贝到自己的vimrc文件。

为避免切换"paste"选项,请使用加号寄存器进行粘贴。

  • 如果Vim是已集成系统剪贴板的版本,就可以完全避免与paste选项打交道了。
  • Vim集成了系统剪贴板的情况下,普通模式下的"+p命令用来粘贴加号寄存器中的内容,即系统剪贴板的镜像。
  • 更多细节,请参见系统剪贴板("+)与选择专用寄存器("*).
  • Vim集成了系统剪贴板的情况下,无论paste与autoindent选项激活与否,该命令都能保证位于剪贴板中的文本缩进不会乱套。

技巧65-宏的读取与执行

把命令序列录制成宏

  • qa 开始录制宏并将其内容保存至寄存器a中。
  • 按q 停止录制。
  • :reg a 查看 a寄存器中的内容。

通过执行宏来回放命令序列

  • 可以用@{register}命令执行指定寄存器的内容。
  • 用@@来重复最近调用过的宏。

以串行方式执行宏

  • 相互影响 例子:技巧68

以并行方式执行宏

  • 互不影响 例子:技巧70

技巧66-规范光标位置、直达目标以及中止宏

  • 黄金法则:在录制一个宏时,要确保每条命令都可被重复执行。

规范光标位置

  • 应该把光标移动到下一处查找匹配项(n),或是当前行的行首(0),又或是当前文件的行首(gg).
  • 如果每次总是从确定的位置开始执行的话,那么命中正确的目标会变得更容易。

用可重复的动作命令直达目标

  • 面向单词的动作命令,如:w,b,e和ge
  • 推荐用查找命令定位定位,或用文本对象。
  • 尽量使你的宏兼具灵活性与重复性。
  • 录制宏的过程中禁止用鼠标。

当动作命令失败时,宏将中止执行。

  • Vim的动作命令可能会执行失败。Vim缺省会发出哔地一声。可以设置visualbell关闭提示音。
  • 如果宏执行动作命令失败了,Vim将中止执行宏的其余命令。

技巧67-加次数回放宏

  • 不用精确计算宏的次数,估算一个足够大的次数。 作者通常是用22这个数字,2与@字啊用一个键上,容易输入。
  • 在下面行每个+号左右加上空格
  • 录制宏qqf+s + jkq
  • qq:录制宏保存在q寄存器里
  • f+:查找+号
  • s:删除+号并进入插入模式
    • :输入"空格+空格"
  • jk::退出插入模式(也可以用<Esc>)
  • q:退出宏录制
  • 22@q
x="("+a+","+","+b+","+c+","+d+","+e+")";

技巧68-在连续的文本行上重复修改

  • 对于多行范围内的重复性改动,可以先录制一个宏。然后再在没一行上回放,这将会极大减轻我们的工作量。
  • 该功能可用串行或并行两种执行宏的方式实现。

demo1

  • 目标文本
1. one
2. two
3. three
4. four
  • 转换后的文本
1) One
2) Two
3) Three
4) Four

录制工作单元。

  • 先在第一行上做出修改,并将其录制下来。
qa 开始录制宏保存到a寄存器
0f. 将光标先放在行首,查找.符号
r) 将.替换成)
w~ w移动大下一个单词的首字母 ~大小写反转
j 跳转到下一行
q 结束宏录制
3@a 调用宏3次。
  • 并行方式1:使用可视模式选择选区。
VG: normal @a
  • 并行方式2:使用行号指定范围执行宏命令。
:2,4 normal @a

demo2

  • 目标文本
1. one
2. two
//test
3. three
4. four
  • 转换后的文本
1) One
2) Two
//test
3) Three
4) Four
  • demo2如果使用demo1中的串行方式允许到test相应行就会出错,这个时候需要用并行方式。

决策:串行还是并行?

  • 串行或者并行,哪种方式更好呢?答案是看情况。
  • 以并行的方式在多处执行更为健壮。
  • 如果在执行时遇到一处错误,而我们正想利用这些警告更正错误时,以串行、多次的方式执行宏可以更容易定位出问题所在。
  • 在掌握这2种技术后,可以自己判断在哪种情况下应该使用哪种方式了。

总结

  • 基础知识点回顾
  • qa 录制宏保存在a寄存器
  • q结束录制宏
  • 3@a 3次调用寄存器a里面的宏
  • 0跳到行首
  • f. 查找字符.
  • r) 替换当前字符为)
  • w 向前移动一个字符
  • ~ 字符大小写反转
  • j 向下移动一行
  • :2,4 normal @a 底行模式在2到4行执行命令寄存器a中保存的宏
  • VG 进入可视模式选择行从当前行到最后一行
  • 使用串行还是并行,具体看情况而定。

技巧69-给宏追加命令

  • 在录制宏的过程中可能会漏掉某个步骤。在这种情况下,没必要重头开始录制,可以在现有宏的结尾附加额外的命令。
  • 如果是在结尾缺少命令可以附加,如果是在中间或前面就不能了。
  • 追加到a寄存器的方法:例如需要追加j
qA
j
q
  • 追加到q寄存器的方法:例如需要追加j
qQ
j
q

结论

  • 这条技巧可以让我们在没录制完就不小心按了q结束了的情况下可以继续录制。
  • 如果是在宏的开头或者中间的某个位置添加内容,技巧72中,将学习一种更好的方法,用于修改改已录制好的宏。

技巧70-在一组文件中执行宏

建立目标文件列表

:args *.lua
  • 显示参数列表中的内容
:args

录制宏

  • 在开始录制前,首先要确保光标已经位于参数列表中的第一个文件中
:first
  • 正常录制宏

以并行方式执行此宏

  • 先丢弃录制宏时的修改,防止批量执行时对第一个缓冲区执行了2次。
:edit!
  • 执行宏
:argdo normal @a

以串行方式执行宏

qA 追加宏录制
:next 打开下一个缓冲区文件
q 结束宏录制
22@q 批量运行宏

保存所有文件的改动

  • 方法1
:argdo write
  • 方法2
:wall
  • 方法3
qA
:wnext
q

结论

  • 多个缓冲区执行宏的时候,串行的方式比并行的更好一些,出错了,更容易发现。

技巧71-用迭代求值的方式给列表编号

在每行加入连续的数字

  • 修改前文本
aaa
bbb
ccc
ddd
eee
  • 修改后文本
1) aaa
2) bbb
3) ccc
4) ddd
5) eee

方法1,利用快捷键

Ctrl-a:数字+1
Ctrl-x:数字-1

方法2,利用寄存器,基于Vim的脚本

:let i=0
:let i += 1
:echo i
  • 插入变量i的值:
<Ctrl-r>=i<CR>
  • 录制宏
:let i=1
qa
I<Ctrl-r>=i<CR>)<Esc>
:let i+= 1
q
  • 执行宏
jVG
:`<,`>normal @a

技巧72-编辑宏的内容

将宏粘贴到文档中

  • put
G 跳到最后一行
:put a 将寄存器a中的内容粘贴到当前行的下方

编辑宏

  • 宏复制到文档中后,可以像编辑正常文本一样编辑宏了。

将宏从文档复制回寄存器

  • 方法1
  • 副作用:寄存器会包含一个拖尾字符^J,表示一个换行符,大多数情况无关紧要,但有时会改变宏的意义。
"add 或者:d a
  • 方法2,用面向字符的复制操作
0  光标移动到行首
”ay$ 复制文本当前字符到行尾部,保存到a寄存器
dd 使用dd删除这一行

结论

  • 使用寄存器得特别谨慎(出于宏中的键盘编码罗列的诸多原因)。
  • 如果只需要将1条命令附加于宏的结尾,使用技巧69更简单。
  • 也可以编写Vim脚本来操作寄存器。例如:能用substitute()函数。
:let @a=substitute(@a,''\~'','vU','g')
:h function-list 查看更多帮助

技巧73-调整查找模式的大小写敏感性 学习笔记

全局设置大小写敏感性

  • :set ignorecase Vim的查找模式将不区分大小写。

每次查找时设置大小写敏感性

  • \c 忽略大小写。
  • \C 强制区分大小写。

启用更加智能的大小写明个性设置

  • smartcase
  • 调整查找模式的大小写敏感性
模式ignorecasesmartcase匹配
foooff-foo
fooon-foo Foo FOO
fooononfoo Foo FOO
FooononFoo
Fooonofffoo Foo FOO
\cfoo--foo Foo FOO
foo\C--foo

技巧74-按正则表达式查找时,使用\v模式开关 学习笔记

  • Vim正则表达式的语法风格更接近POSIX.
  • 使用very magic模式开关,就可以让Vim采用我们更为熟悉的正则表达式语法了。

用magic搜索模式查找十六进制颜色代码

  • 文本
body {color:#3c3c3c;}
a {color:#0000EE;}
strong {color:#000;}
  • 查找
/#\([0-9a-fA-f]\{6}|[0-9a-fA-F]\{3}\)
    ```

## 用very magic 搜索模式查找十六进制颜色代码
- 可以用\v模式开关来统一所有特殊符号的规则。
- very magic模式:除_、大小写字母以及数字0~9之外的所有字符都具有特殊含义。
- :h \v 查看帮助
- \v模式开关使得Vim的正则表达式引擎表现的更像是Perl,Python或者Ruby所为。但是有差异。
- 与规定的哪个必须转义或者不得转义相比,\v模式开关的规则更容易记忆。
- 加了\v开关特殊字符都不需要加反斜杠了,可读性更强了。

/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})


## 用十六进制字符类进一步优化模式

\x:代表[0=9a-fA-F] /\v#(\x{6}|\x{3})


- 字符#没有特殊含义,因此可按原义匹配。
- Vim的解释是任何还未具备特殊含义的字符都被"保留以备将来扩展时使用"(参见:h/\\)
- 尽管#目前不具有特殊含义,但是以后可能会有。

技巧75-按原义查找文本时,使用\V原义开关 学习笔记

按原义查找文本时,使用\V原义开关

  • 使用\V会使得其后的模式中只有反斜杠有特殊的意义。
  • 例如想查找a.k.a
/a.k.a  会匹配很多结果,因为.代表任意字符
/a\./k\.a 能正确匹配结果,但是需要对每个.进行转义
/\Va.k.a 只会匹配a.k.a
  • 如果想用正则表达式查找,就用模式开关\v(小写的v)
  • 如果想按原义查找文本,就用原义开关\V(大写的V)

技巧76-使用圆括号捕获子匹配 学习笔记

  • 当指定一个模式时,可以捕获其子匹配并在其他地方引用它们。
  • 此功能与substitute命令组合起来尤为好用,但它可用于定义某一类模式,这类模式的特点是重复包含某个单词。
  • 例子
I love Paris in the
the springtime.
  • 一个专门用来匹配重复单词的正则表达式
/\v<(\w+)\_s+\1>
  • (): 任何圆括号内部的匹配文本都会自动保存到一个临时的仓库。
  • \1 : 可以用\1引用这段被捕获的文本。
  • 如果模式中包含不止一组圆括号,则可以用\1、\2,直到\9,引用被每对()捕获的子匹配。
  • 不论模式中是否使用了圆括号,元字符\0永远会引用整个匹配。
  • <和>两符号将用于匹配单词边界
  • 元字符_s会匹配空白符或换行符
  • 在查找模式中使用子匹配的场景并不太多。

技巧77-界定单词的边界 学习笔记

  • 在very magic搜索模式下,用<与>符号表示单词定界符。
  • \w匹配单词类字符:包括字母、数字以及符号"_"。
  • \W匹配除单词类字符以外的其他字符。

使用圆括号,但不捕获其内容

  • 有时候只想使用圆括号的分组功能,但并不关系捕获的子匹配。例如可以使用下面的模式来匹配作者名字的两种形式。
/\v(And|D)rew Neil
  • 如果不想捕获圆括号内的内容"And"或"D",可以在圆括号前面加上%,指示Vim不要将括号内的内容赋值给寄存器\1
/\v%(And|D)rew Neil
  • 只有1个括号的情况下,上面2种方式似乎没有什么差别,但是有多个括号时,这种方法就很有用处了。
  • 例如,想把所有的名和姓替换成姓和名:
/\v(%(And|D)rew) (Neil)
:s//\2, \1/g
  • 可以用\W\ze\w模拟元字符<
  • 可以用\w\ze\W表示元字符>
  • 在very magic 模式下,<与>字符可直接解析为单词定界符,magic,nomagic以及very nomagic 搜索模式下,必须将它们转义。
  • 在Vim文档中查阅这些选项,得在前面附加一个转义符:
:h \<
:h \>

技巧78-界定匹配的边界

  • 有时候,可能想指定一个范围较广的模式,但只对匹配结果的一部分感兴趣。Vim中的元字符\zs与\ze可以帮助我们处理这种情况。
  • 一个匹配的边界通常对应一个模式的起始与结尾。
  • 可以使用元字符\zs与\ze对匹配进行裁剪。
  • 与单词定界符类似,\zs与\ze均为零宽度元字符。

例子

  • 查找Practical Vim 所有出现的地方都会被高亮
/Practical Vim<CR>
  • 查找Practical \zsVim 只有匹配项中的Vim会高亮
/Practical \zsVim
  • 匹配引号开始引号结尾
/\v"[^"]+"<CR>
  • 匹配引号开头引号结尾高亮引号内的内容
/\v"\zs[^"]+\ze"<CR>
  • 环视表达式

技巧79-转义问题字符

  • \V 原义开关使得按原义查找文本变得更容易,因而. + 以及*的特殊含义被屏蔽掉了。但还有一些字符,其特殊含义无法被屏蔽。

正向查找时要转义/字符

  • 进行正向查找时,必须转义/字符。

反向查找时要转义?字符

  • 执行反向查找时,符号?会被当作查找域的结束符。要对?进行转义。

每次都要转义符号 \

  • 必须寨查找域中为每个反斜杠各添加一个反斜杠。

用编程的方式转义字符

  • escape(@u,'/') 为每个/与\加上反斜杠前缀。
  • getcmdtype()
  • 正向查找时getcmdtype().'' 将产生"/"
  • 反向查找时getcmdtype().'' 将产生"?"

技巧80-结识查找命令

1. 执行一次查找

  • 在普通模式按下 / 调出Vim的查找提示符,按下<CR>键时,Vim才会开始查找,按<Esc>退回到普通模式。
  • 默认是循环查找的。
  • 关闭循环查找:wrapscan 可以用:h wrapscan查看具体方法。

2. 定制查找的方向

  • / 正向查找
  • ? 反向查找

3. 重复上一次查找

  • n 命令 用于跳到下一处匹配
  • N 命令 用于跳到上一处匹配
命令用途
n跳到下一处匹配
N跳到上一处匹配
gn进入面向字符的可视模式,并选中下一处匹配
gN进入面向字符的可视模式,并选中上一处匹配

4. 回溯之前的查找

  • <Up>键(我比较喜欢用C-p和C-n进行查找,方向键能不用就不用)
  • 技巧34和技巧85中有讨论,后续会进行补充关联

技巧81-高亮查找匹配

  • Vim可以高亮查找匹配,但该功能在缺省情况下并没有被激活。
  • 启用hlsearch 可以高两匹配。

禁用高亮查找功能

  • 高亮查找功能非常有用,但它有时却不太受欢迎。
  • 禁用高亮查找功能:
:set nohlsearch
或
:se hls!
  • 临时关闭查找高亮,直到下次查找
:nohlsearch

技巧82-在执行前查找当前预览第一处匹配

  • incsearch 允许在没有执行回车前提前预览查找项。
  • .vimrc中配置永久生效
set incsearch
  • 按Esc能退出预览,光标回到原来位置

  • 提前预览可以用来检查是否存在一处匹配

技巧83-将光标偏移到查找匹配的结尾

  • 查找时将光标置于lang结尾的方法
/lang/e/<CR>

技巧84-对完整的查找匹配进行操作

  • Vim的查找命令允许高亮所有匹配并在它们之间跳转。
  • 通过gn命令可以对匹配当前模式的文本进行操作。(Vim7.4.110后支持)
  • \C强行匹配大小写。
  • gUgn将查找的匹配项转为大写。再按点重复执行。
  • dgn删除查找匹配项。按点命令重复执行。
  • 例如想吧logger.ELOG 改为ELOG:
/logger.<CR>
dgn
.

技巧85-利用查找历史,迭代完成复杂的模式

  • 匹配单引号内部任意字符
/\v '.+'
  • .+执行了贪婪匹配,它匹配了尽可能多的字符。
  • 匹配单引号内部任意字符(单引号除外)
/\v'.[^']+'
  • 匹配单引号内部任意字符(非组成单词的单引号除外)
/\v'([^']|'\w)+'
  • 查看之前的查找命令
q/
  • 将匹配引号括起来的内容保存在\1寄存器中
/\v'(([^']|'\w)+)'
  • 替换查找的内容,单引号换成双引号
:%s//"\1"/g
  • 将查找域留空,Vim将重用上一此的查找命令

  • 完整替换命令

:%s//\v'(([^']|'\w)+)'/"\1"/g

总结

  • 正则表达式用法,匹配成对单引号的方法:/\v'.+'
  • 将查找域留空,Vim将重用上一此的查找命令
  • 使用查看历史查找或使用q/查看历史查找,逐步改进命令,使用incsearch来预先查看搜索。最终达到目的。

技巧86-统计当前模式的匹配个数

  • 方法1:
/DLOG
:%s///gn
  • 方法2
  • 其中%表示只在当前文件查找
  • 模式域留空的目的是让:vimgrep使用当前查找的模式。
/DLOG
:vimgrep //g %
  • 方法3:
:cnext
:cprev

技巧87-查找当前高亮选区中的文本

  • 在普通模式下,*命令可以查找光标下的单词。

在可视模式下查找当前单词

  • 在可视模式下,*命令将查找光标下的单词。
  • 可视模式下,使用visual star search插件
  • :h mapmode-x

技巧88-认识substitute命令

substitute命令允许先查找一段文本,再用另一段文本将其替换掉。命令语法如下:

:[range]s[ubstitue]/{pattern}/{string}/[flags]

[range]对每一条Ex命令都有效

利用标志位调整substitute命令的行为

  • 标志位g:使得substitue命令可以在全局范围内执行。
  • 标志位c:让我们有机会确认或拒绝每一次修改。
  • 标志位n:会抑制正常的替换行为,即让Vim不执行替换操作,而只报告本次命令匹配的个数。
  • 标志位e:屏蔽错误提示。
  • 标志位&:让Vim重用上一次的标志位。
flag含义例子
g使得substitute命令在全局范围内执行技巧89
c每处修改进行询问技巧90
n抑制正常的替换行为技巧86
e屏蔽错误提示-
&指示Vim重用上一次substitute命令所用过的标志位技巧93

替换域中的特殊字符

使用:h sub-replace-special 查看特殊字符的完整列表

部分常用符号

符号描述例子
\r插入一个换行符-
\t插入一个制表符-
\插入一个反斜杠-
\1插入第1个子匹配技巧94
\2插入第2个子匹配技巧94
\0插入匹配模式的所有内容-
&插入匹配模式的所有内容-
~使用上一次调用:substitute时的{string}技巧93
\={Vim script}执行{Vim script}表达式;并将返回的结果作为替换{string}技巧95,技巧96

返回

技巧89-在文件范围内查找并替换每一处匹配

将文件中的going都替换成rolling

:%s/going/rolling/g

技巧90-手动控制每一次替换操作

将content替换成copy并确认是否修改

:%s/content/copy/gc
  • y 替换此处匹配

  • n 忽略此处匹配

  • q 退出替换过程

  • l 替换此处匹配后退出

  • a 替换此处与之后的所有的匹配

  • <C-e> 向上滚动屏幕

  • <C-y> 向下滚动屏幕

  • 查看帮助

:h s_c

技巧91-重用上次的查找模式

  • substitute命令的查找域留空,意味着Vim将会重用上次的查找模式。
  • <C-r><C-w> 粘贴光标当前内容
  • <C-r>/粘贴上次查找内容

技巧92-用寄存器的内容替换

1. <C-r>{register},可以将寄存器的内容插入命令行。

2.用复制专用寄存器的内容替换上一次的模式

:%s//\=@0/g

3.将选中的内容存入a寄存器

"ay

技巧93-重复上一次substitute命令

  • g&在整个文件范围内重复上一次命令
  • gv命令激活可视模式,并重新将上次被选中的文本高亮起来。
  • :%&&在整个文件范围内重复执行上一个查找替换命令。

技巧94-使用子匹配重排CSV文件的字段

例子:

last name,first name,emial
san,zhang,zhang san@qq.com
si,li,lisi@qq.com
wang,wu,wangwu@qq.com

重排:

/\v^([^,]*),([^,]*),([^,]*)$
:%s//\3,\2,\1

\1:匹配姓氏,\2:匹配名字,\3:匹配电子邮箱。

技巧95-在替换过程中执行算术运算

文档:

<h2>Heading number 1</h2>
<h3>number 2 heading</h3>
<h4>Another heading</h4>

修改:

/\v\</?h\zs\d
:%s//\=submatch(0)-1/g

技巧96-交换两个或更多的单词

文本:

The dog bit the man.

想把dog和man互换:

\v(<man>|<dog>)
:%s//\={"dog":"man","man":"dog"}[submatch(1)]/g

使用Abolish.vim:超级substitue命令

Subvert命令,简写为:S

:%S/{man,dog}/{dog,man}/g

技巧97-在多个文件中执行查找与替换

  • 例子:把Pragmatic Vim 都改成Practical Vim
/Pragmatic\ze Vim
  • 元字符\ze把单词Vim从匹配中排除掉(见技巧78),然后运行substitute命令
:%s//Practical/g

使用:vimgrep在工程范围内查找

/Pragmatic\ze Vim
:vimgrep // **/*.txt
  • 查找域留空,Vim使用当前的查找模式
  • 通配符**/*.txt,匹配当前目录下的所有后缀为.txt的文件

使用:cfdo在整个工程范围内执行substitute命令

  • 设置hidden
  • 该项设置可以无需存盘就可以从莫个被修改的文件中切换出去。
:set hidden
  • 批量替换
:cfdo %s//Practical/gc
  • 批量存盘
:cfdo update
  • 合并修改存盘
:cfdo %s//Practical/g | update

技巧98-认识global命令

  • :global 命令允许在摸个指定模式的所有匹配行上允许Ex命令。
  • :global命名通常采用以下形式(参见:h :g)
:[range] global[!] /{pattern}/ [cmd]
  • 在缺省情况下,:global命令的作用范围是整个文件(%).
  • {pattern} 域与查找历史相互关联,如果留空,Vim自动使用当前查找模式
  • [cmd] 可以使除:global 命令之外的任何 Ex 命令。 默认为:print
  • :global! 或者:vglobal 反转(v表示invert)
  • :global 命令在指定[range]内的文本行执行时通常分为两轮:
    1. 第一轮,Vim在所有[pattern]的匹配行首做上标记。
    2. 第二轮,再在所有已标记的文本上执行[cmd]。
  • [cmd]的范围可以单独设定。

技巧99-删除所有包含模式的文本行

  • 将:global命令与:delete命令组合使用,可以快速裁剪文件内容。

用':g/re/d' 删除所有匹配

  • 文本
<ol>
<li>
<a href="cfanzp.csdn.net/">
show cfanzp blog1
</a>
</li>
<li>
<a href="cfanzp.csdn.net/">
show cfanzp blog2
</a>
</li>
</ol>
  • 执行命令
/\v\<\/?\w+>
:g//d
  • 执行后文本
show cfanzp blog1
show cfanzp blog2
  • 与:substitue命令类似,也可将:global命令的查找域留空。
  • \v 开启very magic模式
  • < 匹配<
  • /? 匹配可选的正斜杠
  • \w+ 匹配一个或多个单词
  • 匹配单词结尾的分隔符>

grep的来历

  • global命令的简写形式
  • re表示regular expression
  • p 是:print的缩写
  • /去掉就是grep
:g/re/p

用':v/re/d' 之保留匹配行

  • 删除所有不包含cfanzp的行
  • vgroup 简写为v
:v/cfanzp/d

技巧100-将TODO项收集至寄存器

  • :global和:yank 结合可以解决这个问题
    • 用大写的A是附加到寄存器a(追加),小写的a会覆盖寄存器a
    • "ap 可以将a寄存器的内容粘贴出去。
:g/TODO/yank A
:reg a
  • 将所有的TODO项复制到文件结尾
:g/TODO/t$

技巧101 将CSS文件中所有规则的属性按字母排序

对单条规则的属性进行排序

  • 文本
html {
    margin:0;
    padding:0;
    border:0;
}
  • 执行命令
vi{
:'<,'>sort
  • 执行后文本
html {
    border:0;
    margin:0;
    padding:0;
}

对所有规则的属性进行排序

  • :g/{pattern}/[range][cmd]
:g/{/ .+1,/}/-1 sort
  • 上例分析

    • .符号代表当前行
    • +1,-1代表偏移量
    • .,/}/ 表示从当前行开始,一直匹配模式/}/的那一行为止。
  • :global命令的广义形式

:g/{start}/ .,{finish} [cmd]

技巧102-认识ctags

1. 安装ctags

  • 安装ctags
sudo apt-get install ctags
  • 查看安装版本
ctags --version

2. 用ctags 创建代码库的索引产生一个tags标签文件文件

ctags *

3. 详解标签文件

  • 标签文件的前几行由元数据组成。而此后的没一行文本均由关键字、文件名以及关键字在源代码中的位置这3项内容构成。
  • 关键字是按照字母顺序排列的。

4. 用模式定位关键字,而不是用行号

  • ctags 不采用绝对行号,而是用查找命令定位每一处关键字

5. 用元数据标记关键字

  • 目前使用的扩展格式,允许在末尾添加额外字段,为关键字提供元数据。

技巧103-配置Vim使用ctags

  • 生成ctags文件
:!ctags -R
  • 添加键盘映射,按F5就可以更新索引。
:nnormap <f5> :!ctags -R<CR>

在每次保存文件时自动执行ctags

:autocmd BufWritePost * call system("ctags -R")

通过版本控制工具的回调机制自动执行ctags

  • 在Tim Pope的<> 一文中,讲解了如何为post-commit、post-merge 以及post-checkout等事件建立回调机制。

技巧104-使用Vim的标签跳转命令,浏览关键字的定义

  • Vim与ctags的集成,使得代码中的关键字变成了某种形式的超链接。

跳转到关键字的定义处

<C-]>
  • 后退返回
<C-t>

关键字存在多处匹配时,可以指定跳转的位置。

  • g<C-]>命令会从标签匹配列表中挑出可选项供我们选择。
  • 只需要输入相应的数字并按下键。
g<C-]>
  • 也可以使用tselect
:tselect
:tprev
:tfirst
:tlast
  • 可以参考unimpaired插件

使用Ex命令

:tag {keyword} 跳转到匹配{keyword}的第一处标签。

技巧105-不用离开Vim也能编译代码

在Vim中编译工程

  • 在c或c++工程中,进入Makefile所在目录,然后在命令行模式输入:make 即可编译工程。
  • :make! 结尾的!将指示Vim只更新quickfix列表,而不跳到第一处错误。
  • :cnext 可以跳转到quickfix列表的下一出错位置。
  • :copen 可以打开quickfix列表。
  • :h quickfix 查看quickfix帮助。

技巧106-浏览Quickfix列表

  • quickfix 列表会保存一组针对单个或多个文件内容的位置信息。
  • 查看帮助
:h quickfix
  • 填充quickfix列表的一些命令
:make
:grep
:vimgrep
:Ag
  • 浏览Quickfix列表的命令
命令用途
:cnext跳到下一项
:cprev跳转到上一项
:cfirst跳转到第一项
:clast跳转到最后一项
:cnfile跳转到下一个 文件中的第一项
:cpfile跳转到上一个文件的最后一项
:cc N跳转到第N项
:copen打开quickfix窗口
:cclose关闭quickfix窗口
:cdo {cmd}在quickfix列表中的每一行执行{cmd}
:cfdo {cmd}在quickfix列表中的每一个文件执行{cmd}

结实位置列表

  • 位置列表要多少有多少,但是特定时刻只有一个quickfix列表。
  • 以下命令会使用位置列表
:lmake
:lgrep
:lvimgrep

Quickfix的基本移动命令

:cnext
:cprevious(cprev)
:cfirst
:clast
  • 插件 unimpaired

Quickfix的快速前进/后退命令

  • cnext,cprev前面可以附加执行次数,例如
:5cnext 每次间隔5项进行浏览

使用Quickfix窗口

  • 运行:copen,可以打开一个包含quickfix列表内容的窗口
  • quickfix窗口中可以使用k,j进行上下滚动
  • 在光标置于某匹配行时,键按下,将会打开相应的文件
  • :q 可以推出quickfix
  • :cclose 也可关闭quickfix

技巧107-回溯以前的Quickfix列表

  • 运行:colder命令可以回溯quickfix列表之前的某个版本(Vim会保存最近10个列表)。
  • 从旧的quickfix列表回到比较新的列表,可以运行cnewer。
  • colder,cnewer都支持次数,例如:
:3coder
:5cnewer

技巧108-定制外部编译器

  • Vim的:make命令不限于调用外部的make程序,也可以调用任何安装在机器上的编译器。

配置Vim,使其在运行:make时可以调用nodelint,即JSLint的命令接口。

  • nodelint依赖Node.js,可以通过NPM命令进行安装
npm install nodelint -g
  • makeprg 选项运行指定运行:make时调用的程序,帮助:h 'makeparg'
  • 通过以下命令,可以指示Vim运行nodelint
  • 其中%将被扩展成当前文件所在的路径
:setlocal makeprg=NODE_DISABLE_COLORS=1\ nodelint\ %
  • 如果当前正在编辑~/quickfix/cfanzp_test.js,则在Vim中运行:make,等价于在shell中运行以下命令
export NODE_DISABLE_COLORS=1
nodelint ~/quickfix/cfanzp_test.js
  • 在默认情况下,nodelint采用ANSI色标编码把错误信息高亮为红色。
  • 配置NODE_DISABLE_COLORS=1 将会禁用颜色高亮,这样可以更容易地解析出错信息。

用Nodelint的输出结构填充Quickfix列表

  • errorformat选项允许我们指导Vim如何解析由:make产生的输出结果。
  • 参见:h 'errorformat'
  • 查看选项的默认值:
:setglobal errorformat?
  • lua demo:
  • %f 表示文件名
  • %l 表示行号
  • %m 表示错误信息
errorformat=%*[^"]"%f"%*\D%l: %m,"%f"%*\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%-GIn file included from %f:%l:%c:,%-GIn file included from %f:%l:%c\,,%-GIn file included from %f:%l:%c,%-GIn file included from %f:%l,%-G%*[ ]from %f:%l:%c,%-G%*[ ]from %f:%l:,%-G%*[ ]from %f:%l\,,%-G%*[ ]from %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,"%f"\, line %l%*\D%c%*[^ ] %m,%D%*\a[%*\d]: Entering directory %*[`']%f',%X%*\a[%*\d]: Leaving directory %*[`']%f',%D%*\a: Entering directory %*[`']%f',%X%*\a: Leaving directory %*[`']%f',%DMaking %*\a in %f,%f|%l| %m
  • 可以使用setlocal 来设置错误格式的选项

用一条命令设置 makeprg 与 errorformat

  • errorformat的配置太难记了。
  • 可以将其保存到某个文件并使用:compiler命令来激活它。
  • 帮助 :h :compiler
:compiler nodelint
  • 通过运行以下命令,可以对Vim自带的编译器插件了解得更透彻。
:args $VIMRUNTIME/compiler/*.vim
                            ```

技巧109-不必离开Vim也能调用grep

  • Vim的grep命令给外部的grep程序提供了一层封装。
  • 通过grep在多个文件中查找摸个模式,然后就可以用quickfix列表浏览这些查找结果了。

Vim内部调用grep

  • :grepWaldo * Vim将在后台为我们再shell中执行 grep -n Waldo *,创建一个quickfix列表。

技巧110-定制grep程序

  • vim的:grep 是外部grep程序的包装。
    • 配置grepprg与grepformat可以对vim的grep进行定制。

vim默认的grep设置

'grepformat' 'gfm'      string  (default "%f:%l:%m,%f:%l%m,%f  %l%m")
'grepprg' 'gp'          string  (default "grep -n ",
                                 Unix: "grep -n $* /dev/null",
                                 Win32: "findstr /n" or "grep -n",
                                 VMS: "SEARCH/NUMBERS ")

通过:grep 调用ack

  • 对比ack与grep:http://betterthangrep.com
  • ubuntu 中安装ack
sudo apt-get install ack-grep
sudo ln -s /usr/bin/ack-grep /usr/local/bin/ack
  • OS X中使用Homebrew进行安装
brew install ack
  • ack 实现grep -n的效果
ack --nogroup
  • 采用ack代替grep最简单的方法是把'grepprg'设置成以下值:
:set grepprg=ack\ --nogroup\ $*

通过ack跳转到指定的行或列

  • ack 采用--column参数运行ack时,它会给出每一处匹配的行号与列号。
ack --nogroup --column Waldo *
  • 修改grepprg和grepformat完成这一功能
    • %f表示文件名
    • %l表示行号
    • %c表示列号
    • %m表示匹配的文本
:set grepprg=ack\ --nogroup\ --column\ $*
:set grepformat=%f:%l:%c:%m

其他grep插件

  • Ack.vim
  • fugitive.vim:Ggrep命令

技巧111-使用Vim内置的正则表达式引擎的Grep

  • 使用:vimgrep命令让Vim在所有文件中查找单词。
  • :vimgrep命令会把所有包含匹配项的行加入quickfix列表。
  • 然后可以用:cnext,:cprev 浏览这些结果。
:vimgrep /going/ clock.txt tough.txt where.txt
:cnext
  • 模式域后加上g标志,:vimgrep就把所有匹配此模式的地方都列出来,而不仅仅时首处匹配。
:vimgrep /going/g clock.txt tough.txt where.txt

指定查找哪些文件

  • 使用通配符*
:vim /going/g *.txt
  • 除了使用*和**通配符外还可以用##符号
  • 表示参数列表中的所有文件;

  • 可以先把希望查找的文件加入参数列表;
  • 然后在参数列表中的所有文件上运行:vimgrep。
:args *.txt
:vim /going/g ##

先在文件内查找,再扩大到整个工程

  • 查找don't或 Don't
/[Dd]on't
:vim //g *.txt

查找历史与:vimgrep的关系

  • 用当前查找模式在参数列表的文件中查找
:vim //g ##
  • 另外一种查找
  • 如果想再次执行同一条:vimgrep命令,上述命令将很有用,因为它会把模式保存到命令历史中。
:vim /<C-r>//g ##

技巧112-认识Vim的关键字自动补全

1. 自动补全

  • Vim的自动补全可以再插入模式下触发。
  • ignorecase选项别启用后,自动补全时也会忽略大小写。可以用infercase 修正。

2. 触发自动补全

  • <C-p>与<C-n> 可以再补全列表中反向或正向选择。
  • 触发Vim 自动补全的方法总结
命令补全类型
<C-n>普通关键字
<C-x><C-n>当前缓冲区关键字
<C-x><C-i>包含文件关键字
<C-x><C-]>标签文件关键字
<C-x><C-k>字典查找
<C-x><C-l>整行补全
<C-x><C-o>全能(Omni)补全

技巧113-与自动补全的弹出式菜单进行交互

  • 不论使用哪种自动补全命令,都可以用选择菜单中的上一项或下一项。。
<C-n>
<C-p>
<Down>
<Up>
<C-y> 确认使用当前选中的匹配项(yes)
<C-e> 还原最早输入的文本(从自动补全中exit)
<C-h>(与<BS>) 从当前匹配项中删除一个字符
<C-l> 从当前匹配字项中增加一个字符
{char} 中止自动补全并插入字符{char}

浏览补全列表,但不改变文档内容

  • 使用/时,下/上一项将被选中,但是不会改变文档中的文本。
  • 使用或者将其插入到文档中。

滚动浏览补全列表的同时更新文档内容

  • 不仅可以选择列表中的项,而且会用选中的单词来更新文档。不用在按了。
  • 我更倾向于使用而不是
  • 手指不用离开本位键
  • 不用多敲

放弃所有选项

  • 使用可以恢复到调用自动补全之前的状态。

(e可以记忆成end) ```

随着输入字符的增多,补全列表将得到精简

  • 连续按
  • 触发自动补全,并选中第一项。
  • 选中补全列表的前一项,即在不关闭补全列表的情况下回到输入文本中。
  • 这样可以继续输入,Vim将实时过滤补全列表。

技巧114-掌握关键字的来龙去脉

缓冲区列表

  • 填充自动补全单词列表最简单的方法时使用当前缓冲区中的单词。
  • 基于当前关键字的补全功能就是这样实现的,它可以通过进行触发。
  • 查看缓冲区列表
:ls!

包含文件

  • 各语言外部文件或代码库加载代码
    • 如果Vim建立补全列表时把它们加载起来,对我们大有裨益。
    • 这恰好是 触发关键字补全时发生的事。(:h compl-keyword)
c #include
python import
ruby require
lua require

标签文件

  • ctags 生成标签文件tags
  • 采用ctags建立代码库的索引,它让浏览代码变得更容易。
  • 可以用<C-]>命令调出自动补全。

合而为一

普通关键字自动补全,会把来自于缓冲区列表、包含文件以及标签文件的单词列表组合在一起,并生成补全建议。

  • :h 'complete'

技巧115-使用字典中的单词进行自动补全

有时候,我们想通过自动补全功能输入某个单词,但是它并没有在任何打开的缓冲区、包含文件或标签文件中出现过。这种情况下,可以在字典中查找。

  • :h compl-dictionary
<C-x><C-k>

为了激活该功能,需要为Vim提供一份合适的单词列表。最简单的方法是运行下面的命令来激活Vim的拼写检查功能。

:set spell

如果不想激活拼写检查功能,可以通过dictionary选项来指定一个或多个含有单词列表的文件。

  • :h 'dictionary' 除此之外,还有一种通过拼写字典实现自动补全的方式。技巧123中介绍了其应用实例。

技巧116-自动补全整行文本

自动补全整行文本,vim中用<C-x><C-l>触发

  • :h compl-whole-line
  • 普通关键字补全采用的文件也同样用于生成行自动补全建议列表。Vim会忽略行首的缩进。
  • 面向行的自动补全功能妙就妙在不用知道要复制的行的具体位置,而只需要知道有这样一行额外那把存在即可。
<C-x><C-l>

技巧117-自动补全单词序列

当使用自动补全功能补全单词时,Vim会记住该单词的来源位置。 如果紧接着再次调用自动补全功能,Vim就会插入位于其后的单词。 重复使用<C-x><C-p>来完成补全。

Vim的自动补全不仅仅可以插入单词序列,也可以用于插入一系列的行。 如果重复使用<C-x><C-l>命令,就可以插入文档其他位置上的若干各连续行。

能够自动补全连续的单词或行,通常能比复制粘贴更快得复制文本。 当你的搭档看到你在使用这一技术时,它们肯定会打断你,问你究竟时怎么做到的。

技巧118-自动补全文件名

Vim中的文件名自动补全功能可以通过命令触发

:h comple-filename

Vim的文件名自动补全功能只相对于工作目录的路径扩展,而不是相对于当前编辑文件的路径.

  • 理解这一点很重要。这一点会使得补全文件名,很多时候要在当前目录下才起作用。
    • 先cd到补全目录
    • 在cd - 回到之前目录
    • 希望后期的Vim版本能优化这一问题

技巧119-根据上下文自动补全

全能补全时由Vim实现的intellsense功能。

  • intellsense 是 Intelligent Sense的缩写,指的是一套编程环境。
  • intellsense通过减少程序员常犯的误解、笔误以及其他错误,帮助他们加快编码的流程。

全能补全功能可以通过命令进行触发。

  • 参见:h compl-omni
  • 实际上该功能由专用的文件类型插件实现,因此,必须先加载以下配置行。
  • essential.vim
set nocompatible
filetype plugin on

此外,还必须安装一个为所用语言实现全能补全功能的插件。

  • Vim的发行版本身就支持十几种语言,包括:HTML、CSS、Javascript、PHP、以及SQL。
  • 可以通过:h compl-omni-filetypes 找到完整的支持语言列表。

CSS相对静态的语法特性决定了其非常适合采用全能补全功能。

自己写一个全能补全插件

:h complete-functions

技巧120-对你的工作进行拼写检查

  • 当拼写检查启用后,Vim将对所有未在拼写文件中出现过的单词进行标记。可以在这些拼写错误项之间快速跳转,并让Vim提供更正建议。
  • :set spell 拼写检查错误处会语法高亮。
  • 在缺省情况下,Vim将用包含英文单词的字典进行拼写检查。

操作Vim的拼写检查器

命令用途
]s跳到下一处拼写错误
[s跳到上一处拼写错误
z=为当前单词提供更正建议
zg把当前单词添加到拼写文件中
zw把当前单词从拼写文件中删除
zug撤销针对当前单词的zg或zw命令

技巧121-使用其他拼写字典

  • 一旦启用了Vim的拼写检查器,它将以英语字典作为默认的拼写字典进行单词比较。
  • 通过配置spelllang选项,可以更改其默认设置。
  • spellang选项并不是全局性的,它永远只在本地缓冲区生效。
  • 这意味着在编辑2各或2各以上的文档时,可以分别采用不同的拼写文件。

指定某个语言的区域性变体

  • Vim的拼写文件本身就支持英语的几种区域性变体。
  • 默认设置spelllang=en
  • 意味着所有被以英语为母语的地区所认可的单词都是合法的。
  • 无论输入的是英式拼法还是美式拼法,Vim的拼写检查器都认为时正确的。
  • 可以指示Vim只接受美式拼法。
:set spell
:set spellang=en_us

获取其他语言的拼写文件

  • Vim的发行版本内置了支持英语的拼写文件。
  • 可以到:http://ftp.vim.org/vim/runtime/spell/下载它支持的其他几十种语言的拼写文件。
  • 如果试着加载某个尚未得到系统支持的拼写文件,Vim会提供下载安装的方法。
    • 该功能由一个名为spellfile.vim的插件实现。(:h spellfile.vim)
    • 激活该插件需要在.vimrc中配置:
set nocompatible
plugin on

技巧122-将单词添加到拼写文件中

Vim的拼写字典并非十全十美,但可以通过把单词添加到拼写文件的方式来进一步完善它。

  • 可以用zg命令把光标下的单词加到拼写文件中,使Vim可以识别它。
  • zw命令,可以把光标所在处的单词标记为拼写错误。该命令把该单词从拼写文件中删除。
  • zug 可用于无意中添加或删除了单词到拼写文件中的情况。可以撤销对光标下单词所执行的zg或zw命令。

Vim会把添加到字典中的单词保存至某个拼写文件中。拼写文件名字由所使用的语言以及文件编码类型决定。

  • 例如编辑的时一个UTF-8文件,采用的时英语字典,通过zg命令添加的单词都会被保存到:
~/.vim/spell/en.utf-8.add

为专业术语创建拼写文件

通过配置spellfile选项,可以指定一个文件路径,用于保存由zg和zw命令添加、删除的单词。

  • :h spellfile 查看帮助

Vim允许同时指定多个拼写文件,这意味着可以维护多份单词列表。

  • 例如,当准备为某个章节进行拼写检查时,就可以将包含以下配置行的文件加载进来。
  • 其中jargon.utf-8.add指向本书代码库中的一个文件,它保存了作者维护的Vim术语表。
setlocal spellang=en_us
setlocal spellfile=~/.vim/spell/en.utf-8.add
setlocal spellfile+=~/books/practical_vim/jargon.utf-8.add

对于每一个别拼写检查器误判的单词,目前都有两种方式处理:

  • 通过2zg将其添加到Vim术语表中
  • 通过1zg将其添加到默认的单词列表中

技巧123-在插入模式下更正拼写错误

通常做法:切换到普通模式

[s 命令跳回到发生拼写错误的地方
1z= 将其更正过来

快捷方式:利用拼写自动补全功能

  • 在插入模式下通过<C-x>s命令更正拼写错误。
  • 还可以通过<C-x><C-s>实现同样的功能(与<C-x>s有细节区别)。
  • 只有某行文本出现的拼写错误不止一处时,<C-x>s命令才能发挥处其优势。如果处于插入模式,光标位于行末,由2处拼写错误,只需要2此输入<C-x>s,就可以将2处拼写错误更正回来。