Vim Tips Wiki
Advertisement

Previous TipNext Tip

Tip: #333 - Syntax-based folding

Created: September 23, 2002 18:32 Complexity: intermediate Author: Kartik Agaram Version: 6.0 Karma: 146/56 Imported from: Tip#333

Here's a function to toggle the use of syntax-based folding for a c/c++/java file. It also handles folding markers.

function! OutlineToggle()
    if (! exists ("b:outline_mode"))
        let b:outline_mode = 0
    endif

    if (b:outline_mode == 0)
        syn region myFold start="{" end="}" transparent fold
        syn sync fromstart
        set foldmethod=syntax

        silent! exec "%s/{{{/<<</"
        silent! exec "%s/}}}/>>>/"

        let b:outline_mode = 1
    else
        set foldmethod=marker

        silent! exec "%s/<<</{{{/"
        silent! exec "%s/>>>/}}}/"

        let b:outline_mode = 0
    endif
endfunction

Comments

I took Kartik's implementation and played with it, then played with it some more and finally got it to work. The "syn region myFold start="{" end="}" transparent fold" method does not like to work when you have other syn groups for {,}. I found this annoying (as I like my colored Braces!) so I figured a pure marker method would work nearly (or just as) good, and it does at least for my uses.

Hopefully everything works just did v0.03 and I have run out of time, enjoy!

outlinetoggle.vim from my plugin dir>>>

