tags:

views:

844

answers:

1

Hi, I'm trying to make a simple Vim script that would create very compact top-level folds for c files. Ideally, if it was run on this code:

static void funca(...)
{
   ... 
}

/* Example comment */
static void funcb(...)
{
   ... 
}

Then it would create folds which would look like this when closed:

+-- x Lines: static void funca(...)----------------------
+-- x Lines: static void funcb(...)----------------------

So basically it would be like foldmethod=syntax with foldlevel=1, except that each fold would start one line further up, and would extend further down to include all following blank lines.

I know how to make one of these folds (assuming foldmethod=manual):

/^{<cr>kVnn?^$<cr>zf

But I'm not sure how to put it into a function. This is my effort:

function Cfold()
  set foldmethod=manual  " Manual folds
  ggzE                   " Delete all folds
  while (/^{<cr>)        " Somehow loop through each match
     kVnn?^$<cr>zf       " This would work fine except for the last function
  endwhile
endfunction
map <Leader>f  :call Cfold()<cr>

But it isn't valid, I'm not entirely sure how functions work. Also, it won't work for the last function in the file, since it won't find '^{' again. If someone could help me get this working, and somehow add a case for the last function in a file, I would be extremely grateful.

Thanks in advance :)

+2  A: 

You can create folds programmatically using the foldexpr and foldtext. Try this, though you may have to tweak CFoldLevel so it doesn't swallow non-function parts of the code:

function! CFoldLevel(lnum)
  let line = getline(a:lnum)
  if line =~ '^/\*'
    return '>1' " A new fold of level 1 starts here.
  else
    return '1' " This line has a foldlevel of 1.
  endif
endfunction

function! CFoldText()
  " Look through all of the folded text for the function signature.
  let signature = ''
  let i = v:foldstart
  while signature == '' && i < v:foldend
    let line = getline(i)
    if line =~ '\w\+(.*)$'
      let signature = line
    endif 
    let i = i + 1
  endwhile

  " Return what the fold should show when folded.
  return '+-- ' . (v:foldend - v:foldstart) . ' Lines: ' . signature . ' '
endfunction

function! CFold()               
  set foldenable
  set foldlevel=0   
  set foldmethod=expr
  set foldexpr=CFoldLevel(v:lnum)
  set foldtext=CFoldText()
  set foldnestmax=1
endfunction

See :help 'foldexpr' for more details.

a paid nerd
Thanks so much :), that was exactly what I was looking for. It took a little modifying, but I have it working just how I want it, and can finally remove the markers from my C projects. Much appreciated.
Vincent L