[vim] What is your most productive shortcut with Vim?

I've heard a lot about Vim, both pros and cons. It really seems you should be (as a developer) faster with Vim than with any other editor. I'm using Vim to do some basic stuff and I'm at best 10 times less productive with Vim.

The only two things you should care about when you talk about speed (you may not care enough about them, but you should) are:

  1. Using alternatively left and right hands is the fastest way to use the keyboard.
  2. Never touching the mouse is the second way to be as fast as possible. It takes ages for you to move your hand, grab the mouse, move it, and bring it back to the keyboard (and you often have to look at the keyboard to be sure you returned your hand properly to the right place)

Here are two examples demonstrating why I'm far less productive with Vim.

Copy/Cut & paste. I do it all the time. With all the contemporary editors you press Shift with the left hand, and you move the cursor with your right hand to select text. Then Ctrl+C copies, you move the cursor and Ctrl+V pastes.

With Vim it's horrible:

  • yy to copy one line (you almost never want the whole line!)
  • [number xx]yy to copy xx lines into the buffer. But you never know exactly if you've selected what you wanted. I often have to do [number xx]dd then u to undo!

Another example? Search & replace.

  • In PSPad: Ctrl+f then type what you want you search for, then press Enter.
  • In Vim: /, then type what you want to search for, then if there are some special characters put \ before each special character, then press Enter.

And everything with Vim is like that: it seems I don't know how to handle it the right way.

NB : I've already read the Vim cheat sheet :)

My question is:

What is the way you use Vim that makes you more productive than with a contemporary editor?

This question is related to vim vi

The answer is


Session

a. save session

:mks sessionname

b. force save session

:mks! sessionname

c. load session

gvim or vim -S sessionname


Adding and Subtracting

a. Adding and Subtracting

CTRL-A ;Add [count] to the number or alphabetic character at or after the cursor. {not in Vi

CTRL-X ;Subtract [count] from the number or alphabetic character at or after the cursor. {not in Vi}

b. Window key unmapping

In window, Ctrl-A already mapped for whole file selection you need to unmap in rc file. mark mswin.vim CTRL-A mapping part as comment or add your rc file with unmap

c. With Macro

The CTRL-A command is very useful in a macro. Example: Use the following steps to make a numbered list.

  1. Create the first list entry, make sure it starts with a number.
  2. qa - start recording into buffer 'a'
  3. Y - yank the entry
  4. p - put a copy of the entry below the first one
  5. CTRL-A - increment the number
  6. q - stop recording
  7. @a - repeat the yank, put and increment times

I am a member of the American Cryptogram Association. The bimonthly magazine includes over 100 cryptograms of various sorts. Roughly 15 of these are "cryptarithms" - various types of arithmetic problems with letters substituted for the digits. Two or three of these are sudokus, except with letters instead of numbers. When the grid is completed, the nine distinct letters will spell out a word or words, on some line, diagonal, spiral, etc., somewhere in the grid.

Rather than working with pencil, or typing the problems in by hand, I download the problems from the members area of their website.

When working with these sudokus, I use vi, simply because I'm using facilities that vi has that few other editors have. Mostly in converting the lettered grid into a numbered grid, because I find it easier to solve, and then the completed numbered grid back into the lettered grid to find the solution word or words.

The problem is formatted as nine groups of nine letters, with -s representing the blanks, written in two lines. The first step is to format these into nine lines of nine characters each. There's nothing special about this, just inserting eight linebreaks in the appropriate places.

The result will look like this:

T-O-----C
-E-----S-
--AT--N-L
---NASO--
---E-T---
--SPCL---
E-T--OS--
-A-----P-
S-----C-T

So, first step in converting this into numbers is to make a list of the distinct letters. First, I make a copy of the block. I position the cursor at the top of the block, then type :y}}p. : puts me in command mode, y yanks the next movement command. Since } is a move to the end of the next paragraph, y} yanks the paragraph. } then moves the cursor to the end of the paragraph, and p pastes what we had yanked just after the cursor. So y}}p creates a copy of the next paragraph, and ends up with the cursor between the two copies.

Next, I to turn one of those copies into a list of distinct letters. That command is a bit more complex:

:!}tr -cd A-Z | sed 's/\(.\)/\1\n/g' | sort -u | tr -d '\n'

: again puts me in command mode. ! indicates that the content of the next yank should be piped through a command line. } yanks the next paragraph, and the command line then uses the tr command to strip out everything except for upper-case letters, the sed command to print each letter on a single line, and the sort command to sort those lines, removing duplicates, and then tr strips out the newlines, leaving the nine distinct letters in a single line, replacing the nine lines that had made up the paragraph originally. In this case, the letters are: ACELNOPST.

Next step is to make another copy of the grid. And then to use the letters I've just identified to replace each of those letters with a digit from 1 to 9. That's simple: :!}tr ACELNOPST 0-9. The result is:

8-5-----1
-2-----7-
--08--4-3
---4075--
---2-8---
--7613---
2-8--57--
-0-----6-
7-----1-8

This can then be solved in the usual way, or entered into any sudoku solver you might prefer. The completed solution can then be converted back into letters with :!}tr 1-9 ACELNOPST.

There is power in vi that is matched by very few others. The biggest problem is that only a very few of the vi tutorial books, websites, help-files, etc., do more than barely touch the surface of what is possible.


