One of the more standard vim tweaks is to have parens, braces, brackets, and quotes auto-close—that is, you type ( , and the ) is inserted automatically. This can be a big help in keeping track of nested groups. This is easy to do poorly; to do it well takes a little more thought. I took a look at TextMate's rules and mimicked them (mostly). Put all this stuff in your .vimrc (_vimrc on Windows).



Note: A couple of these tweaks are modified or copied outright from the Vim Scripts repository.



Auto-close pairs

)

Map the auto-close for non-quotes. This is trivial:

inoremap ( ()<Left> inoremap [ []<Left> inoremap { {}<Left> autocmd Syntax html,vim inoremap < <lt>><Left>

No big deal; when the opening character is typed, insert the closing character and hit <Left> so the cursor is between them. Function to check next character.

function! ClosePair(char) if getline('.')[col('.') - 1] == a:char return "\<Right>" else return a:char endif endf Map closing characters. Now, all you need to do is link the closing characters to the function:

inoremap ) <c-r>=ClosePair(')')<CR> inoremap ] <c-r>=ClosePair(']')<CR> inoremap } <c-r>=ClosePair('}')<CR> Map the auto-close for quotes. This is only slightly more difficult than ()[]{} , because of the case where you might add an escaped quotation mark to a string. It requires a separate function: since the opening and closing characters are the same, we can't map the closing to ClosePair . So we put it all in one function:

function! QuoteDelim(char) let line = getline('.') let col = col('.') if line[col - 2] == "\\" "Inserting a quoted quotation mark into the string return a:char elseif line[col - 1] == a:char "Escaping out of the string return "\<Right>" else "Starting a string return a:char.a:char."\<Left>" endif endf

Then just need to map that:

inoremap " <c-r>=QuoteDelim('"')<CR> inoremap ' <c-r>=QuoteDelim("'")<CR>



.vimrc

Wrap visually selected text

a

(

vnoremap ( <ESC>`>a)<ESC>`<i(<ESC> vnoremap ) <ESC>`>a)<ESC>`<i(<ESC> vnoremap { <ESC>`>a}<ESC>`<i{<ESC> vnoremap } <ESC>`>a}<ESC>`<i{<ESC> vnoremap " <ESC>`>a"<ESC>`<i"<ESC> vnoremap ' <ESC>`>a'<ESC>`<i'<ESC> vnoremap ` <ESC>`>a`<ESC>`<i`<ESC> vnoremap [ <ESC>`>a]<ESC>`<i[<ESC> vnoremap ] <ESC>`>a]<ESC>`<i[<ESC>

Backspace in empty pair deletes both

matchpairs

function! InAnEmptyPair() let cur = strpart(getline('.'),getpos('.')[2]-2,2) for pair in (split(&matchpairs,',') + ['":"',"':'"]) if cur == join(split(pair,':'),'') return 1 endif endfor return 0 endfunc

func! DeleteEmptyPairs() if InAnEmptyPair() return "\<Left>\<Del>\<Del>" else return "\<BS>" endif endfunc

inoremap <expr> <BS> DeleteEmptyPairs()

matchpairs