Vim实用技巧总结

《Practical Vim》(《Vim实用技巧》) 是关于Vim技巧最好的教程,豆瓣评分9.1。之前断断续续地看过,不过没整理笔记。这书得经常翻看并实践,以后把看书和Vim练习的笔记记录整理在此,便于反复复习和练习使用。

1
ed 为 ex 之父,ex 为 vi 之父,而 vi 为 Vim 之父。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

Vim折叠
https://www.cnblogs.com/welkinwalker/archive/2011/05/30/2063587.html

zR 展开当前文件所有的折叠
zM 折叠当前文件所有可以折叠的

zc 折叠当前行
zo 打开当前折叠

zO 对所在范围内所有嵌套的折叠点展开
zC 对所在范围内所有嵌套的折叠点进行折叠

za 打开/关闭当前折叠 zc/zo
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898

以下是《Vim使用技巧》笔记和摘录。

####################################### 第一部分 模式 #######################################

. 重复上次操作
* 查找光标所在的单词 按n查找下一个 N回到上个
/string 查找字符串string 按n查找下一个 N回到上个
:%s/content/copy/g 全文档替换

<C-g>  查看文件状态

f{ch}  查找字符
F{char}  反向移动到上一个 {char} 所在之处
t{char}  正向移动到下一个 {char} 所在之处的前一个字符上
T{char}  反向移动到上一个 {char} 所在之处的后一个字符上
; 重复f{ch}
, 回到上次的f{ch}

s 删除光标所在字符,进入插入模式
cw 删除从光标开始到单词结束的所有字符,进入插入模式
db 删除从光标起始位置到单词开头的内容,但会原封未动地留下最初光标所在字符
b 回到单词首个字符
e 定位到单词最后一个字符
dw 删除光标所在字符到单词结尾部分
aw 文本对象(text object)
daw 删除了该单词,它还会删除一个空格 命令解读为“delete a word”,这样比较容易记忆
dap 删除一段
dl == x 删除一个字符
~  切换大小写字符
g~  大小写切换 gu小写  gU大写 gUaw将当前单词变成大写 gUap整段变成大写
貌似~ vu vU 比g~ gu gU快..
= 自动缩进 gg=G 自动缩进这个文档

Vim 的语法只有一条额外规则,即当一个操作符命令被连续调用两次时,它会作用于当前行。
所以 dd 删除当前行,而 >> 缩进当前行。gU 命令是一种特殊情况,我们既可以用 gUgU ,
也可以用简化版的 gUU 来使它作用于当前行。

VG 行可视 从当前行到文档结尾
V10j 行可视 从当前行下面再选中10行

行可视后 :'<,'>normal .  针对行可视块 执行命令 .

I 不管光标在哪里 在行首插入
A 不管光标在哪里 在行尾插入

