sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #77: Displaying search results using folds

 tip karma   Rating 25/13, Viewed by 3259 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   June 11, 2001 15:33      complexity:   intermediate
author:   Peter Bismuti      as of Vim:   6.0

A guy I work with told me about a function that an old IBM text editor had that he said was useful, and that is to create folds in the file after a search such that every line that is visible contains the search pattern(except possibly the first). All lines that do not contain the search pattern are folded up to the last occurence of the pattern or the top of the file.  

One use for such a function is to be able to make a quick and dirty api of a source file.  For example, if working in Java, you could run the function using the pattern "public|protected|private" and ithe results would be that only the method headers would be visible (well, close enough).  

function! Foldsearch(search)
        normal zE          "erase all folds to begin with
        normal G$          "move to the end of the file
let folded = 0     "flag to set when a fold is found
        let flags = "w"    "allow wrapping in the search
        let line1 =  0     "set marker for beginning of fold
        while search(a:search, flags) > 0
                let  line2 = line(".")
"echo "pattern found at line # " line2
                if (line2 -1 > line1)
                        "echo line1 . ":" . (line2-1)
                        "echo "A fold goes here."
                        execute ":" . line1 . "," . (line2-1) . "fold"
let folded = 1       "at least one fold has been found
                let line1 = line2     "update marker
                let flags = "W"       "turn off wrapping
" Now create the last fold which goes to the end of the file.
        normal $G
        let  line2 = line(".")
"echo "end of file found at line # " line2
        if (line2  > line1 && folded == 1)
                "echo line1 . ":" . line2
                "echo "A fold goes here."
                execute ":". line1 . "," . line2 . "fold"

" Command is executed as ':Fs pattern'"
command! -nargs=+ -complete=command Fs call Foldsearch(<q-args>)
" View the methods and variables in a java source file."
command! Japi Fs public\|protected\|private

 rate this tip  Life Changing Helpful Unfulfilling 

<< Folding for Quickfix | rotating mail signatures >>

Additional Notes

bismuti@cs.fsu.edu, June 11, 2001 15:38
The comments I added broke the script, just delete before trying to run.
bismuti@cs.fsu.edu, June 11, 2001 15:41

This pattern works better to create a Java API, it enforces white space
at the end of the word.

igor@tyumbit.ru, June 20, 2001 21:18
If foldmethod=syntax then VIM complains " E352: Cannot erase folds with current 'foldmethod'  "
Need to check if foldmethod = syntax then normal zR
cz_butler@yahoo,com, June 16, 2002 20:50
The original commands were something like
  x all
  s string
Every line with "string" was displayed, the rest were folded.

I'm new to folding, but I placed the following in my vimrc

set foldexpr=getline(v:lnum-1)!~@/&&getline(v:lnum)!~@/&&getline(v:lnum+1)!~@/
map \z :set foldmethod=expr foldcolumn=2 foldlevel=0

The foldexpr uses @/ (the last search pattern)
The lnum-1,lnum+1 makes line before/after visible (context)
To invoke /string/, then \z  - can it be any easier?
erichbox@yahoo.com, July 21, 2002 11:23
This kind of expression based folding is very similar to XEDITs HIDE macro--with an important difference.  HIDE would temporarily "remove" all lines containing /string/ from the buffer.  You could then edit the file as if these lines were truly gone, and SHOW ALL to replace the HIDden lines at their original locations.  This was true horizontal slicing.

Is there a way to fold up text in this manner and then make a vertical slice through the text (for instance: <C-v>jjjjI"inserted text"<esc> ) that does *not* affect the folded text?  Can buffers be employed to this end somehow?  
kgergely@mcl.dontspam.hu, August 21, 2002 9:05
What I need is to leave some lines around matches. Is it possible?
hari_vim at yahoo dot com, April 1, 2004 11:34
I have a new feature in my foldutil.vim (vimscript #158) that supports the same concept. You just pass in "-1" for context which essentially tries to expose only the matched lines.
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to vim@vim.org after searching the archive. Help Bram help Uganda.
Sponsored by Web Concept Group Inc. SourceForge.net Logo