The Control+R mechanism is very useful :-) In either insert mode or command mode (i.e. on the : line when typing commands), continue with a numbered or named register:

  • a - z the named registers
  • " the unnamed register, containing the text of the last delete or yank
  • % the current file name
  • # the alternate file name
  • * the clipboard contents (X11: primary selection)
  • + the clipboard contents
  • / the last search pattern
  • : the last command-line
  • . the last inserted text
  • - the last small (less than a line) delete
  • =5*5 insert 25 into text (mini-calculator)

See :help i_CTRL-R and :help c_CTRL-R for more details, and snoop around nearby for more CTRL-R goodness.


Vim Plugins

There are a lot of good answers here, and one amazing one about the zen of vi. One thing I don't see mentioned is that vim is extremely extensible via plugins. There are scripts and plugins to make it do all kinds of crazy things the original author never considered. Here are a few examples of incredibly handy vim plugins:

rails.vim

Rails.vim is a plugin written by tpope. It's an incredible tool for people doing rails development. It does magical context-sensitive things that allow you to easily jump from a method in a controller to the associated view, over to a model, and down to unit tests for that model. It has saved dozens if not hundreds of hours as a rails developer.

gist.vim

This plugin allows you to select a region of text in visual mode and type a quick command to post it to gist.github.com. This allows for easy pastebin access, which is incredibly handy if you're collaborating with someone over IRC or IM.

space.vim

This plugin provides special functionality to the spacebar. It turns the spacebar into something analogous to the period, but instead of repeating actions it repeats motions. This can be very handy for moving quickly through a file in a way you define on the fly.

surround.vim

This plugin gives you the ability to work with text that is delimited in some fashion. It gives you objects which denote things inside of parens, things inside of quotes, etc. It can come in handy for manipulating delimited text.

supertab.vim

This script brings fancy tab completion functionality to vim. The autocomplete stuff is already there in the core of vim, but this brings it to a quick tab rather than multiple different multikey shortcuts. Very handy, and incredibly fun to use. While it's not VS's intellisense, it's a great step and brings a great deal of the functionality you'd like to expect from a tab completion tool.

syntastic.vim

This tool brings external syntax checking commands into vim. I haven't used it personally, but I've heard great things about it and the concept is hard to beat. Checking syntax without having to do it manually is a great time saver and can help you catch syntactic bugs as you introduce them rather than when you finally stop to test.

fugitive.vim

Direct access to git from inside of vim. Again, I haven't used this plugin, but I can see the utility. Unfortunately I'm in a culture where svn is considered "new", so I won't likely see git at work for quite some time.

nerdtree.vim

A tree browser for vim. I started using this recently, and it's really handy. It lets you put a treeview in a vertical split and open files easily. This is great for a project with a lot of source files you frequently jump between.

FuzzyFinderTextmate.vim

This is an unmaintained plugin, but still incredibly useful. It provides the ability to open files using a "fuzzy" descriptive syntax. It means that in a sparse tree of files you need only type enough characters to disambiguate the files you're interested in from the rest of the cruft.

Conclusion

There are a lot of incredible tools available for vim. I'm sure I've only scratched the surface here, and it's well worth searching for tools applicable to your domain. The combination of traditional vi's powerful toolset, vim's improvements on it, and plugins which extend vim even further, it's one of the most powerful ways to edit text ever conceived. Vim is easily as powerful as emacs, eclipse, visual studio, and textmate.

Thanks

Thanks to duwanis for his vim configs from which I have learned much and borrowed most of the plugins listed here.


I was surprised to find no one mention the t movement. I frequently use it with parameter lists in the form of dt, or yt,


Automatic indentation:

gg (go to start of document)
= (indent time!)
shift-g (go to end of document)

You'll need 'filetype plugin indent on' in your .vimrc file, and probably appropriate 'shiftwidth' and 'expandtab' settings.


You can search the content of a register.

Suppose that your register x contains

string to search

To search this string, you have to type in normal mode
/CTRL-rxENTER

It'll paste the content of x register.


Use the builtin file explorer! The command is :Explore and it allows you to navigate through your source code very very fast. I have these mapping in my .vimrc:

map <silent> <F8>   :Explore<CR>
map <silent> <S-F8> :sp +Explore<CR>

The explorer allows you to make file modifications, too. I'll post some of my favorite keys, pressing <F1> will give you the full list:

  • -: The most useful: Change to upper directory (cd ..)
  • mf: Mark a file
  • D: Delete marked files or the file the cursor is on, if nothing ismarked.
  • R: Rename the file the cursor is on.
  • d: Create a new directory in the current directory
  • %: Create a new file in the current directory

You asked about productive shortcuts, but I think your real question is: Is vim worth it? The answer to this stackoverflow question is -> "Yes"

You must have noticed two things. Vim is powerful, and vim is hard to learn. Much of it's power lies in it's expandability and endless combination of commands. Don't feel overwhelmed. Go slow. One command, one plugin at a time. Don't overdo it.

All that investment you put into vim will pay back a thousand fold. You're going to be inside a text editor for many, many hours before you die. Vim will be your companion.


http://www.viemu.com/a-why-vi-vim.html is a good advocacy article. It explains the power of using the . command to repeat the last edit.

Copy/Cut & paste. I do it all the time. With all the classical editors you press Shift with the left hand, and you move the cursor with your right hand to select text. Then Ctrl+C copies, you move the cursor and Ctrl+V pastes.

With Vim it's horrible:

