A Vim Journey: Mastering Visual and Command-line Modes
Welcome back to the second part of my Vim journey! In the previous post, we covered the fundamentals of Vim: understanding modes, the structure of commands (operator + motion + count), and how to think in Vim’s language. If you haven’t read it yet, I recommend starting there first.
In this post, we will dive deeper into two modes that I briefly mentioned: Visual mode and Command-line mode. These modes unlock even more powerful text manipulation capabilities that will make you wonder how you ever lived without them.
Visual Mode
In the first post, I mentioned that Visual mode is like taking a mouse and selecting text. While that’s true, it undersells just how powerful this mode can be. Visual mode comes in three flavors, each designed for different selection needs.
The Three Types of Visual Mode
- Character-wise (
v): Select text character by character. This is the closest to traditional mouse selection. - Line-wise (
V): Select entire lines at once. Perfect for working with blocks of code. - Block-wise (
Ctrl-v): Select a rectangular block of text. This is the game changer that most GUI editors struggle to match.
Let’s explore each one with practical examples.
Character-wise Selection
Press v to start character-wise visual mode, then use any motion to extend your selection. Some useful combinations:
vw- select to the start of the next wordv$- select to the end of the linevip- select inner paragraphvi{orvi(- select inside braces or parentheses
Remember from part 1 how we used ci" to change inside quotes? You can use vi" to visually select that same text first, giving you a preview before you act on it.
Line-wise Selection
Press V (capital V) to start line-wise visual mode. This always selects entire lines, which is incredibly useful when working with code. You don’t need to worry about being at the start or end of the line.
Some practical uses:
Vap- select a paragraph (code block separated by blank lines)V5j- select 5 lines downward- After selecting, press
>or<to indent or dedent the entire block - Or use
:sortto sort the selected lines alphabetically
Block-wise Selection (The Secret Weapon)
This is where Vim truly shines. Press Ctrl-v to start block-wise visual mode, which lets you select a rectangular block of text. This enables you to edit multiple lines at the same position simultaneously.
Let’s say you have this code:
const name = "Alice";
const age = 25;
const city = "NYC";
And you want to add export before each line. Here’s how:
- Place your cursor on the
cin the firstconst - Press
Ctrl-vto start block selection - Press
2jto extend the selection down to cover all three lines - Press
I(capital I) to insert at the beginning of the block - Type
exportand pressEsc(don’t panic when what you typed only appears on one line, the magic happens when you pressEsc)
All three lines now have export prepended. This is incredibly powerful for batch editing.
Another common use case is commenting out code:
function something() {
doThis();
doThat();
doMore();
}
To comment out the function body, block-select the lines, press I, type // , and press Esc. All lines are commented at once.
A Handy Tip: Reselecting
After you perform a visual selection and operate on it, pressing gv reselects the same area. This is useful when you want to apply multiple operations. For example, if you indent something with >, you can press gv and > again to indent further.
Command-line Mode
Command-line mode is where Vim really shows its power for bulk text processing. Operations that would take minutes of clicking and dragging in a GUI editor can be done in seconds with a single command.
Substitution: Search and Replace
The basic substitution pattern is:
:s/old/new/flags
But the real power comes from specifying ranges:
:%s/foo/bar/g- Replace all occurrences in the entire file:5,10s/foo/bar/g- Replace only in lines 5 through 10:'<,'>s/foo/bar/g- Replace in your visual selection (Vim auto-fills this when you press:from visual mode):.,+5s/foo/bar/g- Replace from current line to 5 lines below
Common flags you should know:
g- Replace all occurrences on each line (without it, only the first match per line is replaced)c- Confirm each replacement interactivelyi- Case insensitive matching
For example, :%s/const/let/gc will replace all const with let throughout the file, but ask for confirmation on each one. This is great when you want to be selective.
Global Commands: The Power Tool
The global command runs an action on every line matching a pattern:
:g/pattern/command
Here are some practical uses:
:g/TODO/d- Delete all lines containing TODO:g!/import/d- Delete all lines NOT containing “import” (the!inverts the match):g/^$/d- Remove all blank lines:g/error/t$- Copy all lines with “error” to the end of the file (tcopies,mmoves)
Filtering Through External Commands
One of Vim’s most powerful features is the ability to pipe text through external shell commands:
:.!date- Replace the current line with the output of thedatecommand:5,10!sort- Sort lines 5 through 10:%!jq .- Format the entire file as JSON (requires jq to be installed)
In visual mode, you can select code and run :!python3 to execute it and replace the selection with the output.
Range Shortcuts
Understanding range shortcuts makes command-line mode even more powerful:
.- Current line$- Last line of the file%- Entire file (shorthand for1,$)'<,'>- Visual selection (auto-filled when entering command mode from visual mode)
You can even use patterns as ranges. For example, :.,/end/s/foo/bar/g means “from here to the next line containing ‘end’, replace foo with bar”.
Other Useful Commands
:r filename- Read a file and insert its contents below the cursor:w !sudo tee %- Save a file with sudo privileges (useful when you forgot to open with sudo):e!- Reload the current file, discarding unsaved changes
The Norm Command: Bridging Normal and Command-line Modes
The :norm (or :normal) command is one of Vim’s hidden gems. It lets you execute normal mode commands from the command line, which becomes incredibly powerful when combined with ranges.
The basic syntax is:
:[range]norm {commands}
Why is this useful? Remember in part 1 how we learned that Vim’s power comes from combining operators and motions? The norm command lets you apply those same combinations to multiple lines at once.
Let’s start with a simple example. Say you want to add a semicolon to the end of lines 5 through 10:
:5,10norm A;
This runs A; (append at end of line, type semicolon) on each line in that range. Without norm, you would have to go to each line manually, press A, type ;, press Esc, and repeat.
Here are more practical examples:
:5,10norm I//- Comment out lines 5-10 by inserting//at the start:%norm A,- Add a comma to the end of every line in the file:'<,'>norm ^dw- Delete the first word of each line in your visual selection:g/TODO/norm 0i[DONE]- Prepend[DONE]to every line containing TODO
That last example shows the real power: combining norm with the global command :g. You can run any normal mode sequence on lines matching a pattern.
A note on special keys: If you need to use keys like Esc or Enter in your norm command, use norm! with Ctrl-v to insert literal control characters. However, for most use cases, you can design your commands to avoid needing Esc by using commands that don’t enter insert mode, or by structuring your edit differently.
Combining with Visual Block Mode
Here’s a powerful combination: select a block with Ctrl-v, then press : (Vim will auto-fill :'<,'>), and type norm A; to append a semicolon to each line in your selection.
This is actually more flexible than using I or A in block mode directly, because norm can execute any sequence of normal mode commands, not just inserting text. For example, :'<,'>norm f=lciw0 would find the = sign on each selected line, move right, and change the next word to 0.
Conclusion
Visual mode and Command-line mode are where Vim’s efficiency truly shines. With Visual mode, you can precisely select text in ways that most editors can’t match, especially with block selection. With Command-line mode, you can perform bulk operations that would be tedious or impossible with a mouse.
The best way to memorize these commands is to force yourself to use Vim instead of GUI editors. You will get stuck with “How do I do this in Vim?” moments, but if you solve each one, you’ll memorize them far better than just reading.
Of course, I won’t tell you to stop reading those posts about Vim altogether (like this one 😉); they still serve a purpose. Although you won’t remember everything I wrote here right away, it will leave an impression in your mind that you can do something like that in Vim. When the situation arises, you will remember, “I think I can do that in Vim, let me look it up again,” and then you will find the command quickly because you have a mental model of how Vim works now.
In the next part of this series, we’ll explore Vim Registers, Clipboard and Window/Buffer/Tab Management. Stay tuned!