How to boost your Vim productivity
sheerun.net
sheerun.net
I've been using vim for 15+ years now, since late 1990's. I use viemu in Visual Studio and I've written code in 10+ languages in vim. I've written non-trivial vimscripts and integration tools with other parts of my workflows over the years. I love how comfortable it feels, and I feel crippled when I have to use a 'normal' editor; like walking with a little pebble in your shoe - not a big a deal enough to prevent you from doing anything you could otherwise, but still damn uncomfortable.
With that said, I'm not convinced that I've actually saved time with it. I shudder if I think of the many man-days I spend 10 years ago on getting this and that plugin working, tweaking settings and keybindings for things I use twice a month tops and automating things that I could have done manually 10 times faster. It's not like regular editors are that much slower to use. It felt like throwing off a yoke when I dumped all those plugins so that I could focus on writing software, instead of tweaking the editor so that I could write programs with a few keystrokes.
So yeah, that was gramps' advice I guess...
I think this is terrible advice. While it is true that one should avoid getting lost down the plugin rabbit hole, for many of us, the whole point of Vim is that it is a configurable, composable editor.
As for being "cripped" without my vimrc, well, moving tiny text files around is pretty much a solved problem at this point. And as a developer, I'd prefer to optimize my 99.9% of the time environment, and not worry about the .1% of the time I'm away from it.
I do, however, recommend that your vimrc is something you should build up over time, understanding what you are putting into it, rather than grabbing some big off-the-shelf framework and using it without understanding what is going on.
- Go version: https://github.com/samuell/devbox-golang
- Python version: https://github.com/samuell/devbox-python
I love being able to SSH in to a fresh docker (yes, I use fat SSH:able docker), and enjoy full auto-completion for python and Go! :)
But yeah, except for the auto-completion and a few minor tweaks, there's not too much extras there.
Plus, the overhead is a lot less.
Without stuff like that I'm still fine should I find myself on a remote machine. But I don't see an issue with making myself more comfortable than just being 'fine' on my personal setup where I spend most of my time.
I think the key is to vet your plugin and mapping choices to ones that expand upon vim in some way and avoid those that override core functionality or prevent you from learning them. If you do that you should be fine without imposing an arbitraty vimrc length.
From memory I've only changed about 5 lines in my vimrc ? enabling mouse and setting indentation levels for some less common filetypes.
I've done major swaps between Emacs and (n)vi over the years (currently all vi all the time now, but if you caught me last year, I was ~6 years into my Emacs phase...) -- anyway: the fussing and portability is what kept me from developing custom elisp scripts that I couldn't be guaranteed to have sitting down at every computer, and what now keeps me in nvi, and my nvi usage pretty "vanilla". It's not clear to me if its only the fear of getting caught w/o a custom environment is what's keeping me from developing that environment, but regardless, my env is vanilla.
Edit: typos
This also means when I had a computer outage and borrowed my wife's MBA without an dev tools aside from what came with OS X, I logged into dropbox, copied my .profile from dropbox and magically had a working, customized Vim on her computer. After a Git clone I was productive in maybe 20 minutes tops. Just imagine trying to do that with visual studio (i've tried, there goes a day).
1. You have to import/export every time a change is made!
2. Visual Studio takes like 6 hours to install.
2. I install VS quite a bit, it's not that long at all. More time than sublime et all though, agreed. I usually have it as my "parallel" process while I go clone my repos.
If I had to choose 1 plugin, I would choose Unite. It's great for development projects where you have lots of files. Especially when you set up key bindings. Having 3+ files open at the same time (model, view, controller, tests) is a pain to have to type the paths each time. Often times you need to open them have them open at the same time. Having quick keybindings to open new windows and navigate them are really a blessing. The default controls are too much of a pain for this workflow.
The ones that highlight syntax errors in python, or js, or that spit out compilation errors for C are a must, and one of the most important features for me.
The plugins that take hours to configure, and let you press on key instead of three for some infrequent action: yes, avoid them. No matter how fancy they look, and how well someone tries to sell it to you.
CtrlP is also a must for me. Instantly open any file, even if I vaguely recall it's name. And no configuration necessary (though you can optionally tweak it a bit).
I've also been using vim for 10 or 15 years. I typically use a couple of plugins (1-3) and that's it. I leave the key bindings alone. I've never liked vimscript and have only done a few things there. Luckily I started that way and stayed that way, so vim actually has saved me time.
This means using :normal and macros instead of :s for most of my search/replace actions; using H, M, L, {, } to navigate quickly in the lines visible on the screen, and using f/F/t/T/;/,/% to navigate quickly within a line.
I would say that 98% of my autocomplete needs are fulfilled by token completion (:help i_CTRL-N) and line completion (:help i_CTRL-X_CTRL-L).
I frequently use the command-line window (:help c_CTRL-F) and listing matching names (:help c_CTRL-D).
I specifically don't have mappings that involve the leader key, and I don't use the Ctrl-P plugin or a package manager or anything like that -- I honestly don't think that mapping <Leader>w to :w<CR> will make me any more productive in Vim.
Interesting. Can you please elaborate more on this?
i = foo(a, 42, 1)
j = bar(b, c, 100, 2) # this is a comment (well, duh)
bazbar(etc, 3)
You want to edit the last parameter in each function call -- change it to 'hello'. I have two ways of approaching this: macros (interactive) or :norm (less interactive).1. Put your cursor on the first byte in the first line, type qq to record a macro of your change, q to finish. Select the rest of the lines in visual line mode and type :'<,'>norm @q to run the macro on each of the remaining lines.
2. Select the lines in visual line mode and type, for instance, :'<,'>norm %F,ws'hello' This is the "non-interactive" version of the above since the macro keystrokes are given directly to :normal. Pro: ability to undo keystrokes unlike when recording a macro. Con: cannot actually see the effect of the keystrokes (but with practice, this is not a problem).
(Note that colon in visual mode automatically inserts the :'<,'> so you only have to type :norm ...)
I find the declarative nature of regexes/:s to be too restrictive -- I much prefer the operational nature of macros/:normal, since that lets me make the change I want directly, without me having to phrase the change as a regular expression.
I could also use CTRL-A in normal mode to increment the last argument in each line: :'<,'>norm %b^A (where ^A is the literal, typed CTRL-V CTRL-A)
I feel like a wizard whenever I use :normal in a non-trivial manner.
I normally include a move to next line part in my macro and then guess at how many times to run it (20@q, repeat until I get it right). It's actually the main reason I often don't bother using macros.
This is such a great tip. Thanks!
:'<,'>g/foobar/norm @q
will run the macro only on the subset of selected lines that match the regex "foobar". :g/.../ will match the regex against all lines in the file.Another tip: when you forget to add the move to next line to your macro, you don't have to start over. You can append to a macro, just use the upper-case register name instead. So to append a down and move to beginning of line to macro 'a', you'd type qAj0
:%s/.)/hello)/
simpler? Maybe that's because I know nothing about macros. Thanks for the explanation.
The PAPI library has a utility program papi_avail which prints a table of supported performance counters. The lines may look like this:
PAPI_VEC_SP 0x80000069 Yes Single precision vector/SIMD instructions
PAPI_VEC_DP 0x8000006a Yes Double precision vector/SIMD instructions
PAPI_REF_CYC 0x8000006b No Reference clock cycles
For a course project, I wanted to turn this into a C-array like this: {PAPI_VEC_SP, "Single precision vector/SIMD instructions"},
{PAPI_VEC_DP, "Double precision vector/SIMD instructions"},
{PAPI_REF_CYC, "Reference clock cycles"},
Using :norm, this transformation can be achieved in the following way: :'<,'>norm I{^[eldedecw, "^[A"},
(where ^[ is a literal escape, typed CTRL-V ESC.)Anecdotally, it is faster for me to type up such a line than an equivalent regular expression, since I use vi normal mode commands much more than regular expressions.
/^\(\S*\)\s*\S*\s*\S*\s*\(\p*\)
:%s//{\1, "\2"},
"Now they have two problems."As a side note, I love how Vim is basically a functional programming language for text editing.
{ down { down {
to insert all three leftmost brackets. up up up
to go to first bracket. shift+left
to select first bracket. cmd+d cmd+d cmd+d
to select all three next brackets including the first. ctrl+shift right
to move all three cursors to the end of word. comma space "
to type your characters with all three cursors. cmd+right
to go to end of line with all three cursors. " } ,
to type your characters with all three cursors.21 presses (29 keys), compared to your 32. And all I had to think about was where the cursor was.
(Not to be pedantic, of course!)
Basically, I achieved my wizard-level C++, Vim and Git knowledge during my three years as a part-time student programmer in the basic research center MADALGO. I took the time to study the documentation (respectively the C++11 draft, :help and the git man pages) whenever I was curious. For Vim in particular, I made sure to eliminate all repeated keysmashing in my daily workflow, which "unfortunately" required me to learn about macro wizardry.
My only advice is to keep practicing, to keep trying to spot inefficiencies in your own workflows, and to actively eliminate these inefficiencies by studying the Vim help pages.
" search. cw (or cs, c whatever) to replace/fix. esc. n.n.n.n.
vnoremap <silent> s //e<C-r>=&selection=='exclusive'?'+1':''<CR><CR>
\:<C-u>call histdel('search',-1)<Bar>let @/=histget('search',-1)<CR>gv
omap s :normal vs<CR>
A really simple, dumb example: http://showterm.io/040c49ac158cdda15fbcaI usually use the asterisk to search for the token under the cursor, edit the sought token using cw and then n.n.n.n. to replace later occurrences. I don't see how the mapping makes this more efficient.
But would you mind giving an explanation as to what the other things you listed do (f/F/t/T/;/,)?
From just playing with them, it seems like f goes to the next character that you type and F does the same but backwards. t/T does the same but instead of going to the character it goes one before/after.
I can't figure out what , and ; are for though..
fx moves the cursor to the next occurrence of x, and semicolon repeats the search. To repeat the search in the opposite direction, use comma. 4tx moves the cursor right before the 4th occurrence of x right of the cursor in the line. F and T move backwards instead of forwards; in that case, semicolon continues moving backwards and comma moves forwards (similar to / ? n N).
It takes a while to get used to, but it has made me much more efficient compared to when I just pressed wwwww or eeeee or bbbb to get where I wanted in a line.
I use t / f a lot when cutting things, though there's probably a better way (from the article, I just discovered gn to visually select the next item matching the previous search).
eg, I might have a name that I want to replace in a couple of spots so I find it easy to do something like:
/AIDOS<CR>cfSNEWNAME<ESC>n.n.n.
It's generally when it's a bit less calculated. If I knew I was replacing a load of stuff I'd use :%s/AIDOS/NEWNAME/gc\includegraphics{test.png}
if you stand inside the curly brackets and type ciB (change in Brackets) you get this
\includegraphics{}
with your cursor active inside the brackets, just awesome ..
(I think of "B" as beginning of a Word [including punctuation], so it would confuse me to use the "B" meaning braces)
I read 'ci(' as change what's inside parents. I read 'ci{' as change inside braces. 'ca(' and 'ca{' grab the parents and the braces as well.
=========================
These combinations work for (d)elete as well. If your cursor is over the 4th letter of a 6 letter word, 'dw' will delete to the end of the word. 'diw' on the other hand will delete the whole word. (I've never tried 'daw' although I know 'da(' works)
It's because 'iw', 'aw', and the like are commands of their own when an operator like 'c' or 'd' precedes [1]. So 'di)' is interpreted as 'd' followed by the 'i)' command (if I'm interpreting it correctly!), not as 'd' followed by 'i' followed by ')', which is nonsense.
I hope that was clear - just trying to understand vim better :)
[1]: http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objec...
I'm not as much of a purist, but that line jumped out at me too. For me, the attraction of vim is primarily in raw out-of-the-box editing power and ubiquity. Relying on custom binds for basic actions really hurts the ubiquity half of the equation. And really is :w<CR> where one wastes time in vim? If I wanted to customize everything I'd probably switch to emacs.
Still, it's interesting to see how many different ways vim can be optimized according to individual workflows.
"%" works fine for moving around, but when I use it to edit it always surprises me, which direction it goes. I almost think vim is psychic, because "%" goes the wrong direction for me at least 80% of the time. There must be a deterministic rule governing this, but can anyone explain to me what it is?
For example, remapping the paste key to paste + move to end is cool, but `ppppp` to paste 5 times circumvents vim's killer repetition. Want to paste 100 copies? (hopefully you do this rarely). Just type `100p` and you're done. I won't bother typing out the obvious sequence of repeated `p` presses, but you get the drift.
Also, remapping v to progressively select larger surrounding text objects will keep you from learning that you can perform any action on the 3rd parent curly braces by following the action with the text object `3a{` or `3a}`. Select it: `v3a{`, delete it: `d3a{`, comment it out `gc3a{` ([2]), whatever. If there's an action in vim you can perform it on a text object which can usually start with some count.
I really do mean language, too. When I'm using vim, I feel a lot more like I'm communicating with my computer than trying to figure out how to do what I want to do.
The actions are there: delete, change, select. The direct objects are there: braces, this line, line number N, end of this word, the next character C, this paragraph. The prepositions are there: inside, outside, up to (inclusive, exclusive).
Heck, the sensible defaults feel a whole lot like the "understood" words that you can leave out of sentences. Instead of "navigate to line 30", you can just use the shortcut for "line 30" (30G) and be done.
One of my favorite things about vim is the number of times I've literally been surprised that vim didn't read my mind and go where I was looking. Once you're familiar with the different pieces, it's so good that you might expect it to read your mind.
</almost-blog-post>
I tell people learning Vim or Emacs that they should treat it like learning a new programming language -- a programming language for text manipulation. (In particular, don't attempt a first project in C++ while writing your first report in LaTeX, both in Vim for the first time -- it will not be a pleasant experience!)
>It seems like vvv is slower than vp but in practice I don’t need to think beforehand what to select, and what key combination to use.
The way I've always used vim and always thought it was intended to be used is that you do think beforehand. You sit at your editor, think about what changes you want to make, and then key in a set of precision commands in vim-editing-language and it happens.
>This way v replaces viw, vaw, vi", va", vi(, va(, vi[, va[, vi{, va{, vip, vap, vit, vat, ... you get the idea.
I kind of like the precision of having all of those different things, and of course the option of using them for more than just visual select but also change, delete, and so on. Although I suppose this doesn't remove any of those keymappings, I must protest remapping Ctrl+v: I can't even use an editor without block select.
I imagine there's a plugin (or even builtin feature) that at least generalises "s, (s , [s, tags and things of that sort though.
>Stop that stupid window from popping up: >map q: :q
I know it's a weird and irritating thing to have that window pop up when you meant to quit, but it's actually a very neat interface: a whole vim buffer for recomposing commands and your command history for later execution (almost acme-like). Give the poor guy a chance.
As a counterpoint to what I've pointed out above, I'd like to recommend Drew Neil's [Practical Vim](http://www.amazon.com/Practical-Vim-Thought-Pragmatic-Progra...) to anyone who hasn't read it already. It's got a lot of great content, and really goes a long way to explain vim's quirks and methods of doing things.
One of the useful tips I learnt from that was the ex command "normal", which allows you to execute a string of normal mode commands over a range of lines. So, for example, you can append a semicolon to each line in a visual selection by entering
:'<,'>%normal A;
A small thing, but one that I've used a lot since learning about it. <Leader>p "+p
mapping. I do this all the time ("+p). It's weird because I tend to go through waves of realizing "Oh! I can just remap that!" I feel like I have fairly good vim skills but somehow always forget I can keep making it more efficient than it already is.Thanks for the reminder =].
(Note: I turn rope off in python-mode because it's horribly inefficient, and sometimes causes Vim to delay reacting to user input)
map <F1> <Esc>:w<CR>| "Fast save
imap <F1> <Esc>:w<CR>| "Fast save
map <F2> :make<Up><CR>| "Fast compile
map <F3> :bn<CR>
map <S-F3> :bp<CR>
" Same mapping for gnome-terminal ( see http://stackoverflow.com/q/12813126/164171 )
map ^[O1;2R :bp<CR>
map <F4> :bd<CR>| "Close buffer
map <F5> :cnext<cr>
map <S-F5> :cprev<cr>
imap <F5> <Esc>:cnext<cr>
imap <S-F5> <Esc>:cprev<cr>Probably because that doesn't fit well with touch typing. A great thing about vim is that you can do everything as a touch typist, without reaching for the outlying districts of the keyboard (assuming you've remapped the escape key to capslock, or learned to use ^[, or mapped it).
The sad thing is that I've personally experienced all three of these problems. #%^$ whoever decided that the Function keys should be brightness etc by default.
"Function to commit.
function! GitCommit ()
execute 'write'
let message = input('Enter commit message: ')
execute '!git add ' . bufname('%') . ' && git commit -m ''' . message . ''';'
endfunction
imap <F7> <Esc>:call GitCommit()<CR>
map <F7> <Esc>:call GitCommit()<CR>Perhaps it could be learned, but I haven't learned it yet in ~20 years of typing.
" Filesystem browser
map <F2> :Explore<CR>
" Show whitespace
set listchars=eol:↵,tab:>·,trail:~,extends:>,precedes:<,space:␣
map <F4> :set list!<CR>https://github.com/yramagicman/dotfiles/blob/master/.vim/aft...
vim scp://host//etc/whatever
You can also use .nvimrc instead .vimrc, so only nvim instance on server gets plugins.
No more having to reach for the escape key.
imap jk <ESC>
imap kj <ESC>
I just hit both and j at the same time with my pointer and index fingers so it's essentially one keystroke.For me, having remapped Capslock to Ctrl, this is a dead simple way of hitting Esc without going as far off homerow.
The only pitfall is when you start using someone else's computer and putting caps everywhere.
immediately maps this to ctrl-w m
I also use mouse for resizing.
:he ctrl-w
edit: typo
The Space and Ctrl+Space thing is interesting, but not interesting enough for me to switch (from , and Ctrl+q – with Ctrl being on Caps Lock).