" vim:ff=unix ts=4 ss=4 
" vim60:fdm=marker 
" \file outlinetoggle.vim 
" 
" \brief VIM-Tip #333: Syntax-based folding for c/c++/java 
" 
" \author author: Kartik Agaram as of Vim: 6.0 
" \author Mangled by Feral--AT--FireTop.Com 
" \date Tue, 24 Sep 2002 05:44 Pacific Daylight Time 
" \version $Id$ 
" Version: 0.03 
" History: 
" [Feral:267/02--AT--05:43] v0.03: 
" saves the old marker method now. 
" stoped trying to be clever (just do the command twice heh) 
" v0.02 
" trys to be cleaver and start in the proper outline mode based on if it 
" finds a "{>>" in the file. 


"if exists("loaded_outlinetoggle") 
" finish 
"endif 
"let loaded_outlinetoggle = 1 


" Tip #333: Syntax-based folding for c/c++/java 
" tip karma Rating 0/0, Viewed by 88 
" 
"created: September 23, 2002 18:32 complexity: intermediate 
"author: Kartik Agaram as of Vim: 6.0 
" 
"Here's a function to toggle the use of syntax-based folding for a c/c++/java file. It also handles folding markers. 

function! <SID>OutlineToggle() 
  let OldLine = line(".") 
  let OldCol = virtcol(".") 
  if (! exists ("b:outline_mode")) 
    let b:outline_mode = 0 
    let b:OldMarker = &foldmarker 
    " :echo confirm(b:OldMarker) 
    " if search("{>>", 'w') == 0 
      " " no modifed marker found, must be normal marker mode 
      " let b:outline_mode = 0 
    " else 
      " let b:outline_mode = 1 
    " endif 
  endif 


  if (b:outline_mode == 0) 
    let b:outline_mode = 1 
    " syn region myFold start="{" end="}" transparent fold 
    " syn sync fromstart 
    " set foldmethod=syntax 
    " set foldmethod=indent 

    set foldmethod=marker 
    set foldmarker={,} 

    silent! exec "%s/{{{/{<</" 
    silent! exec "%s/}}}/}>>/" 
  else 
    let b:outline_mode = 0 
    set foldmethod=marker 
    let &foldmarker=b:OldMarker 
    " set foldmarker={{{,}}} 

    silent! exec "%s/{<</{{{/" 
    silent! exec "%s/}>>/}}}/" 
  endif 

  execute "normal! ".OldLine."G" 
  execute "normal! ".OldCol."|" 
  unlet OldLine 
  unlet OldCol 
  execute "normal! zv" 
endfunction 

"***************************************************************** 
"* Commands 
"***************************************************************** 
:command! -nargs=0 OUTLINE call <SID>OutlineToggle() 

" 
"EOF 
<<<

feral--AT--firetop.spammersdie.com , September 24, 2002 5:47


Nice. Not changing foldmethod is definitely more elegant.

Kartik Agaram , September 25, 2002 20:52


So, how would I set vim up to fold all c and cpp files when I load them?

This sounds like it should be in the syntax file for cpp just like the pl syntax file allows perl_fold=1.

bronson--AT--real-time.com , May 20, 2003 6:36


Hi, The tip in the comment is great. As is the whole concept of easy folding. I popped this into my .vimrc: map <silent> <F12> :OUTLINE<CR> This makes F12 switch in and out of outline (folded) mode.

You could probably use autocommand to make the folding happen when you open something you want to fold.

Rich S. , January 9, 2004 13:05


I wish I had same thing for comments /* */, but foldermarker does not support regular expression. How about adding alternative foldermarkers ? So, we may write:

set foldermarker1={,} 
set foldermarker2=/*,*/ 

To me it sounds like a cool feature.

Please, check more simple implementation and it works with mouse, I tried to reproduce Visual Studio C# editor :) It looks almost the same. This is optimum combination to work with Java files.

set foldmarker={,} 
set foldmethod=marker 
set foldtext=substitute(getline(v:foldstart),'{.*','{...}',) 
set foldcolumn=4 
set foldlevelstart=1 

ostrygun--AT--cs.com , June 17, 2004 18:09


Combined feral--AT--firetop.spammersdie.com 's tip with the fold columns based on tip comment by cs.com

Here is the code

" \file outlinetoggle.vim
" \brief VIM-Tip #333: Syntax-based folding for c/c++/java
" \author Kartik Agaram as of Vim:   6.0
" \author Mangled by Feral@FireTop.Com
" \author Further mauled by rajas_sambhare@lycosNOSPAMMONKEYBUSINESS.com
" \date Tue, 24 Sep 2002 05:44 Pacific Daylight Time
" \version $Id$
" Version: 0.04
" History:
" [Feral:267/02@05:43] v0.03:
" saves the old marker method now.
" stoped trying to be clever (just do the command twice heh)
" v0.02
" trys to be clever and start in the proper outline mode based on if it
" finds a "{>>" in the file.
" [Rajas:07/16/04] v0.04.1:
" Combined feral's tip with the foldcolumn method and cleaned out comments
" from ferals code. Changed commands name to FOLD (shorter :)

" Tip #333: Syntax-based folding for c/c++/java
" tip karma Rating 0/0, Viewed by 88
"
"created: September 23, 2002 18:32 complexity:   intermediate
"author: Kartik Agaram as of Vim:   6.0
"
"Here's a function to toggle the use of syntax-based folding for a c/c++/java file. It also handles folding markers.

function! <SID>OutlineToggle()
  let OldLine = line(".")
  let OldCol = virtcol(".")
  if (! exists ("b:outline_mode"))
    let b:outline_mode = 0
    let b:OldMarker = &foldmarker
  endif


  if (b:outline_mode == 0)
    let b:outline_mode = 1
    set foldmethod=marker
    set foldmarker={,}
    silent! exec "%s/{{{/{<</"
    silent! exec "%s/}}}/}>>/"
    set foldcolumn=4
  else
    let b:outline_mode = 0
    set foldmethod=marker
    let &foldmarker=b:OldMarker
    silent! exec "%s/{<</{{{/"
    silent! exec "%s/}>>/{{{/"
    set foldcolumn=0
  endif

  execute "normal! ".OldLine."G"
  execute "normal! ".OldCol."|"
  unlet OldLine
  unlet OldCol
  execute "normal! zv"
endfunction

"*****************************************************************
"* Commands
"*****************************************************************
:command! -nargs=0 FOLD call <SID>OutlineToggle()
" End of code

Copy and save this as outlinetoggle.vim in your Vim/vim63/plugins directory. To toggle folding, type :FOLD Remember you can use :zE to expand all folds.

rajas_sambhare--AT--lycosNOSPAMMONKEYBUSINESS.com , July 15, 2004 10:04


Arghh! I'm trying to get C-code folding and hiding all comments, but I've tried all of the above with no luck! Help!... :(

Anonymous , March 14, 2005 9:36


It would be cool it there was some way of folding the previous line for those of us that write code like

int function(....) 
{ 
  .... 
} 

so that the function name was the folded highlight.

Anonymous , June 22, 2005 12:19


you can always do

set foldtext=v:folddashes.substitute(getline(v:foldstart-1),'/\\*\\\|\\*/\\\|{{{\\d\\=',,'g') 

to have the highlighting be the previous lines text.

Anonymous , October 15, 2005 18:50


When in folding mode is it possible to fold a section, like it is possible to unfold one?

bow--AT--skip.informatik.gu.se , October 29, 2005 14:31


now when I open file using gvim, the function is folded, and I happened to get a keyboard comment let one of the unfold, but I don't know how to refold them back.

i.e. what's the key borad comment to

  • fold
  • unfold

a region.

get some tips from http://www.ssds.ucdavis.edu/unix/unix-7-10-14-8.html but don't understand what is zo zc, how to use and where.

Anonymous , May 15, 2006 15:45


zo = Open a fold zc = Close a fold (The fold region must already exist) zfm = 'zf' means to create a fold of movement 'm'

So, if i had a block of code:

if( predicate ) 
{ 
  someFunction(); 
} 

If you move the cursor to one of the curly braces, in command mode you type 'zf%', then you will end up with a fold looking something like this:

if( predicate ) 
3 lines: { 

The "3 lines: {" will be highlighted, indicating that you have created a fold. Also, "3 lines" tells you how many lines were folded.

andrewford--AT--optonline.net , May 18, 2006 9:49


Great! just what I want, thanks!

Anonymous , August 30, 2006 0:01


Just a note to all fold users,

:set fmr={,} 
:set fdm=marker 

Is a quick and easy way to allow folding of anything between angle brackets.

then zM closes all folds and zR opens them all. so I don't know why you need this elaborate solution...

infinull--AT--gmail.com , November 23, 2006 0:57


Advertisement