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 yank, delete
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.
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!
:tildeop will make ~ act as an operator such as d or c, so that you can type ~4w to invert the case of the next 4 words.
@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!
you’ve got g~, you don’t need tildeop
I think you mean ddp to switch lines, unless I’m missing something.
yes,it may be ddp to switch lines
giwould get you back where you where editing. also,along with g; and g,Man, how could I forget that first one! I’ll add it to the article.
gv – last visual selection (useful too in the context of gi)
Pingback: Vim Anti-Patterns - Control+R
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.
Is it just me with the weird feeling that using ‘%’ extensively (especially with a plug-in like matchit) is highly overlooked in this blog post?
% is useful, but it’s hard to type. Otherwise, I completely agree with your assessment.
I usually remap TAB to % in normal mode. That makes the matching much more accessible.
The problem with mapping TAB to % is that breaks CTRL-i, which sucks when you get in the habit of using CTRL-o (go to previous jump) and CTRL-i (go to next jump).
Not really sure why that happens.
VIM is a little wonky around CTRL-I and , they’re apparently inseparable. My solution, because I’m deeply in love with mapping to %, is to use CTRL-P in it’s place:
nnoremap
xnoremap
I think HTML tag escaping ate the important part of this comment
Instead of pressing escape or Control-[ you can also use Control-c, which I find easier.
Just be aware that it skips any InsertLeave autocmds.
CTRL-C and ESC are very different things. Use them if you want, but don’t let other people believe they’re interchangeable. I would say that using CTRL-C in place of ESC is an ANTIPATTERN for Vim :)
ehy not bind jk to ESC ? like: imap jk
Unless you have a plugin-heavy setup or a configuration that depends on InsertLeave events, this works OK, but I’d advise against it for the reasons Derek gives here.
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.
Another great motion for i/a is t, for the content of tags. An absolute godsend.
Couple this with tpope’s surround plugin and you can quickly add/delete/change the surrounding tags for any given content as well. Surround feels so natural to use that I think it should really just be part of the Vim core.
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.
Pingback: Bookmarks for February 7th | Chris’s Digital Detritus
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.
I mapped f5 to toggle relative line numbers, because often I also want to know exactly where I am. map :call ToogleRelativeNumber()
dip or dap is often enough
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.
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
Pingback: Learning the vi language
One command you forgot:
:r!cmd
It runs cmd in the terminal and pastes the output into your vim file.
Fewer characters .. in command mode: !!cal
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.
Actually, having to type backtick-space-backtick-space…
I was wondering recently why there is gI (0i) and I (^i), but A ($a) and no gA. In my opinion A should be rather g_a and additional gA would do $a. Plain remapping would give me repeatability with the dot.
You should mention ctrl + i and ctrl + o for jumping back and forth between places in the code that you’ve made edits.
I use g; and g, for this, as noted in the article. Thanks for suggesting alternatives though!
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.
Vim makes you feel like a text surgeon; you operate precisely and unambiguously. It’s a very directed kind of command set.
@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!
Great article, great comments. Thanks!
You’re welcome! It’s proven unexpectedly popular.
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.
So how do you type “ and ” – it’s not the same as “?
Looks like formatting issue:
the first “ is keys backtick-backtick and the second one ” is apostrophe-apostrophe
Use CTRL-o instead
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”)
in normal mode: ZZ
save and exit
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.
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.
What’s the left hand side of the mapping? Looks like it got chopped out.
Oops, it got stripped… it’s space in angle brackets.
Does this form take entities?
<space>
Right:
nnoremap <Space> @q
Pingback: Essenz 2012/02/08 | duetsch.info
L to go to the bottom of the screen H to go to the top of the screen
Pingback: Bookmarks for 2 February 2012 through 8 February 2012 « Pilgrim Steward
Great post!
I found your search bar at the top with the magnifying glass very chic. I am moving my website to WP and would love to know what you did in WP to get this search widget. Would you mind telling me please? Thanks.
This is just a very slightly tweaked Twentyeleven theme. I think the search comes standard.
Considering vim anti-patterns, rather than just posting my favourite command, I would say you should point out the following anti-patterns:
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 )
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.
Pingback: 2012년 2월 9일 it 기술동향 |
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 !
Hi Fred; actually, in recent versions of Vim, Ctrl+P and Ctrl+N do work for the history. But you can also press Ctrl+F while in command mode to pull up the command line window instead, and then just move up and down in that as you would any buffer in normal mode, and press Enter on any of the commands to run it.
Hi, thanks for the answer, CTRL-F does the stuff indeed. For the new featire of CTRL-P/N I will try to recompile vim… cause I’m still on a 7.3 compiled in 2010…
Hi again,
Just recompiled vim 7.3 (Included patches: 1-434) to check if cCTRL-P or cCTRL-N worked like and but unfortunatly it does not. Do I miss something here ? Is there an option to add to activate it ?
Hi Fred; what operating system are you using? This works fine with a vanilla Vim setup on Debian GNU/Linux Sid for me.
The following mappings will fix it for you (I have these in my .vimrc in fact):
:cnoremap
:cnoremap
It didn’t display right:
:cnoremap <C-P> <Up> :cnoremap <C-N> <Down>
Thanks for sharing information. quite useful.
Pingback: Infovore » Links for February 8th through February 9th
Pingback: Vim anti-patterns | ./martijn
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!)
I use a spanish keyboard http://en.wikipedia.org/wiki/File:KB_Spanish.svg
and for I use this maps
ino ç vn ç
sorry the ESC is don’t displayed, the maps
ino ç ESC vn ç ESC
Pingback: StartupDigest | The best information about the tech startup world
Pingback: vim | Pearltrees
Pingback: 2011w06 « blog.padowi.se
Pingback: Programming Highlight - 2 | Planeta Globo.com
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
Pingback: Weekly Vim Focus « Phonons
Pingback: Python: String Formatting and Enumerate
Pingback: Lazy Reading for 2012/02/26 – DragonFly BSD Digest
Pingback: Compilado de enlaces « programacion@droope
ge, gE
repeating substitution also @: if last command
Pingback: Quora
Pingback: Week three of Vim | Evan Hahn dot com
Pingback: Resources For Learning Vim ⊆ David Xia
Pingback: Vim - Techniques | Pearltrees
Pingback: Compilado de enlaces « programacion@droope
Pingback: Vim misconceptions | Arabesque
Pingback: Avoiding the arrow keys | Arabesque
Nice and elaborated article. Helped me in learning about vim editor. Thanks a lot.
You are most welcome!
Pingback: Advanced Vim registers | Arabesque
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! ;-)