courtesy of various videos on thoughtbot yt channel
Vim is more than just a text editor; it’s a language for interacting with text. Learning Vim is an investment in your most-used tool, paying dividends in speed and efficiency for the rest of your career. This guide synthesizes the best advice and techniques to take you from a complete novice to a proficient Vim user, all without getting overwhelmed.
Your initial goal is to become “good enough” to use Vim for your daily tasks. Don’t start at work where the pressure is high. Play with it on personal projects first.
vimtutor
Open your terminal and type vimtutor
. This is a 30-minute interactive tutorial that covers the essential commands. Go through it multiple times until the basic movements feel natural.
Vim’s power comes from its use of “modes.” The same key does different things depending on the current mode.
Esc
to return here from any other mode.i
.v
.Golden Rule: Spend most of your time in Normal Mode. Get in and out of Insert Mode as quickly as possible.
To avoid frustration, make these two changes immediately:
Esc
constantly. Re-mapping Caps Lock to Esc
makes this painless. Use a tool like Karabiner-Elements on macOS.Commit to not using the mouse. This forces you to learn Vim’s navigation commands and eliminates the context switch between keyboard and mouse, which is a huge source of inefficiency.
Stop memorizing commands. Start thinking in the Vim language. The basic grammar is Verb + Noun.
Example: dw
= delete word.
These are the core actions you’ll use:
d
: Deletec
: Change (deletes the text and enters Insert Mode)y
: Yank (copy)v
: Visually select>
: Indent<
: OutdentThis is how you specify what to change.
Motions operate from the cursor’s current position.
w
: Forward to the start of the next word.b
: Backward to the start of the previous word.j
: Down one line.k
: Up one line.$
: To the end of the line.0
: To the beginning of the line.^
: To the first non-blank character of the line.f{char}
: Find the next occurrence of {char}
on the current line.t{char}
: Move till (just before) the next {char}
./{pattern}
: Search for a pattern.Text objects are more powerful because they operate on a “thing” regardless of your cursor’s position within it. They often use i
(inner) or a
(a/around).
iw
: inner wordip
: inner paragraphi"
: inner double quotesi(
: inner parenthesesit
: inner tag (for HTML/XML)Pro Tip: Prefer text objects over motions. ciw
(change inner word) is more robust and repeatable than cw
(change word).
The .
key repeats your last change. This is the single most important command for efficiency. Structure your edits to be repeatable with the dot command.
Efficient editing is mostly about getting your cursor to the right place quickly. Ditch the arrow keys, and then ditch hjkl
for most movements.
H
: Jump to the Highest line on the screen.M
: Jump to the Middle line on the screen.L
: Jump to the Lowest line on the screen.gg
: Go to the top of the file.G
: Go to the bottom of the file.{line_number}G
: Go to a specific line number (e.g., 50G
).zz
: Center the current line on the screen.zt
: Move the current line to the top of the screen.zb
: Move the current line to the bottom of the screen.Ctrl-D
: Scroll down half a screen.Ctrl-U
: Scroll up half a screen.Ctrl-F
: Scroll forward a full screen.Ctrl-B
: Scroll backward a full screen./{pattern}
: Search forward for a pattern.?{pattern}
: Search backward for a pattern.*
: Search forward for the word under the cursor.#
: Search backward for the word under the cursor.Enable relative line numbers with :set relativenumber
. This shows line numbers relative to your cursor’s position. Instead of counting, you can just see that you need to delete 7 lines and type d7j
.
Reduce errors and save keystrokes by using Vim’s powerful built-in completion features.
In Insert Mode, start typing a word and press:
Ctrl-P
: Complete with the previous match in the file.Ctrl-N
: Complete with the next match in the file.Keep pressing the key to cycle through all available matches.
Vim can complete entire sequences of words or lines.
Ctrl-X Ctrl-P
: In Insert Mode, completes the word based on the preceding text. Hit it again to pull in the next word from the matched sequence.Ctrl-X Ctrl-L
: The same as above, but for entire lines. This is a game-changer for boilerplate code.Ctrl-X Ctrl-O
provides language-aware “Omni” completion. For example, type a variable name, a dot (.
), and then hit the combo to get a list of valid methods for that object’s class.
In Insert Mode, start typing a path and press Ctrl-X Ctrl-F
to complete file and directory names.
~/.vimrc
Your Vim configuration lives in ~/.vimrc
. This is where you’ll put all your settings. Store your dotfiles in Git for version control and portability. When starting, it’s okay to borrow a .vimrc
from a friend or a trusted source like thoughtbot’s dotfiles.
You can get incredibly far with Vim’s native features. Before installing a plugin, see if Vim can do it already.
set path+=**
in your .vimrc
, you can use :find
with wildcards and tab completion to open any file in your project.ctags -R .
to index your codebase. Then use Ctrl-]
to jump to a definition and Ctrl-T
to jump back.:edit .
opens netrw
, Vim’s built-in file explorer.:read
template files from a skeleton directory.While a minimalist approach is powerful, some plugins are so good they feel essential. These are often cited as game-changers:
ds"
, cs"'
, ysiw"
).gc
verb for commenting out lines and blocks.:find
is good, a fuzzy finder is faster for many. It allows you to type a few characters of a file name to find it instantly.Vim is a tool you can spend a lifetime mastering. Embrace the philosophy of continuous improvement. When something feels slow or clunky, remember the mantra: “There is always a better way.” Look it up, learn it, and add it to your vocabulary.
The goal isn’t just to be fast; it’s to make the act of editing so fluid that you can focus all your mental energy on what truly matters: solving problems.
(Content from “Learning vim in a week.md”)
Hello everyone, I’m Mike Coutermarsh. About nine months ago, I switched to Vim from Sublime Text, so I’m by no means an expert. In fact, half the people in this room are probably better at Vim than I am. But because I’m so close to the learning experience, I consider myself something of an expert at learning Vim. I still remember the pain, the frustration, and the breakthroughs.
This guide is for anyone who has ever thought about learning Vim but felt overwhelmed. Maybe you’ve opened it once and couldn’t figure out how to close it. Maybe you’ve tried to learn a few times, only to go back to your old editor. My goal is to get you from that stage to being “good enough” to use Vim on a real project at work.
This is the number one thing I hear. “I have too much contract work,” or “I need to stay productive, I can’t afford to slow down.” My goal with this talk is to give you a roadmap to bridge that gap. Once you start using Vim every day for your job, you’ll learn new things constantly and your productivity will skyrocket.
We always hear that learning Vim is hard. But let’s be honest—most of us are programmers, and learning programming is hard. Learning Vim is easy by comparison, but it’s different. And that difference is what makes it feel so difficult.
To that, I offer a piece of advice that I apply to many parts of life:
Sometimes you gotta work a little so you can ball a lot.
Yes, learning Vim is a little work. Yes, it can be frustrating. But the payoff is so huge that it’s absolutely worth it. When you feel that pain, remember the payoff.
The single most important lesson I learned from this journey is the immense value of investing in your tools. If coding is your career, every minute you spend improving how you use your editor pays dividends every single day for the rest of your career. It’s a massive investment in yourself.
To make your journey smoother, here are six things you should know before you even begin.
Whatever editor you’re using now—Sublime, VS Code, TextMate—they’re all on the same planet. Vim is on an entirely different one. You cannot approach it with the same mindset. People say it’s hard because they try to use it like their old editor. Embrace the fact that it’s different. Because it’s different, it’s better.
This might seem counterintuitive to my goal of getting you productive at work, but you shouldn’t start there. Nothing is worse than facing a production issue when you don’t know how to copy and paste yet. That’s the fastest way to quit. Play around with it at night, on weekends, or during your lunch break. Once you have the basics down, then you can bring it to your day job.
I don’t care how cool your gaming mouse is. You are done with it. The biggest benefit of ditching the mouse is eliminating the constant context switch between typing and clicking. It seems crazy once you stop doing it. An added bonus for me was that the wrist pain I used to get from mousing all day completely disappeared. I’m not a doctor, but it seems to make sense.
Every developer considering a switch has a mental list of three things their editor must do, or they won’t even try. “But can it do multi-cursor editing?” “But can it integrate with my debugger?” The answer to all of these questions is yes, it can. Suppress those feelings of doubt. Whatever your old editor did, Vim can do it, and probably do it better. Don’t let that mental checklist hold you back.
As you’re learning, you will inevitably run into something that feels slow, clunky, or frustrating. In those moments, remember this mantra: There is always a better way. I promise. You can type the weirdest, most specific problems into Google, and someone has written a blog post about it.
After about two or three weeks, I felt like I could do everything I used to do in Sublime, and I stopped actively learning. That was a mistake. I found that if I intentionally focused on learning one new thing about Vim every week, my productivity gains compounded incredibly quickly. Vim isn’t something you learn and are done with; it’s a continuous process.
This isn’t just a suggestion; in my opinion, you need to do this.
The core reason Vim is hard to learn is its use of modes. The meaning of a key changes depending on the context, or mode, you are in.
Escape
.i
.v
.When I first started learning, I thought Vim users were geniuses who had memorized thousands of cryptic key combinations. That’s not it at all. Vim is a language.
For example, to change the text inside a set of parentheses, you use the command ci(
.
Don’t memorize c-i-(
. Instead, think in the language:
c
= changei
= inside(
= parenthesesYou’ll find yourself saying “change inside parentheses” in your head. What would di"
do? Delete inside quotes. It’s a compositional language, not a list of commands to memorize.
My advice: Say them in your head, not out loud. You’ll have more friends that way. And grab a Vim cheat sheet to have on hand as you start.
~/.vimrc
Vim out of the box is uncool. You have to configure it to be cool. Your new best friend for this task is a file in your home directory called .vimrc
.
This file, known as a “dotfile” because of the leading period, is where all your settings live. My strong recommendation is to put your dotfiles in Git and on GitHub. This gives you:
git clone
your dotfiles, and your entire editor setup is ready to go.When you’re starting out, steal your friend’s dotfiles. It’s hard to know what you want when you don’t know what’s possible. Find someone whose setup looks cool and start with theirs. If you don’t have a friend who uses Vim, you can steal mine from my GitHub (no judgment on the weird stuff in there, please). The dotfiles from thoughtbot are also an excellent starting point.
The actual process of learning is pretty simple.
vimtutor
. Open your terminal and type vimtutor
. This command launches a 25-30 minute interactive tutorial that covers all the basic movements. Do it in small chunks. Go through it multiple times until the movements start to feel natural in your fingers. If vimtutor
isn’t for you, check out Vim Adventures, a game that teaches you Vim concepts.vim-rails
or vim-rspec
if you’re a Rails developer.After you’ve gone through this process, you need to pick a date and just commit. I remember coming into work one Monday morning and announcing to my coworkers, “This week, I’m only using Vim.” The social pressure worked. I hid Sublime from my dock. Every time I got stuck, I looked up the solution instead of switching back.
Every day got easier. By the end of the week, I was golden. I never had to switch back again.
That’s all I have. Thank you for listening, and feel free to reach out if you need help on your journey.
(Content from “Mastering Vim Language.md”)
Hello, I’m Chris Toomey. As someone who helps run a Vim meetup and works with the editor every day at thoughtbot, it’s probably no surprise that I love Vim. It’s my favorite tool, and also the one I use the most.
One of the core reasons for this enduring affection is that over the many years I’ve used it, I’ve yet to hit the ceiling. I’ve never found that edge where I could say, “I’ve learned it. I know all of Vim.” In fact, I’ve never met anyone who has.
This might sound like a negative, but to me, it’s Vim’s greatest strength. Since this is the tool I use most, I love that I can constantly sharpen the saw, constantly get better, and continuously adapt the editor to my workflows. I don’t want a tool with a ceiling; I want to keep improving, and Vim delivers on that.
A lot of people talk about how fast you can be in Vim. While speed is a nice benefit, it’s not the primary reason I use it. You’ll often hear the quote, “Typing is not the bottleneck,” used as an argument against investing time in an editor like Vim. And I agree—speed alone isn’t a compelling enough reason.
But the core of that statement is what’s truly interesting: thinking is the bottleneck. The time I spend not typing is the most important. I have a limited amount of useful thought I can put out into the world on any given day, and I want to spend precisely zero of those “thought units” on my editor.
This is why I love Vim. It gives me a language to express the changes I want to make in the most concise and efficient way I’ve ever found. I don’t have to translate my intentions for the editor; it feels like Vim speaks my language. When I figure out the change I want to make, I put my hands on the keyboard, and it just happens. It’s a magical and practical way to work, ensuring no thought cycles are wasted on the mechanics of editing.
Vim’s killer feature is the language it provides for defining changes.
Most editors treat inserting text as the primary action. You press a key, and that character appears. Vim flips this on its head. It recognizes that as writers, and especially as programmers, we spend most of our time editing existing text, not writing new text from scratch.
Vim chose to optimize for editing, and I believe this was a brilliant choice. It provides a rich language to express changes concisely and repeatably.
The syntax of this language is simple: Verb + Noun.
For example:
d
is the verb for delete.w
is the noun for word.Typed in sequence, dw
becomes the command to delete a word.
This simple structure has two incredibly powerful characteristics:
dw
), you can move anywhere else in your document and press the dot (.
) key to repeat that exact same change. You define a change once and stamp it out wherever needed.u
), Vim undoes the entire dw
operation as a single, atomic change. It doesn’t restore individual characters; it restores the whole word, just as you removed it.The verbs are the starting point for any command. Here are a few of the most common ones:
d
: Delete the specified text.c
: Change the text (deletes it and enters insert mode).y
: Yank the text (Vim’s term for copy).>
: Indent the text.<
: Outdent the text.v
: Visually select the text.This is where the language truly expands. Everything you use to move around in Vim also serves as a noun to operate on.
Motions define a region of text from your cursor’s current position to a new one.
w
: Forward to the start of the next word.b
: Backward to the start of the previous word.j
: Down one line. (So 2j
is down two lines).If you’re at the beginning of “result” and type cw
, you will change a word. This is useful, but it requires your cursor to be in the right starting position.
This is where things get mind-expanding. Text objects allow you to operate on a defined body of text, no matter where your cursor is within that body. They often start with i
(inner) or a
(a/around).
iw
: inner wordi"
: inner double quotesip
: inner paragraphit
: inner tag (for HTML/XML)If my cursor is anywhere inside the word initialize
, diw
will delete the inner word. If my cursor is inside a quoted string "hello world"
, ci"
will change the inner quoted text, leaving the quotes intact.
This is a more expressive and repeatable way to edit. The change ciw
(change inner word) will work correctly when repeated with .
, regardless of where your cursor is inside the next word. The motion-based cw
will not.
These are the most precise nouns, allowing you to target almost anything you can see.
f{char}
: Find the next occurrence of {char}
on the line.t{char}
: Move till (up to, but not including) the next {char}
./{pattern}
: Search for a {pattern}
.These motions are unbelievably powerful. Imagine you want to change from your cursor up to the letter L
. You can simply type ctL
(change till L
). If you want to change everything up to the word “other” somewhere far away in your file, you can type c/other
and hit Enter.
When you combine these elements, the possibilities explode. With a conservative estimate of:
…you arrive at over 2,000 distinct, composable commands by learning only about 30 core concepts. And “learning” is a strong word. When I want to delete an inner word, diw
just falls out of my fingers. I don’t translate it; it’s how I think.
.
command. This forces you to think in the most efficient and expressive way possible.ciw
is better than cw
. Text objects are more robust, repeatable, and less dependent on cursor position.set relativenumber
. Instead of doing mental math to figure out you need to go down 6 lines, Vim will just show you the number 6
. Then you can d6j
to delete those 6 lines without a second thought.viwp
(visually select inner word, then paste) is less efficient and less repeatable than using a dedicated plugin that provides a gr
(go replace) verb. Visual mode is a great way to discover a missing piece in your Vim vocabulary.The beauty of Vim’s language is that it’s extensible. You can add new verbs and nouns with plugins.
ds"
: delete surrounding "
cs"'
: change surrounding "
to '
ysiw"
: you surround an inner word with "
gc
verb for commenting.
gcip
: comment out an inner paragraph.gr
verb to go replace a text object with the contents of your clipboard.ii
(inner indent block) and ai
(an indent block).ie
and ae
to operate on the entire file.do..end
blocks.These plugins don’t just add features; they add to the vocabulary, further expanding the thousands of command combinations at your disposal.
Having a composable language for defining operations on text objects is one honking great idea. It’s the core of what makes Vim such a powerful and enduring tool. By focusing on mastering this language—both its built-in features and its extensions—you can offload the mental burden of editing and save your precious brainpower for solving real problems.
Thank you for reading. Now, go forth and compose.
(Content from “Vim Navigation.md”)
Hello everyone, my name is Daniel, and today I want to talk about navigating within a file in Vim. I have two reasons for choosing this topic.
First, for beginners, it’s incredibly hard to do anything if you aren’t comfortable moving around. I remember when I gave up my mouse, I felt claustrophobic without my scroll wheel. Getting to a specific line was easy, but seeing the surrounding context was a real struggle.
Second, I have a theory that more proficient Vim users often plateau in their knowledge. Once you can accomplish a task, you just do it. If it takes you three commands instead of one, that’s often good enough. There’s no incentive to take five minutes to look up a better way.
So, I want to go over a lot of really basic commands. If you’re a Vim expert, maybe you’ll know them all, but I have a feeling everyone will learn one or two things. After this, you’ll have no excuse for not knowing them.
Let’s dive in.
Let’s start with the fundamentals. I’m sure if you’re cool enough to be at a Vim meetup, you know these:
j
: Go down one line.k
: Go up one line.G
: Go to the bottom of the file.gg
: Go to the top of the file.Of course, what makes Vim great is that you can prefix these with a number. 50gg
will take you to line 50.
This is where things get interesting. These commands are about moving around relative to what you can currently see on your screen.
L
: Move cursor to the Lowest line on the screen.M
: Move cursor to the Middle line on the screen.H
: Move cursor to the Highest line on the screen.I think the G
commands get all the press, but these are incredibly useful for quick, precise movements within your current viewport.
Picture this: you search for a method, and it appears at the very bottom of the screen—an inconvenient place to work. You need to adjust your view without losing your place.
zz
: Center the current line on the screen. This is a command I use constantly. I get to where I want to go, then hit zz
to see the context above and below.zt
: Move the current line to the top of the screen. Great for when you find what you need and want to see everything that follows.zb
: Move the current line to the bottom of the screen.What if you just want to nudge the screen a bit?
Ctrl-E
: Scroll the screen down one line, keeping the cursor in place.Ctrl-Y
: Scroll the screen up one line, keeping the cursor in place.When I was first learning, I would press j
then k
to achieve this. Ctrl-E
and Ctrl-Y
are the right way to do it.
For bigger jumps:
Ctrl-D
: Move down half a screen.Ctrl-U
: Move up half a screen.Ctrl-F
: Move forward one full screen.Ctrl-B
: Move backward one full screen.Ctrl-D
and Ctrl-F
are your new scroll wheel. I find the full-screen jumps a bit jarring, so I use a plugin called SmoothScroll that animates the movement, making it easier to follow.
0
: Move to the absolute beginning of the line (column zero).^
: Move to the first non-blank character on the line. (This is usually what you want).$
: Move to the end of the line.g_
: Move to the last non-blank character of the line.The g_
command is surprisingly useful. I often paste text from Stack Overflow that has trailing whitespace. I can write a quick macro to clean it up: qqg_D$jq
(start macro, go to last non-blank character, delete to end of line, go down, stop macro). Then I can just hold @q
to fix the whole block.
Percentage-Based Jumps: Instead of jumping to line 10 (10G
), you can jump 10% of the way down the file with 10%
. I don’t know the exact use case, but it’s a cool command to have in your back pocket.
Searching for the Word Under the Cursor: Everyone knows *
searches forward for the word under your cursor. But did you know that #
(the pound or hash key) does the same thing, but searches in reverse? It’s perfect for finding the previous occurrence of a variable or method.
Big Words vs. Small Words: What does Vim consider a “word”? When you use w
(next word) or e
(end of word), you’ll notice it stops at hyphens, periods, and other symbols. This is because Vim is operating on “small words.”
If you want to treat something like My.Cool.Class
as a single unit, you need to use “big words.”
W
: Move forward by a Word (delimited by whitespace).B
: Move backward by a Word.E
: Move to the End of a Word.This is a game-changer. diW
(delete inner Word) is a command I use constantly, especially with period-delineated class names in object-oriented languages.
Marks: Your Personal Bookmarks: If you find yourself repeatedly returning to a specific spot in a file, stop trying to remember the line number. Set a mark.
m{a-z}
: Set a local (file-specific) mark. mm
is a common choice. `{a-z}
: Jump to the exact position (line and column) of the mark.'{a-z}
: Jump to the first non-blank character of the line containing the mark.You can also use capital letters (m{A-Z}
) to set global marks that you can jump to from any file.
That’s everything I have. I hope this tour of intra-file navigation has given you a few new tools to add to your arsenal. The key to getting faster isn’t about memorizing every command; it’s about building a fluid vocabulary of movement that lets you get where you want to go without thinking. No more excuses.
(Content from “Letting Vim do the typing.md”)
Hi everybody, I’m George. As humans, we’re pretty bad at typing. I probably spend eight, nine, maybe even ten hours a day at my keyboard, and I still make mistakes all the time. I chose to use Vim, an editor that’s all about efficiency and saving keystrokes. So why would I spend all my time engaging in the slow, manual, error-prone process of typing?
Tonight, I want to talk about all the different ways Vim can help you reduce the amount of typing you do by letting it do the work for you.
Before we dive in, we need to talk a little bit about editor philosophy. The battle between Vim and Emacs has raged since the beginning of time. They are both great editors, but they have very different approaches.
i
to enter Insert mode, where keys add text. In Normal mode, those same keys perform edits.Everything I’m going to show you today involves staying in Insert mode and holding down modifier keys, which might feel very Emacs-like. However, it still fits perfectly within the Vim philosophy.
Vim is efficient because we think in terms of atomic edits. You enter Insert mode, make a change, and exit. That entire operation is a single edit that you can repeat with the dot (.
) key and undo with u
.
But what if, as part of that single edit, you need to insert text that Vim has definitely seen before—a variable name from your code, text from a register, or a line from another file? Conceptually, that’s all part of the same edit.
Consider this example: I want to type “hello world,” and I know “hello” is in register a
and “world” is in register b
.
The Normal mode way would be:
"ap
(paste from register a) -> a
(enter insert) ->
(space) -> ESC
-> "bp
(paste from register b)
That’s four separate edits. The dot command would only repeat the last one, and I’d have to hit u
four times to undo it. Conceptually, it was one action: adding “hello world” to the document.
There’s a better way.
Ctrl-R
and Ctrl-A
Power-upsWe can achieve the same result as one atomic edit by staying in Insert mode.
i
to enter Insert mode.Ctrl-R
. Vim will prompt you for a register.a
. Vim inserts the content of register a
(“hello”).space
.Ctrl-R
again, then b
. Vim inserts “world”.Enter
, then ESC
.Now, that entire “hello world” insertion is a single, repeatable, and undoable edit. This is why it’s okay to hold down the Ctrl
key in Insert mode sometimes.
Bonus Tip: The dot register (.
) always contains the last text you inserted. In Insert mode, Ctrl-R .
will re-insert that text. Even better, Ctrl-A
is a shortcut that does the exact same thing. This is fantastic for when you want to repeat an insertion but need to change the motion that precedes it.
The biggest category of things where you want Vim to do the typing for you is completion. When you’re programming, you repeat the same words over and over: language keywords, variable names, class names. Vim has a powerful, built-in completion system that requires no plugins.
Ctrl-P
and Ctrl-N
Let’s say you want to type the word “quick,” and it already exists in your document.
q
.Ctrl-P
(Previous). Vim will look backward through the file and complete the word to “quick.”You can keep pressing Ctrl-P
to cycle through all matches. Vim is smart; it will even find matches in other open files and show you which file they came from. The opposite of Ctrl-P
is Ctrl-N
(Next), which searches forward. These two keystrokes are the foundation for browsing options in all the other types of completion we’ll discuss.
Most programmers use Ctags, a program that indexes your source code and finds where things like classes and methods are defined. Once you have a tags
file, Vim can use it for more than just jumping to definitions—it can use it for completion.
Say you want to type a class name that starts with H
. If you use Ctrl-P
, you might get “Hello” from a string or “How” from another file. But you know you want a symbol from your program.
This is where Vim’s completion sub-mode comes in.
H
.Ctrl-X
to enter completion mode.Ctrl-]
(tag completion).Vim will now only offer completions from your tags
file. No more sifting through irrelevant words. It’s precise and targeted.
Ctrl-X Ctrl-F
This is another incredibly useful completion type. Need to reference a file path?
ex
for an “examples” folder.Ctrl-X Ctrl-F
(File completion).Vim will complete the directory or file name for you, and you can use Ctrl-N
and Ctrl-P
to cycle through options, just like tab-completion in the shell. No more typos in your file paths.
This is where things get really fancy. What if you want to insert a sequence of words from another part of your file?
Say you have the line “the quick brown fox…” and you want to type “the slow brown fox…“.
the slow br
.Ctrl-X Ctrl-P
. Vim will complete “brown.”Ctrl-X Ctrl-P
again. Vim, remembering the context, will pull in the next word, “fox.”You can keep hammering Ctrl-X Ctrl-P
to pull in an entire sequence of words. This is a lifesaver for repetitive boilerplate code, like the structure of a JavaScript test. It lets you pull in the entire structural scaffolding without typing a single extra character.
Ctrl-X Ctrl-L
This is my favorite Vim feature of all time. It works just like context-aware word completion, but for entire lines.
When you’re writing tests, you often have very similar setups for success and failure cases. You can start typing the first line of the block you want to copy, then hit Ctrl-X Ctrl-L
(Line completion). Vim will insert that line. Hit it again, and it will pull in the next line. And the next.
This is the number one thing that makes people I’m pairing with say, “Whoa, what did you just do?” It’s unbelievably fast and comes up surprisingly often.
Vim also has a language-aware completion system called Omni completion, triggered by Ctrl-X Ctrl-O
.
If you have a string in Ruby and you want to call a method on it but can’t remember the name, just type .
and then Ctrl-X Ctrl-O
. Vim will show you a list of all available String methods. “Oh yeah, capitalize
! That’s the one.”
This works surprisingly well out of the box for many languages, especially if you have syntax highlighting enabled.
complete
SettingIt wouldn’t be Vim if you couldn’t customize all of this. The complete
setting tells Vim where to look for completions and in what order. By default, it looks in:
.
)w
)u
)t
)i
)You can add to this list. For example, I add kspell
, which tells Vim to also look in the spelling dictionary, but only when spell-checking is turned on (:set spell
). This is great for when you’re writing prose in Git commit messages or emails and can’t quite remember how to spell “quotidian.”
That’s my little tour of Vim’s built-in completion. By letting Vim do the typing, you save keystrokes, reduce errors, and free up your mind to focus on what really matters: solving problems.
Thanks for listening.
(Content from “Get faster with vim.md”)
Hello and welcome to The Weekly Iteration. Today, we’re diving into one of my favorite topics: how to get faster in Vim. Joe and I are here to drop some knowledge bombs on you. Take shelter.
First things first: if you’re not a Vim user or you’re just starting out, you don’t need to be scared. Vim has this intense mythology around it where people think it’s incredibly hard to learn. To be fair, certain Vim users help propagate that elitist attitude, but the truth is, it’s not that hard.
Here’s how I recommend you start: open your terminal and type vimtutor
. It’s an interactive, 15-minute tutorial that walks you through the most basic commands. Honestly, after 15-20 minutes, you are ready to start editing text and getting stuff done. Within a couple of days, you’ll be productive. In a few weeks, I think you’ll surpass your old editor’s speed.
So, don’t be afraid. Get started.
Now, let’s say you’re an intermediate user. You know the basics, but you want to keep improving. How do you get to that next level of proficiency? Here are a handful of nuggets and recommendations.
There’s a reason it’s called Normal mode—it’s where you should normally be. Think of Insert mode as a lousy vacation spot: get in, do what you have to do (type text), and get out as quickly as possible.
When you’re new to Vim, it’s tempting to use Insert mode for everything. You might go into Insert mode and hold down backspace to delete characters or use the arrow keys to move around. You can actually configure Vim to disable these actions in Insert mode, forcing you to use the more efficient Normal mode commands. Taking away these crutches, at least for a while, will make you a much more efficient user.
It’s tempting to move your hand over to the arrow keys, but don’t do it. Learn h
, j
, k
, and l
for movement. Why? Because it keeps your fingers on the home row, saving you the time and effort of constantly moving your hand back and forth. All that sounds trivial, but when you start combining these keys with other commands—deleting, indenting, copying—it makes a massive difference.
But here’s the crazy part: once you’ve mastered hjkl
, you should stop using them too.
hjkl
are for fine-grained, one-character-at-a-time movements. You want to be moving more efficiently. Any time you find yourself holding down a key or pressing it more than once, consider it a “smell”—an indication that there’s a better way.
Instead, learn to move by:
w
moves forward by words, b
moves back. e
moves to the end of words.f
and t
are two of my favorite motions. If I want to change something up to a {
on the current line, I can type ct{
(change till {
). f{
would find and include the brace in the operation.One of the great things about modal editing is that any movement you can perform, you can also repeat. If you need to delete up to a curly brace on three consecutive lines, you can do it once with dt{
, then move down and hit .
twice. That’s where the real power at scale comes from. You’re not just saving a few milliseconds on one line; you’re making subsequent edits cost almost nothing.
You might notice in my editor that the current line is always 0
, and the lines above and below are numbered relative to it. This feature (set relativenumber
) makes it incredibly easy to operate on ranges of lines without doing mental math.
If I want to delete the next seven lines, I don’t have to count. I just see the number 7
and type 7dd
(or d7j
). Done.
Even in small files, you’ll almost always be working with single-digit numbers instead of trying to calculate the difference between line 152 and 158. It’s a huge gain.
A huge portion of editing is just getting your cursor to the right place. Here are some better alternatives to holding j
or k
:
H
, M
, and L
will jump your cursor to the top, middle, and bottom of the screen, respectively. They are fantastic for getting roughly where you want to go in one keystroke./
. For example, /for_user
will jump you right to that method call. You develop an instinct for what will be a unique search term over time.The most important thing is to adopt a “seek and destroy” mindset rather than a “scan and destroy” one. A great plugin to encourage this is Hard Mode, which disables the arrow keys, hjkl
, and other character-wise navigation commands.
While you can get very far with vanilla Vim, a few plugins are so good they feel like they should be built-in.
app/models/user.rb
, you can just type us
and hit enter. These plugins also offer powerful commands for opening files in new tabs or splits.:A
takes you to the test file, :R
takes you to the schema definition.cs"'
: Change surrounding double quotes to single quotes.ds{
: Delete surrounding curly braces.ysiw"
: You surround an inner word with double quotes.Every time I have to edit HTML without surround.vim
, it’s a miserable experience. This plugin is a game-changer.
That’s it! Some high-level advice, specific motions to practice, and a few essential plugins to check out. I hope this was useful, and I’d love to hear your own Vim tips and experiences. Talk to you soon.
(Content from “Vim without plugins.md”)
Hello, I’m Max. You might know me from my time in various tech roles, from writing code for Fortune 500s and indie game developers to, more recently, education and project management. As a tech industry wanderer with around 20 years of programming under my belt, I’ve developed a deep appreciation for my tools—especially Vim.
I love Vim. It’s not always easy to use, but I love it anyway. I wanted to put this guide together because I see a common pattern, especially with the rise of fast-paced coding bootcamps. It’s easy to get up and running by piling on plugins that do the heavy lifting for you. While there’s nothing wrong with that, it can create a gap in your understanding of the tool you use every day.
This post is not about hating on plugins or convincing you to uninstall them all. My goals are simple:
I firmly believe that truly understanding our tools is one of the most overlooked priorities in technology. When you find a balance—using a plugin when it makes sense, but also taking the time to dive into the core features of Vim—you unlock an incredible level of speed and efficiency. And that’s good for everybody.
So, let’s explore how you can replicate the functionality of some of the most popular plugins using nothing but Vim itself.
To follow along, all you need is a few lines in your vimrc
file. These settings form the bedrock for everything we’re about to do.
" Tell Vim not to pretend to be its ancient predecessor, vi.
set nocompatible
" Turn on syntax highlighting.
syntax enable
" Enable the filetype plugin system (for netrw, our file browser).
filetype plugin on
This is a small “cheat,” as netrw
is technically a plugin, but it comes bundled with every modern Vim installation, so I consider it a core feature.
Many developers rely on plugins like Command-T, Command-P, or Fuzzy-Find to quickly open files. But you can get a surprising amount of mileage out of Vim’s built-in features with one simple configuration.
It all starts with this humble option:
set path+=**
Let’s break this down. set path
modifies Vim’s internal list of directories to search when you use file commands. The +=
appends to the existing list. The magic is the **
. This special pattern tells Vim to search recursively through every subdirectory from your current working directory.
This is why I always run Vim from the root of my project. With this path
setting, Vim can reach into any file, no matter how deeply nested it is.
How to Use It:
:find TCP
and hit Tab
. Vim will autocomplete the full path to TCP.rb
, even if it’s buried in lib/game/network/
.:find *CP
will find all files ending in CP
.wildmenu
option enabled (set wildmenu
), hitting Tab
on an ambiguous search (like :find *.rb
) will display a menu of all possible matches. You can navigate this list with Tab
and Shift-Tab
.Bonus Tip: Buffer Jumping
If you’ve already opened a file, it exists in Vim as a “buffer.” You can list all open buffers with :ls
. To jump to any of them, just use the :b
command with a unique part of its name.
:b tcp
will instantly switch to the buffer for TCP.rb
. No tabbing, no full paths.
Between :find
and :b
, you have a powerful, lightning-fast navigation system without a single third-party plugin.
What’s a “tag”? Think of it as any important identifier in your code: a class name, a method, a function, a variable. When you see a method call and want to see its definition, tag jumping is your best friend.
This requires one external tool: ctags. It’s pre-installed on most Linux systems and available via Homebrew on macOS (brew install ctags
).
Once installed, navigate to your project’s root directory in your terminal and run this command:
ctags -R .
The -R
flag means “recursive,” just like our **
in Vim. This command scans your entire project and creates a single tags
file, which is an index of every definition it found. Vim automatically knows to look for this file.
Now for the Magic:
exit
.Ctrl-]
.exit
is defined.What about ambiguous tags? If a method like initialize
is defined in multiple classes, Vim has you back:
g
then Ctrl-]
.To navigate back up the chain after you’ve drilled down through several definitions, just press Ctrl-T
. Each press will take you one step back up the tag stack, right back to where you started. It’s an incredibly convenient way to explore a large, unfamiliar codebase.
Autocomplete is another area with a universe of plugins. But Vim’s built-in completion is surprisingly robust and requires zero setup. It automatically reads from your tags
file, all open buffers, and even follows require
or import
statements for the language you’re in.
Ctrl-N
(next) or Ctrl-P
(previous). Vim will pop up a menu with all possible completions.Ctrl-X
sub-mode offers more granular control.
Ctrl-X Ctrl-N
: Complete from the current file only.Ctrl-X Ctrl-F
: Complete file and directory names. This is a lifesaver. Start typing a path like lib/
and hit this combo to get a list of files in that directory right in your editor.Ctrl-X Ctrl-]
: Complete from your tags file only. This is great for ensuring you’re only using defined methods and classes.Before reaching for a heavy autocomplete plugin, try leveraging these commands. You might find they cover 90% of what you need.
As I mentioned, netrw
is the cantankerous but functional file browser that comes with Vim. It’s not as intuitive as NERDTree, but it’s free and already there.
To use it, just edit a directory:
:edit .
You’ll get a file listing where you can:
Enter
on a file to open it.Enter
on a directory to expand it.v
to open a file in a vertical split.t
to open a file in a new tab.It’s surprisingly full-featured, with options for creating directories, marking files, and even connecting to remote filesystems over SSH. I won’t blame you for using a plugin here—I use NERDTree myself—but it’s worth knowing that a capable file browser is just one command away.
This one is a bit more complex, but once you understand it, it’s a superpower. Instead of a plugin, we’ll use a Vim mapping to read a template file directly into our buffer.
Here’s the mapping I use to create a basic HTML5 template:
" In normal mode, typing ,html will insert my HTML skeleton file.
nnoremap ,html :read ~/.vim/skeletons/skeleton.html<CR>3jWF]a
Let’s dissect this work of art:
nnoremap ,html
: This creates a non-recursive mapping in normal mode. ,html
is the trigger. The comma (,
) is my “leader” key—a prefix for all my custom commands.:read ...
: This is the command part. The :
enters command mode. read
does what it sounds like: it reads the contents of a file.~/.vim/skeletons/skeleton.html
: This is just a plain text file containing my HTML template.<CR>
: This is the special code for the “Enter” key (Carriage Return). It executes the :read
command.3jWF]a
: This is a sequence of normal mode commands that moves the cursor into the <title>
tag for immediate editing. It’s a nice-to-have, not a need-to-have.With this one line in my vimrc
and a folder of plain-text template files, I have a fast, simple, and infinitely flexible snippet system that I completely control.
Plugins for test integration are fantastic, but you can build a basic version yourself. The goal is to run your tests and have Vim parse the output so you can jump directly to failing tests.
This relies on Vim’s Quickfix list. The process looks like this:
Configure your test runner to output errors in a specific format: filename:line_number:error_message
. I use a simple custom RSpec formatter for this.
Tell Vim what command to run. We use the makeprg
option:
set makeprg=bundle\ exec\ rspec\ --format\ QuickfixFormatter
Run the tests. Instead of switching to your terminal, just type :make
in Vim.
Navigate the errors. Vim will run the command, parse the output, and populate the Quickfix list. Now you can use these commands to fly through your failures:
:cnext
(:cn
): Jump to the next error.:cprevious
(:cp
): Jump to the previous error.:clist
(:cl
): Show a list of all errors.:cc 2
: Jump directly to error #2.This setup has saved me countless hours by keeping me in the editor and focused on the code that needs fixing.
:help
If you take only one thing away from this, let it be this: use the help system. It is one of the most thorough, well-built help systems I have ever encountered.
:help <command>
: Get help on any command.:help i_ctrl-n
: Look up what Ctrl-N
does specifically in insert mode. (Use c_
for command mode, v_
for visual mode, etc.):helpgrep <keyword>
: This is the ultimate tool. It searches every single help document for your keyword and puts the results in a Quickfix list for you to navigate.Reading through the docs is how I found all of this stuff. Some of it I stumbled on by accident. Giving yourself the opportunity for those “Wait, it just does that?!” moments is how you’ll truly master this incredible editor.
Yes, of course. My philosophy is to use small, targeted plugins that provide a specific quality-of-life improvement that Vim can’t easily replicate. I use Tim Pope’s excellent plugins (like surround.vim
), syntax highlighters for specific filetypes, and as I mentioned, NERDTree.
The point isn’t to be a purist; it’s to be intentional. If a plugin makes your life easier, use it. But don’t let it be a black box. By understanding what Vim can do on its own, you build a stronger foundation and become a more capable developer.
That’s all I’ve got. I hope this look under the hood of Vim has been useful. Now, go forth and configure!
Enjoyed the article? I write about 1-2 a month. Subscribe via email or RSS feed.