Wednesday, December 28, 2011

useful vim tips

Vim is definitely a text editor you need to learn progressively because it has an interesting learning curve. If you have not read "Seven Habits of Effective Text Editing" from Bram Moolenaar (main author of Vim), please do that first. There is also an updated version of this article that can be found here. Basically, there are three steps to improve your Vim skills through daily work:
  1. find repeated actions that are not efficient or quick enough
  2. find a quicker way (search online, ask around, read documentation and tutorials, etc.)
  3. practice the new tricks and make it a habbit
So, basically I am trying to take notes about some new tricks I learned over the past week. Hopefully, I will do the iterations and find even more efficient ways to do these in the future.


Quickly move around on a line.

0 (zero) moves the cursor to the beginning of a line (white spaces are considered as characters)
$ moves the cursor to the end of a line (white space are considered)
^ moves the cursor to the beginning of a line (white space ignored)
g_ moves to cursor to the end of a line (white space ignored)

For example (using + to stand for space here for illustration purpose):
++a line++
- -    - - 
0 ^    $ g_

w, W move the cursor forward to the beginning of a word, the difference between the two is W uses white space as separator. So, for me w is quite useful in code, W is useful in the textual sentences.

e, E move the cursor forward to the end of a word, same difference as in w and W.

b, B move the cursor backward to the beginning of a word, difference is again the separator.

ge, gE move the cursor backward to the end of a word.

*, # to quickly move forward and backward to the same word under the cursor. This is faster than search using / and press N and n.

o adds a new line under current line and start insert.
O adds a new line above current line and start insert.
s deletes the character under cursor and start insert.
S deletes the current line and start insert.
D deletes from cursor to the end of line.
C deletes from the cursor to the end of line and start insert.


Quickly move around in code.

% matches the parenthesis, bracket and curly brace. For example, put the cursor on a closing curly brace  and % takes the cursor to the matching opening brace.

[{ and ]} to match the opening and closing curly braces. Place the cursor inside a code block, using these two to quickly move to the beginning and end of the closes curly braces pair.

gd jumps to the local variable definition when the cursor is on a variable name.
gD jumps to the global variable definition.


Use . (dot) command to repeat the last change in normal mode. See Vim Twiki "repeat last change".

You can also do N. to repeat the change N times. For example, dd command delete the current line, use . to delete another line, use 5. to delete additional 5 lines.

There is also a similar repeat trick @: for last command made on command line. For example, on the command line, we do :!ls to list files in the current directory. Then, we can do @: to repeat it again.


Copy/cut and paste text in visual mode. See Vim Twiki "copy and paste using visual selection".
  • put cursor to the beginning of the desired text
  • enter visual mode: use v to begin character-based selection, V to begin line based selection, ctrl-v to begin vertical block based selection (move the cursor will select the whole columns of text)
  • put cursor to the end of the desired text
  • use d to cut, y to copy
  • put the cursor to the paste position
  • use p to paste after the desired position, P to paste before the desired position
On the Vim twiki, there is also the tip to overwrite the same amount of text using the copied/cut text using Nvp, NVp, N^Vp depending on the selection mode (character, line or block).


Disable auto-indentation, manual indentation.

Sometimes, I had one annoying problem when I copy and paste formatted source code from another application - Vim will reformat the content and mess up with the indentations. To prevent Vim from retabbing, use :set paste. After you are done, use :set nopaste to diable paste. You can also add a key binding using set pastetoggle in your .vimrc file. See Vim Twiki "Toggle auto-indenting for code paste" for more details.

Instead, you want manual indentation. In normal mode, == indents the current line. In line-based visual mode (V or shift-v), select several lines and = indents them all.


Jump in the change list, moving back and forth in changed positions in the current file. One common task is to jump back and forth between edit positions. See Vim Twiki "list changes to the current file".
  • `.  jumps to the last edit position
  • g; jumps back in the change list
  • g, jumps forward in the change list
  • :changes to show the change list
Interestingly, there is another (probably less useful) jump list that records the default last 100 positions a user makes a jump. A jump is one of search, substitute and mark. See Vim Twiki "jumping to previously visited locations".
  • ctrl-O to jump back in jump list
  • ctrl-I to jump forward in jump list
  • :jumps to show the jump list


Auto expansion, adding comments, etc.

One common case when coding is to add comments. So, how do you add something like these lines:

  • ///////////////////////////
  • /*------------------*/
  • /*************** <multiple lines of text> *************/
Ni/<esc> inserts N / (slash), quite useful for N repeating characters.

Another way is to use auto expansion. For example, you can add these into your .vimrc:

:ab #b /************************************************
:ab #e ************************************************/
:ab #l /*----------------------------------------------*/

Then, in the edit mode, you can type #b<enter> to automatically insert /*******.

Text objects.

Last, I found out about Vim text objects, it is so powerful and convenient that saved me a lot of time. For details, please read this great post "Vim Text Objects: The Definitive Guide" and Vim documentation on text objects.

Note that text object is more convenient than motion when you want to delete a chunk of text, you don't need to move cursor to particular position. For example, the difference between dw and diw is that when you want to use dw to delete a word, you must move the cursor to the beginning of that word first. For diw, you can place the cursor anywhere inside that word.

For example, I want to refactor code that has a string value hard coded to use a variable:

public class Hello {

    public static void main(String[] args) {
        System.out.println("hello, world");
        showMe();
    }

    public static void showMe() {
        System.out.println("hello, world");
    }
}

// refectored
public class Hello {

    public final static String hi = "hello, world";
    public static void main(String[] args) {
        System.out.println(hi);
        showMe();
    }

    public static void showMe() {
        System.out.println(hi);
    }
}

So, I can add a variable hi="hello world", then replace the string value "hello, world" on line 4 and line 9 using text object:

  1. move to line 4, a position before the string "hello, world", in normal mode, type ca", this will delete the string value including the quotes and change to insert mode.
  2. type the new variable name hi
  3. move to line 9, a position before the same string
  4. type . to repeat the replacement
  5. done!
One extra tip. Using text objects, you can delete/update the content inside the double quotes, but how do you delete the double quotes only? You can do this:


  1. move cursor to one of the double quotes
  2. use % to jump to the matching double quotes, delete it using x
  3. use Ctrl-o or two back-ticks (``) to jump back to the first double quote, delete it using x
  4. done!


No comments:

Post a Comment