Vim Best Practices For IDE Users
Vim Best Practices For IDE Users
If you don’t have time to read the Vim User Manual, I sifted through it for
you with a focus on IDE users.
Sebastian Carlos
·
Follow
Published in
Better Programming
·
49 min read
·
Feb 23, 2023
13
Amazon
Introduction
Vim is more than just a text editor. It’s a powerful tool that can boost your
productivity and creativity.
You’ve probably heard the endless debates about Vim vs NeoVim, Vim vs
Emacs, Vim vs IDEs, and editors vs IDEs. You’ve also probably wondered if
you should customize Vim to act like an IDE or your IDE to act like Vim.
What if I told you that modern IDEs can emulate most of the Vim features
you love, even some advanced ones? In this guide I’ll show you 90 tips to
get familiar with Vim, focusing on Vim emulation on popular IDEs like VS
Code and IntelliJ IDEA.
You’ll see that only a few of the frequently used features are not supported,
and I’ll point them out for you. By the end, you’ll have a better idea of what
Vim emulation can do, and you can use this knowledge to decide which
environment is best for you.
If you are experienced with Vim, you can skip ahead and skim through the
headlines. If something piques your interest, feel free to deep dive.
Resources
Other resources that you might want to keep in mind include:
• The official cheat sheet, “Quickref”.
• Vim tutor. An official 30-minute interactive tutorial built into Vim itself.
(Now it’s built into the JetBrains Vim plugin too.)
• The Commands Index. An index containing every single Vim command.
• The “you don’t grok vi” answer on StackOverflow. Undoubtedly the
greatest piece of literature on StackOverflow.
• The browser game Vim Adventures. The first level is free. For $25 you
unlock a pretty legit learning experience to develop muscle memory.
• The guide “Learn Vim the Smart Way”.
• The Vim Wiki, the greatest repository of Vim tips.
• Throughout this guide you’ll see links to vimhelp.org, an HTML version
of the Vim help pages which is kept up-to-date automatically with Vim’s
built-in help.
Which Vim mode should you use?
For JetBrains editors (IntelliJ, WebStorm, PyCharm and others, and soon
Fleet), there is an excellent Vim plugin called IdeaVim.
If you are using VSCode, there are two options: The first is the standard Vim
plugin, which is very popular these days. The second is vscode-neovim,
which creates a Vim mode by embedding NeoVim itself. Note that the
standard Vim plugin also has an experimental embedding of NeoVim to
enable some features.
It is worth noting that the JetBrains team has also considered embedding
NeoVim, but it is not likely to happen in the near future, and they have their
reasons.
In addition, many users praise the Vim plugin for Visual Studio, but I do not
use that IDE myself, so I will not include it in this guide.
With that out of the way, let’s dive in!
Section 1: The first steps in Vim
1. The tilde (~) lines indicate lines not in the file
Maybe you were wondering what those funny symbols on the edge of your
screen are when you open Vim on a terminal.
They are useful to differentiate empty lines from the abyss after the file
ends. Sure, IDEs use line numbers to convey the same information, but Vim
is classy enough to predate innovations like “line numbers are on by
default.”
As an IDE user, you won’t see the tildes.
2. Vim is a “modal” editor
Vim is modal. That means that the editor behaves differently, depending on
which mode you are in.
Most GUI editors are what is called “modeless,” in which all commands can
be performed using the same set of keys at all times. They provide a more
intuitive and user-friendly interface, especially when paired with innovations
such as the mouse.
However, advanced users claim that modal is faster and more powerfull,
even if there is a certain delay introduced by changing mode.
3. The main modes are “Normal mode” and “Insert Mode”
In Normal mode the characters you type are commands. In Insert mode the
characters are inserted as text.
Vim starts in Normal mode. There are several ways to go to Insert mode, the
most common is the i command (i for Insert). Then you can enter text. To go
back to Normal mode (no matter what mode you are in), press <Esc>.
Some users find that the <Esc> key can be difficult to reach, so they remap it
to a more accessible key like “Caps Lock.” I use a keyboard with a thumb
cluster, so I have my <Esc> key there.
The normal in other GUI editors is that you can enter text whenever you
want. But in Vim, “normal” is typing commands. Welcome to the new
normal.
To better tell that you are in Insert mode, Vim displays an --Insert-- text at the
bottom of the screen and changes the look of the caret. The IDEs display it
too.
4. Use “hjkl” to move around
Ah yes, the dreaded “hjkl” is a true test of courage. It’s the way to tell adults
from kids in the Vim world.
You can use h to go left, j to go down, k to go up, l to go right:
Historically, this comes from the keyboard Bill Joy was using when he
created “vi”, the predecessor of Vim in 1976:
The modern arrow keys are also available for Vim, but a lot of people think
that the “hjkl” keys are more accessible for touch typing, as you don’t have
to move the hands from the “home row.”
This is also true for non Qwerty users: Most people agree that the default
locations of the “hjkl” key are also comfortable in both Colemak and
Dvorak.
Are you still on Qwerty and don’t touch type? Consider upgrading your
keyboard skills with this guide:
You’re Missing Out on The Best Keyboard Experience
It’s 2023. There’s no reason to use your grandparent’s keyboard any longer.
sebastiancarlos.com
One way to remember these commands is that h is on the left, l is on the right
and j points down. But you can use whatever mnemotechnic you want.
You’ll get used to them soon.
5. Delete characters with “x”
To delete a character under the cursor, press x. (This is a throwback to the
typewriter days, when you deleted by typing xxxx over words.)
In most text editors, the undo and redo commands are performed using
the CTRL-Z and CTRL-SHIFT-Z shortcuts respectively.
Vim instead uses u and CTRL-R respectively.
Additionally, Vim has a U (undo line) command to undo all changes made to
a line in one step. Note that the U command is a change by itself, which can
be undone and redone with u and CTRL-R.
IDEs on Vim mode allow you to use either u/CTRL-R or CTRL-Z/CTRL-SHIFT-Z.
It’s up to you to go “full Vim” or to keep using familiar shortcuts. In this
case, I prefer the Vim way because the u key is very ergonomic.
Some VSCode users have encountered problems with Vim’s undo stack
being out of sync with the IDE’s stack.
8. Other ways to insert text: “I”, “a”, “A”, “o”, “O”
Insertion is nice, and there are many ways to go about it:
i — insert text before the cursor:
All good things must come to an end, including the “I can’t exit Vim” meme.
To exit, use the ZZ command. This command writes the file and exits.
To quit without saving changes, do :q!. The colon (:) enters Command-line
mode, the q command tells the editor to quit, and the override command
modifier (!) is needed because Vim is a bit cheeky and doesn’t want to throw
unsaved changes.
If you want to throw the changes but continue editing the file,
the :e! command reloads the original version of the file.
There’s also ZQ , which does the same as :q!. Pick your poison!
On IDEs, these commands won’t allow you to close the IDE itself. They just
attempt to close the current file.
IDEs tend a lot more towards constant auto-save, so these commands are
more permissive than their terminal Vim counterparts because you are more
likely to find that your changes are already saved when you try to close a
file.
12. Finding :help
There is also the e command that moves to the next end of a word
and ge, owhich moves to the previous end of a word:
If any of these commands reach the end of the line, it will move into the next
or previous line accordingly.
14. Words vs WORDS
In Vim there are two kind of words: Words and WORDS.
The commands on the previous section work on “words,” soon we’ll see
other commands that work on uppercase “WORDS”
But what is the difference between the two? A good rule of thumb is “word
until punctuation, WORD until whitespace.” But if you want the gory
technical details, read on:
A word is:
• A sequence of letters, digits, underscores, and some special ASCII
characters (as specified in the default value of the iskeyword option: @,48–
57,_,192–255).
:set iskeyword+=-
The $ command takes a count. It causes the editor to move to the end of a
following line.
For some mysterious reason, the 0 and ^ commands don’t take a count. No
one knows why. I guess this is the kind of bizarre behavior that you have to
expect when using a 50 year old editor. In any case, most people don’t even
use the $ count.
17. Single-character search commands: “f”, “F”, “t”, “T”
The command fx searches forward in the line for the single character “x”.
Note that you can search for any character you want, but it will search only
in the current line. f stands for “Find”.
F does the same but it searches backwards.
t and T are very similar but they only go “till” one character before the
searched command.
Any of these four commands can be repeated with ;. , repeats the search in
the other direction.
18. Matching a parenthesis or bracket with “%”
Let’s say you are on a parenthesis or bracket and you want to jump to its
match, just press % and you’re done.
Now, if you are not on a parenthesis or bracket, pressing % will look for the
next parenthesis forward on the current line, and try to jump to it’s match.
This behaviour is a bit quirky for my tastes, so I try to only press % when
I’m on top of a parenthesis already.
On Vim, it’s recommended to install the “matchit package,” which
enhances % to allow jumping between HTML tags, etc. The only reason why
it’s not installed by default is because of backward compatibility with vi.
JetBrains supports it. VSCode doesn’t, but there’s an open issue and
a plugin.
19. Moving to a specific line: “G”, “gg”, “H”, “M”, “L”
With a count, the G command takes you to a specific line. 17G takes you to
line 17.
Without a count, G takes you to the last line.
gg is a shortcut for 1G, which takes you to the first line. You can think that
you just lost a match on League of Legends and you said “gg”, which means
that you need to get back to work and go to the top of a file.
Another way to move to a line is using the % command with a count. For
example 50% moves you to halfway the file.
To navigate to the top, middle, or bottom of the visible screen,
press H (high), M (middle) or L (low). By default there is a scroll offset
setting that prevents the cursor from reaching the very edge of the screen. I
like this default, but you can change it if you want. On JetBrains you can
change the scrolloff option directly in the .ideavimrc file, which we will discuss
later on.
20. Telling where you are: the mystical power of line numbers.
Showing the line number in your editor? Are innovations like this really
possible in our day and age?
They sure are, you can enable them by running the command :set number,
which sets the “number” option.
If you miss your prehistoric coding experience, just run :set nonumber. Since
“number” is a boolean option, prepending “no” to its name switches it off.
Some advanced users like to set the option :set relativenumber, which shows the
line numbers relative to the line that has the cursor. This is useful for vertical
navigation with j and k preceded by a count: You can just type the relative
number as the count. Personally, I prefer other ways to navigate vertically, as
I’ll show you later.
Again, on IDEs you don’t have to worry about :set number because line
numbers are on by default. Both IDEs support :set relativenumber.
21. Scrolling around: “CTRL-U/D”, “CTRL-E/Y”, “CTRL-B/F”
CTRL-U moves your viewport window half a screen up, while CTRL-D moves
the viewport half a screen down. You will be using them all the time. You
can remember them by thinking “Up, Down.”
If you want to move the viewport just by one line, use CTRL-E to go forward
and CTRL-Y to go backwards.
If you want to go up and down by one full screen, you can do CTRL-
B (backwards) and CTRL-F (forwards). But I don’t recommend these last two,
they are pretty dizzying in practice.
22. Aligning the cursor with the viewport: “zz”, “zt”, “zb”
Sometimes your cursor is close to the bottom of your viewport but you want
it on the center. Easy, just press zz. Your cursor will remain on the same line
but the viewport itself will scroll so that the line with the cursor is at the
center of the screen.
Similarly, the zt command puts the cursor line at the top, and zb at the
bottom.
23. Searches: “/”, “?”, “n”, “N”
Now we’re getting into the most advanced navigation technique in all of
Vim.
To search for a string, use the / command. If you want to find the word
“include”, for example, type /include, then press <Enter> to execute the
command.
To find the next occurrence of the same string use the n command.
Now that you have a lot of options that you like, it might be a good idea to
write them into a .vimrc file so that they load every time you start Vim.
If you are using Vim mode on a JetBrains editor, it comes with it’s
own .ideavimrc. It creates it for you in your home directory.
If you are using Vim mode on VSCode, you need to change the settings
manually, but there’s experimental support for a .vimrc file too.
28. Using regular expressions on search
Yes, Vim search with the / and ? commands support regular expressions.
If you are familiar with regular expressions, you’ll find that they work pretty
much as you would expect.
For instance, the ^ character matches the beginning of a line, and
the $ character matches the end of a line. The . (dot) character matches any
character.
For full details, check here.
Keep in mind that, because of the regular expression support, the
characters .*[]^%/\?~$ have special meanings. If you want to use them in a
normal search you must “escape” them by putting a \ in front of them.
29. Using marks: `{mark}, CTRL-O, CTRL-I
When you make a jump to a position, say with the G command, Vim
remembers the position from before this jump. This position is called a
mark. To go back where you came from, use the `` command.
If you use the same command a second time you will jump back again. That
is because the ` command is a jump on itself.
Generally, every time you do a command that can move the cursor further
than within the same line, this is called a “jump”. j and k are not considered
to be a jump, even when you use a count to make them move the cursor
quite a long way away.
Pressing `` repeatedly will bounce you back and forth between two single
positions.
The CTRL-O command jumps to older positions (Hint: O for older). CTRL-
I then jumps back to newer positions (Hint: for many common keyboard
layouts, I is just next to O). These commands even take you across files.
The :jumps command gives a list of positions you jumped to:
leap.nvim
It is my opinion that this is the single best way to navigate on text files using
your keyboard, even if purist would like to see me six feet underground for
this statement.
And I’m not the only one, as both Vim modes in JetBrains
editors and VSCode support this. I heavily encourage you to enable it and
never look back.
You might wonder, which key should you use to activate “EasyMotion”? It’s
up to you, but the acclaimed author of leap.nvim suggests that the s key is a
reasonable choice for this kind of motion, even if you lose the “s = cl”
shortcut, which we’ll see in the next section.
Section 3: Making Small Changes
32. Operators and motions: “d”
The dw command deletes a word. You may recognize the w command as the
move word command. In fact, the d command may be followed by any
motion command, and it deletes from the current location to the place where
the cursor winds up.
The 4w command, for example, moves the cursor over four words.
The d4w command deletes four words:
If at any point you change your mind, press <Esc> and you’ll leave Visual
mode.
39. Visual Line Mode: “V”
If you want to work on whole lines, use “V” to start Visual Line Mode. You
will see right away that the whole line is highlighted. When you move up or
down, the selection is extended whole lines at a time.
40. Visual Block Mode: “CTRL-V”
If you want to work on a rectangular block of characters, use CTRL-V to
start Visual Block Mode. This is not very useful, but I guess it’s useful when
working on tables or on some fancy ASCII art.
Actually, this mode is quite good for inserting text on several lines
simultaneously. In a sense, it’s a precursor of multi-caret editing. We’ll show
you how it works later.
41. Hello from the other side: “o”, “O”
If you have selected some text in Visual mode, and discover that you need to
change the other end of the selection, use the o command (Hint: o for other
end). The cursor will go to the other end, and you can move the cursor to
change where the selection starts. Pressing o again brings you back to the
other end.
When using blockwise selection, you have four corners. o only takes you to
one of the other corners, diagonally. Use O to move to the other corner in the
same line.
42. “Putting” it all together: “p”, “P”
When you delete something with d, x, or another command, the text is
saved. You can “paste” it back by using the p command. (The Vim name for
“paste” is “put”, if you go around saying “paste” you’re gonna sound like a
newbie).
If you delete an entire line, the p command puts the text line below
the cursor. If you delete part of a line (a word, for instance), the p
command puts it just after the cursor.
The P command puts text like p, but before the cursor.
43. “Yank” is the new “copy”: “y”, “yy”
To copy text from one place to another, you could delete it, use u to undo
the deletion and then p to put it somewhere else.
There is an easier way: yanking. The y operator copies or “yanks” text into a
“register”. Then a p command can be used to put it. We’ll take a deeper look
into registers later on, but you can think of them as “places to keep stuff”.
Yanking is just a Vim name for copying. The c letter was already used for the
change operator, and y was still available. Calling this operator “yank” made
it easier to remember to use the y key.
Since y is an operator, you use yw to yank a word. Notice that yw includes the
white space after a word. If you don’t want this, use ye.
The yy command yanks a whole line, just like dd deletes a whole line.
And remember, for the love of God, please enable the “yank
highlighting” plugin, which allows you to visualize the thing that you just
yanked. This is vital for getting a hang of the yank.
Both VSCode and JetBrains editors support it.
44. Return to civilization — using the clipboard: “*
Operating systems have a system-wide “clipboard”, this is the thing that you
copy and paste into, allowing a mind-blowing level of interoperation
between different software tools.
You can “yank” and “put” into and from the clipboard. For that you can use
the normal y (yank) and p (put) commands, but prepend “* (double-quote
star) before them.
What is this weird "* syntax? Well, as we said, Vim has registers. The
general syntax to get the content from a specific register is "a, where a is the
register symbol. In this case, star (*) is the symbol for the “selection
register,” a special register that’s connected to the system clipboard.
45. Object-oriented programming: Text Objects
Get ready for one of the most important tools in your Vim toolset: Text
Objects.
If the cursor is in the middle of a word and you want to delete that word,
usually you need to move back to its start before you can do dw.
But there is a simpler way, dawg. Just type daw:
" You can write comments by starting a line with double quotes (")
" Unlike Command-line mode, you don't neet to type a colon (:) before.
set number
In Unix systems, this file is usually in your home directory: ~/.vimrc. NeoVim
is polite enough to follow recent conventions and avoid polluting your home
directory: It puts the vimrc file in ~/.config/nvim/init.vim.
As mentioned, VSCode has experimental vimrc support, but it only supports
mappings. For options, you can just type them as commands and VSCode
will preserve them for the next time you open the editor. Also, most of the
options that you might want to configure for its Vim mode are already
available as regular settings on the Vim extension.
In JetBrains editors, there is a very capable .ideavimrc file in which you can
add both options and mappings. This file is placed in your home directory,
but you can edit it quickly with a button on the status bar.
Also, .ideavimrc comes pre-loaded with some options taken directly from
Vim’s official defaults.vim, a file with nice improvements for people who don’t
care about backward compatibility with vi.
50. The “undofile” option: Persistent Undo
An underrated feature of Vim, which is off by default, is the undofile option.
This will store the undo information in a file. The result is that when you
change a file, exit Vim, and edit the file again, you can undo the changes
made previously.
When undofile is on, the undo information is normally saved on a file in the
same directory, which I find quite annoying. This can be changed with
the undodir option. You can find more information about undo
persistence here.
Neither VSCode nor JetBrains editors support this feature, although there’s
an open issue for VSCode. But to be fair, I think this IDE-like behavior is
better served by an IDE feature that preserves the local history of your files:
On JetBrains this is called “Local History”, and on VSCode it’s
called “Timeline View”.
51. Getting rid of other annoying Vim files on your directory
Besides the undo files, using old-school Vim will also generate backup
files (if enabled) and swap files to recover from crashes. You can configure
Vim to use a different directory for these files to remove them from your
directory.
Or just ignore them on your .gitignore file to live in blissful ignorance:
*.swp
*.swo
But if you don’t use the original Vim at all, you don’t need to worry about
this.
52. Sourcing with “source”
One of the commands that you can run in your vimrc file is “source”. This
command “sources”, which is a fancy Linux way to say that it will execute
the commands in another file. This is useful for splitting your vimrc file into
multiple files, or for loading a file with mappings from another vimrc file.
JetBrains supports this. If you want to reuse you configuration between Vim
and Vim mode, you can put the following on your .ideavimrc file:
source ~/.vimrc
After you execute the :map command, all you have to do to put {} around a
word is to put the cursor on the first character and press F5.
In this example, the trigger is a single key, but it can be any string. Keep in
mind that when you use an existing Vim command, that command will no
longer be available. One key that can be used without conflicts is the
backslash (\). You can follow it with other characters:
:map \p i(<Esc>ea)<Esc>
:map \c i{<Esc>ea}<Esc>
The :map command (with no arguments) lists your current mappings for
normal mode. The command with no arguments is supported by JetBrains
but not yet by VSCode.
We’ll take a closer look into mappings later on.
55. Plugins and Packages
Vim’s functionality can be extended by adding plugins. A plugin is nothing
more than a Vim script file loaded automatically when Vim starts.
There are some shenanigans to remember when using plugins, like
the runtimepath option, help files, and so on. To improve some of these issues,
Vim 8 (released in 2016) introduced the concept of “package,” which is
basically a collection of plugins that automate some of these pain points.
One example of a package is the aforementioned “matchit” package.
Instead of dealing with plugins and packages directly, many Vim and
Neovim users prefer to use package managers like vim-plug and lazy.nvim.
The plugin ecosystems and communities of both Vim and NeoVim are
strong and active.
For Vim mode, the situation is much simpler as fewer plugins are available.
In JetBrains, you can simply check the list of available plugins and follow
the instructions for each one. Same for VSCode.
56. More about options
If you want to know all about Vim options, you have two options (no pun
intended):
• You can check the full alphabetical list of options in the documentation.
Lord have mercy.
• Or you can type :options on Vim, which opens a friendly UI to navigate all
options grouped by sections.
In any case, expect only some options to be useful to you, and many won’t
work on Vim mode.
57. Fix your wrapping with “whichwrap”
One of the options that you should change from the default is whichwrap.
You see, on every text editing software, pressing the left key at the
beginning of a line will take you to the end of the previous line, and pressing
right at the end of a line will take you to the beginning of the next line.
Don’t believe me? Open notepad and try it. It’s very convenient.
But Vim is not like that. The cursor just stays there. To fix it, do this:
set whichwrap=b,s,<,>,h,l,[,]
:set iskeyword&
Another funny tidbit from this section of the docs is :TOhhtml, a weirdly
capitalized command that turns whatever file you open into an HTML file
with syntax highlighting. You could use it to share code with others, but I
have no idea what’s a reasonable use case for it.
Section 5: Editing more than one file
59. Vim file commands that you can’t use in Vim mode
Vim has a lot of commands for working with multiple files and switching
between them: :edit, :find, :hide, :next, :previous, :args, :first, :last and :saveas.
No Vim mode fully supports these commands. And frankly, they don’t make
much sense on IDEs anyway. At least, they won’t be practical until the IDEs
implement related features like filename tab completion.
Naturally, your IDE already supports working with multiple files, usually
through more sensible shortcuts and GUIs.
60. Jumping from file to file: CTRL-^
To quickly jump between two files, press CTRL-^ (or CTRL-6). It’s a quick way
to toggle between the current file and the last edited file.
It’s supported on JetBrains but not on VSCode.
61. File marks (aka Global marks)
Previously we saw that you can place your own named marks (a through z).
That works within one file. Each file has its own set of marks, they are local
to the file.
There are also marks with an uppercase letter. These are global, and they can
be jumped to from any file.
It’s often useful to think of a simple connection between the mark letter and
where it is placed. As a boomer example, you can use the H mark in a header
file, M in a Makefile, and C in a C code file.
Both editors support lowercase and uppercase marks:
• VSCode shows the marks on the gutter by enabling the “Show Marks in
Gutter” setting.
• JetBrains shows the global marks on the gutter as they are integrated
with the IDE’s “Mnemonic Bookmarks” feature, which is basically the
same feature. There’s an issue to also show the lowercase marks on the
gutter.
62. Using registers
When you want to copy several pieces of text from one file to another, it
might save time to copy each piece of text to its own register.
Here we will use the registers named a to z (but just like Skywalker, soon
you’ll find out there are others). To copy a sentence to the y register,
type “fyas. The yas command yanks a sentence like before (yas queen!). It’s
the “f that tells Vim to place the text in the f register.
You can then paste from a specific register with “fp. The text stays in the
register until you yank something else into it, so you can put it in as many
times as you desire.
As a reminder, the star (*) register is a special register that allows to yank
and put to the system clipboard (by doing "*).
As another reminder, deleting and changing text also saves it to a register.
For example, you can type "fdaw to delete a word and save it to the f register.
The :registers command shows you the text on every register. This works on
both VSCode and JetBrains.
Section 6: Splitting windows
63. Split your editor
Screens are big these days, so it makes sense to split them to see multiple
files at the same time, or different parts of the same file at the same time.
Most editors can be split into different rectangular regions. On Vim, these
regions are called “windows,” a term that should not be confused with the
concept of overlapping windows on modern GUIs like operating systems.
To open a new window, you can use the :split command (or CTRL-W s), which
splits the screen horizontally into two windows showing the same file. To
split them vertically, use :vsplit or CTRL-W v.
CTRL-W w can be used to jump between all the open windows. It wraps
around once it reaches the last window.
You’ll notice that all the window commands on Vim have the form CTRL-W
{char}, in which you must press CTRL-W first and then another character.
(CTRL-W CTRL-{char} does the same thing, in case you let go of the CTRL key
a bit later.)
To close a window, use the :close command (or CTRL-W c).
The :only command (or CTRL-W o) closes all windows except the current one.
64. Changing window size
While there are commands to change a window size (CTRL-W + and CTRL-W -),
they are extremely clumsy.
Fortunately, and to the surprise of everyone, the Vim documentation actually
recommends using the mouse (!!) to resize windows. Yes, Vim has mouse
support. Naturally, if Vim does it, you should feel no shame at all when
resizing splits with the mouse on your IDE.
For any tmux user out there: Mouse resizing also works on tmux, but you
need to enable it.
65. Moving between windows
Simply use CTRL-W followed by any of the navigation keys (h, j, k, l).
If what you want to do is move the windows themselves because they are
out of order, do CTRL-W followed by the uppercase version of the navigation
keys (H, J, K, L). Unfortunately, this is not supported in VSCode or JetBrains.
66. Vim diff
Vim has some diff functionality to see the difference between two files or
between a modified file and its original version.
Neither Vim mode supports this. But let’s be honest: if you are using an IDE,
you probably want to use its built-in diff. It’s one of those things that looks
way better with a GUI.
Still, it’s worth remembering the CLI command vimdiff (or nvim -d for
NeoVim) if you want to quickly see the diff between two files in your
terminal. It’s better than the colorless diff command.
67. Vim tabs
It must be observed that every single modern GUI editor known to humanity
— including but not limited to Sublime Text, Atom, VSCode, and JetBrains
editors — let you split the editor and then have tabs inside each split.
But Vim does the opposite — It has tabs that contain splits (aka windows):
This is just a design difference. There’s no one correct way to design the
layout of an editor. Both have advantages and disadvantages.
In fact, Vim only visually doesn’t have tabs in each window — Vim users
can still switch what file each window is displaying, and they usually don’t
care about amenities like having a tab bar in each split.
You actually have more freedom in Vim because a file doesn’t belong to
some window; they’re entirely independent. Any window can display any
file.
The Vim tab system is not really a different or opposite way of doing it. It’s
an additive feature on top of the usual windows: You can think of Vim tabs
as different layouts (arrangements of windows) for different contexts. In fact
a similar feature is called “Layouts” on JetBrains.
This diagram shows how Vim users think about their editing environment. It
shows the distinction between layout elements (tabs and windows) and files
(aka buffers):
Naturally, Vim mode plugins don’t support Vim-style tabs as they just don’t
exist in IDEs. Still, the following Vim commands for tabs have been
repurposed by both VSCode and JetBrains to work on the IDE-style tabs:
• gt Goes to the next tab. If preceded by a number, it goes to the tab with
that number. (The first tab is 1, not 0.)
• gT Goes to the previous tab.
If you want to close a tab, use any of the Vim commands that close files,
because IDE tabs are basically just files.
Section 7: Using the GUI
68. Vim has an official GUI edition: gVim
Unknown to most (although some Vim users swear by it), Vim has a GUI
edition called gVim. It’s the same experience, but with some improvements
to bring Vim into the ’90s, like menus, scrollbars, and (gasp!) a toolbar.
As an IDE user, you are even deeper into the GUI life, so this information
won’t affect you except for the satisfaction of knowing that even an old-
school editor like Vim is flirting with the powers of graphics and non-
monospaced fonts.
69. The forbidden mode: Select mode
Even more unknown is Vim’s elusive “select mode.” Most people who find
themselves there do so by accident.
Select mode is like Visual mode, because it is also used to select text. But
there is an obvious difference: When typing text, the selected text is deleted
and the typed text replaces it.
You need to enable it to use it, but it’s enable by default on Windows when
trying to select with the mouse.
In short, “select mode” is a haphazard mode added just to placate some
Windows users who can’t handle an editor that does its own thing when
selecting text with a mouse.
Section 8: Making big changes
70. Record and playback commands: Vim macros
Of all the Vim features we’ve seen, I guarantee that none will bring you
more satisfaction than macros.
You already know that the . (dot) command repeats the preceding change.
But what if you want to repeat anything at all, like a sequence of multiple
changes and movements?
That’s where macros, or “command recording,” come in. There are three
steps:
1. The q{register} command starts recording keystrokes into the register
named {register}. The register name must be between a and z.
2. Type your commands.
3. To finish recording, press q (without any extra character).
You can now execute the macro by typing the command @{register}.
Let’s look at an example. You have a list of filenames that look like this:
stdio.h
fcntl.h
unistd.h
stdlib.h
#include "stdio.h"
#include "fcntl.h"
#include "unistd.h"
#include "stdlib.h"
We’ll see more Ex commands later on. But I’ll continue to refer to them as
command-line commands in this article.
78. Command ranges
Let’s see what else we can do with the “range” section of a command.
The simple form of a range is {number},{number}. For
example, :1,5s/this/that/g executes the substitute command on the lines 1 to 5
(line 5 included).
A number can be used to address one specific line.
Some commands (not :substitute) work on the whole file when you do not
specify a range. To make them work just on the current line, you can use
the . (dot) address.
The $ character refers to the last line. For example, to substitute in the lines
from the cursor to the end, do :.,$s/yes/no/.
The % range that we used before, is actually a short way to say 1,$.
79. Using patterns in command ranges
It’s time to look at an advanced example.
Suppose you are editing a chapter in a book, and want to replace all
occurrences of “grey” with “gray”. But only in this chapter, not in the next
one. You know that only chapter boundaries have the word “Chapter” in the
first column. This command will work then:
:?^Chapter?,/^Chapter/s=grey=gray=g
You can see a search pattern is used twice. The first ?^Chapter? finds the line
above the current position that matches this pattern. Similarly, /^Chapter/ is
used to search forward for the start of the next chapter. Note that the
matching ? and / at the end of the search patterns are only used to separate
the patterns from everything that follows.
To avoid confusion with the slashes, the = character was used in the
substitute command here. A slash or another character would have worked as
well.
80. Add and subtract in command ranges
You can add an offset of lines to any item on a range.
Here, for example, we search for a pattern and then use the line above
it: /Chapter/-1
And here we specify the range that starts three lines below the cursor and
ends five lines before the last line in the file: .+3,$-5
81. Other range tricks: Marks, visual mode, and number of lines
shortcut
Instead of figuring out the line numbers of certain positions, remembering
them and typing them in a range, you can use marks: :’t,’b
You can select text with Visual mode. If you then press : to start a colon
command, you will see this: :’<,’>
The ‘< and ‘> are actually marks, placed at the start and end of the Visual
selection. you can mix the marks with other items if you want: :’>,$
One cool trick: When you know how many lines you want to change, you
can type the number and then :. For example, when you type 5:, you will
get: :.,.+4. Thus, it spans five lines.
82. The global command
The :global command is one of the more powerful features of Vim. It allows
you to find a match for a pattern and execute a command there. The general
form is:
:[range]global/{pattern}/{command}
Since the pattern we are looking for contains a slash, this uses the plus
character to separate the pattern. Next comes the substitute command that
changes “foobar” into “barfoo”. The default range for the global command is
the whole file. Thus no range was specified in this example.
The global and normal commands are supported by JetBrains
but not by VSCode.
83. Advanced Visual Block tricks: I, A, $, c, C, r, u, U, ~ J
Let’s go back for a moment to Visual Block mode and see what are some
advanced tricks that you can do when a block of text is selected.
The command I{string}<Esc> inserts the text {string} in each line, just
left of the visual block. As you type, the text appears on the first line only.
After you press <Esc> to end the insert, the text will magically be inserted in
the rest of the lines contained in the visual selection.
The A command works the same way, except that it appends after the right
side of the block.
If you have a block selected, you can use $ to make the block extend to the
end of each line.
The Visual block c command deletes the block and then throws you into
Insert mode. C is the same but additionally deletes everything from the block
to the end of the line.
To fill the entire selection with one character, use r. To make all characters
uppercase, use U. For lowercase use u. To swap case do ~. To join all the
lines in the use J. Note that these commands work also on visual and visual
line modes.
84. Shifting (aka Indentation)
To shift lines to the right or to the left, you have a few options.
In normal mode, press << or >>. This only shift the current line.
In any visual mode, press < or > to shift all the lines in the selection.
The downside of the method above is that the selection is lost after shifting.
A modern innovation on graphical editors is that the selection is preserved
after every indentation, giving you the chance to play around until you find
the spacing that you like.
Here’s a common addition to .vimrc, which adds this conventional behavior: