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 word
  • v$ - select to the end of the line
  • vip - select inner paragraph
  • vi{ or vi( - 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 :sort to 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:

  1. Place your cursor on the c in the first const
  2. Press Ctrl-v to start block selection
  3. Press 2j to extend the selection down to cover all three lines
  4. Press I (capital I) to insert at the beginning of the block
  5. Type export and press Esc (don’t panic when what you typed only appears on one line, the magic happens when you press Esc)

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 interactively
  • i - 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 (t copies, m moves)

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 the date command
  • :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 for 1,$)
  • '<,'> - 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!