The Under-appreciated Magic of Vim's Visual Mode
Visual Mode in Vim is more than just Visual Mode. You can perform complex operations when you use Normal Mode commands in Visual Mode.
The modal nature of Vim can be intimidating for new users. However, once you understand how modes work, you will realize that Vim offers far better control and efficiency over text manipulation compared to a typical editor.
In this article, we’ll explore the magic of Vim’s Visual Mode and learn how to use it in conjunction with Command Mode to manipulate text with minimal effort.
A brief overview of Vim Modes
Normal Mode: This is the default mode when you launch Vim. In this mode, users don't input text directly; instead, they execute commands to navigate or manipulate text. For example, pressing
G
in Normal Mode takes you to the end of the file.Insert Mode: This mode allows for direct insertion or modification of text, similar to the functionality found in other text editors. To enter Insert Mode, press
i
,a
, or other corresponding keys. To return to Normal Mode, press theESC
key.Visual Mode: Visual Mode enables you to select text visually, whether it’s character-by-character, line-by-line, or in a block format. It acts as a bridge between navigation and editing, enhancing the precision and power of text selection, especially when combined with commands from Normal Mode.
Command Mode: This mode is used to execute commands that involve file operations, search-and-replace actions, or settings. Command Mode can be enabled by typing the colon (
:
) in Normal Mode. For example, to quit Vim, use:q
.
Using Visual Mode + Command Mode + Normal Mode
When you select a block of text visually by pressing v
or CTRL+v
, you can then press the colon (:
) to enter Command Mode. You’ll see a prompt like <,'>
, but don’t worry—that’s part of the command, so don’t remove it.
Type normal
or norm
after the >
character, which brings you to the Visual-Command Mode we’re discussing.
This allows you to execute Normal Mode commands such as x
, I
, A
, and more. Let’s look at an example.
A Few Use Cases and Examples
The normal
command is often useful for tasks that can be challenging or awkward to achieve using other Vim commands.
Removing the #
Character from Selected Lines
To uncomment lines, we can visually select the lines using v
and then j
or k
, and enter Command Mode with :normal
.
In Normal Mode, to delete a character, you press x
. To remove the first character in each line, you can type the following (remember, <,'>
is appended automatically as soon as you press the colon):
:'<,'>normal ^x
Explanation:
<,'>
is added automatically when you press colon and it indicates the range of lines you've selected.normal
tells Vim that we will run normal commands on the visually selected text.^
indicates the beginning of a line.x
removes a character.
The capital I
in Normal Mode places the cursor in front of the first character in the line. Therefore, to comment out those lines again, we can do something similar:
:'<,'>normal I#
Explanation:
The
I#
in Normal Mode will insert#
at the beginning of each line.
Appending to multiple lines at once
Suppose we have an invalid JSON document that does not have commas at the end of each array object:
{
"name": "John"
"age": 30
"city": "New York"
}
To append a comma to the end of each array item, we can visually select the lines and perform a Normal Mode A
command, which appends a character to the end of each line:
:'<,'>normal A,
That will produce the following fixed JSON document:
{
"name": "John",
"age": 30,
"city": "New York"
}
Applying Search-Based Movements and Operations
Now, let’s assume we want to get rid of all the values—how can we remove every character after the colon at once?
We can select those lines visually and apply the following command:
:'<,'>normal f:lD
Explanation:
The
f
command in Normal Mode takes the cursor to the preceding character, i.e., the colon.The
l
(lowercase "L") moves the cursor one character to the right because we want to keep the colon itself.D
is the same asd$
, which means deleting until the end of the line.
That will leave us with:
{
"name":
"age":
"city":
}
Combining Complex Normal Mode Commands for Formatting
Suppose we have the following paragraphs:
This is a line of text.
Here’s another line.
A third line is here.
And we want to quickly wrap each line in HTML <p>
tags. Using the normal
command allows you to execute multiple keystrokes that can’t be done with a single substitute command.
How to Add HTML Tags:
Select the lines you want to wrap in HTML tags.
Enter Command Mode by pressing
:
.Type
normal
followed byI<p>
, indicating the insertion of<p>
at the beginning of each line.Press
CTRL+v
and thenESC
. This will add^[
to the line, signaling the end of the first command.Type the last part, which is appending
</p>
to the end of each line. This is done using theA
command in Normal Mode as we saw before.
Altogether, the command should look like this:
:'<,'>normal I<p>^[</p>
That looks magical!
Remember that if you literally type this, Vim will treat the ^[
characters as a literal string.
Final Thoughts
Combining Visual Mode with Normal Mode commands via Command-Line mode greatly minimizes the effort required to perform complex operations, such as adding HTML tags to the beginning and end of lines. It reduces the complexity of your commands.
Selecting text visually is also very convenient in Vim. It allows you to use Normal Mode navigation commands to select text precisely. For example, to select everything inside square brackets, you can use vi{
. That’s much simpler compared to dragging the mouse.
The ease of visually selecting text makes the :normal
command even more powerful, enabling you to find creative and efficient ways to accomplish tasks.