* yy to copy one line (you almost never want the whole line!)
* [number xx]yy to copy xx lines into the buffer. But you never know

exactly if you've selected what you wanted. I often have to do [number xx]dd then u to undo!

I'm sure the other answers have explained better, but You're Doing It Wrong. I often use visual mode to select text to yank or delete, which is similar to your shift + select example, but Vim has a clear advantage here because your hands never leave home row to do it. yy is a great command but I often do Vy instead if I want to yank a whole line.


In addition to the great reply about grokking vi, it should be noted that vim does add some very vi-like features that make using vi commands nicer. The one that comes to mind first are text objects: instead of {!}fmt to reformat the current paragraph, !apfmt does the same. It works by first specifying that we want to select a text object, which is the current paragraph. Similar, to change the current string literal (foo to bar for an example), instead of T"ct"bar (move to just after the previous ", change until just before the next ", insert bar), you can say ci"bar: change inside (innermost) quotes, inserting bar.

Thinking in terms of text objects instead of movement commands is quite nice.


Bulk text manipulations!

Either through macros:

  • Start with recording: qq
  • Do stuff
  • Stop recording: q
  • Repeat: @q (the first time), @@ after that.
  • Repeat 20 times: 20@@

Or through regular expressions:

  • Replace stuff: :%s/[fo]+/bar/g

