-
Notifications
You must be signed in to change notification settings - Fork 1
/
vim-presentation.tex
991 lines (883 loc) · 69.4 KB
/
vim-presentation.tex
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
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
\documentclass{beamer}
\usepackage{subfig}
\usepackage{hyperref}
\usepackage{csquotes}
\usepackage[Q=yes]{examplep}
\hypersetup{
colorlinks=true,
linkcolor=blue,
filecolor=magenta,
urlcolor=cyan,
}
\mode<presentation> {
\usetheme{Madrid}
}
\title[\textcolor{white}{Vim - Fun and Efficient}]{\huge Vim \\
\large Making text editing fun and efficient
}
\author{Alec Gibson}
\institute[BlueCat]
{
BlueCat Networks \\
\medskip
\textit{agibson@bluecatnetworks.com}
}
\date{November 24, 2020}
\begin{document}
\begin{frame}[fragile]
\titlepage % Print the title page as the first slide
\end{frame}
\begin{frame}[fragile]
\frametitle{Presentation Details}
\begin{itemize}
\item This presentation was created in Neovim 0.5.0 using the Beamer Latex package
\item The source code is available \href{https://github.com/alec-gibson/vim-fun-and-efficient}{in a repo on my GitHub}
\item For discussions about Vim, please post in the company \#vim-geeks slack channel!
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Disclaimer}
\small The target audience of this talk is not seasoned users of Vi-family editors (though you are more than welcome to stay if this describes you). Many of the features I will refer to as Vim features were Vi features first. I never used Vi, and clarifying when features were introduced in Vim's lineage is outside the scope of this talk. So for the purpose of this talk they are Vim features.\\
\vspace{0.5cm}
Furthermore, I personally use Neovim, not Vim. Neovim is a fork of Vim with slightly tweaked default options, no Benevolent Dictator For Life, and which tends to implement new features more quickly. Both operate almost identically, but if you want to be guaranteed to be able to follow along with everything I say in this talk, you might want to use Neovim as well. I noticed on Sunday that backspace works as you would expect in insert mode when you use Neovim, but has some different eccentric behaviour in Vim. This can be easily fixed by setting the `backspace' option, but if you don't want to deal with it, you can just use Neovim instead.
\end{frame}
\begin{frame}[fragile]
\frametitle{Goal}
\small
After learning Vim's basics in university, I decided to start using it full-time when I started working at BlueCat at the beginning of May. At first, my workflow was quite inefficient --- all my knowledge came from vimtutor, and several Reddit posts I had read. Since then, my knowledge of Vim has expanded massively, and my editing has become much more fluent, so I wanted to share what I've learned with other interested developers.\\
\vspace{0.5cm}
This talk is meant to make it easier for other developers to make the same transition as me, from a standard point-and-click text editor or IDE to Vim. I try to cover many of Vim's core features, so that you have some idea what it is capable of (which is a considerable amount) instead of immediately reaching for plugins. Where possible, I try to mention what features I have found particularly useful, and to outline why I feel learning Vim has been a net positive to my work as a developer. No section of this talk is exhaustive - Vim's feature set is so huge that covering any topic exhaustively would take forever and be very boring. Instead I try to cover the most important stuff, and reference documentation so you can learn the rest at your leisure.
\end{frame}
\begin{frame}[fragile]
\frametitle{Overview}
\tableofcontents
\end{frame}
\section{About Vim}
\begin{frame}[fragile]
\frametitle{About Vim}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\frametitle{What is Vim}
\centerline{\large According to vim.org}
\vspace{0.5cm}
\small Vim is a highly configurable text editor built to make creating and changing any kind of text very efficient. It is included as \enquote{vi} with most UNIX systems and with Apple OS X.\\
\vspace{0.5cm}
Vim is rock stable and is continuously being developed to become even better. Among its features are:\\
\begin{itemize}
\item persistent, multi-level undo tree
\item extensive plugin system
\item support for hundreds of programming languages and file formats
\item powerful search and replace
\item integrates with many tools
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\centerline{\large Here are some important features I think were missed:}
\vspace{0.5cm}
\small
\begin{itemize}
\item Vim is very lightweight, meaning it runs smoothly on any modern computer and performs well over SSH.
\item Vim's startup time is nearly instantaneous.
\item Because Vim runs in a terminal it works nicely with other terminal utilities (like tmux), and you can pipe the output of scripts directly into Vim.
\item Vim's configuration is scriptable, so you can define custom functions then use them in commands and keybindings.
\item Once you learn Vim you can use it everywhere - its keybindings are supported in most other editors either natively or through plugins (including VSCode, Emacs, and IntelliJ to name a few)
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\centerline{\large And most importantly....}
\vspace{0.5cm}
\small \textbf{If you have not used them before, learning Vim's keybindings will provide you with an extremely efficient way to edit text files.}\\
\end{frame}
\begin{frame}[fragile]
\frametitle{Who Should Try Vim?}
\centerline{\large You may appreciate Vim if you:}
\vspace{0.5cm}
\begin{itemize}
\item Spend a large amount of your day editing plain text files (common in software development and IT)
\item Make frequent use of your terminal emulator
\item Appreciate the value of keyboard shortcuts
\item Like to customize your tools to suit your workflow
\item Want to make an investment in learning a single editor which works for every programming language
\item \textbf{And especially} if you need a way to automate performing boring, repetitive edits to text files
\end{itemize}
\end{frame}
\section{A Minimal Vim Workflow}
\begin{frame}[fragile]
\frametitle{A Minimal Vim Workflow}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\frametitle{Modal Editing}
\small
\begin{block}{Modal Editing}
Vim is a modal text editor, meaning keypresses in Vim perform different actions depending upon the editor's current \enquote{mode}.\\
\end{block}
When you edit a file in Vim, the editor starts in \enquote{normal} mode. This can confuse new users, because Vim's normal mode treats every key on the keyboard as a binding for a shortcut. To start off learning Vim, let's look at the smallest possible set of features you need to edit files.
\end{frame}
\begin{frame}[fragile]
\frametitle{Basic Vim File Operations}
\small
\begin{itemize}
\item To open a file in Vim, type \verb+vim {filename}+ in your terminal emulator.
\item To change the current open file, type \verb+:e /path/to/file<CR>+ (including the colon at the start).
\item To save the current file, type \verb+:w<CR>+.
\item Finally, to exit Vim type \verb+:q<CR>+.
\end{itemize}
\begin{block}{What's That CR Symbol?}
\verb+<CR>+ stands for Carriage Return, and is how you represent the Enter/Return key in Vim keybindings.
\end{block}
\begin{block}{Popular Variants}
Popular variants of these commands include \verb+:wq<CR>+ to save and quit, and \verb+:wq!<CR>+ to force Vim to save and quit (ignoring any warnings while doing so).
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Basic Vim Editing}
\small
The simplest (though probably the slowest) way to navigate a file in Vim is using the arrow keys. To make changes in the current file, press \verb+i+ to enter \enquote{insert} mode. In insert mode, keys behave the way they would in any other text editor - letter and number keys insert their corresponding characters, and \verb+<BS>+ (backspace) deletes the previous character.$\ast$ \\
\vspace{0.5cm}
If you want to run any of the file operations from the previous slide, just press \verb+<ESC>+ (escape) to return to normal mode first.
\begin{block}{Using Your Mouse in Vim!?}
It's true, Vim supports using your mouse. Just set the required option by typing \verb+:set mouse=a<CR>+ in normal mode.
\end{block}
\begin{block}{$\ast$ Why Doesn't Backspace Work?}
Vim's default backspace behaviour in insert mode is unintuitive. You can make it behave the way you probably expect by typing \verb+:set bs=2<CR>+. Sometimes it will already work, because many Linux distros ship a default Vim configuration which sets this option.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small This is enough Vim to edit config files on servers over SSH (albeit slowly), or to use while setting up a minimal Linux installation on a PC. \\
\vspace{0.5cm}
However, if this was the most efficient way to edit files in Vim, \textbf{the editor would have died out long ago}.
\end{frame}
\section{Vim Can Do More}
\begin{frame}[fragile]
\frametitle{Vim Can Do More}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\frametitle{Why The Minimal Workflow Isn't Enough}
\small
The minimal Vim workflow I described in the previous section is seriously inefficient. Here are a few reasons why:
\begin{itemize}
\item Using the mouse requires you to take your right hand off the keyboard
\item Using the arrow keys requires you to take your right hand off the home row
\item You can only move one character at a time using the arrow keys
\item You can only delete one character at a time using \verb+<BS>+
\item If your cursor is in the middle of some text, you have to move to the end to delete it
\item We don't have any way to copy and paste
\item We don't have a way to undo mistakes
\item This workflow doesn't include any way to search the current file
\item Repeated edits need to be executed manually each time
\end{itemize}
Vim's normal mode has features which solve all these issues.
\end{frame}
\begin{frame}[fragile]
\frametitle{Movement Keybindings}
\small
\begin{block}{Problem}
\begin{itemize}
\item Using the mouse requires you to take your right hand off the keyboard
\item Using the arrow keys requires you to take your right hand off the home row
\end{itemize}
\end{block}
Vim solves these issues by using the keys \verb+h, j, k, and l+ as alternatives to the arrow keys while in normal mode. These behave in the following manner:
\begin{description}
\item[h] Move left one character
\item[j] Move down one character
\item[k] Move up one character
\item[l] Move right one character
\end{description}
These keybindings are well-known enough that other programs which also use hjkl for navigation often refer to them as \enquote{Vim keys}.
\end{frame}
\begin{frame}[fragile]
\frametitle{Moving Longer Distances}
\small
\begin{block}{Problem}
\begin{itemize}
\item You can only move one character at a time using the arrow keys
\end{itemize}
\end{block}
Vim's normal mode contains many keybindings for moving more than one character at a time. Here are some I use frequently:
\begin{itemize}
\item \verb+w/b+: Move forward/back by one word at a time
\item \verb+0/$+: Move to the start/end of the current line (use \verb+^+ instead of 0 to move to the first non-whitespace character of the line)
\item \verb+<C-d>+/\verb+<C-u>+: Move down/up by half a screen at a time
\item \verb+gg/G+: Move to the start/end of the current file
\end{itemize}
\begin{block}{Useful Keybindings: f and F}
Typing f\{char\} searches the current line for the chosen character, and using F searches backwards. Pressing \enquote{;} jumps to the next occurrence, and pressing \enquote{,} goes to the previous occurence (very useful if you overshoot your target). This is often the fastest way to jump to a specific location on the current line.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{Repeating Movements Multiple Times}
Most Vim commands allow you to prepend a number to multiply their effects. For example:
\begin{itemize}
\item typing \verb+5j+ in normal mode moves your cursor down 5 lines.
\item typing \verb+3w+ moves your cursor forward 3 words
\item typing \verb+10fe+ moves your cursor to the tenth occurence of the character \enquote{e} following it on the current line
\end{itemize}
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Keybindings for Editing}
\small
Vim has a number of keybindings for editing the current file's contents. We can start with keybindings which operate on single characters:
\begin{itemize}
\item \verb+x+: delete the character under the cursor
\item \verb+r{char}+: replace the character under the cursor with \{char\}
\item \verb+~+: swap the case of the character under the cursor
\item \verb+<C-a>+/\verb+<C-x>+: increment / decrement the number under the cursor
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Operating on Chunks of Text}
\small
\begin{block}{Problem}
\begin{itemize}
\item You can only delete one character at a time using \verb+<BS>+
\end{itemize}
\end{block}
Operating on chunks of text is a place where Vim's keybindings shine. Vim separates these edits into keybindings it calls \enquote{operators} and \enquote{motions}.
\begin{block}{Operators}
Operators are the verbs of the edit - they are things like \enquote{delete}, \enquote{change}, \enquote{yank} (Vim language for \enquote{copy}), \enquote{indent}, \enquote{format}, etc.
\end{block}
\begin{block}{Motions}
Motions are like nouns - they define what the operator should operate on. Examples of motions would be \enquote{a word}, \enquote{until the end of the line}, or \enquote{to the end of the file}.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
Operators:
\begin{itemize}
\item \verb+d+: delete
\item \verb+c+: change (delete, then enter insert mode)
\item \verb+y+: yank (copy)
\item \verb+<+/\verb+>+: decrease / increase indent
\item \verb+=+: format (works well for C-style languages, but is configurable)
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\small
Example Edits:
\begin{itemize}
\item \verb+dl+: delete to the right (same as x)
\item \verb+dh+: delete to the left
\item \verb+dw+: delete word
\item \verb+c$+: change to the end of the line
\item \verb+yG+: yank to the end of the file
\item \verb+dt_+: delete to the next underscore $\ast$
\end{itemize}
$\ast$ Note: \verb+t+ and \verb+T+ act like \verb+f+ and \verb+F+, but they stop one character before the character being searched for. These are extremely useful for operating on all the text before a certain target character. \verb+Snake_case+, \verb+kebab-case+ and \verb+camelCase+ are used frequently in source code files, so it often works well to make your target character the next underscore, hypen, or a specific capital letter.
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{Shortcuts for Common Operations}
There are also some special editing keybindings to make frequently required editing operations more convenient. Repeating the operator twice means to apply it to the current line (\verb+dd+ deletes the current line, \verb+yy+ yanks the current line, etc.). There are also shortcuts for when you capitalize the operators - \verb+D+ deletes to the end of the line, \verb+Y+ is equivalent to \verb+yy+, etc.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
For most motions, the easiest way to understand the behaviour of Vim edits is to imagine the behaviour of the cursor if you typed the motion without the operator, then the operator will be applied to the characters spanned by that motion. This is why, for example, \verb+dw+ doesn't delete the entire word the cursor is currently inside, but rather deletes from the current cursor position to the beginning of the next word.\\
\vspace{0.5cm}
Sometimes this is not the behaviour we want - sometimes we want to delete the entire word the cursor is currently inside. We will explore how to do this using \enquote{text objects} next.
\end{frame}
\begin{frame}[fragile]
\frametitle{Text Objects}
\small
\begin{block}{Problem}
\begin{itemize}
\item If your cursor is in the middle of some text, you have to move to the end to delete it
\end{itemize}
\end{block}
Up until now, the motions we have applied to operators have also been normal mode navigation keybindings. This is not always the case. After typing the operator but before the motion, Vim is in a special mode called \enquote{operator-pending} mode, and this mode has some of its own unique keybindings. Text objects are an example of keybindings for operator-pending mode. These keybindings let operators work on an area of text the cursor is already inside - for example the current word or the surrounding set of quotation marks.
\end{frame}
\begin{frame}[fragile]
\small
examples of text objects:
\begin{itemize}
\item \verb+iw/aw+: inner / around word
\item \verb+is/as+: inner / around sentence
\item \verb+ip/ap+: inner / around paragraph
\item \verb+i"/a"+: inner / around quoted string
\item \verb+i(/a(+: inner / around \verb+()+ block
\item \verb+i[/a[+: inner / around \verb+[]+ block
\item \verb+i{/a{+: inner / around \verb+{}+ block
\end{itemize}
Language plugins often add text objects, for example to operate on the contents of classes and functions.
\end{frame}
\begin{frame}[fragile]
\small
Each of the \enquote{inner} variants of the provided text objects ignore whitespace and surrounding delimiters. The \enquote{around} variants include the surrounding delimiters and whitespace. \\
\vspace{0.5cm}
For example, \verb+di"+ will delete the contents of the quotation marks the cursor is currently inside, but will not touch the quotation marks themselves. In contrast, \verb+da"+ will delete the contents of the quotation marks, the quotation marks, and surrounding whitespace. \\
\vspace{0.5cm}
To frame this differently, if you had a series of quoted strings separated by spaces, \verb+di"+ would delete the contents of the current string, but repeating it again would do nothing. In contrast, \verb+da"+ would delete the current quoted string so that the cursor ends on the next quoted string, so if you repeated the edit it would delete each quoted string in turn.
\end{frame}
\begin{frame}[fragile]
\frametitle{Pasting, or \enquote{Putting}}
\small
\begin{block}{Problem}
\begin{itemize}
\item We don't have any way to copy and paste
\end{itemize}
\end{block}
We've seen how to yank text already using the \verb+y+ operator. Now all you need to do to \enquote{put} it (Vim language for pasting) is to press \verb+p+.\\
\vspace{0.5cm}
It is important to know, deleting in Vim does not just delete the chosen text, but behaves more like the \enquote{cut} operation in other popular editors. That is to say, when you use the \verb+d+ operator, the deleted text will be the next thing \enquote{put} when the user presses \verb+p+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Searching}
\small
\begin{block}{Problem}
\begin{itemize}
\item This workflow doesn't include any way to search the current file
\end{itemize}
\end{block}
Searching is very quick in Vim, and is often the fastest way to navigate a file. Press \verb+/+ to initiate a search, then type in the pattern to search for (patterns are regular expressions so, among other things, they can include wildcards) and press \verb+<CR>+ to start the search. To move to the next search result press \verb+n+ and to move to the previous result press \verb+N+. Here are a few other useful keybindings for searching:
\begin{itemize}
\item \verb+?+: start a search in the opposite direction
\item \verb+q/+: view a history of previous search patterns (press \verb+<CR>+ on one to search for it in the current file)
\item \verb+/<CR>+: search again using the most recently used search pattern
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Undo and Redo}
\small
\begin{block}{Problem}
\begin{itemize}
\item We don't have a way to undo mistakes
\end{itemize}
\end{block}
You can undo the most recent edit by pressing \verb+u+, and you can press \verb+u+ multiple times to continue undoing edits. An example of a single \enquote{edit} in Vim would be a single operator + motion combination. Everything you type from pressing \verb+i+ to enter insert mode until returning to normal mode is considered a single edit, so pressing \verb+u+ once will undo all of it.\\
\vspace{0.5cm}
You can press \verb+<C-r>+ to \enquote{redo} the most recently undone edit. Like with \verb+u+, you can repeatedly press \verb+<C-r>+ to redo more undone edits.\\
\vspace{0.5cm}
If you accidentally undo too much then edit the document, it is still possible to recover - Vim keeps track of your branching undos. We'll discuss this later in the Vim Power Tools section when we discuss the Undo Tree.
\end{frame}
\begin{frame}[fragile]
\frametitle{Repeating Edits}
\small
\begin{block}{Problem}
\begin{itemize}
\item Repeated edits need to be executed manually each time
\end{itemize}
\end{block}
We discussed on the previous slide what a single \enquote{edit} is in Vim. You can repeat the most recent edit by pressing the \verb+.+ key.\\
\vspace{0.5cm}
Effectively using \verb+.+ takes a lot of practice, and requires that you plan your edits to be repeatable. For example, if you run \verb+diw+ to delete a word, then \verb+i+ to enter insert mode and type its replacement, subsequent presses of \verb+.+ will perform the insertion but not the deletion. If you want the deletion to be included in the repeated edit, you could use \verb+ciw+ instead.\\
\vspace{0.5cm}
Vim supports many ways to repeat edits. I'll discuss macros, \verb+:substitute+ and \verb+:global+ in the \enquote{Power Tools} section of this talk. All of these are more flexible than the \verb+.+ key.
\end{frame}
\begin{frame}[fragile]
\frametitle{How to Find Help}
\small
Vim comes with extensive documentation built-in, accessible using the \verb+:h+ command (short for \verb+:help+, which works too if you want to be verbose). If you want to look up what a particular keybinding does, you can run \verb+:h {key}<CR>+ to look up the corresponding help file. If you don't know the name of the help file you are looking for, you can run \verb+:helpgrep {phrase}<CR>+ to search all Vim's help files for a particular phrase. Helpgrep fills Vim's \enquote{quickfix} list with its results - we will discuss the quickfix list more later, but for now just know you can run \verb+:cnext<CR>+ to go to the next result and \verb+:cprev<CR>+ to go to the previous result.
\end{frame}
\begin{frame}[fragile]
\frametitle{How to Learn Vim}
\small
If you want more thorough materials to learn Vim, you can start by running \verb+vimtutor+ in your terminal (it usually comes with your installation of Vim). After completing vimtutor, you can read Vim's user manual for a lengthy but readable guide to all of Vim's most important features. To read the user manual, run \verb+:h user-manual<CR>+ in Vim.
\end{frame}
\section{Power Tools}
\begin{frame}[fragile]
\frametitle{Power Tools}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\small
Now that we've covered most of the basic features of Vim, you have seen one of the reasons many developers swear by it as their editor of choice - the ability to modularly compose edits using operators and navigation keybindings gives you a very terse language for quickly editing documents. However, there are probably still some people wondering \textbf{why would anyone want to use this editor}? Hopefully the features I discuss in this section will help make a stronger case in favour of Vim.
\end{frame}
\begin{frame}[fragile]
\small
To start with, I'll cover Command-Line Mode and Visual Mode to round out our understanding of Vim's modes. Then we'll get into some of (what I consider) Vim's killer features - the jump list, registers, macros, \verb+:substitute+, \verb+:global+, and the undo tree. By the end of this section I'll have explained enough of Vim's features that, if you became fluent in their usage, you could edit single files in Vim quite efficiently. \\
\vspace{0.5cm}
After this section, we'll cover ways to manage editing multiple files in a single Vim session, then we'll finish up with a short introduction to Vim configuration.
\end{frame}
\begin{frame}[fragile]
\frametitle{Command-Line Mode}
\small
Many of Vim's features are accessible using keybindings in normal mode. However, we can also access features by writing out the names of commands to execute using Vim's command-line mode. Press \verb+:+ to enter command-line mode, then you can type in the name of a command and hit \verb+<CR>+ to execute it and return to normal mode. If you change your mind, you can press \verb+<ESC>+ to go back to normal mode without executing a command.\\
\vspace{0.5cm}
\begin{block}{We've Seen This Before}
We have already learned several Vim command-line mode commands. The file operations we learned (\verb+:w+, \verb+:q+ and \verb+:e+) all execute in command-line mode, as do the \verb+:h+ and \verb+:helpgrep+ commands. Vim doesn't require you to type the whole name of a command to execute it - you just need to type enough to disambiguate it from other commands. The file operations we learned are actually short forms for \verb+:write+, \verb+:quit+ and \verb+:edit+.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{How Do I See My Command-Line History?}
When you are in command-line mode, you can press the up and down arrow keys (or \verb+<C-p>+ and \verb+<C-n>+, emacs style) to select previously run commands. You can view your command-line history by typing \verb+q:+ in normal mode. This will open a window showing past commands you've run, where you can edit a previous command, then execute the edited version using \verb+<CR>+.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Visual Mode}
\small
One of the disadvantages of Vim's operator/motion syntax for defining an edit, is that you need to decide on the appropriate motion for an edit on the spot after already commiting to an operator. If you would prefer to make your selection of text to operate on first, then specify the operator after, Vim contains three different \enquote{visual modes} which allow you to do just that.
\vspace{0.5cm}
\begin{block}{Character-Wise Visual Mode}
The simplest visual mode Vim offers is character-wise visual mode, often just refered to as visual mode. You can enter this visual mode by pressing \verb+v+, and exit to normal mode using \verb+<ESC>+. While in any visual mode, your current text selection will be highlighted. You can move the cursor to change where the visual selection ends, or press \verb+o+ to instead change where the selection starts. After making your selection you can use operators on the selected text, like \verb+d+ to delete it, or \verb+y+ to yank it.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{Line-Wise Visual Mode}
You can press \verb+V+ (capital V) to enter line-wise visual mode - a variant of visual mode which only selects entire lines. I often use this version of visual mode to delete or yank data which is formatted into separate lines, such as a function, a JSON object, or a chunk of YAML. It is also useful for constraining the scope of some command-line commands, something we'll explore more when we discuss the \verb+:substitute+ command.
\end{block}
\begin{block}{Block-Wise Visual Mode}
You can press \verb+<C-v>+ to enter block-wise visual mode, which lets you select a rectangular region of text. I have found this most useful when I want to add, remove or modify a prefix for several lines. For example, if I wanted to create a bulleted list, I would use block-wise visual mode to select the first character of several lines, press \verb+I+ to insert at the start of each line's selection in the block (a special block-wise visual mode mapping), type \verb+-+, then press \verb+<ESC>+. Upon returning to normal mode, all my selected lines would be updated to begin with a hyphen.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{The Jump List}
\small
This is a simple feature, but it is \textbf{constantly} useful, and I wish every text editor had it. Vim keeps track of every time you use a motion to move a significant distance, and stores these locations you've jumped to in its \enquote{jump list}. You can view this jump list by running the \verb+:jumps+ command.\\
\vspace{0.5cm}
The useful part is that Vim lets you jump back to older locations you've been using \verb+<C-o>+ and newer locations using \verb+<C-i>+. This means for example, if you created a tags file using ctags, you could jump to a function's definition using \verb+<C-]>+. Then, using the jump list you could use \verb+<C-o>+ to jump back to where the function is called when you're done looking at it. I use this functionality constantly when reading new code I haven't seen before.\\
\vspace{0.5cm}
Note: the \verb+<C-]>+ keybinding also lets you jump to referenced help pages inside \verb+:help+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Registers}
\small
Instead of using the system clipboard, Vim uses a large collection of \enquote{registers} to store text for use elsewhere. Many operators can be prefixed with a register name, to make them use that register. To tell Vim you are specifying a register, you start with \verb+"+ - a quotation mark - followed by a single key for the register name. For example:
\begin{itemize}
\item \verb+"ayy+: yank the current line, and put it into register \verb+a+
\item \verb+"add+: delete the current line, and put it into register \verb+a+
\item \verb+"ap+: insert the contents of register \verb+a+ at the cursor's location
\end{itemize}
You can also use a capital letter to tell Vim to append to a register instead of replacing the register's contents. Many of the non-character keys on the keyboard are also used for registers with special purposes (\verb+"+ is the default register, \verb+_+ is no register, \verb|+| can be configured to use the system clipboard, etc). You can learn more about these by reading \verb+:help registers+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Macros}
\small
Vim allows you to execute arbitrary strings of characters stored in a register as a macro! For an easy way to record a macro, Vim provides a convenient keybinding - \verb+q+ - which allows you record a sequence of keypresses into a register. For example:
\begin{itemize}
\item \verb+qadwq+: record the characters \verb+dw+ into register \verb+a+
\item \verb+qAdwq+: record the characters \verb+dw+ into register \verb+a+, appending to the current contents of the register
\end{itemize}
\vspace{0.5cm}
Once you have recorded a macro into a register, you can the execute the macro using the \verb+@+ keybinding, followed by the name of the register to execute:
\begin{itemize}
\item \verb+@a+: execute the contents of register \verb+a+ as a macro
\item \verb+@@+: execute the last executed macro again
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{Repeating Macros}
Like most of Vim's commands, you can prefix the execution of a macro with a number to specify the number of times to repeat that macro. If Vim reaches the end of the current file while executing a macro, it stops executing it (this is useful, because you can include a search in your macro to find the next place to execute it).
\end{block}
\vspace{0.5cm}
Because macros just execute the contents of a register, there are many ways to record a macro - you don't have to use \verb+q+! If you want, you could write the macro in your current file, then yank it into a register to execute it. Or you could record part of your macro in register \verb+a+, stop recording, then append to that same register using \verb+qA+. Vim's macro system is extremely flexible, and is a good way for repeating edits which are too complex to use the \verb+.+ key.
\end{frame}
\begin{frame}[fragile]
\frametitle{:substitute}
\small
One of the more common features people use in a text editor is the ability to search for and replace a sequence of characters. To do this, Vim provides the \verb+:substitute+ command which has the following syntax:
\vspace{0.5cm}
\begin{block}{:substitute syntax}
\verb+:[range]s[ubstitute]/{pattern}/{replacement}/[flags]+
\end{block}
\vspace{0.5cm}
This syntax provides a great deal of flexibility, allowing you to match strings using a regular expression, use matched subexpressions in the pattern's replacement, and limit what lines to perform the substitution on. But before we get into these more advanced (but very much worth learning) features, we'll explore some examples of basic \verb+:substitute+ usage.
\end{frame}
\begin{frame}[fragile]
\frametitle{:substitute examples}
\small
\begin{itemize}
\item \verb+:s/asdf/qwerty+: replace the first occurence of \verb+asdf+ with \verb+qwerty+ on the current line
\item \verb+:s/asdf/qwerty/g+: replace every occurence of \verb+asdf+ with \verb+qwerty+ on the current line (the \verb+g+ flag means replace every occurence instead of just the first one)
\item \verb+:1,10s/asdf/qwerty/g+: replace every occurence of \verb+asdf+ with \verb+qwerty+ on lines 1 to 10 of the current file
\item \verb+:%s/asdf/qwerty/g+: replace every occurence of \verb+asdf+ with \verb+qwerty+ on every line in the current file (Vim uses the range \verb+%+ as a synonym for \verb+1,$+, meaning every line in the current file)
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Patterns}
\small
One of the best things about Vim's \verb+:substitute+ command is that it doesn't just match verbatim strings of characters, but instead uses a full system of regular expressions. Obviously, outlining all the regular expression rules would be too much for this presentation, but I'll list some of the features I use most often (this assumes the \enquote{magic} option is set, which effects what characters need to be escaped to take on a special meaning):
\begin{itemize}
\item \verb+.+: any character
\item \verb+*+: any number of repetitions
\item \verb+^+: the start of a line
\item \verb+$+: the end of a line
\item \verb+\(\)+: group contents into a subexpression (this subexpression can be used with \verb+*+, and can be referenced in the pattern's replacement)
\end{itemize}
There is much more that you can do with Vim's regular expression system. To learn more, read \verb+:help pattern+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Using Matched Patterns in the Replacement}
\small
Often you want to perform a substitution, but provide some context so that you avoid the pattern matching false-positives. You can do this using subexpressions in your \verb+:substitute+ command's pattern. After using a pattern containing subexpressions, you can reference them in the replacement using \verb+\0+ to mean the whole matched pattern, and \verb+\{num}+ to mean the \verb+{num}+th subexpression. Here is an example which hopefully illustrates how useful this can be:\\
\begin{verbatim}
:%s/func \(.*\)(/func (s *MyStruct) \1(
\end{verbatim}
This command's pattern matches \enquote{func }, followed by an arbitrary string of characters (captured in a subexpression), followed by an opening bracket --- this is the pattern followed by a function definition in Golang. The replacement takes the function name, and replaces its prefix with \enquote{func (s *MyStruct) }. This substitute command could be used to turn all the functions in a file into methods for a struct you defined!
\end{frame}
\begin{frame}[fragile]
\frametitle{Restricting a Substitution's Range}
\small
Sometimes I find that I want to perform a substitution only in a select portion of a file. For example, I might want to rename a variable inside a single function, but not touch variables of the same name in other functions. I have already shown that you can restrict \verb+:substitute+ by providing \verb+{start},{end}+ as the range. I never do this because Vim works so nicely with line-wise visual mode for setting ranges. Just select the lines you want to use as the range for your \verb+:substitute+, then press \verb+:+ and Vim will automatically insert \verb+'<,'>+ as the range. This range means the current visually selected lines, and it uses a pair of \enquote{marks} to denote these.
\begin{block}{Marks}
Marks are a feature Vim uses to store locations in files. I am going to annoy some Vim users by skipping discussing their usage in this talk, purely to save time and because I don't use them much personally. A good introduction to marks is provided in Vim's user manual, and you can read it by running \verb+:help 03.10+.
\end{block}
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{One More Substitute Trick}
You have seen the \verb+g+ flag for substitutions to make them replace every occurence, instead of just the first one on each line. Another flag I use frequently is \verb+c+, which makes \verb+:substitute+ ask for permission before performing each substitution. This is great if you only want to perform the substitution in some cases, and you're feeling too lazy to define a more complex regular expression to only match those specific cases.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{:global}
\small
When using macros, a fairly common workflow is to search for the next place to execute your macro, and include this search in the macro recording so that when you execute the macro many times, it automatically finds its next place to execute each time. A similar workflow can also be performed with the \verb+:global+ command, which uses the following syntax:\\
\vspace{0.5cm}
\begin{block}{:global syntax}
\verb+:[range]g[lobal]/{pattern}/[command]+
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{:global commands}
\small
\verb+:global+ is extremely flexible --- it just runs the command you specify on matches for your provided pattern, using the same regular expression syntax as the \verb+:substitute+ command. If you don't provide a command, global uses \verb+:p[rint]+ by default, which prints the matching lines for you to view them. You could use \verb+:d[elete]+ to delete matching lines, or even \verb+:s[ubstitute]+ to perform a substitution only on lines which match the provided pattern. For the ultimate in flexibility, you can use the \verb+:norm[al]+ command to execute a string of keybindings in normal mode on matching lines.\\
\vspace{0.5cm}
\begin{block}{:global!}
If you want to run a command starting at the beginning of lines which match your pattern, just use \verb+global!+ instead of \verb+global+.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{:normal and :execute}
\small
The \verb+:normal+ command provides a way for you to use normal mode keybindings in command-line mode. This is useful for some commands which run other command-line commands, such as \verb+:global+, or \verb+:cdo+ (which we'll learn about in the next section).\\
\vspace{0.5cm}
One difficulty with the \verb+:normal+ command is when you want to use a special character, such as \verb+<ESC>+ or \verb+<CR>+. When you want to do this, just wrap it in an \verb+:execute+ command, which takes a string containing a command and executes it in command-line mode, and allows you to escape special characters. For example:\\
\begin{verbatim}
:exe "norm ifunc \<ESC>A{"
\end{verbatim}
This command enters insert mode, types \enquote{func }, hits \verb+<ESC>+ to go back to normal mode, then inserts an opening curly brace at the end of the line.
\end{frame}
\begin{frame}[fragile]
\frametitle{Interacting With The Shell}
\small
Vim supports calling external commands using the \verb+:!{cmd}+ command. For example you could run \verb+!ls+ to run \verb+ls+ in a piped non-interactive shell and view the contents of the current directory. When running shell commands, Vim lets you reference the current filename using \verb+%+.\\
\vspace{0.5cm}
If you want to read the output of a shell command into the current file, you can run \verb+:r[ead] !{cmd}+. You can also filter several lines of the current buffer through an external command using \verb+:{range}!{cmd}+. You can use line-wise visual mode to select a range of lines to run a filter on like with \verb+:substitute+, or you can use the normal mode operator \verb+!+ for running a filter on an area of text defined using a motion. \verb+!!+ is a shortcut for running a filter command on the current line.
\end{frame}
\begin{frame}[fragile]
\frametitle{The Undo Tree}
\small
Here's a perilous situation which can occur in almost any editor: you edit a file for a while, and after making your edits, you realize you deleted something which you should not have deleted. To get that deleted text back, you \enquote{undo} multiple times, intending to copy the deleted text, so you can \enquote{redo} your changes and paste. However, you accidentally edit the file while in the older state! Now you can't redo your changes, and you've just accidentally lost all the work you had done!\\
\vspace{0.5cm}
Thankfully, Vim keeps track of your entire \enquote{undo tree} to avoid exactly this issue. The easiest way to use this feature is using the \verb+g-+ and \verb|g+| normal mode keybindings. These keybindings go to \enquote{older} and \enquote{newer} text states respectively, regardless of whether there were \enquote{undo} operations in the middle. In the situation I outlined, even though you'd performed an edit after undo-ing, you can just press \verb+g-+ to go to older text states until you have your edits back.
\end{frame}
\begin{frame}
\begin{block}{Making the Undo Tree More Usable}
I find the full power of Vim's undo tree is really unlocked with plugins for visualizing it, so you can easily walk to any node in the undo tree. The one I use is \href{https://github.com/mbbill/undotree}{undotree by mbbill}.
\end{block}
\end{frame}
\section{Managing and Editing Multiple Files}
\begin{frame}[fragile]
\frametitle{Managing and Editing Multiple Files}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\frametitle{Multiple Files in Vim}
\small
The following summary of Vim's terminology regarding viewing files can be found by running \verb+:help window+:
\begin{itemize}
\item A buffer is the in-memory text of a file.
\item A window is a viewport on a buffer.
\item A tab page is a collection of windows.
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Buffers}
\small
Again quoting from Vim's help files: \enquote{A buffer is a file loaded into memory for editing. The original file remains unchanged until you write the buffer to the file.}\\
\vspace{0.5cm}
When you open a new file in Vim, a new buffer is created for that file and made active, and the current buffer is hidden. You can run \verb+:ls+ to view a list of buffers together with their state and buffer numbers. Then to switch to another buffer, run \verb+:b[uffer] {num}+ with the buffer number you want to switch to.\\
\vspace{0.5cm}
NOTE: I rarely use \verb+:e+ for opening files, and I rarely use \verb+:b+ for switching buffers. Often if I know I'll want to edit a file again, I keep it open in a split window or a tab page. I'll discuss my workflow for switching to files I don't already have open in splits or tabs when I discuss \textbf{Finding Files Quickly} at the end of this section.
\end{frame}
\begin{frame}[fragile]
\frametitle{Windows}
\small
All of Vim's window management commands are prefixed with \verb+<C-w>+. By default, you can use \verb+<C-w> s+ to split your current window into two, one on-top of the other, and \verb+<C-w> v+ to split your window side-by-side. You can also perform these operations in command-line mode using \verb+:sp[lit]+ and \verb+:vs[plit]+. To switch between open windows, you can use \verb+<C-w> [hjkl]+ to switch to the window in the indicated direction. To round out the basic window management commands, you can use \verb+<C-w> c+ to close the current window, and \verb+<C-w> o+ to close every window but the current one.\\
\vspace{0.5cm}
\begin{block}{How I Manage Windows}
In the next section we will discuss configuring Vim, and I'll show how to remap keys. I have rebound splitting and switching windows because I do these actions frequently and I find it annoying to have to press \verb+<C-w>+ every time. I have switching windows bound to \verb+<C-[hjkl]>+ to switch to the window in the indicated direction, and splitting bound to \verb+<SPC> [hjkl]+ (pressed one after another) to split in the indicated direction.
\end{block}
\end{frame}
\begin{frame}[fragile]
\begin{block}{Closing vs Quitting Windows}
The difference between \verb+<C-w> c+ and \verb+:q+ is that closing a window leaves the buffer open in memory, and will fail if you try to close the last window open in Vim. In contrast, quitting a window also deletes the current buffer, will close Vim if this is the last window open, and fails if there are unwritten changes to the current buffer. \verb+<C-w> q+ is synonymous with \verb+:q+.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Tabs}
\small
As stated in Vim's documentation, a tab page is a collection of windows. To create a new tab page run \verb+:tabnew+ (you'll notice the tab bar appears at the top of the window), then you can use \verb+gt+ and \verb+gT+ to go forwards and backwards through your open tab pages. If you have many tab pages open, you can jump to a specific one using \verb+{num}gt+ which jumps to tab page number \verb+{num}+ (as opposed to jumping \verb+{num}+ tab pages forwards as you might expect). Closing the last open window on a tab page also closes the tab page.
\end{frame}
\begin{frame}[fragile]
\frametitle{Vimgrep}
\small
If you want to search files by their contents, Vim comes with a built-in grep implementation callable using the \verb+:vimgrep+ command. Vimgrep has the following syntax:\\
\begin{verbatim}
:vimgrep /{pattern}/ {files}
\end{verbatim}
The patterns used by vimgrep are the same as those used in Vim when searching and substituting, including all the regular expression goodies. The syntax for specifying files can be looked up using \verb+:help {file}+. Here are the basics which I use most often:
\begin{itemize}
\item \verb+./foo/bar+ --- paths to files
\item \verb+*+ --- wildcards which match anything (including nothing)
\item \verb+**+ --- wildcards which match anything (including nothing), and recurses into subdirectories
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Grep}
\small
The problem with vimgrep is that it reads every file it searches into memory in Vim, which allows it to use the powerful Vim pattern syntax, but makes it quite slow. If you want a faster grep implementation, you can use Vim's \verb+:grep+ command, which interacts with an external grep command specified by the 'grepprg' option. Both vimgrep and grep load their results into a quickfix list. We'll discuss how to use these lists on the next slide.
\end{frame}
\begin{frame}[fragile]
\frametitle{Quickfix Lists}
\small
Quickfix lists are Vim's way of showing lists of locations in files. These lists are used by \verb+:vimgrep+ and \verb+:grep+, as well as \verb+:make+ which is used for compiling files then showing errors, and several plugins. You can open the quickfix list in a window using the \verb+:copen+ command and close it with \verb+:cclose+. The quickfix list contains one location per line (filename, line + column number and line contents). You can navigate the quickfix list just like any other buffer, and pressing \verb+<CR>+ on a line takes you to that location in the specified file.\\
\vspace{0.5cm}
There are also commands for jumping between file locations in the quickfix list without navigating the list manually and selecting an entry. You can use the \verb+:cnext+ and \verb+:cprev+ commands to jump to the next and previous locations in the list respectively (I use these frequently enough that they're mappend to \verb+<C-n>+ and \verb+<C-p>+). There are also \verb+:cfirst+ and \verb+:clast+ commands which jump to the start and end of the list.
\end{frame}
\begin{frame}[fragile]
\frametitle{Cdo}
\small
One of the killer features of Vim's quickfix lists is the command \verb+:cdo {command}+. This command goes through the files in the quickfix list one-by-one, and executes the provided command on each entry in the quickfix list. This allows you to perform project-wide search and replace by first grepping for your pattern, then running the following combination of commands:
\begin{verbatim}
:cdo s/{pattern}/{replacement}/g | update
\end{verbatim}
You need to include the \verb+| update+ portion of the command. In Vim's command-line mode a vertical bar separates two commands to run one-after-another. You need to run update after the command used with \verb+:cdo+, because otherwise Vim will fail to close the current buffer when it changes files. Note, \verb+:update+ is just like \verb+:w[rite]+, but it only writes the file if its contents changed.\\
\end{frame}
\begin{frame}[fragile]
\small
\begin{block}{Multiple Quickfix Lists}
Vim keeps track of the last 10 quickfix lists, so if you perform another grep or make command you don't lose the previous one's results. To switch to the previous quickfix list, you can execute \verb+:colder+, and to switch to the next one you can run \verb+:cnewer+.\\
\end{block}
\vspace{0.5cm}
Because \verb+:cdo+ can be used with any Vim command, it is extremely flexible. The next slide is an example of a time I used \verb+:cdo+ in my work with BlueCat to perform a task which would have been much more tedious without it:\\
\end{frame}
\begin{frame}[fragile]
\frametitle{Cdo With Normal}
\small
In our Golang repositories, we frequently propagate errors including messages and error codes, so that we can identify what error occurred higher in the callstack. The resulting error message from a chain of these \verb+stacktrace.Propagate+ calls is several error messages concatenated together, so we decided to make the propagated error messages start with lowercase letters, otherwise they just look funny. To convert all existing error messages in the current project to start with lowercase letters (with Vim open in the project's base directory), I ran the following commands $\ast$:
\begin{itemize}
\item \verb+:vimgrep /stacktrace\.Propagate/ ./**+
\item \verb+:cdo exe "norm f\"lvu" | update+
\end{itemize}
$\ast$ NOTE: I have changed the commands slightly from the originals (posted in the \#vim-geeks channel), so they would work in a vanilla Vim installation without depending upon any files already being open.
\end{frame}
\begin{frame}[fragile]
\frametitle{Related Topics to Look Into}
\small
Vim keeps track of several other lists similar to the quickfix list. The argument list keeps track of files provided to Vim from the command line when Vim was started up. It comes with its own \verb+:argdo+ command, and \verb+:next+ and \verb+:prev+ commands, similar to the quickfix list equivalents. For more information, see \verb+:help argument-list+. \\
\vspace{0.5cm}
Vim also keeps track of lists called \enquote{location lists}, which are window-local quickfix lists. There are equivalent commands to the quickfix list commands which start with \enquote{l} instead of \enquote{c} to use a location list instead of a quickfix list. To read more, see \verb+:help location-list+.\\
\vspace{0.5cm}
There are many other commands similar to \verb+:cdo+ which act on different sets of lines or buffers. See the help pages for \verb+:bufdo+, \verb+:tabdo+, \verb+:argdo+, \verb+:windo+, \verb+:ldo+, \verb+:cfdo+ and \verb+:lfdo+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Finding Files Quickly}
\small
When I first started using Vim full-time, one of the biggest pain points for me was finding and opening files. Even with tab-completion, I always found \verb+:e+ painfully slow. Vim comes with a file-manager plugin called \verb+netrw+ preinstalled, so that when you open a path which is a directory in Vim, it opens it in netrw so you can navigate to the file you want to open. Even this felt slow. Vim provides a \verb+:find+ command which is actually pretty good when combined with the 'wildmenu' option to turn on tab-completion, but it requires setting the 'path' option correctly, and it doesn't interactively show you matches as you type. I ended up settling on a pair of plugins I have installed, which I think would be sufficient for most Vim users.\\
\end{frame}
\begin{frame}[fragile]
\frametitle{Fuzzy Finder}
\small
Most of the time when I want to open a file, I do so using fzf.vim --- a fuzzy-finder plugin which interfaces with the \verb+fzf+ command-line tool. This plugin provides a \verb+:Files+ command, which lists files recursively from the current directory, then narrows the list as I type. I can select a file to open from the list at any time using \verb+<CR>+, and I can move up or down the list using the arrow keys or \verb+<C-n>+ and \verb+<C-p>+. I also frequently use the \verb+:Rg+ command as an interactive interface for ripgrep to do fast searches of project file contents, and \verb+:Helptags+ to interactively search the names of \verb+:help+ subjects.\\
\vspace{0.5cm}
Note, I always open my Vim instance in the base directory of the project I'm working on, so that my fzf commands search all the project files. This is also important for my project drawer (discussed on the next slide) because it makes sure the full file tree is displayed.
\end{frame}
\begin{frame}[fragile]
\frametitle{Project Drawer}
\small
This is something of a controversial topic in online Vim discussions, but I also like to use a project drawer plugin (to see the argument against this, read \href{http://vimcasts.org/blog/2013/01/oil-and-vinegar-split-windows-and-project-drawer/}{the Vimcasts ``Oil and Vinegar'' article}). I have a keyboard shortcut to toggle my project drawer open and closed, and I have it set to show the location of the current file in the project when I open it. I mainly use this plugin to view the structure of a repository I'm not very familiar with, to quickly switch to another file in the same package, and to quickly create new files without having to type the full file path into an \verb+:e+ command. The project drawer plugin that I use is \href{https://github.com/lambdalisue/fern.vim}{fern.vim}, but \href{https://github.com/preservim/nerdtree}{NERDTree} is definitely the most popular one.
\end{frame}
\section{Configuration}
\begin{frame}[fragile]
\frametitle{Configuration}
\tableofcontents[currentsection]
\end{frame}
\begin{frame}[fragile]
\frametitle{The Vimrc}
\small
Vim's configuration file is located at \verb+~/.vimrc+ or \verb+~/.vim/vimrc+ on Unix systems (neovim's config file is at \verb+~/.config/nvim/init.vim+). This configuration file contains a set of commands which Vim runs every time it starts up. The lines in your vimrc are executed in a special Vim mode called \enquote{ex mode}, which executes commands like the ones you execute in command-line mode, except it executes them one after another without requiring a colon before each command. To read more about ex mode, you can refer to \verb+:help Ex-mode+.
\end{frame}
\begin{frame}[fragile]
\frametitle{Setting Options}
\small
Vim has a bunch of options you can either toggle on and off or set values for to change the behaviour of the editor. If you're curious, you can see a quick listing of options Vim accepts at \verb+:help option-list+. To toggle an option on use the command \verb+:set {option}+, to turn it off use \verb+:set no{option}+, and to change the value of a non-boolean option you can use the command \verb+:set {option}={value}+.\\
\end{frame}
\begin{frame}[fragile]
\frametitle{Learning About Options}
\small
On the next slide I'll go over some options I like to have set. This is a very small subset of the options you can set in Vim, so please explore Vim's help files if you want to learn more - a great place to start would be \verb+:help 05.8+ and \verb+:help 05.9+, which are sections in the user manual which deal with options. You can find my full neovim configuration in \href{https://github.com/alec-gibson/dotfiles}{my dotfiles repo hosted on GitHub}.
\begin{block}{Looking Up Option Documentation}
When you are looking up an option in Vim's help files, the convention is that help topics for options are surrounded with single quotation marks. For example, running \verb+:help undofile+ shows you documentation for the vimscript undofile() function, but \verb+:help 'undofile'+ shows the documentation for the 'undofile' option.
\end{block}
\end{frame}
\begin{frame}[fragile]
\frametitle{Useful Options}
\small
\begin{enumerate}
\item \verb+lazyredraw+: increases performance by stopping Vim from redrawing the screen while executing macros.
\item \verb+showmatch+: when the cursor is on a bracket, highlight the matching bracket.
\item \verb+smartindent+: automatically indent lines - works well for C-like languages.
\item \verb+number+: turn on line numbers.
\item \verb+relativenumber+: number lines relative to the current line (useful for \verb+{num}j+ and \verb+{num}k+ to jump a specific number of lines up or down).
\item \verb+cursorline+: highlight the current line to make it more visible.
\item \verb+undofile+: use persistent undo, so you can close and reopen Vim and still keep the file's undo history.
\end{enumerate}
\end{frame}
\begin{frame}[fragile]
\frametitle{Options Specifically For Searching}
\small
\begin{enumerate}
\item \verb+ignorecase+: makes Vim ignore case by default when searching.
\item \verb+smartcase+: only used in combination with \verb+ignorecase+ - overrides \verb+ignorecase+ if you include a capital letter in your search pattern.
\item \verb+incsearch+: highlight search results as you are typing your pattern.
\item \verb+hlsearch+: after starting your search, highlight search results (you can disable highlighting for the current search by running \verb+:noh+, and it will turn back on when you search again).
\item \verb+inccommand+: \textbf{Neovim Only}, this options lets you see the effects of a \verb+:substitute+ command while you are typing it.
\end{enumerate}
\end{frame}
\begin{frame}[fragile]
\frametitle{Keybindings}
\small
If you find there's a command, or a sequence of normal mode shortcuts which you run frequently, you can bind it to a keymapping to make it faster. The simplest command for setting up a custom keymapping is the \verb+:map+ command which uses the following syntax:\\
\begin{verbatim}
:map {lhs} {rhs}
\end{verbatim}
For example, if you wanted to remap \verb+gw+ so that it saves the currently file, you could put the following line into your vimrc:\\
\begin{verbatim}
map gw :w<cr>
\end{verbatim}
\end{frame}
\begin{frame}[fragile]
\frametitle{You Usually Shouldn't Use :map}
\small
The \verb+:map+ command has a couple major flaws:\\
\begin{itemize}
\item The keybinding is recursive, meaning if any of the keys in the \verb+{rhs}+ of the mapping are themselves the \verb+{lhs}+ of another mapping, that keymapping will also be applied.
\item The keybinding it sets up applies in every Vim mode. Usually this is not what you want, because the \verb+{rhs}+ of your mapping will usually be mode-specific.
\end{itemize}
To solve the first issue, Vim provides a \verb+:noremap+ command which behaves exactly like \verb+:map+ but ignores any keymappings in the \verb+{rhs}+. To solve the second issue, Vim allows you to add prefixes to specify what mode the keymapping applies in, for example \verb+:nmap+ for normal mode, \verb+:imap+ for insert mode and \verb+:cmap+ for command-line mode. Both of these can be (and often should be) combined, for example in the \verb+:nnoremap+, \verb+:inoremap+ and \verb+:cnoremap+ commands. Most of the time, \verb+:nnoremap+ is the command you should be using for remapping keys in normal mode.
\end{frame}
\begin{frame}[fragile]
\frametitle{The Leader Key}
\small
Many people find it convenient to start many of their custom keybindings with a common prefix. To facilitate this, Vim allows you to set a \enquote{leader} key by setting a variable called \enquote{mapleader}. The following command which sets my leader key to \verb+<SPC>+ is in my neovim config file:\\
\begin{verbatim}
let mapleader = " "
\end{verbatim}
After setting this variable, the leader key can be referred to as \verb+<leader>+ in keymappings. For example, I have the following mapping in my neovim configuration to map \verb+<SPC> e+ to run the \verb+:Files+ command from the fzf plugin, to let me find files by name quickly:\\
\begin{verbatim}
nnoremap <leader>e :Files<cr>
\end{verbatim}
\end{frame}
\begin{frame}[fragile]
\frametitle{Abbreviations}
\small
Very similar to mappings, Vim supports a feature called abbreviations, which allow you to set short forms which will expand into their full form after typing a \enquote{non-keyword} character. You can explore setting the 'iskeyword' option, however I just remember that \verb+<SPC>+ and \verb+<CR>+ are both non-keyword characters. This means that, when I type a command-line mode abbreviation, I can just hit \verb+<CR>+ to run it after expanding, or I can type a space if I want to edit the expanded string.\\
\vspace{0.5cm}
The place where I have found abbreviations most useful is in command-line mode, for long commands which I might sometimes want to edit before running. For example, I have the following abbreviation for running all the Golang tests in the current repository in a tmux split (this uses \href{https://github.com/benmills/vimux}{the vimux plugin} for interacting with another tmux split from inside Vim):\\
\begin{verbatim}
cnoreabbrev gta exec "call VimuxRunCommand(
`cd ".getcwd()." && clear && go test ./pkg/...')"
\end{verbatim}
(this is all on one line in my config, but had to be split to fit the slide)
\end{frame}
\begin{frame}[fragile]
\frametitle{Plugins}
\small
Sometimes, despite Vim's expansive feature set, there are some features which are nice to have, but are not built into Vim by default. For these features, there is an expansive plugin library available, some of which add features to Vim, and others make Vim's built-in features more accessible.\\
\vspace{0.5cm}
Vim has a built-in way of managing plugins, which allows you to clone plugins into a particular directory where Vim picks them up and loads them automatically. Personally I have never tried managing plugins in this way --- I adopted \href{https://github.com/junegunn/vim-plug}{vim-plug by junegunn} (the same author who wrote fzf) as my plugin manager quite early on, and it has worked very well for me.
\end{frame}
\begin{frame}[fragile]
\frametitle{Using Vim-Plug}
\small
To install vim-plug, you can download a single vimscript file, and put it in Vim's autoload directory (\verb+~/.vim/autoload+ by default on unix systems). Once vim-plug is installed, you can make a list of plugins for vim-plug to manage in your vimrc. Here is an example to show the syntax:\\
\begin{verbatim}
call plug#begin()
Plug `morhetz/gruvbox'
Plug `lambdalisue/fern.vim'
...
call plug#end()
\end{verbatim}
Each of these plugins correspond with the a username and repository name on GitHub. Once you have set this up in your vimrc, you can use the command \verb+:PlugInstall+ to install all the plugins you have listed, and \verb+:PlugUpdate+ to update all your plugins to their latest versions. If you remove a plugin from the list in your vimrc, you can run \verb+:PlugClean+ to remove unused plugins from your filesystem.
\end{frame}
\begin{frame}[fragile]
\frametitle{fugitive.vim}
\small
fugitive.vim is one of Vim's most popular plugins, written by one of the most prolific and popular Vim plugin authors --- tpope. This plugin provides an interactive git workflow inside Vim, largely through a single \verb+:G+ command. When run on its own, this command opens a split window which shows the current status of the git repository Vim was opened inside. This status window has several custom keybindings which let you perform convenient git operations:
\begin{itemize}
\item \verb+<C-n>/<C-p>+: go to the next/previous changed file, or changed hunk inside an expanded file diff
\item \verb+=+: expand or collapse the current file diff
\item \verb+-+: stage or unstage the file that the cursor is currently over
\item \verb+cc+: create a commit containing the staged changes, and start writing the commit message (you can quit the commit window to cancel the commit, or write it to finalize the commit).
\end{itemize}
This plugin also allows you to view git logs, blames, and execute arbitrary git commands by using the \verb+:G+ command as if it is \verb+git+ on the command line.
\end{frame}
\begin{frame}[fragile]
\frametitle{fzf.vim}
\small
fzf.vim is another extremely popular plugin. It provides you with a standard user interface for fuzzily matching entries in a list. This plugin allows you to implement your own custom commands using this fuzzy match feature, however it also comes with several very useful commands out of the box:\\
\begin{itemize}
\item \verb+:Files+: open a file by fuzzily matching filenames enumerated recursively from Vim's base directory
\item \verb+:Rg+: fuzzily search the results of a \verb+ripgrep+ command (ripgrep is a trendy modern implementation of grep which is very fast)
\item \verb+:Helptags+: fuzzily search tags for topics in Vim's help files
\item \verb+:Buffers+: swap buffers by fuzzily matching the names of open files
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Language Server Protocol}
\small
For a long time, there has been a lively debate online regarding whether Vim can really replace an IDE, because of its lack of some language-specific features such as automatic imports, jumping to symbol definitions / references / interface implementations, autocompletion, the ability to view documentation, etc.\\
\vspace{0.5cm}
As part of the development of Visual Studio Code, Microsoft developed the Language Server Protocol, which was standardized in 2016. This protocol allows text editors to be decoupled from language support. All the editor needs is the ability to act as an LSP client, then it can interact with separate language servers, which provide support for a particular language.\\
\vspace{0.5cm}
Currently \verb+coc.nvim+ is the most popular LSP client implementation for Vim and Neovim. It is unique compared to other LSP client implementations in that it also supports \enquote{coc extensions}, which are forked directly from VSCode extensions. These extensions can provide more features than the community maintained language servers. If you want IDE-like autocompletion and language-specific features in Vim, \verb+coc.nvim+ is currently the easiest way to achieve this.
\end{frame}
\section{Further Learning}
\begin{frame}[fragile]
\frametitle{Useful Topics Not Covered}
\small
Unfortunately, there is not enough time in this presentation to cover all of Vim's features, or even all the features I use. The following topics are still very useful to know about, despite not fitting into my talk.
\begin{itemize}
\item Marks (\verb+:help 03.10+)
\item Vimscript (warning, this one is long: \verb+:help usr_41.txt+)
\item Write and execute your own functions (\verb+:help user-functions+, \verb+:help :call+)
\item Creating custom commands (\verb+:help user-commands+)
\item Autocommmands (\verb+:help 40.3+)
\end{itemize}
If you want to have your mind blown by a Vim plugin, check out \href{https://github.com/puremourning/vimspector}{vimspector}, which uses multiple Vim windows to create a full IDE-like debugger inside Vim.
\end{frame}
\begin{frame}[fragile]
\frametitle{Links For Further Learning}
\small
I have found the following resources useful while learning to use Vim. Consider taking a look if you feel like learning new Vim features, or gaining a new perspective on features you already know about.
\begin{itemize}
\item Max Cantor's talk \href{https://www.youtube.com/watch?v=XA2WjJbmmoM}{\enquote{How to Do 90\% of What Plugins Do (With Just Vim)}}
\item Erik Falor's talk \href{https://www.youtube.com/watch?v=MquaityA1SM}{\enquote{From Vim Muggle to Wizard in 10 Easy Steps}}
\item Chris Toomey's talk \href{https://www.youtube.com/watch?v=wlR5gYd6um0&t=132s}{\enquote{Mastering the Vim Language}}
\item Drew Neil's book Practical Vim and the content on his website: \href{http://vimcasts.org}{vimcasts.org}
\item Romaine Lafourcade's \href{https://gist.github.com/romainl/4b9f139d2a8694612b924322de1025ce}{Vim-related GitHub gists}, and the articles from his Vim-themed online advent calendar: \href{https://vimways.org/2019/}{Vimways}
\end{itemize}
\end{frame}
\section{Goodbye}
\begin{frame}[fragile]
\centerline{\huge All Praise VI VI VI}
\vspace{0.5cm}
\centerline{\huge Editor of The Beast}
\begin{figure}
\centering
\subfloat{{\includegraphics[width=0.3\linewidth]{saintignucius.jpg} }}% Created by Wouter van Oortmerssen
\qquad
\subfloat{{\includegraphics[width=0.3\linewidth]{freebsd-daemon.png} }}% Created by Poul-Henning Kamp under the beer-ware license (https://svnweb.freebsd.org/base/head/share/examples/BSD_daemon/README?view=markup)
\end{figure}
\end{frame}
\end{document}