<C-a> <C-x>查找行内数字进行加减 前缀数字可以定义加减多少
<C-[> == Esc键
<C-o> 切换到插入-普通模式
插入-普通模式是普通模式的一个特例,它能让我们执行一次普遍模式命令。在此
模式中,我们可以执行一个普通模式命令,执行完后,马上就又返回到插入模式。

在当前行正好处于窗口顶部或底部时,有时我会滚动一下屏幕,以便看到更多的上下文。
用 zz 命令可以重绘屏幕,并把当前行显示在窗口正中,这样就能够阅读当前行之上及之下的半屏内容。
常常会键入 <C-o>zz,在插入-普通模式中触发这条命令。此操作完成后就会直接回到插入模式,
因此我可以不受中断地继续打字。

「.范式」 用一次按键移动,另一次按键执行,最理想的模式
口诀::执行、重复、回退。

插入模式下的命令:
<C-h> 删除一个字符 跟delete键一样
<C-w> 删除一个单词
<C-u> 删除至行首

这些命令不是插入模式所独有的,甚至也不是 Vim 所独有的,在 Vim 的命令行模式中,
以及在 bash shell 中,也可以使用它们。

不离开插入模式,粘贴寄存器中的文本:
yt,  从光标复制到, 默认复制到寄存器0
<C-r>0 粘贴寄存器0的内容

如果寄存器中包含了大量的文本,你也许会发现屏幕的更新有些轻微的延时。
这是因为 Vim 在插入寄存器内的文本时,其插入方式就如同这些文本是由键盘上一个个输进来的。
因此,如果 ‘textwidth’ 或者‘autoindent’ 选项被激活了的话,那么最终就可能会出现不必要的
换行或额外的缩进。
<C-r><C-p>命令则会更智能一些,它会按原义插入寄存器内的文本,并修正任何不必要的缩进
不过这个命令有点不太好 输入!因此,如果我想从一个寄存器里粘贴很多行文本的话,
我更喜欢切换到普通模式,然后使用某个粘贴命令

表达式寄存器<C-r>= 后面接运算表达式,回车后即可得到结果,方便一些简单的计算。

用字符编码插入非常用字符:
ga 显示光标所在字符的字符编码
<C-v>065 插入字母A 十进制0开头
<C-v>u00bf 十六进制 u开头
<C-v>{nondigit} 按原义插入非数字字符

用二合字母插入非常用字符:
<C-k>12 插入½
<C-k>?I 插入¿

用替换模式替换已有文本:
R 由普通模式进入替换模式,替换完一个光标会自动往右移,逐个替换
r 直接在普通模式替换单个字符
Vim 还有另外一种替换模式,称为虚拟替换模式(Virtual Replace mode)。
该模式可由 gR 命令触发,它会把制表符当成一组空格进行处理。假设我们把光标移到一个占屏幕 8 列宽
制表符上,然后切换到虚拟替换模式,在输入前 7 个字符时,每个字符都会被插入到制表符之前;
最后,当输入了第 8 个字符时,该字符将会替换制表符。
在虚拟替换模式中,我们是按屏幕上实际显示的宽度来替换字符的,而不是按文件中所保存的字符进行替换。
这会减少意外情况的发生,因此我建议在可能的情况下尽量使用虚拟替换模式。

可视模式:
Vim 具有 3 种不同的可视模式,分别用于操作字符文本、行文本或块文本。
v 字符文本
V 行文本
<C-v> 块文本
gv 重选上次的高亮选区  不过如果上次的选区被删除了,它也许会工作得不太正常。

viw 高亮选择光标所在单词 按c删除后进入插入模式

如果当前处于面向字符的可视模式,我们可以按 V 来切换到面向行的可视模式,
或是用 <C-v> 来切换到面向列块的可视模式。然而,如果在面向字符的可视模式
中再次按 v,就会回到普通模式。所以,你可以把 v 键当成在普通模式及面向字符的
可视模式间转换的开关,V 及 <C-v> 键也一样可以在普通模式及其对应的可视模式间切换。
当然了,你总是可以按 <Esc> 或 <C-[>回到普通模式(就像退出插入模式那样)。

可视模式下o键可以切换活动的首尾两端,然后重新调整选区的边界即可
重复执行面向行的可视命令示例:
Vj选中两行 > . 缩进两次 也可以2> 不过推荐使用. 可以有视觉反馈,也方便撤回

可视模式可能比 Vim 的普通模式操作起来更自然一些,但是它有一个缺点:在这 个模式下 . 命令
有时会有一些异常的表现。我们可以用普通模式下的操作符命令来规避此缺点。
只要可能,最好用操作符命令,而不是可视命令

vit 选择标签里的内容。vit 可被解读为高亮选中标签内部的内容
(visually select inside the tag),其中,it 命令是一种被称为文本对象(text object)
的特殊动作命令
选中后U将选中变为大写,.重复操作,只能影响相同的选中长度

vit U 的效果用普通模式下实现就不会出现影响长度不同的问题:

gUit j. j. 更佳!

这两种方式都只需要 4 次按键操作:vitU 及 gUit,但其背后的含义却大相径庭。
在可视模式所采用的方式里,这 4 次按键可以被当做两个独立的命令。
vit 用来选中选区,而 U 用来对选区进行转换。与之相反的是,gUit 命令可以被当成一个单独的
命令,它由一个操作符(gU)和一个动作命令(it)组成。

如果我们想使点命令能够重复某些有用的工作,那么最好要远离可视模式。作为 一般的原则,
在做一系列可重复的修改时,最好首选操作符命令,而不是其对应的可视模式命令。

这并不是说可视模式出局了,它仍然占有一席之地。因为并非每个编辑任务都需 要重复执行,
对一次性的修改任务来说,可视模式完全够用。并且,尽管 Vim 的动作命令允许我们进行精确的移动,
不过有时要修改的文本范围的结构很难用动作命令表达出来,而处理这种情形却恰恰是可视模式所擅长的。
分使用场景进行选择。

用面向列块的可视模式编辑表格数据:
<C-v>3j x.. gv r| 列块4行减小缩进 重新选中添加分隔符|
yyp Vr- 添加横线-
<C-v>jje c xxx <Esc> 列块选中同一个单词替换
在 Vim 列块可视模式中,修改命令的表现或许有点怪,它看上去有点不一致。
删除操作会同时影响所有被选中的行,但插入操作只影响顶行(至少在处于插入模 式的期间)。
不过在实践中,最终的结果没什么区别。因为你处于插入模式的时间很短,所以没必要太过惊讶。

<C-v>jj$ A; xxx <Esc> 列块模式行后添加相同的内容

命令行模式:
出于历史原因,在命令行模式中执行的命令又被称做 Ex 命令。
我们可以用 Ex 命令读写文件(:edit 和 :write),创建新标签页(:tabnew)及 分割窗口(:split),
或是操作参数列表(:prev/:next)及缓冲区列表(:bprev/:bnext)。
事实上,Vim 为几乎所有功能都提供了相应的 Ex 命令(参见:h ex-cmd-index获得完整列表)。

普通模式命令一般操作当前字符或当前行,而 Ex 命令却可以在任意位置执行
使 Ex 命令脱颖而出的最让人赞叹的功能,是它们拥有能够在多行上同时执行的能力。

Ex命令有:print(:p) :delete(:d) :join :substitute :normal等
在一行或多个连续行上执行命令,指定行范围:
:10 将光标定位到第10行  相当于普通模式下10G
:10p 打印第10行 :1,9p 打印第1到9行  p换成d即为删除
操作前会先移动光标
:{start},{end} 这种模式{start} 和 {end} 都是地址。到目前为止,我们已经看到过用行号作为地址,
然而很快就会看到也能用查找模式或是位置标记作为地址。
:.,$p 打印当前行到最后一行
符号 % 也有特殊含义,它代表当前文件中的所有行: :%p 打印所有行
这和运行 :1, $p 是等效的。这种简写形式在和 :substitute 命令一起使用时非常普遍:
:%s/Practical/Pragmatic/ 把每行内的第一个“Practical”替换为“Pragmatic” 加g则是所有都替换 
i表示大小写不敏感

我们也可以用高亮选区选定一个范围,而不是用数字指定。VG :'<,'>p
Vim 也接受以模式作为一条 Ex 命令的地址, 如 :/<html>/,/<\/html>/p  打印html标签和标签之间的内容
用偏移对地址进行修正:
:2 :.,.+3p 打印2-5行
0 虚拟行,位于文件第一行上方
第 0 行在文件中并不真实存在,但它作为一个地址,在某些特定场景下会很有用处。 特别是,
在把指定范围内的行复制或移动到文件开头时,可以用它做 :copy {address} 及 :move {address} 
命令的最后一个参数。

:copy 命令(及其简写形式 :t  :co)让我们可以把一行或多行从文档的一部分复制到另一部分, 
而 :move(:m)命令则可以让我们把一行或多行移到文档的其他地方。
:[range]t {address}  
:6t. 复制第6行内容放到当前行下面
:t6 复制当前行到第6行下面
:t$ 复制当前行到文本结尾
:t. == yyp
:'<,'>t0 把高亮选中的行复制到文件开头

以上的t换成m就是移动了。
重复上次的 Ex 命令非常简单,只需普通模式下按@:即可
普通模式命令适合在光标附近进行操作,而 Ex 命令则可以远距离操作。

在指定范围上执行普通模式命令:
如果想在一系列连续行上执行一条普通模式命令,我们可以用 :normal 命令。此命令在与 . 命令或宏结合使用时,
我们只需花费很少的努力就能完成大量重复性任务。
A;<Esc> 每行尾添加分好 jVG :'<,'>normal . 选中下面所有行 全部执行 . 命令 
以上例子等价于 :%normal A;
符号 % 代表整个文件范围,因此 :%normal A; 告诉 Vim 在文件每行的结尾都
添加一个分号。在做此修改时会切换到插入模式,但是在修改完后 Vim 会自动返回到普通模式。
在执行指定的普通模式命令之前,Vim 会先把光标移到该行的起始处。因此在执行时,用不着担心光标的位置。
例如,下面这条命令可以把整个 JavaScript 文件注释掉::%normal i//
虽然用 :normal 命令可以执行任意的普通模式命令, 但是我发现当它和 Vim的重复命令结合在一起时,最为强大,
既可以用 :normal . 应对简单的重复性工作, 也可以用 :normal @q 应对较复杂的任务。

自动补全 Ex 命令:
<C-d> 显示可用的补全列表
Tab 自动补全 按多次会循环遍历可选

在多个补全项间选择:
习惯用 bash shell 的方式工作,那么下面的设置会满足你的需要:
set wildmode=longest,list
习惯于 zsh 提供的自动补全菜单,或许会想试试这个:
set wildmenu 
set wildmode=full
当 ‘wildmenu’ 选项被启用时, Vim 会提供一个补全导航列表。 我们可以按 <Tab> 、<C-n> 或 <Right> 
正向遍历其列表项,也可以用 <S-Tab>、<C-p> 或 <Left> 对其进行反向遍历。

把当前单词插入到命令行:
* 查找光标当前单词 cw修改
批量修改使用:s 
:%s//bar/g  表示把最近的搜索结果都替换成bar  比如之前用*查找了foo 就会把所有的foo都替换成bar
等价于 :%s/foo/bar/g 参考:http://vim.wikia.com/wiki/Search_and_replace
Ex命令模式下按 <C-r><C-w>插入光标所在的单词,按<C-r><C-a>输入光标所在的字符串
打开你的 vimrc 文件,把光标移到其中的一项设置上,然后输入 :help <C-r><C-w> 就可以查阅该设置的文档了。

命令行窗口:
普通模式下,输入 q:,打开命令行窗口
可以用 k 及 j 键在历史中向前或向后移动,也可以用 Vim 的查找功能查找某一行。在按下 <CR> 键时,
将会把当前行的内容当成 Ex 命令加以执行。命令行窗口的好处在于它允许我们使用 Vim 完整的、区分模式的编辑
能力来修改历史命令。
当命令行窗口处于打开状态时,它会始终拥有焦点。这意味着,除非关闭命令行窗口,否则我们无法切换到其他窗口。 
要想关闭命令行窗口,我们可以执行 :q 命令 (就像关闭普通 Vim 窗口那样),或是按 <CR> 。
我们正在命令行上构建一条 Ex 命令,做到一半时,才意识到需要更强大的编辑能力,
按<Ctrl-f>从命令行模式切换到命令行窗口。

运行 Shell 命令:
在 Vim 的命令行模式中,给命令加一个叹号前缀就可以调用外部程序。
注意区分 :!ls 和 :ls 的不同之处。前者调用的是 shell 中的 ls 命令,而 :ls 调用的是 Vim 的内置命令,
用来显示缓冲区列表的内容。
在 Vim 的命令行中,符号 % 代表当前文件名。例如,如果我们正在编辑 某个 Ruby 文件,
那么可以用下面的方式执行此文件:
:!ruby %

:!{cmd} 这种语法适用于执行一次性命令,但是如果想在 shell 中执行几条命令要怎么做?
可以执行 Vim 的 :shell 命令来启动一个交互的 shell 会话, exit 命令可以退出此 shell 并返回 Vim。

假设我们正在 bash shell 中运行 Vim,然后需要执行一些 shell 命令。我们可以先按Ctrl-z 挂起 Vim 所属
的进程,并把控制权交还给 bash。此时 Vim 进程在后台处于挂起状态,让我们可以像往常一样与 bash 会话进行交互。
运行jobs命令以查看当前的作业列表。在 bash 中,我们可以用fg命令唤醒一个被挂起的作业,把它移到前台。
这会让 Vim恢复成挂起前的状态。Ctrl-z和fg命令比 Vim 所提供的:shell和exit命令更加方便快捷。

把缓冲区内容作为标准输入或输出:
:read !{cmd} 命令让我们把命令的标准输出重定向到缓冲区。正如你所期望的 一样,:write !{cmd} 做相反的事。
它把缓冲区内容作为指定 {cmd} 的标准输入。
:read !ls 把ls命令执行的结果插入到当前光标的下方
:write !sh 在 shell 中执行当前缓冲区中的每行内容 注意 :write! sh是不一样的,表示强制覆盖文件sh

使用外部命令过滤缓冲区内容:
:[range]!{filter}  使用外部程序 {filter} 过滤指定的 [range]

first name,last name,email 
john,smith,john@example.com 
drew,neil,drew@vimcasts.org 
jane,doe,jane@example.com

我们想基于第二个字段“姓氏”来重排这些记录。我们可以用 -t’,’ 参数告诉 sort 命令,这些记录以逗号分隔,
然后再用 -k2 参数指定按第二个字段进行排序。因为文件的第一行是标题信息, 我们想把它们保留在文件顶部, 
因此需要用范围 :2,$ 把它排除在排序范围之外。下列命令将完成我们想要的功能:
:2,$!sort -t',' -k2
Vim 对某些外部命令会另眼相待。例如,make 及 grep 在 Vim 中都有包装命令, 这些命令不仅执行起来更方便,
而且 Vim 还会将它们的输出解析、导入到 quickfix 列 表中。


####################################### 第二部分 文件 #######################################
用缓冲区列表管理打开的文件:
文件是存储在磁盘上的,而缓冲区则存在于内存中。
绝大多数 Vim 命令都用来操作缓冲区,不过也有一些命令针对文件进行操作,
这当中包括 :write、:update 及 :saveas 命令。
:ls 命令会列出所有被载入到内存中的缓冲区的列表
:bnext 命令可以切换到列表中的下一个缓冲区
% 符号指明哪个缓冲区在当前窗口中可见,而 # 符号则代表轮换文件。按<C-^>可以在当前文件和轮换文件间快速切换
轮换文件意思应该是被编辑过的文件(在vim中打开过的文件)
我们可以用 4 条命令来遍历缓冲区列表。 
:bprev 和 :bnext 在列表中反向或正向移动,每次移动一项;
:bfirst 和 :blast 则分别跳到列表的开头和结尾。
:ls 列表的开头有一个数字,它是在缓冲区创建时由 Vim 自动分配的编号。
我们可以用 :buffer N 命令直接凭编号跳转到一个缓冲区
或是用更直观的 :buffer {bufname} 格式实现同样的功能
:bufdo 命令允许我们在 :ls 列出的所有缓冲区上执行 Ex 命令,不过在实际应用中,我发现 :argdo 更加实用
删除缓冲区:
:bdelete N1 N2 N3 
:N,M bdelete

用参数列表将缓冲区分组:
参数列表易于管理,适用于对一批文件进行分组,使其更容易访问。
用 :argdo 命令可以在参数列表中的每个文件上执行一条 Ex 命令。
参数列表是 vi 的一个功能,而缓冲区列表是 Vim 引入的增强功能
参数列表是缓冲区列表的一个强力补充

填充参数列表:
cd mvc (mvc是一个目录)
vim
打开后直接命令行模式 :args app.js index.html 则会把app.js和index.html载入缓冲区
如果只是想在列表里增加几个文件,用这种方式就行了。它的好处是可以指定文件的次序,但它也有一个缺点,
那就是手动增加文件的工作量比较大。如果想往参数列表中加入大量文件,那么使用通配符会快得多。

用 Glob 模式指定文件:
通配符是一个占位标记,它代表了可用于文件或目录名称的字符。* 符号用于匹 配 0 个或多个字符,
但它的范围仅局限于指定的目录,而不会递归其子目录;;** 通配符也匹配 0 个或多个字符,但它可以递归进入
指定目录的子目录:
:args *.*   :args **/*.js   :args **/*.*
也可以指定多种后缀::args **/*.js **/*.css

用反引号结构指定文件:
:args `cat .chapters`
Vim 会在 shell 中执行反撇号(`)括起来的命令,然后再把 cat 命令的输出作 为 :args 命令的参数。
虽然本例是用 cat 命令获取 .chapters 文件的内容,但实际上我们可以用这种方式执行任意可用的 shell 命令。
然而,此功能并不是所有系统都可用。

参数列表比缓冲区列表更容易管理,这使其成为对缓冲区进行分组的理想方式。 
通过使用 :args {arglist} 命令,一下就可清空并重新设置参数列表,
接着就可以 用 :next 及 :prev 命令遍历参数列表中的文件,或是用 :argdo 命令在列表中的每个缓冲区
上执行同一条命令。:缓冲区列表就像是我的计算机桌面(desktop),它永远是乱七八糟的;
而参数列表则像一个整洁的独立工作区(workspace),只有在需要扩展空间时才会用到它。

管理隐藏缓冲区:
Vim 对被修改过的缓冲区会给予特殊对待,以防未加保存就意外退出。
No write since last change (add ! to override)
ls 缓冲区前有一个 + 号,表示这个缓冲区被修改过了。如果现在保存文件的话,缓冲区的内容就会被写入磁盘里,
而 + 号也会消失了。缓冲区被标记为 h,表示它是一个隐藏缓冲区(hidden)。
:q Vim 会把第一个有改动的隐藏缓冲区载入当前窗口,这样我们就可以决定如何处理它。
如果要保留修改,可以执行 :write 命令把缓冲区保存到文件;
如果想摒弃此修改,可以执行 :edit!,重新从磁盘读取此文件,这会用文件的内容覆盖缓冲区中的内容。
当缓冲区内容与磁盘文件一致后,我们就可以再次尝试执行 :q 命令了。
如果会话里有不止一个被修改过的隐藏缓冲区,那么每次执行 :quit 命令时, Vim 都会激活下一个未保存
的缓冲区。同样的,我们可以用 :write 及 :edit! 来保存或摒弃此修改。
当没有其他窗口和隐藏缓冲区时,:q 命令就会关闭 Vim。
如果想退出 Vim 而不想对未保存的修改进行检查,可以执行 :qall! 命令;
如果想保存所有有改动的缓冲区而无需逐个检查,可以用 :wall 命令。

将工作区切分成窗口:
<C-w> s 水平分  == :sp {file}
<C-w> v 垂直分  == :vsp {file}
<C-w> hjkl 在窗口之间移动
<C-w>w 切换活动窗口 循环
关闭窗口
:close 关闭活动窗口 
:only 关闭除活动窗口外的所有其他窗口

改变窗口大小及重新排列窗口:
<C-w>= 使所有窗口等宽、等高
<C-w>_ 最大化活动窗口的高度
<C-w>| 最大化活动窗口的宽度
[N]<C-w>_ 把活动窗口的高度设为[N]行
[N]<C-w>| 把活动窗口的宽度设为[N]列

用标签页将窗口分组:
用 Vim 的标签页可以把工作分隔到不同的工作区。 Vim 中的标签页更像是 Linux 中的虚拟桌面,
而不是像其他文本编辑器中的标签页。
:lcd {path} 命令让我们可以设置当前窗口的本地工作目录。如果我们创建了一个新标签页,
并用 :lcd 命令切换到另一个目录,那么就可以把每个标签页限制在不同的工程范围内。
注意::lcd 只影响当前窗口,而非当前标签页。如果一个标签页包含了两个或更多的窗口,
我们可以用 :windo lcd {path} 命令为所有这些窗口设置本地工作目录。

:tabedit {filename} 命令可以打开一个新的标签页, 如果省略了{filename} 
参数的话,那么 Vim 会创建一个新标签页,里面包含一个空缓冲区。
如果活动标签页中只包含一个窗口,那么 :close 命令将关闭此窗口以及包含此窗口的标签页。
我们也可以用 :tabclose 命令来关闭当前标签页,无论其中有多少个窗口。 
最后,如果想关闭除当前标签页外的所有其他标签页,可以用 :tabonly 命令。

标签页的编号从 1 开始, 我们可以用 {N}gt 命令在标签页间切换,可以把此命 令记成“跳到标签页{N}”。
当此命令带一个数字前缀时,Vim 会跳到指定编号的标签 页;如果省略了数字前缀,则会跳到下一个标签页。
gT 命令的功能与此相同,只是跳转方向相反。

使用:find 打开文件:
先配置path:
:set path+=app/**
** 通配符会匹配 app/ 目录下的所有子目录。
配置了path之后就可以使用:find来查找文件了,有些插件已经配置了自动添加path的配置

除了查看和编辑文件内容以外, Vim 还允许查看目录的内容。 Vim 发行版中自带的 netrw 插件
允许我们对文件系统进行管理。
要想返回上级目录,可以使用 - 键, 或是把光标移到 .. 条目上再按 <CR>。
:e.  打开文件管理器,并显示当前工作目录
:E  打开文件管理器,并显示活动缓冲区所在的目录

把文件保存到不存在的目录中:
:edit {file} 命令一般用于打开一个已存在的文件。然而,如果我们指定了一个不存在的文件路径, 
那么 Vim 就会创建一个新的空白缓冲区。
调用外部的 mkdir 程序 对此做出补救:
:!mkdir -p %:h   % 符号代表活动缓冲区的完整文件路径  它会展开成当前文件的完整路径
:w

以超级用户权限保存文件:
以超级用户运行 Vim 的情况并不常见, 然而有时我们不得不把修改保存到一 个需要 sudo 权限的文件中。 
无需重启 Vim 就能实现这一功能, 我们可以把这个任务委派给一个以 sudo 运行的 shell 进程来完成。
:w !sudo tee % > /dev/null
此时,Vim 需要与我们进行两次交互。首先要输入用户 drew 的密码,
然后 Vim 会警告我们该文件已被修改了,并显示出一个选项菜单。 
在这里,我建议按 l 键重新将该文件载入缓冲区。
:write !{cmd} 命令会把缓冲区的内容作为标准输入 传给指定的{cmd},{cmd} 可以是任何外部程序
该命令的后半部分可以展开为 下面的命令:tee /etc/hosts > /dev/null。
这条命令会把缓冲区的内容当作标准输入,并用它来覆盖 /etc/hosts 文件的内容。
之后,Vim 会检测到该文件已经被一个外部程序修改。一般情况下这意味着缓冲区中的内容和文件不同步了,
这就是为什么 Vim 会提示我们做出选择,是要保留缓 冲区中的版本,还是载入磁盘上的版本?
然而在本例中,文件与缓冲区的内容刚好是 完全一致的。


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

区分实际行与屏幕行:
理解实际行与屏幕行间的差别很重要,因为 Vim 提供了不同的动作命令来操作这两者。j 和 k 命令会根据实际行
向下及向上移动,而 gj 和 gk 则是按屏幕行向下及向上移动。

基于单词移动:
w 正向移动到下一单词的开头
b 反向移动到当前单词/上一单词的开头
e 正向移动到当前单词/下一单词的结尾
ge 反向移动到上一单词的结尾

每个面向单词的动作命令,都有一个面向字串的命令与其对 应,这当中包括 W、B、E 和 gE。
一个单词由字母、数字、下划线,或其他非空白字符的序列组成,单词间以空白字符分隔
而字串的定义则更简单,它由非空白字符序列组成,字串间以空白字符分隔
如果你想更快地移动的话,可以用面向字串的动作命令;而如果你想以更细的粒 度移动的话,
则可以用面向单词的动作命令。


用精确的文本对象选择选区:
文本对象允许我们操作括号、被引用的文本、XML 标签以及其他文本中的常见结构。
Vim 的文本对象由两个字符组成,第一个字符永远是 i 或是 a。我们一般说, 以 i 开头的文本对象会选择分隔符内部的
文本,而以 a 开头的文本对象则会选择包 括分隔符在内的整个文本。 为了便于记忆, 可以把 i 想成“inside”,
而把 a 想成 “around” 或“all”。
it和at表示标签和标签内容
i( 和 i) 等同,a[ 和 a] 也相同

Vim 的文本对象分为两类:一类是操作分隔符的文本对象,如i)、i"和it; 一类用于操作文本块,如单词、句子和段落。
我把第一类标注为“分隔符文本对象”,因为它们以配对的符号作为开始和结束。
单词、句子以及段落则以文本结构的范围进行界定,因此我把这一类称为“范围文本对象”。
iw 当前单词
aw 当前单词及一个空格
iW 当前字串
aW 当前字串及一个空格
is 当前句子
as 当前句子及一个空格
ip 当前段落
ap 当前段落及一个空行

一般来说,d{motion} 命令和 aw、as 和 ap 配合起来使用比较好,而c{motion}命令和 iw 及类似的文本对象
一起用效果会更好。(空格的问题 删除与修改)

设置位置标记,以便快速跳回:
mm 和 `m 命令是一对便于使用的命令,它们分别设置位置标记 m,以及跳转到该标记。
Vim 会自动帮我们设置一些位置标记,这些标记用起来非常方便。
`` 当前文件中上次跳转动作之前的位置
`. 上次修改的地方
`^ 上次插入的地方
`[ 上次修改或复制的起始位置
`] 上次修改或复制的结束位置
`< 上次高亮选区的起始位置
`> 上次高亮选区的结束位置

在匹配括号间跳转:
命令允许我们在一组开、闭括号间跳转。它可作用于 ()、{}以及[]
修改{}示例,要先执行一次 % 命令,在执行%命令时,Vim 会自动为发生跳转的地方设置一个位置标记,
而后我们就可以按``跳回那里。

在配对的关键字间跳转:
Vim 在发布时带了一个名为 matchit 的插件,它增强了 % 命令的功能。激活此插件后,% 命令
就可以在配对的关键字间跳转。
虽然 matchit 随 Vim 一起发布,但它缺省并未使能。下面的 vimrc 将使 Vim 在启动时自动加载
matchit 插件:
set nocompatible 
filetype plugin on 
runtime macros/matchit.vim
此插件提供的增强功能非常有用,因此我建议你激活该插件
我最喜欢的一个插件是 Tim Pope 写的 surround.vim
用它可以很容易地给选中的文本加分隔符。
 
遍历跳转列表:
:jumps
Vim 会记录跳转前后的位置,并提供了一些命令让我们能够沿原路返回。
动作命令在一个文件内移动,而跳转则可以在文件间移动。
<C-o> 命令像后退按钮一样,而与之互补的 <C-i> 命令则像是前进按钮。
这两条命令允许我们对 Vim 的跳转列表进行遍历。
任何改变当前窗口中活动文件的命令,都可以被称为跳转命令。
Vim 会把执行跳转命令之前和之后的光标位置,记录到跳转列表中。
:edit 命令打开了一个新文件
就可以用 <C-o> 和 <C-i> 命令在这个新文件以及原本的文件之间来回跳转。
 
gf  跳转到光标下的文件名
<C-]>  跳转到光标下关键字的定义之处
 
遍历改变列表:
:changes
用g; g, 命令反向或正向遍历改变列表。你可以拿 ; 和 , 命令当参考,来帮你记忆
要想跳到上次文档中被更改过的地方,我们可以按 g;。它会跳到上次完成编辑时光标所在的行及列上。
其结果与按 u<C-r> 类似,只是它不会对文档造成暂态的改变。
 
u 撤销更改  <C-r> 重做最新的更改
 
gi  快速回到退出的地方继续编辑。此命令会用 `^ 标记恢复光标位置,并切换到插入模式,这真是省时省力的好办法!

跳转到光标下的文件:
Vim 会把文档中的文件名当成一个超链接。在进行了正确的配置后,我们就可以 gf 命令跳转到光标下的文件了。
指定文件的扩展名:
‘suffixesadd’ 选项允许我们指定一个或多个文件扩展名(要先设置path),当 Vim 用 gf 命令搜寻文件名时,
会尝试使用这些扩展名
:set path+=app/**
:set suffixesadd+=.rb
每次用 gf 命令时,Vim 都会在跳转列表中增添一条记录,因此我们总是可以用 <C-o> 命令返回原处。
suffixesadd和path选项可以针对每个缓冲区进行设置,因此对不同的文件类型可以设置不同的值。
除 Ruby 以外,Vim 在发布时也附带了很多其他编程语言 的文件类型插件。
因此在实际应用中,你不会自己经常设置这两个选项。

<C-]>命令的作用也类似,它也需要进行一些配置,然而 一旦正确配置好,
它就允许我们从函数调用的地方直接跳到该函数定义的地方。

跳转列表和改变列表如同“面包屑小径”一样,它们允许我们沿原路返回。
而 <C-]> 命令则像是“虫洞”,它把我们从代码的一个地方传送到另一个地方。

用全局位置标记在文件间快速跳转:
m{letter} 命令允许我们在当前光标位置创建一个位置标记。
小写字母会创建局部于缓冲区的标记,而大写字母则创建全局标记。
设置好标记后,就可以用 `{letter} 命令使光标快速回到标记所在之处。
全局位置标记是一种书签,让我们可以在文件间跳转。全局标记在我们分析完代码,并想快速跳回一个文件时特别有用。

:vimgrep /fooBar/ **  
查找代码中所有出现 fooBar() 函数的地方。缺省情况下,:vimgrep 会直接跳到它所找到的第一处匹配上,
这或许会切换到另外一个文件。假设代码里有几十处匹配 fooBar 模式的条目。对每个 :vimgrep 所找到的匹配项,
在 quickfix 列表中都会为之创建一条记录。回到执行前的位置,可以利用全局标记。
一般来说,要养成在使用与 quickfix 列表有关的命令前, 如 :grep 、 :vimgrep 及:make,设置全局标记的习惯。


###################################### 第四部分 寄存器 #######################################
用无名寄存器实现删除、复制与粘贴操作:
通常情况下,在讨论剪切、复制与粘贴这 3 组操作时,指的都是操作系统剪贴板。 
不过,在 Vim 的术语里,我们操作的是寄存器,而并非剪贴板。
x dd 等这些命令之后内容会放到无名寄存器,p可以直接粘贴无名寄存器的内容。
"{register} 前缀的方式指定要用的寄存器。若不指明,Vim 将缺省使用无名寄存器。
如果我们想把当前单词复制到寄存器 a 中,可 执行 "ayiw,或者,可以用 "bdd,把当前整行文本剪切至寄存器 b 中。
在此之后, 我们既可以输入 "ap 粘贴来自寄存器 a 的单词,也可使用 "bp 命令粘贴来自寄存器 b 的一整行文本,
两者互不干扰。
除了普通模式的命令外,Vim 也提供用于删除、复制与粘贴操作的 Ex 命令。
例如,我们可以执行 :delete c,把当前行剪切到寄存器 c,然后再执行 :put c 命令将其粘贴至当前光标所在行之下。

复制专用寄存器("0):
复制专用寄存器,顾名思义,仅当使用 y{motion} 命令时才会被赋值。换句话讲,
使用 x、s、c{motion} 以及 d{motion} 命令均不会覆盖该寄存器。如果我们复制了一些文本,
可以确信该文本会一直保存于寄存器 0 中,直到我们复制其他文本时才会被覆盖。
复制专用寄存器是稳定的,而无名寄存器是易变的。

:reg "0 查看寄存器内容

有名寄存器("a – "z)
黑洞寄存器 "_  删除文本却不想覆盖无名寄存器中的内容时,此命令很管用。

系统剪贴板("+)与选择专用寄存器("*):
如果我们在外部程序中用剪切或复制命令获取了文本,就可以通过 "+p 命令(或在插入模式下用 <C-r>+)
将其粘贴到 Vim 内部。相反地,如果在 Vim 的复制或删除命令之前加入 "+ ,相应的文本将被捕获至系统剪贴板。
这意味着我们能够轻松地把文本粘贴到其他应用程序中了。

X11 视窗系统支持另一种被叫作主剪贴板(primary)的剪贴板,它保存着上次被高亮选中的文本,
可以用鼠标中键(如果有的话)把它们粘贴出来。Vim 的星号寄存器对应主剪贴板,可用 * 号.

"+  X11 剪贴板,用剪切、复制与粘贴命令操作
"*  X11 主剪贴板,用鼠标中键操作

Windows 与 Mac OS X 操作系统并没有主剪贴板的概念,因此 "+ 寄存器与 "* 寄 存器可以混用,
它们都代表系统剪贴板。X11 剪贴板的功能可在编译 Vim 时被激活或禁用。如果想验证该功能是否在
自己的 Vim 中被激活,可运行 :version 命令,然后找到 xterm_clipboard 关键字。
如果它前面有个减号,就表示你这个版本的 Vim 不支持该功能,而加号则表示此功能已被激活。
查看是否支持: vim --version | grep clip

在 mac 下编译也不能支持xterm_clipboard,未解决.但"+ "*是可用的.

表达式寄存器("=):
输入一段 Vim 脚本表达式并按 <CR> 执行,如果返回的是字符串(或者可被强制转换成字符串的数据),
Vim 将会使用它。

Vim 还提供了几组可被隐式赋值的寄存器。它们被称作只读寄存器:
"%  当前文件名
"#  轮换文件名
".  上次插入的文本
":  上次执行的 Ex 命令
"/  上次查找的模式

”/ 寄存器并非只读,可以用 :let 命令对其进行显式的赋值。但为了方便起见,我们仍把它列入该表。

用寄存器中的内容替换高亮选区的文本:
yiw jww ve p  先复制单词 调到下行,用可视模式选中要替换单词,粘贴替换

与系统剪贴板进行交互:
除了 Vim 内置的粘贴命令,我们有时也要用到系统粘贴命令。但当 Vim 在终端内部运行时,
使用该命令经常会产生意外的结果。为了避免这些问题,可在执行系统粘 贴命令之前激活 ‘paste’ 选项。
激活“autoindent(自动缩进)”选项,这样一来,当我们再次把系统剪贴板的文本粘贴出来时,
必然会引起奇怪的后果:
:set autoindent
设置键 :set pastetoggle=<f5>

如果你运行的 Vim 是已集成系统剪贴板的版本,就可以完全避免与 'paste' 选项打交道了。
普通模式下的 "+p 命令用来粘贴加号寄存器中的内容,即系统剪贴板的镜像。
无论 'paste' 与 'autocommand' 选项激活与否,该命令都能保证位于剪贴板中的文本缩进不会乱套。


宏的读取与执行:
把命令序列录制成宏q{register},按q结束
示例: qa A;^[Ivar q
查看寄存器a内容
:reg a

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

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

宏的执行是串行好还是并行好呢?
nqa 这种是串联,遇到错误会停止, normal @a是并联,针对可视化选中的每一行执行宏命令.
以并行的方式在多处执行宏更为健壮。
但如果宏在执行时遇到一处错误,而我们正想利用这些警告更正错误时,以串行、多次的方式执行宏
可以更容易定位出问题所在。

可在参数列表的所有缓冲区内执行宏了:
:argdo normal @a
:argdo write 可保存参数列表中的全部文件,但如果简单地运行以下命令的话,会更快:
:wall

基本的 Vim 脚本:
let i=0  let i+=1
:echo i

let+宏示例:
:let i=1
qa
I<C-r>=i<CR>)<Esc>
:let i += 1
q

将宏粘贴到文档中:
G 
:put a
为什么不直接用 "ap 命令呢?因为,在本例的上下文中,p 命令会把寄存器 a 的内容粘贴至当前行的
光标之后。而:put 命令总会将它们粘贴至当前行的下方,无论寄存器保存的是面向行的还是
面向字符的文本块。

将宏从文档复制回寄存器:
运行 "add(或者 :d a),但这么做可能会在以后导致问题。dd 命令将执行面向行的删除操作,
因此,寄存器会包含一个拖尾字符 ^J.
该字符表示一个换行符,且在大多数情况下,该字符都无关紧要。但有时这个拖尾字符可能会改变宏的意义。
为了保险起见,用面向字符的复制操作把这些字符从文 档复制回寄存器会更安全.
0 "ay$ dd 这样就把宏的内容保存回寄存器 a
用substitute也可以修改:
:let @a=substitute(@a, '\~', 'vU', 'g')

################################# 第五部分 模式 ###############################
按模式匹配及按原义匹配
查找、substitute 以及 global 命令的驱动核心是 Vim 的搜索引擎

如果启用‘ignorecase’设置,Vim 的查找模式将不区分大小写。这项设置具有副作用,
即会影响Vim 关键字自动补全的行为。
每次查找时设置大小写敏感性:
通过使用元字符 \c 与 \C,可以覆盖Vim缺省的大小写敏感性设置。
小写字母 \c 会让查找模式忽略大小写,而大写字母 \C 则会强制区分大小写。
/\cfoo    不区分foo大小写查找


按正则表达式查找时,使用 \v 模式开关:
与 Perl 相比,Vim 正则表达式的语法风格更接近 POSIX。对于已经熟悉 Perl 正则表达式的程序员
来说,这是一个令人失望的消息。但是,通过使用 very magic 模式开关,
就可以让 Vim 采用我们更为熟悉的正则表达式语法了。
我们可以利用 \v 模式开关来统一所有特殊符号的规则。该元字符将会激活 very magic 搜索模式,
即假定除_、大小写字母以及数字 0 到 9 之外的所有字符都具有特殊含义
\v 模式开关使得 Vim 的正则表达式引擎表现得更像是 Perl、Python 或者 Ruby 所为。
尽管如此,它们之间仍然存在差异,但Vim \v 模式开关的规则更容易记忆。
尽管 # 目前不具有特殊含义,但不意味着将来的版本也会这样。
万一将来 # 被赋予了特殊含义,我们必须要将其转义后,才可以匹配“#”字符本身。

按原义查找文本时,使用 \V 原义开关:
在正则表达式中使用的特殊字符,在按模式查找时用起来很顺手,但如果我们想按原义查找文本时,
它们就变成了阻碍。使用 very nomagic 原义开关,可以消除附加在 .、* 以及 ? 等大多数字符上
的特殊含义。
/a.k.a.  ->  /a\.k\.a\.  ->  /\Va.k.a.
:substitute 命令的查找域留空,Vim 将使用上一次的查找模式,会导致某些意想不到的错误发生。

作为通用法则,如果你想按正则表达式查找,就用模式开关\v,如果你想按原义查找文本,就用原义开关\V。

界定单词的边界:
/the  ->  /\v<the><CR> 前或后有空格

有时我们只想使用圆括号的分组功能,但并不关心所捕获的子匹配。例如,可以使用以下模式来匹配
我名字的两种形式:
/\v(And|D)rew Neil

无论我们采用的是正向还是反向查找方式,反斜杠字符永远都需要转义。

当我们使用 / 键执行一次查找时,Vim 将进行正向扫描。而如果是用 ? 键调出 查找提示符的话,
Vim 则会进行反向查找。

:set hlsearch  高亮查找匹配
:set nohlsearch  禁用高亮
:nohlsearch(:noh)  暂时禁用高亮 禁用当前而已 下次查找还是会高亮的

:set incsearch    在执行查找前预览第一处匹配

<C-r><C-w>  根据预览结果对查找域自动补全,但一旦在查找内容中加入元字符 \v 前缀,
<C-r><C-w> 会把光标下的完整单词,而不是单词的余下部分,作为补全的内容

:%s///gn  统计当前模式的匹配个数 
调用的是:substitute 命令,但标志位 n 会抑制正常的替换动作。
该命令不会对每处匹配进行替换,而是简单地统计匹配的次数,并将结果显示到命令行上。

将上次的查找命令插入到Ex模式中 <C-r>/


在整个文件范围内重复面向行的替换操作:
:s/target/replacement/g
突然,我们意识到了失误,应该加上前缀 % 才对。
接下来,我们只需输入 g& 即可在整个文件的范围内重复这条命令。

我们总是可以指定一个新的范围,并使用 :&& 命令重新执行替换操作。至于上次用的范围是什么并不重要。
具体来说,:&& 命令本身只作用于当前行,:'<,'>&& 会作用于高亮选区,而 :%&& 会作用于整个文件。
正如我们已经看到的那样,g& 命令作为 :%&& 的快捷方式,使用起来会更方便一些。

:args **/*.txt
/Pragmatic\ze Vim
:argdo %s//Practical/ge
Vim 会对所有这些文件执行 substitute 命令.e表示忽略错误

在所有的缓冲列表中查找:
/the
:vimgrep /<C-r>// **/*.txt
默认值显示当前缓冲区的查找结果.
每个由 vimgrep 返回的匹配都将在 quickfix 列表中被记录下来,
打开查看quickfix列表 :copen



global 命令:
:global 命令结合了 Ex 命令与 Vim 的模式匹配这两方面能力。
凭借该命令,我们可以在某个指定模式的所有匹配行上运行 Ex 命令。
就处理重复工作的效率而言,global 命令是除点范式以及宏之外,最为强大的 Vim 工具之一。

在缺省情况下,:global 命令的作用范围是整个文件(%),
这一点与其他大多数 Ex 命令(包括 :delete、:substitute 以及 :normal)有所不同,
这些命令的缺省范围仅为当前行(.)。
{pattern} 域与查找历史相互关联。这意味着如果将该域留空的话,Vim 会自动使用当前的查找模式。
:global 命令通常采用以下形式:
:[range] global[!] /{pattern}/ [cmd]
如果我们不指定任何 [cmd],Vim 将缺省使用 :print。

Grep 一词的来历:
请仔细琢磨一下 :global 命令的简写形式::g/re/p
re 表示 regular expression,而 p 是 :print 的缩写,它作为缺省的 [cmd] 使用。

用 ':g/re/d' 删除所有的匹配行
用 ':v/re/d' 只保留匹配行

将 TODO 项收集至寄存器:
通过把 :global 和 :yank 这两条命令结合在一起,我们可以把所有匹配 {pattern} 
的文本行收集到某个寄存器中。
:g/TODO  可以显示所有TODO

qaq 清空寄存机a的内容
reg a 查看验证
我们可以把包含 TODO 注释的行复制到此寄存器中了:
:g/TODO/yank A   将所有匹配模式 /TODO/ 的文本行依次附加到寄存器 a
此后,我们只需在任意分割窗口中打开一个新缓冲区,再运行 "ap 命令,
就可以将寄存器 a 的内容粘贴进去了。

另一种解决方案:
:g/TODO/t$
该命令是将所有 TODO 项复制 到当前文件的末尾,而不是把它们附加到寄存器。一旦运行完该命令,
我们就可以在 文件的末尾看到这些 TODO 项了。

甚至可以将 :global 命令与 :bufdo 或 :argdo 一起搭配使用,从一组文件中收集所有的 TODO 项。

Vim的排序简单使用示例:
vi{  :'<,'>sort
{}中的内容,使用vim内容排序函数进行排序.


################################# 第六部分 工具 ###############################
“只做一件事,并做到极致”是 Unix 哲学的精髓所在。

通过 ctags 建立索引,并用其浏览源代码:
ctags 是一个外部程序,它通过扫描代码库,生成关键字的索引。
ctags *.rb 创建了一个名为 tags 的纯文本文件,其内容是 ctags 经过对 3 个源文件的分析
而生成的关键字索引。
每一行文本均由关键字、文件名以及关键字在源代码中的位置这 3 项内容构成。
关键字是按照字母顺序排列的,Vim可以采用折半查找法快速地定位到某个关键字。

配置 Vim 使用 ctags:
想在 Vim 中使用基于 ctag 的跳转命令,首先,要确保标签文件是最新的, 
其次,要让 Vim 知道到哪里去找标签文件。

手动执行 ctags:
:!ctags -R
该命令将从 Vim 当前的工作目录开始,遍历其所有的子目录,并为其中的每一个文件建立索引。
最终,再把这个标签文件保存到当前工作目录中。
调整一下命令,加入 --exclude=.git 或 --languages=-sql 等类似的参数,
如果每次手动输入命令的话,势必会很麻烦。
可以建立映射:
:nnoremap <f5> :!ctags -R<CR>

在每次保存文件时自动执行 ctags:
Vim 的自动命令(autocommand)功能允许我们在某个事件发生时调用一条命令,
这些事件包括缓冲区的创建、打开或者保存等。因此,我们可以创建一条自动命令,
在每次保存文件时自动调用 ctags:
:autocmd BufWritePost * call system("ctags -R")

通过版本控制工具的回调机制自动执行 ctags:
每当提交代码改动时,自动更新代码库的索引。此法很好地兼顾了前两种方式的优缺点。

使用 Vim 的标签跳转命令,浏览关键字的定义:
按下 <C-]> 展示了实际的操作过程:光标将会从当前所在的关键字跳转到它的定义处。
Vim 会为我们访问过的标签维护一个历史列表。
在浏览标签历史记录时,<C-t> 命令会充当“后退按钮”的角色。

我们还可以用 g<C-]> 命令来代替 <C-]>。如果当前关键字只有一处匹配,
这两条命令的行为将完全一致,但如果发生了多处匹配的情况,g<C-]> 命令会从标签匹配列表
中挑出可选项供我们选择.
:tselect 命令,调出标签匹配列表
也可以用:bnext、:tprev、:tfirst、:tlast

