Skip to content

Instantly share code, notes, and snippets.

@ap
Created July 10, 2009 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ap/144619 to your computer and use it in GitHub Desktop.
Save ap/144619 to your computer and use it in GitHub Desktop.
" 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>
@aghast
Copy link

aghast commented Jan 8, 2014

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment