Vim Tips Wiki
Tip 842 Printable Monobook Previous Next

created January 4, 2005 · complexity intermediate · author Vladimír Marek · version 6.0

I have been seeking for some 'perfect' abbrevs for long time. They have to work in C code, but not in strings or comments. They have to place cursor inside the function and leave Vim in insert mode, so that I can just continue typing. They have to respect my indenting, and they have to produce exactly the same results when I start the abbreviation by <C-]> or just by <Space> (no bothersome space should appear). And they should be easy to maintain. I thought that this is not possible, but after seeing Luc Hermitte's lh-cpp-ftplugins, I found my way through.

Here is what I got:

" Help delete character if it is 'empty space'
" stolen from Vim manual
function! Eatchar()
  let c = nr2char(getchar())
  return (c =~ '\s') ? '' : c

" Replace abbreviation if we're not in comment or other unwanted places
" stolen from Luc Hermitte's excellent
function! MapNoContext(key, seq)
  let syn = synIDattr(synID(line('.'),col('.')-1,1),'name')
  if syn =~? 'comment\|string\|character\|doxygen'
    return a:key
    exe 'return "' .
    \ substitute( a:seq, '\\<\(.\{-}\)\\>', '"."\\<\1>"."', 'g' ) . '"'

" Create abbreviation suitable for MapNoContext
function! Iab (ab, full)
  exe "iab <silent> <buffer> ".a:ab." <C-R>=MapNoContext('".
    \ a:ab."', '".escape (a:full.'<C-R>=Eatchar()<CR>', '<>\"').

call Iab('#d', '#define ')
call Iab('#i', '#include <><Left>')
call Iab('#I', '#include ""<Left>')
call Iab('printf', 'printf ("\n");<C-O>?\<CR>')
call Iab('if', 'if ()<CR>{<CR>}<Left><C-O>?)<CR>')
call Iab('for', 'for (;;)<CR>{<CR>}<C-O>?;;<CR>')
call Iab('while', 'while ()<CR>{<CR>}<C-O>?)<CR>')
call Iab('else', 'else<CR>{<CR>x;<CR>}<C-O>?x;<CR><Del><Del>')
call Iab('ifelse', 'if ()<CR>{<CR>}<CR>else<CR>{<CR>}<C-O>?)<CR>')
call Iab('intmain', 'int<CR>main (int argc, char **argv)<CR>'.
 \ '{<CR>x;<CR>return 0;<CR>}<CR><C-O>?x;<CR><Del><Del>')

For me it's working, I also tried it with plain Vim (without .vimrc), but it may depend on some settings.


You can look at Dr Chip's C Stubs plugin "drcstubs.vim".

May I ask why this "simplified" version? Why get rid of the support of markers (aka placeholders)?

BTW, with my last version of lh-cpp (not yet uploaded), the mappings and abbreviations, are much more easier to maintain -> e.g. for "if":

Inoreabbr <buffer> <silent> if <C-R>=Def_AbbrC('if ',
  \ '\<c-f\>if (!cursorhere!) {\n!mark!\n}!mark!')<CR>

" Surround the visual selection with curly-brackets -> instructions-block
vnoremap <buffer> <silent> <localleader>if
  \ <c-\><c-n>@=Surround('if (!cursorhere!) {', '}!mark!',
  \ 1, 1, '', 1, 'if ')<CR>

" Surround the visual selection with "round"-brackets -> condition
vnoremap <buffer> <silent> <LocalLeader><localleader>if
  \ <c-\><c-n>@=Surround('if (', '!cursorhere!) {\n!mark!\n}!mark!',
  \ 0, 1, '', 1, 'if ')<CR>

nmap <buffer> <LocalLeader>if V<LocalLeader>if
nmap <buffer> <LocalLeader><LocalLeader>if V<LocalLeader><LocalLeader>if

Luc Hermitte