public
Last active

  • Download Gist
delimiters.vim
VimL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
" DELIMITERS MADE LESS ANNOYING
"
" Main novelty here (if it is one): this does NOT try to be helpful by
" inserting the closing delimiter for you when you type an opening one.
" Instead it only tries to be smart about what to do when you type a closing
" delimiter yourself.
"
" If you just typed an empty delimiter pair, it'll move the cursor back
" inside. If you type a closing delimiter the cursor is already on (or to
" the left of, if the cursor is on a space), it'll skip the cursor past that
" delimiter without inserting it.
"
" That way you never end with superfluous delimiters to delete, which deletion
" itself can be tricky to perform, since the editor might be trying to be
" helpful about deletions as well. Instead, you only ever get delimiters you
" explicitly typed yourself.
"
" I had trained myself into the good habit of typing pairs together anyway.
" The only annoying part of that habit is the manual cursor placement work;
" but that work is quite predictable almost all of the time. That's exactly
" the sort of work that computers are for.
 
function! IsEmptyPair(str)
for pair in split( &matchpairs, ',' ) + [ "''", '""', '``' ]
if a:str == join( split( pair, ':' ),'' )
return 1
endif
endfor
return 0
endfunc
function! WithinEmptyPair()
let cur = strpart( getline('.'), col('.')-2, 2 )
return IsEmptyPair( cur )
endfunc
function! SkipDelim(char)
let cur = strpart( getline('.'), col('.')-2, 3 )
if cur[0] == "\\"
return a:char
elseif cur[1] == a:char
return "\<Right>"
elseif cur[1] == ' ' && cur[2] == a:char
return "\<Right>\<Right>"
elseif IsEmptyPair( cur[0] . a:char )
return a:char . "\<Left>"
else
return a:char
endif
endfunc
inoremap <expr> ) SkipDelim(')')
inoremap <expr> ] SkipDelim(']')
inoremap <expr> } SkipDelim('}')
inoremap <expr> ' SkipDelim("'")
inoremap <expr> " SkipDelim('"')
inoremap <expr> ` SkipDelim('`')
inoremap <expr> <BS> WithinEmptyPair() ? "\<Right>\<BS>\<BS>" : "\<BS>"
inoremap <expr> <CR> WithinEmptyPair() ? "\<CR>\<CR>\<Up>" : "\<CR>"
inoremap <expr> <Space> WithinEmptyPair() ? "\<Space>\<Space>\<Left>" : "\<Space>"
vmap q( s()<C-R>"<Esc>
vmap q) s()<C-R>"<Esc>
vmap q[ s[]<C-R>"<Esc>
vmap q] s[]<C-R>"<Esc>
vmap q{ s{}<C-R>"<Esc>
vmap q} s{}<C-R>"<Esc>
vmap q' s''<C-R>"<Esc>
vmap q" s""<C-R>"<Esc>
vmap q` s``<C-R>"<Esc>

In my particular version of Vim (VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Aug 24 2013 18:58:47)
the vmap commands do not work as I think you intend them to work. I get ()foo instead of (foo). Changing the mapping to s(") works fine, though.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.