其实,我们不必非得将光标移到关键字上,才能进行标签跳转,也可以用 Ex 命令达到同样的目的。
:tag {keyword} 与 :tjump {keyword} 就分别等同于<C-]>与g<C-]>的功能。

浏览所有以 phone 为结尾的关键字定义:
:tjump /phone$

浏览Quickfix列表命令:
:cnext 跳转到下一项
:cprev 跳转到上一项
:cfirst 跳转到第一项
:clast 跳转到最后一项
:cnfile 跳转到下一个文件中的第一项
:cpfile 跳转到上一个文件中的最后一项
:cc N 跳转到第 n 项
:copen 打开 quickfix 窗口
:cclose 关闭 quickfix 窗口

当 quickfix 窗口处于活动状态时,我们可以像平常一样使用 :q 将其关闭。 
但如果其他窗口是活动窗口的话,我们也可以通过 :cclose 将其关闭。


:grep 命令是外部 grep 程序的包装器。 通过配置‘grepprg’ 与‘grepformat’ 这两个选项,
我们可以对 Vim 查找的行为进行定制。
ack比grep快,强大
ack --nogroup --column Waldo *
:set grepprg=ack\ --nogroup\ --column\ $*
:set grepformat=%f:%l:%c:%m
grep 采用的是 POSIX 风格的正则表达式,而 ack 则采用的是 Perl 风格的正则表达式。
如果 :grep 命令在后台调用 ack,可能会引起误导。与其这样,
你为什么不创建一条名为 :Ack 的命令,使其名副其实呢?Ack.vim插件恰好符合以上需求。

:vimgrep 命令允许我们使用 Vim 自带的正则表达式引擎,实现跨文件的查找功能。


触发自动补全:
通过 <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-f> 文件名补全
<C-x><C-o> 全能(Omni)补全  内置插件 filetype plugin on

<C-n> 可能会产生更多的补全建议,因为除了当前缓冲区以外,它还用其他来源来填充补全列表。
<C-e> 来终止本次自动补全。

:set spell 来激活 Vim 的拼写检查功能
z=  获取 Vim 提供的更正建议列表
1z=  直接改成建议列表的第一项

<C-x><C-f>  补全当前文件名

指定某个语言的区域性变体:
Vim 的拼写文件本身就支持英语的几种区域性变体。缺省设置 spelllang=en 
意味着所有被以英语为母语的地区所认可的单词都是合法的。
:set spell
:set spelllang=en_us
设置Vim 只接受美式拼法

为专业术语创建拼写文件:
setlocal spelllang=en_us 
setlocal spellfile=~/.vim/spell/en.utf-8.add 
setlocal spellfile+=~/books/practical_vim/jargon.utf-8.add

更多阅读学习资料: