Vim anti-patterns

The benefits of getting to grips with Vim are immense in terms of editing speed and maintaining your “flow” when you’re on a roll, whether writing code, poetry, or prose, but because the learning curve is so steep for a text editor, it’s very easy to retain habits from your time learning the editor that stick with you well into mastery. Because Vim makes you so fast and fluent, it’s especially hard to root these out because you might not even notice them, but it’s worth it. Here I’ll list some of the more common ones.

Moving one line at a time

If you have to move more than a couple of lines, moving one line at a time by holding down j or k is inefficient. There are many more ways to move vertically in Vim. I find that the two most useful are moving by paragraph and by screenful, but this depends on how far and how precisely you have to move.

  • { — Move to start of previous paragraph or code block.
  • } — Move to end of next paragraph or code block.
  • Ctrl+F — Move forward one screenful.
  • Ctrl+B — Move backward one screenful.

If you happen to know precisely where you want to go, navigating by searching is the way to go, searching forward with / and backward with ?.

It’s always useful to jump back to where you were, as well, which is easily enough done with two backticks, or gi to go to the last place you inserted text. If you like, you can even go back and forth through your entire change list of positions with g; and g,.

Moving one character at a time

Similarly, moving one character at a time with h and l is often a waste when you have t and f:

  • t<char> — Move forward until the next occurrence of the character.
  • f<char> — Move forward over the next occurrence of the character.
  • T<char> — Move backward until the previous occurrence of the character.
  • F<char> — Move backward over the previous occurrence of the character.

Moving wordwise with w, W, b, B, e, and E is better, too. Again, searching to navigate is good here, and don’t forget you can yankdelete or change forward or backward to a search result:

y/search<Enter>
y?search<Enter>
d/search<Enter>
d?search<Enter>
c/search<Enter>
c?search<Enter>

Searching for the word under the cursor

Don’t bother typing it, or yanking/pasting it; just use * or #. It’s dizzying how much faster this feels when you use it enough for it to become automatic.

Deleting, then inserting

Deleting text with intent to replace it by entering insert mode immediately afterward isn’t necessary:

d2wi

It’s quicker and tidier to use c for change:

c2w

This has the added benefit of making the entire operation repeatable with the . command.

Using the arrow keys

Vim lets you use the arrow keys to move around in both insert and normal mode, but once you’re used to using hjkl to navigate, moving to the arrow keys to move around in text feels clumsy; you should be able to spend the vast majority of a Vim session with your hands firmly centered around home row. Similarly, while the Home and End keys work the same way they do in most editors, there’s no particular reason to use them when functional equivalents are closer to home in ^ and $.

So wean yourself off the arrow keys, by the simple expedient of disabling them entirely, at least temporarily:

noremap <Up> <nop>
noremap <Down> <nop>
noremap <Left> <nop>
noremap <Right> <nop>

The benefits of sticking to home row aren’t simply in speed; it feels nicer to be able to rest your wrists in front of the keyboard and not have to move them too far, and for some people it has even helped prevent repetitive strain injury.

Moving in insert mode

There’s an additional benefit to the above in that it will ease you into thinking less about insert mode as a mode in which you move around; that’s what normal mode is for. You should, in general, spend as little time in insert mode as possible. When you want to move, you’ll get in the habit of leaving insert mode, and moving around far more efficiently in normal mode instead. This distinction also helps to keep your insert operations more atomic, and hence more useful to repeat.

Moving to Escape

The Escape key on modern keyboards is a lot further from home row than it was on Bill Joy’s keyboard back when he designed vi. Hitting Escape is usually unnecessary; Ctrl+[ is a lot closer, and more comfortable. It doesn’t take long using this combination instead to make reaching for Escape as you did when you were a newbie feel very awkward. You might also consider mapping the otherwise pretty useless Caps Lock key to be another Escape key in your operating system, or even mapping uncommon key combinations like jj to Escape. I feel this is a bit drastic, but it works well for a lot of people:

inoremap jj <Esc>

Moving to the start or end of the line, then inserting

Just use I and A. Again, these make the action repeatable for other lines which might need the same operation.

Entering insert mode, then opening a new line

Just use o and O to open a new line below and above respectively, and enter insert mode on it at the same time.

Entering insert mode to delete text

This is a pretty obvious contradiction. Instead, delete the text by moving to it and using d with an appropriate motion or text object. Again, this is repeatable, and means you’re not holding down Backspace. In general, if you’re holding down a key in Vim, there’s probably a faster way.

Repeating commands or searches

Just type @: for commands or n/N for searches; Vim doesn’t forget what your last search was as soon as you stop flicking through results. If it wasn’t your most recent command or search but it’s definitely in your history, just type q: or q/, find it in the list, and hit Enter.

Repeating substitutions

Just type & to repeat the last substitution on the current line. You can repeat it on all lines by typing g&.

Repeating macro calls

Just type @@.

These are really only just a few of the common traps to avoid to increase your speed and general efficiency with the editor without requiring plugins or substantial remappings. Check out the Vim Tips wiki for some other really helpful examples.

108 thoughts on “Vim anti-patterns

  1. Three tips that I love in Vim:

    Use of ~ to change case of a letter. ‘xp’ to change the order of two characters. ‘dp’ to change the order of two lines.

    • Yes! For the first one, consider :set tildeop.

      The swapping ones are funny; when you first read them you think “I’m never gonna need that,” and then you end up using it all the time.

      • Damn, tildeop is brilliant! And I never knew…

        Good list of tips in the article. Especially “ and Ctrl+[ for Esc. Both of those had got past me.

        I’d suggest people check out `. too; it takes you to the position where the last change (rather than an insert, which is what gi will relocate you to) was made.

        • Please can you explain what tidleop does? The help just says “When on: The tilde command “~” behaves like an operator”. Thanks!

          • @Michiel de Mare – (I think the maximum comment nesting depth has been reached so will have to reply here)

            Thanks for the reply. That’s what I thought it meant, but I seem to have that behaviour already without an explicit “set tildeop” in my vimrc. That’s why I wasn’t seeing any difference in what ~ does when doing “set tildeop” and “set notildeop”. Maybe one of the other options like “site nocompatible” toggles this as well?

            Thanks again!

  2. Pingback: Vim Anti-Patterns - Control+R

  3. Don’t forget grabbing to multiple registers, and using Control+R to paste them while in insert mode. Multiple registers saves me time when yanking, and combined with :registers, Control+R saves time by pasting from insert mode. Great tips all around!

    • I do use Ctrl+R intermittently, but I consider pasting text to be something done from normal mode with p/P, and you can prepend an appropriate register to that with e.g. “+.

      • ^R is more than just insert mode though, it’s also something you can do at the command/search prompt. One thing I use that for is to search for something I’ve just changed/deleted (using /^R”), to find any other occurrences of it.

  4. Great tips, thanks. One note re: “Instead, delete the text by moving to the start or end of it and using d with an appropriate motion.” Moving to the start or end is often unnecessary too since you can use the “i” or “a” motion to delete “inside” or “around” whatever you happen to be inside, e.g. “diw” to delete the word (but not the adjacent spaces) under the cursor, or “ca(” to delete everything inside the parentheses the cursor is currently inside, as well as the parentheses themselves, and go into insert mode. I wrote up what is probably a better explanation awhile back on my friend’s Vim blog: http://dailyvim.tumblr.com/post/1174026416/i-for-inside-a-for-around

    • “ca(” can be replaced with “cab” “ca{” can be replaced with “caB”

      I use “ciB” all the time to replace the content of functions, and “cib” to replace parameter lists in functions. Way easier and faster than using ( and {.

      Basically anything where you’re using ( or { can be substituted with b or B respectively.

      Also, you can d/c/y with i/a against single quotes (‘), double quotes (“), angle brackets (<), sentences (s), paragraphs (p) and more.

    • Yes, text objects are the way to go, but because I use older systems a bit that don’t actually have it I’ve gotten in the habit of moving to the start of text I want to delete first. I might actually clarify that a bit now.

  5. Pingback: Bookmarks for February 7th | Chris’s Digital Detritus

  6. Great tips. Something I’ve found that has increased my speed as of late (especially during refactoring sessions) is turning on relative line numbers. This is mostly useful for yanking / deleting blocks of text. If I’m at the signature of a 13 line method and I want to move it, I can very quickly see that I need to delete the following 13 lines, so pulling the entire method out of the document becomes:

    d13j

    • I tried relative numbers but never quite got the hang of it; lots of people swear by them though. I guess I figure if I have line numbering on it’s usually not too much of a mental calculation to operate on a range of lines within the screen. I mostly use the line numbers to navigate to particular lines with e.g. 110G, and relativenumber kind of confuses that.

  7. Great tips, I use 95% of these all the time. Some others I use:

    gu + motion – Change text to lower case gU + motion – Change text to upper case

    ctrl + a – Increment number under cursor ctrl + x – Decrement number under cursor

    I once had a css file with 1000 or so class definitions that each had a different background position that I needed to decrement by 4 pixels. The above two + a recorded macro allowed me to make the change in a few seconds. Speaking of macros:

    q + identifier – Starts recording a macro any number of actions q – Ends recording of a macro @ + identifier – Repeats the macro under the current cursor position n + @ + identifier – Repeats the macro n times, can be extremely powerful

    Need to insert the same text at the beginning of multiple lines?

    v to go into visual block mode select appropriate lines using movement keys shift + i to go into insert mode with count support type insertion escape

    • The brilliant thing about Ctrl+A and Ctrl+X is that like most operators you can prepend a count to it, to increment or decrement a number by a fixed amount. Combining this with tpope’s speeddating plugin makes for some pretty astonishing functionality.

  8. Can’t edit my comment, but the last part was supposed to be:

    ctrl + v to go into visual block mode select appropriate lines using movement keys shift + i to go into insert mode with count support type insertion escape

  9. Pingback: Learning the vi language

  10. Some of these don’t work well on non-US keyboards, and worse still when in international mode. Imagine having to type backticks four times instead of two, for instance.

    As for o/O, it doesn’t ident correctly in some cases, which is really annoying, and I’ve never seen it do stuff like add “*” for Javadoc comments. Also, “I” adds before the first non-whitespace. “gI” can be a real help sometimes.

  11. I’m not sure the learning curve is all that steep for VIM but rather that it’s so difficult to maintain proficiency because keyboard-only requires so much memorizing – and of a particular anal kind that programmers are usually pretty good at.

    I use a few other professional-ish programs that have hundreds of shortcuts each and the problem to be careful of, is that if you’re not using the software almost every day – you inevitably keep on forgetting lots of them or confusing them. When this happens the speed benefits spoken of here, keep dribbling away.

    • In my experience (18 months of using it as my only editor) this feeling goes away when you stop thinking about it as “memorizing commands” and realise that vim’s commands let you think and describe your editing process in sentences. Granted, this might also be something that happens to work for the types of people who end up becoming programmers anyway, but I think it’s an important thing to underscore.

      When you first start with vim, sure, it’s a bit of memorizing to start with, but all of a sudden, you’re able to actualise your inner monologue as you edit. “Go down three lines, empty the contents of these parens and add some text, then swap this line with the line below it.”

      There’s always new things to learn, but once you’re able to reach the point of literacy and grok the whole action/motion/count concept and translate your thoughts to and from that, it really becomes a joy.

    • @PandaWood,

      The beauty of using Vim is that you will develop sensory memory and will NOT have to memorize where the key combinations are. Assuming that you are a touch typist already, then Vim work becomes automatic (e.g. navigation, insertion, visual mode, etc.). New key combinations take a while to master, but if you practice them enough your fingers will “remember” what to do without consciously thinking “Ctrl-V-j-j-j-j” to select a block of text, or whatever.

      Once you’re proficient with Vim you’ll notice that you don’t have to “think” about which keys you’re having to type.

      Cheers!

  12. You can use “ to go back to the exact position before your search or ” to go to the start of the line you were at before the search.

    Comes handy when you use searching as a primary way to navigate a file.

  13. In terms of avoiding moving only one line at a time, I can’t recommend highly enough the use of relative numbers (set :rnu). It’s infinitely easier to start jumping exactly to the line you want when you can just quickly eyeball it (34kk) instead of having to sit there and do even the most basic arithmetic (“Oh hm, what’s 273-239? Ahhh.. 34! 34kk”)

  14. I recommend setting the repetition rate of your keyboard to very very slow. This helped me weed out the holding of keys inside of Vim very quickly. It’s similar to ing your cursor keys.

  15. Some great tips in here, definitely a few new ones for me. Other commenters have mentioned relative line numbers which are awesome for use with hjkl and dd/yy. One thing no one has mentioned is the quick-macro bind:

    nnoremap @q

    Being able to do super-quick one-off macros with qq and repeat with has been life-changing for me. It is dramatically superior to regex search/replace. Granted the bind is only a minor efficiency improvement, but for new macro users it greatly increases the chances of learning and using one-off macros instinctively.

  16. Pingback: Essenz 2012/02/08 | duetsch.info

  17. Pingback: Bookmarks for 2 February 2012 through 8 February 2012 « Pilgrim Steward

  18. Considering vim anti-patterns, rather than just posting my favourite command, I would say you should point out the following anti-patterns:

    • using index, middle, ring, and little fingers respectively for h, j, k, l (it took me ages to unlearn this habit and use the correct fingers, as a touch-typist would)
    • not using visual mode
    • not setting up any custom mappings (the real power of vim is that you can customize it to how how you like it)
    • not using any plugins (ditto)
    • not mapping ; to : and vice versa (it took me ages to make this change, because you use : so much that it gets really ingrained, which is precisely why it’s worth setting the mapping)
    • I disagree about custom mappings and plugins. One reason I use vim over other editors is its availability in various server environment. I often find myself connecting to a server (under my control or otherwise) to debug a problem. Having familiar environment (plain vim) makes solving production issues more timely. I’ve seen so many people having to “setup” their vim and shell before they could do anything useful.

    • Interesting: * using index, middle, ring, and little fingers respectively for h, j, k, l (it took me ages to unlearn this habit and use the correct fingers, as a touch-typist would) – that’s funny, I created a new layout instead which makes those the home keys ( http://cheater.posterous.com/layout )

      • not using visual mode – for you not using visual mode is an antipattern. For me using visual mode is an antipattern more often, I try to weed that out and use text objects instead.
      • I wouldn’t call visual mode an antipattern generally — it’s one extra key, and great for selecting areas of text that are a bit awkward to define. If you’re a vi purist you could perhaps argue that leaning on it too much as a crutch will cripple you when using a less capable vi implementation.

        Visual block mode, ah, now there’s something I use every day.

  19. Pingback: 2012년 2월 9일 it 기술동향 |

  20. Hi,

    Thanks for the article, it’s a good reminder of the good and bad vim practices. I also try to let my fingers move the closest to the home row, and also avoid using the Up and Down key as far as possible. But I cannot avoid using them in command mode where they are really useful for the command history and cannot unfortunately be replaced by cCTRL-P or cCTRL-N, and I have to say that I use the command line history very often.

    So if you have an idea on how you use it and if you have an alternative to the use of these far Up and Down key, but any advice is welcome !

  21. Pingback: Infovore » Links for February 8th through February 9th

  22. Pingback: Vim anti-patterns | ./martijn

  23. The CTRL+[ key combination is a pain in the ass when you don’t have an US Keyboard, or one which has the [ char in a single key press: e.g. sometimes the [ character is ALTGR+[ or ALT+CTRL+ [ (my case). So yes, ESC is necessary.

    This f*cking escape sequence happens in telnet, ftp and others programs and cannot be changed (sigh!)

  24. Pingback: StartupDigest | The best information about the tech startup world

  25. Pingback: vim | Pearltrees

  26. Pingback: 2011w06 « blog.padowi.se

  27. Pingback: Programming Highlight - 2 | Planeta Globo.com

  28. Vim escape pains had me stumped until I found out that in Konsole (or many other terminals) alt+ results in the sequence ESC

    This makes life so much easier than the ESC to normal mode. If at any point you are in insert mode and want to continue with normal mode, start with alt+.

    e.g. I am in insert mode in the middel of the line and want to open a new line below and continue inserting… my shortcut? no remaps needed just plain and simple alt+o

    or I want to delete the line I am editing to the end, no more ESC and then d$, no! I simply press alt+d then $ simple, hey?

    This makes every normal mode key available from insert mode without that warning of a dire sindrome at the back of keyboards…

    What is really nice is that this works with the movement keys too, so alt+j, alt+k, alt+h and alt+l do what they should… the up side is that in any “normal” editer that is forced down my throat, these are the first mappings I make, allowing me to hold alt down with my left hand while moving in beloved vim style even in eclipes et al…

    nuff said alt+:wq

  29. Pingback: Weekly Vim Focus « Phonons

  30. Pingback: Python: String Formatting and Enumerate

  31. Pingback: Lazy Reading for 2012/02/26 – DragonFly BSD Digest

  32. Pingback: Compilado de enlaces « programacion@droope

  33. Pingback: Quora

  34. Pingback: Week three of Vim | Evan Hahn dot com

  35. Pingback: Resources For Learning Vim ⊆ David Xia

  36. Pingback: Vim - Techniques | Pearltrees

  37. Pingback: Compilado de enlaces « programacion@droope

  38. After half a decade of vim usage, I consider myself to be an intermediate user, but with such informative and well-written articles as yours, I believe I can progress to mastery in only one or two lifetimes.

    I’m very glad now that I was introduced to vim first and not emacs, so that it won’t take me 1,000 lifetimes to master my editor! ;-)

  39. Pingback: Getting Started with Vim

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use Markdown if you want.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>