(But be warned: if you do the latter, you'll have 2 problems :).)


<Ctrl> + W, V to split the screen vertically
<Ctrl> + W, W to shift between the windows

!python % [args] to run the script I am editing in this window

ZF in visual mode to fold arbitrary lines


nnoremap q; q: in my .vimrc, keeps the flow when crafting a complicated search&replace.


All in Normal mode:

f<char> to move to the next instance of a particular character on the current line, and ; to repeat.

F<char> to move to the previous instance of a particular character on the current line and ; to repeat.

If used intelligently, the above two can make you killer-quick moving around in a line.

* on a word to search for the next instance.

# on a word to search for the previous instance.


A third criteria for making editing faster is the number of keystrokes required. I would say this is more important than your other 2. In vim, almost all operations require fewer keystrokes than any other editor I'm familiar with.

You mention that you are having trouble with cut & paste, but it sounds like you need more experience with general motion commands in vim. yank 3 words: y3w yank from the cursor to the next semi-colon: yf; yank to the next occurrence of your most recent search: yn All of those are much faster than trying to navigate with a mouse while holding down a modifier key. Also, as seen in some of the examples in CMS's response, vim's motion commands are highly optimized for efficient navigation in C and C++ source code.

As to the question 'how do I use vim that makes me more productive?', I hope the answer is: "efficiently".


There is loads of vim tricks but as of now, the one that I really enjoy is Ctrl+A as I happen to be dealing with some st**d code that hard-code array index.


Here is another site that I found helpful in learning Vim. It's fun too! :)

VIM Adventures is an online game based on VIM's keyboard shortcuts (commands, motions and operators). It's the "Zelda meets text editing" game. It's a puzzle game for practicing and memorizing VIM commands (good old VI is also covered, of course). It's an easy way to learn VIM without a steep learning curve.


Ctrl-w Ctrl-f ............ open file under cursor in new window
Ctrl-6 ................... alternate file
'0 ....................... open last file
:x ....................... close if save

Quick Cut and Overwrite portion of a line:

A very common task when you are editing a line is to cut from the current cursor location till a certain place and overwrite the new content.

You can use the following commands:

ct<identifier> for forward cutting.

cT<identifier> for backward cutting.

Where is the character in the line till which you want to cut.

Example: Lets say this the line you want to edit and your cursor is at I.

Hi There. I am a Coder and I code in : Python and R.

You want to cut till : and overwrite with I am a programmer, you type: ct: then type I am a programmer. This will result in: Hi There. I am a programmer: Python and R.

Quick Delete portion of a line:

Just like above the following commands delete the content from the current cursor location till the 'identifier'

dt<identifier> for forward delete

dT<identifier> for backward delete

Hope this is useful to you too.


Inserting text to some bit in code:

ctrl + v, (selecting text on multiple lines), I, (type something I want), ESC

Recording a macro to edit text and running it N times:

q, a (or some other letter), (do the things I want to record), q, ESC,
(type N, as in the number of times I want to run the macro), @, a

After mapping the below to a simple key combo, the following are very useful for me:

Jump into a file while over its path

gf

get full path name of existing file

:r!echo %:p

get directory of existing file

:r!echo %:p:h

run code:

:!ruby %:p

ruby abbreviations:

ab if_do if end<esc>bi<cr><esc>xhxO
ab if_else if end<esc>bi<cr><esc>xhxO else<esc>bhxA<cr> <esc>k$O
ab meth def method<cr>end<esc>k<esc>:s/method/
ab klas class KlassName<cr>end<esc>k<esc>:s/KlassName/
ab mod module ModName<cr>end<esc>k<esc>:s/ModName/

run current program:

   map ,rby :w!<cr>:!ruby %:p<cr>

check syntax of current program:

   map ,c :w!<cr>:!ruby -c %:p<cr>

run all specs for current spec program:

   map ,s :w!<cr>:!rspec %:p<cr>

crack it open irb:

   map ,i :w!<cr>:!irb<cr>

rspec abreviations:

   ab shared_examples shared_examples_for "behavior here" do<cr>end
   ab shared_behavior describe "description here" do<cr>  before :each do<cr>end<cr>it_should_behave_like "behavior here"<cr><bs>end<cr>
   ab describe_do describe "description here" do<cr>end
   ab context_do describe "description here" do<cr>end
   ab it_do it "description here" do<cr>end
   ab before_each before :each do<cr>end<cr>

rails abbreviations:

user authentication:

     ab userc <esc>:r $VIMRUNTIME/Templates/Ruby/c-users.rb<cr>
     ab userv <esc>:r $VIMRUNTIME/Templates/Ruby/v-users.erb<cr>
     ab userm <esc>:r $VIMRUNTIME/Templates/Ruby/m-users.rb<cr>

open visually selected url in firefox:

"function
   function open_url_in_firefox:(copy_text)
     let g:open_url_in_firefox="silent !open -a \"firefox\" \"".a:copy_text."\""
     exe g:open_url_in_firefox
   endfunction

"abbreviations
   map ,d :call open_url_in_firefox:(expand("%:p"))<cr>
   map go y:call open_url_in_firefox:(@0)<cr> 

rspec: run spec containing current line:

"function
   function run_single_rspec_test:(the_test)
     let g:rake_spec="!rspec ".a:the_test.":".line(".")
     exe g:rake_spec
   endfunction

"abbreviations
   map ,s :call run_single_rspec_test:(expand("%:p"))<cr>

rspec-rails: run spec containing current line:

"function
   function run_single_rails_rspec_test:(the_test)
     let g:rake_spec="!rake spec SPEC=\"".a:the_test.":".line(".")."\""
     exe g:rake_spec
   endfunction

"abbreviations
   map ,r :call run_single_rails_rspec_test:(expand("%:p"))<cr>

rspec-rails: run spec containing current line with debugging:

"function
   function run_spec_containing_current_line_with_debugging:(the_test)
     let g:rake_spec="!rake spec SPEC=\"".a:the_test.":".line(".")." -d\""
     exe g:rake_spec
   endfunction

"abbreviations
   map ,p :call run_spec_containing_current_line_with_debugging:(expand("%:p")) <cr>

html

"abbreviations

  "ab htm <html><cr><tab><head><cr></head><cr><body><cr></body><cr><bs><bs></html>
   ab template_html <script type = 'text/template' id = 'templateIdHere'></script>
   ab script_i <script src=''></script>
   ab script_m <script><cr></script>
   ab Tpage <esc>:r ~/.vim/templates/pageContainer.html<cr>
   ab Ttable <esc>:r ~/.vim/templates/listTable.html<cr>

"function to render common html template

   function html:() 
     call feedkeys( "i", 't' )
     call feedkeys("<html>\<cr>  <head>\<cr></head>\<cr><body>\<cr> ", 't')
     call feedkeys( "\<esc>", 't' )
     call feedkeys( "i", 't' )
     call include_js:()
     call feedkeys("\<bs>\<bs></body>\<cr> \<esc>hxhxi</html>", 't')
   endfunction

javascript

"jasmine.js
  "abbreviations
   ab describe_js describe('description here', function(){<cr>});
   ab context_js context('context here', function(){<cr>});
   ab it_js it('expectation here', function(){<cr>});
   ab expect_js expect().toEqual();
   ab before_js beforeEach(function(){<cr>});
   ab after_js afterEach(function(){<cr>});

"function abbreviations

   ab fun1 function(){}<esc>i<cr><esc>ko
   ab fun2 x=function(){};<esc>hi<cr>
   ab fun3 var x=function(){<cr>};

"method for rendering inclusion of common js files

   function include_js:()
     let includes_0  = "  <link   type = 'text\/css' rel = 'stylesheet' href = '\/Users\/johnjimenez\/common\/stylesheets\/jasmine-1.1.0\/jasmine.css'\/>"
     let includes_1  = "  <link   type = 'text\/css' rel = 'stylesheet' href = '\/Users\/johnjimenez\/common\/stylesheets\/screen.css'\/>"
     let includes_2  = "<script type = 'text\/javascript' src = '\/Users\/johnjimenez\/common\/javascripts\/jquery-1.7.2\/jquery-1.7.2.js'><\/script>"
     let includes_3  = "<script type = 'text\/javascript' src = '\/Users\/johnjimenez\/common\/javascripts\/underscore\/underscore.js'><\/script>"
     let includes_4  = "<script type = 'text\/javascript' src = '\/Users\/johnjimenez\/common\/javascripts\/backbone-0.9.2\/backbone.js'><\/script>"
     let includes_5  = "<script type = 'text\/javascript' src = '\/Users\/johnjimenez\/common\/javascripts\/jasmine-1.1.0\/jasmine.js'><\/script>"
     let includes_6  = "<script type = 'text\/javascript' src = '\/Users\/johnjimenez\/common\/javascripts\/jasmine-1.1.0\/jasmine-html.js'><\/script>"
     let includes_7  = "<script>"
     let includes_8  = "  describe('default page', function(){ "
     let includes_9  = "it('should have an html tag', function(){ "
     let includes_10 = "  expect( $( 'head' ).html() ).not.toMatch(\/^[\\s\\t\\n]*$\/);"
     let includes_11  = "});"
     let includes_12 = "});"
     let includes_13 = "$(function(){"
     let includes_14 = "jasmine.getEnv().addReporter( new jasmine.TrivialReporter() );"
     let includes_15 = "jasmine.getEnv().execute();"
     let includes_16 = "});"
     let includes_17 = "\<bs>\<bs><\/script>"

     let j = 0

     while j < 18
       let entry = 'includes_' . j
       call feedkeys( {entry}, 't' )
       call feedkeys( "\<cr>", 't' )
       let j = j + 1
     endwhile

   endfunction

"jquery

  "abbreviations

     ab docr $(document).ready(function(){});
     ab jqfun $(<cr>function(){<cr>}<cr>);

Multiple buffers, and in particular fast jumping between them to compare two files with :bp and :bn (properly remapped to a single Shift + p or Shift + n)

vimdiff mode (splits in two vertical buffers, with colors to show the differences)

Area-copy with Ctrl + v

And finally, tab completion of identifiers (search for "mosh_tab_or_complete"). That's a life changer.


I recently (got) discovered this site: http://vimcasts.org/

It's pretty new and really really good. The guy who is running the site switched from textmate to vim and hosts very good and concise casts on specific vim topics. Check it out!


cit – empty the contents of the tag with the transition in insert mode

yit – copy the contents of the tag


gi

Go to last edited location (very useful if you performed some searching and than want go back to edit)

^P and ^N

Complete previous (^P) or next (^N) text.

^O and ^I

Go to previous (^O - "O" for old) location or to the next (^I - "I" just near to "O"). When you perform searches, edit files etc., you can navigate through these "jumps" forward and back.


For Copy/Cut and Paste specifically, using visual mode makes it much easier to adapt from other editors. So the way I normally cut and paste is:

  • Esc - exit Insert mode (skip if you are already in Normal mode)
  • v - turn on visual mode
  • move about the file to select the text you want - visual mode will show you what characters are selected. For a few words w, e and b are useful (move to start of next word, end of next word and start of this/previous word respectively).
  • d - cut the text (use y if you want to copy the text)
  • move about to where you want the text to go
  • p - paste (this pastes after the current character, P pastes before the current character.

Also useful is using V to go into Visual mode (line) which selects whole lines automatically, where ever the cursor is on the line.


Ignoring the question for a moment (my answer is below), a couple of things that might help with your problems with vim:

:map <C-F> /\V

This will make Ctrl-F start a search with the first characters of the search being \V, which turns off all the 'magic', so you don't have to escape anything (just like PsPad).

" CTRL-X and SHIFT-Del are Cut
vnoremap <C-X> "+x
vnoremap <S-Del> "+x

" CTRL-C and CTRL-Insert are Copy
vnoremap <C-C> "+y
vnoremap <C-Insert> "+y

" CTRL-V and SHIFT-Insert are Paste
map <C-V>       "+gP
map <S-Insert>      "+gP

cmap <C-V>      <C-R>+
cmap <S-Insert>     <C-R>+

(taken directly out of mswin.vim from the Vim distribution). This will give you Ctrl-C, Ctrl-V etc for copying and pasting.

Personally, I find the copying and pasting much better with the standard Vim. In Vim I can have the cursor on a line, type yy to copy it, 10p to paste 10 copies of it. With the Align plugin, I can then use Ctrl-V (assuming the windows mappings above aren't used) to visual-block select a column of numbers that has been created; :II then auto-increments that column of numbers. Similarly, with YankRing, I can copy 10 (or more) lines one after another and then paste them back out one after another.

As for the way that Vim makes me more productive, I would say that the tags file is the one thing I couldn't do without anymore. When the cursor is over a tag, I can press Ctrl-] to go to the function (and Ctrl-T to return, as many levels as I like) or ,p to open the function or macro definition (or whatever) in the preview window (which can then be quickly closed with :pcl) or [i to just show a macro definition on the status bar. For navigating complex source code, these tools are invaluable.

The preview window one does rely on a mapping in .vimrc, however:

:map ,p :ptag <C-R><C-W><CR>

The tags file also allows the use of a couple of (my) plugins that give syntax highlighting that shows errors much more clearly (by highlighting recognised tags and not highlighting unrecognised ones) and tag signatures when you move the mouse over a keyword.


Odd nobody's mentioned ctags. Download "exuberant ctags" and put it ahead of the crappy preinstalled version you already have in your search path. Cd to the root of whatever you're working on; for example the Android kernel distribution. Type "ctags -R ." to build an index of source files anywhere beneath that dir in a file named "tags". This contains all tags, nomatter the language nor where in the dir, in one file, so cross-language work is easy.

Then open vim in that folder and read :help ctags for some commands. A few I use often:

  • Put cursor on a method call and type CTRL-] to go to the method definition.

  • Type :ta name to go to the definition of name.



Some productivity tips:

Smart movements

  • * and # search for the word under the cursor forward/backward.
  • w to the next word
  • W to the next space-separated word
  • b / e to the begin/end of the current word. (B / E for space separated only)
  • gg / G jump to the begin/end of the file.
  • % jump to the matching { .. } or ( .. ), etc..
  • { / } jump to next paragraph.
  • '. jump back to last edited line.
  • g; jump back to last edited position.

Quick editing commands

  • I insert at the begin.
  • A append to end.
  • o / O open a new line after/before the current.
  • v / V / Ctrl+V visual mode (to select text!)
  • Shift+R replace text
  • C change remaining part of line.

Combining commands

Most commands accept a amount and direction, for example:

  • cW = change till end of word
  • 3cW = change 3 words
  • BcW = to begin of full word, change full word
  • ciW = change inner word.
  • ci" = change inner between ".."
  • ci( = change text between ( .. )
  • ci< = change text between < .. > (needs set matchpairs+=<:> in vimrc)
  • 4dd = delete 4 lines
  • 3x = delete 3 characters.
  • 3s = substitute 3 characters.

Useful programmer commands

  • r replace one character (e.g. rd replaces the current char with d).
  • ~ changes case.
  • J joins two lines
  • Ctrl+A / Ctrl+X increments/decrements a number.
  • . repeat last command (a simple macro)
  • == fix line indent
  • > indent block (in visual mode)
  • < unindent block (in visual mode)

Macro recording

  • Press q[ key ] to start recording.
  • Then hit q to stop recording.
  • The macro can be played with @[ key ].

By using very specific commands and movements, VIM can replay those exact actions for the next lines. (e.g. A for append-to-end, b / e to move the cursor to the begin or end of a word respectively)

Example of well built settings

# reset to vim-defaults
if &compatible          # only if not set before:
  set nocompatible      # use vim-defaults instead of vi-defaults (easier, more user friendly)
endif

# display settings
set background=dark     # enable for dark terminals
set nowrap              # dont wrap lines
set scrolloff=2         # 2 lines above/below cursor when scrolling
set number              # show line numbers
set showmatch           # show matching bracket (briefly jump)
set showmode            # show mode in status bar (insert/replace/...)
set showcmd             # show typed command in status bar
set ruler               # show cursor position in status bar
set title               # show file in titlebar
set wildmenu            # completion with menu
set wildignore=*.o,*.obj,*.bak,*.exe,*.py[co],*.swp,*~,*.pyc,.svn
set laststatus=2        # use 2 lines for the status bar
set matchtime=2         # show matching bracket for 0.2 seconds
set matchpairs+=<:>     # specially for html

# editor settings
set esckeys             # map missed escape sequences (enables keypad keys)
set ignorecase          # case insensitive searching
set smartcase           # but become case sensitive if you type uppercase characters
set smartindent         # smart auto indenting
set smarttab            # smart tab handling for indenting
set magic               # change the way backslashes are used in search patterns
set bs=indent,eol,start # Allow backspacing over everything in insert mode

set tabstop=4           # number of spaces a tab counts for
set shiftwidth=4        # spaces for autoindents
#set expandtab           # turn a tabs into spaces

set fileformat=unix     # file mode is unix
#set fileformats=unix,dos    # only detect unix file format, displays that ^M with dos files

# system settings
set lazyredraw          # no redraws in macros
set confirm             # get a dialog when :q, :w, or :wq fails
set nobackup            # no backup~ files.
set viminfo='20,\"500   # remember copy registers after quitting in the .viminfo file -- 20 jump links, regs up to 500 lines'
set hidden              # remember undo after quitting
set history=50          # keep 50 lines of command history
set mouse=v             # use mouse in visual mode (not normal,insert,command,help mode


# color settings (if terminal/gui supports it)
if &t_Co > 2 || has("gui_running")
  syntax on          # enable colors
  set hlsearch       # highlight search (very useful!)
  set incsearch      # search incremently (search while typing)
endif

# paste mode toggle (needed when using autoindent/smartindent)
map <F10> :set paste<CR>
map <F11> :set nopaste<CR>
imap <F10> <C-O>:set paste<CR>
imap <F11> <nop>
set pastetoggle=<F11>

# Use of the filetype plugins, auto completion and indentation support
filetype plugin indent on

# file type specific settings
if has("autocmd")
  # For debugging
  #set verbose=9

  # if bash is sh.
  let bash_is_sh=1

  # change to directory of current file automatically
  autocmd BufEnter * lcd %:p:h

  # Put these in an autocmd group, so that we can delete them easily.
  augroup mysettings
    au FileType xslt,xml,css,html,xhtml,javascript,sh,config,c,cpp,docbook set smartindent shiftwidth=2 softtabstop=2 expandtab
    au FileType tex set wrap shiftwidth=2 softtabstop=2 expandtab

    # Confirm to PEP8
    au FileType python set tabstop=4 softtabstop=4 expandtab shiftwidth=4 cinwords=if,elif,else,for,while,try,except,finally,def,class
  augroup END

  augroup perl
    # reset (disable previous 'augroup perl' settings)
    au!  

    au BufReadPre,BufNewFile
    \ *.pl,*.pm
    \ set formatoptions=croq smartindent shiftwidth=2 softtabstop=2 cindent cinkeys='0{,0},!^F,o,O,e' " tags=./tags,tags,~/devel/tags,~/devel/C
    # formatoption:
    #   t - wrap text using textwidth
    #   c - wrap comments using textwidth (and auto insert comment leader)
    #   r - auto insert comment leader when pressing <return> in insert mode
    #   o - auto insert comment leader when pressing 'o' or 'O'.
    #   q - allow formatting of comments with "gq"
    #   a - auto formatting for paragraphs
    #   n - auto wrap numbered lists
    #   
  augroup END


  # Always jump to the last known cursor position. 
  # Don't do it when the position is invalid or when inside
  # an event handler (happens when dropping a file on gvim). 
  autocmd BufReadPost * 
    \ if line("'\"") > 0 && line("'\"") <= line("$") | 
    \   exe "normal g`\"" | 
    \ endif 

endif # has("autocmd")

The settings can be stored in ~/.vimrc, or system-wide in /etc/vimrc.local and then by read from the /etc/vimrc file using:

source /etc/vimrc.local

(you'll have to replace the # comment character with " to make it work in VIM, I wanted to give proper syntax highlighting here).

The commands I've listed here are pretty basic, and the main ones I use so far. They already make me quite more productive, without having to know all the fancy stuff.


You are talking about text selecting and copying, I think that you should give a look to the Vim Visual Mode.

In the visual mode, you are able to select text using Vim commands, then you can do whatever you want with the selection.

Consider the following common scenarios:

You need to select to the next matching parenthesis.

You could do:

  • v% if the cursor is on the starting/ending parenthesis
  • vib if the cursor is inside the parenthesis block

You want to select text between quotes:

  • vi" for double quotes
  • vi' for single quotes

You want to select a curly brace block (very common on C-style languages):

  • viB
  • vi{

You want to select the entire file:

  • ggVG

Visual block selection is another really useful feature, it allows you to select a rectangular area of text, you just have to press Ctrl-V to start it, and then select the text block you want and perform any type of operation such as yank, delete, paste, edit, etc. It's great to edit column oriented text.


Another useful vi "shortcut" I frequently use is 'xp'. This will swap the character under the cursor with the next character.


Visual Mode

As several other people have said, visual mode is the answer to your copy/cut & paste problem. Vim gives you 'v', 'V', and C-v. Lower case 'v' in vim is essentially the same as the shift key in notepad. The nice thing is that you don't have to hold it down. You can use any movement technique to navigate efficiently to the starting (or ending) point of your selection. Then hit 'v', and use efficient movement techniques again to navigate to the other end of your selection. Then 'd' or 'y' allows you to cut or copy that selection.

The advantage vim's visual mode has over Jim Dennis's description of cut/copy/paste in vi is that you don't have to get the location exactly right. Sometimes it's more efficient to use a quick movement to get to the general vicinity of where you want to go and then refine that with other movements than to think up a more complex single movement command that gets you exactly where you want to go.

The downside to using visual mode extensively in this manner is that it can become a crutch that you use all the time which prevents you from learning new vi(m) commands that might allow you to do things more efficiently. However, if you are very proactive about learning new aspects of vi(m), then this probably won't affect you much.

I'll also re-emphasize that the visual line and visual block modes give you variations on this same theme that can be very powerful...especially the visual block mode.

On Efficient Use of the Keyboard

I also disagree with your assertion that alternating hands is the fastest way to use the keyboard. It has an element of truth in it. Speaking very generally, repeated use of the same thing is slow. This most significant example of this principle is that consecutive keystrokes typed with the same finger are very slow. Your assertion probably stems from the natural tendency to use the s/finger/hand/ transformation on this pattern. To some extent it's correct, but at the extremely high end of the efficiency spectrum it's incorrect.

Just ask any pianist. Ask them whether it's faster to play a succession of a few notes alternating hands or using consecutive fingers of a single hand in sequence. The fastest way to type 4 keystrokes is not to alternate hands, but to type them with 4 fingers of the same hand in either ascending or descending order (call this a "run"). This should be self-evident once you've considered this possibility.

The more difficult problem is optimizing for this. It's pretty easy to optimize for absolute distance on the keyboard. Vim does that. It's much harder to optimize at the "run" level, but vi(m) with it's modal editing gives you a better chance at being able to do it than any non-modal approach (ahem, emacs) ever could.

On Emacs

Lest the emacs zealots completely disregard my whole post on account of that last parenthetical comment, I feel I must describe the root of the difference between the emacs and vim religions. I've never spoken up in the editor wars and I probably won't do it again, but I've never heard anyone describe the differences this way, so here it goes. The difference is the following tradeoff:

Vim gives you unmatched raw text editing efficiency Emacs gives you unmatched ability to customize and program the editor

The blind vim zealots will claim that vim has a scripting language. But it's an obscure, ad-hoc language that was designed to serve the editor. Emacs has Lisp! Enough said. If you don't appreciate the significance of those last two sentences or have a desire to learn enough about functional programming and Lisp to develop that appreciation, then you should use vim.

The emacs zealots will claim that emacs has viper mode, and so it is a superset of vim. But viper mode isn't standard. My understanding is that viper mode is not used by the majority of emacs users. Since it's not the default, most emacs users probably don't develop a true appreciation for the benefits of the modal paradigm.

In my opinion these differences are orthogonal. I believe the benefits of vim and emacs as I have stated them are both valid. This means that the ultimate editor doesn't exist yet. It's probably true that emacs would be the easiest platform on which to base the ultimate editor. But modal editing is not entrenched in the emacs mindset. The emacs community could move that way in the future, but that doesn't seem very likely.

So if you want raw editing efficiency, use vim. If you want the ultimate environment for scripting and programming your editor use emacs. If you want some of both with an emphasis on programmability, use emacs with viper mode (or program your own mode). If you want the best of both worlds, you're out of luck for now.


I recently discovered q:. It opens the "command window" and shows your most recent ex-mode (command-mode) commands. You can move as usual within the window, and pressing <CR> executes the command. You can edit, etc. too. Priceless when you're messing around with some complex command or regex and you don't want to retype the whole thing, or if the complex thing you want to do was 3 commands back. It's almost like bash's set -o vi, but for vim itself (heh!).

See :help q: for more interesting bits for going back and forth.


These are not shortcuts, but they are related:

  1. Make capslock an additional ESC (or Ctrl)
  2. map leader to "," (comma), with this command: let mapleader=","

They boost my productivity.


Spend 30 mins doing the vim tutorial (run vimtutor instead of vim in terminal). You will learn the basic movements, and some keystrokes, this will make you at least as productive with vim as with the text editor you used before. After that, well, read Jim Dennis' answer again :)


Use \c anywhere in a search to ignore case (overriding your ignorecase or smartcase settings). E.g. /\cfoo or /foo\c will match foo, Foo, fOO, FOO, etc.

Use \C anywhere in a search to force case matching. E.g. /\Cfoo or /foo\C will only match foo.


I just discovered Vim's omnicompletion the other day, and while I'll admit I'm a bit hazy on what does which, I've had surprisingly good results just mashing either Ctrl + x Ctrl + u or Ctrl + n/Ctrl +p in insert mode. It's not quite IntelliSense, but I'm still learning it.

Try it out! :help ins-completion


My most productive vi/Vim trick is:

:%s

I love being able to use regular expressions on the fly to replace whatever I want inside the file. Every text editor should support regular expressions IMHO.


The series of vim commands ggVGg? applies a Rot13 cipher to the text in your current document.

Gung vf zl zbfg cebqhpgvir fubegphg fvapr V nyjnlf glcr va Ebg13.


Agreed with the top poster - the :r! command is very useful.

Most often I use it to "paste" things:

:r!cat
**Ctrl-V to paste from the OS clipboard**
^D

This way I don't have to fiddle with :set paste.


Last week at work our project inherited a lot of Python code from another project. Unfortunately the code did not fit into our existing architecture - it was all done with global variables and functions, which would not work in a multi-threaded environment.

We had ~80 files that needed to be reworked to be object oriented - all the functions moved into classes, parameters changed, import statements added, etc. We had a list of about 20 types of fix that needed to be done to each file. I would estimate that doing it by hand one person could do maybe 2-4 per day.

So I did the first one by hand and then wrote a vim script to automate the changes. Most of it was a list of vim commands e.g.

" delete an un-needed function "
g/someFunction(/ d

" add wibble parameter to function foo "
%s/foo(/foo( wibble,/

" convert all function calls bar(thing) into method calls thing.bar() "
g/bar(/ normal nmaf(ldi(`aPa.

The last one deserves a bit of explanation:

g/bar(/  executes the following command on every line that contains "bar("
normal   execute the following text as if it was typed in in normal mode
n        goes to the next match of "bar(" (since the :g command leaves the cursor position at the start of the line)
ma       saves the cursor position in mark a
f(       moves forward to the next opening bracket
l        moves right one character, so the cursor is now inside the brackets
di(      delete all the text inside the brackets
`a       go back to the position saved as mark a (i.e. the first character of "bar")
P        paste the deleted text before the current cursor position
a.       go into insert mode and add a "." 

For a couple of more complex transformations such as generating all the import statements I embedded some python into the vim script.

After a few hours of working on it I had a script that will do at least 95% of the conversion. I just open a file in vim then run :source fixit.vim and the file is transformed in a blink of the eye.

We still have the work of changing the remaining 5% that was not worth automating and of testing the results, but by spending a day writing this script I estimate we have saved weeks of work.

Of course it would have been possible to automate this with a scripting language like Python or Ruby, but it would have taken far longer to write and would be less flexible - the last example would have been difficult since regex alone would not be able to handle nested brackets, e.g. to convert bar(foo(xxx)) to foo(xxx).bar(). Vim was perfect for the task.


Actually I was always losing my buffers, so the way I usually copy a range of lines is to just write it to a temp file, and then read it in at the appropriate spot.

e.g.

ka (set the mark)

'a,. w! t (copy everything form the mark into the file t)

.. move your cursor around ..

:.r t (read in t into the current spot).

This probably involves fewer keystrokes than using the buffer, is easier to keep track of, and you can have long lived paste files around. I usually use 1 letter names for the files, for speed.

The key reason why this is fast is that to move your cursor around you just use the search function "/", and "n" if you run into another occurrence of the pattern before you get to where you want to go.


How about further shortcutting shortcuts?


Put into your .vimrc:
nnoremap ; :

This way entering commmandmode ist way easier: ;q or ;w work, instead just :q or :w.

Two keystrokes instead of three, and you will need this very often.


Bad for sysadmins, since they need the same functionality to be given out of the box to be the same on every box everywhere.

But a HUGE improvement for programmers using vi.


. Repeat last text-changing command

I save a lot of time with this one.

Visual mode was mentioned previously, but block visual mode has saved me a lot of time when editing fixed size columns in text file. (accessed with Ctrl-V).


What is the way you use Vim that makes you more productive than with a contemporary editor?

Being able to execute complex, repetitive edits with very few keystrokes (often using macros). Take a look at VimGolf to witness the power of Vim!

After over ten years of almost daily usage, it's hard to imagine using any other editor.


CTRL + A increments the number you are standing on.


You can use \= in an substitution string and is something I do every so often.

If you have what's essentially an unordered list in vim, say using # as a marker, you can convert it over to an ordered list.

# CSSLINT
# PHPCS
# Charlie
# Delta

If it starts on line one, you can do

:1,6s/#/\=line(".")/g

To convert it over to

1 CSSLINT
2 PHPCS
3 Charlie
4 Delta

If it doesn't start on line one, just do the maths:

:16,20s/#/\=line(".") - 15/g

More info at :help sub-replace-expression