diff --git a/vim_plugins/searchfold_0.9.vim b/vim_plugins/searchfold_0.9.vim new file mode 100644 index 000000000..1fb9ba8f9 --- /dev/null +++ b/vim_plugins/searchfold_0.9.vim @@ -0,0 +1,319 @@ +" Vim global plugin -- create folds based on last search pattern +" General: {{{1 +" File: searchfold.vim +" Created: 2008 Jan 19 +" Last Change: 2011 May 24 +" Rev Days: 18 +" Author: Andy Wokula +" Credits: Antonio Colombo's f.vim (Vimscript #318, 2005 May 10) +" Vim Version: Vim 7.0 +" Version: 0.9 + +" Description: +" Provide mappings to fold away lines not matching the last search pattern +" and to restore old fold settings afterwards. Uses manual fold method, +" which allows for nested folds to hide or show more context. Doesn't +" preserve the user's manual folds. + +" Usage: +" z fold away lines not matching the last search pattern. +" +" With [count], change the initial foldlevel to ([count] minus +" one). The setting will be stored in g:searchfold_foldlevel +" and will be reused when [count] is omitted. +" +" iz fold away lines that do match the last search pattern +" (inverse folding), also with [count]. +" +" Z restore the previous fold settings. +" +" Minor Extra: If already in restored state, show a dialog to +" revert all involved local fold options to the global +" defaults. The "(s)how" just prints info. + +" Customization: +" :let g:searchfold_maxdepth = 7 +" (number) +" maximum fold depth +" +" :let g:searchfold_usestep = 1 +" (boolean) +" Controls how folds are organized: If 1 (default), each "zr" +" (after "\z") unfolds the same amount of lines above and +" below a match. If 0, only one more line is unfolded above a +" match. This applies for next "\z" or "\iz". +" +" :let g:searchfold_postZ_do_zv = 1 +" (boolean) +" If 1, execute "zv" (view cursor line) after Z. +" +" :let g:searchfold_foldlevel = 0 +" (number) +" Initial 'foldlevel' to set for z and iz. +" +" :let g:searchfold_do_maps = 1 +" (boolean) +" Whether to map the default keys or not. +" +" Hint: For boolean options, 1 actually means any non-zero number. + +" Related: Vimscript #158 (foldutil.vim) ... still to be checked out +" http://www.noah.org/wiki/Vim#Folding +" Vimscript #2302 (foldsearch.vim) +" Vimscript #578 (allfold.tar.gz) +" +" Changes: +" v0.9 redraw removed, plug map renamed, comments (usestep ...) +" v0.8 added inverse folding (iz), g:searchfold_foldlevel, +" count for z, mappings, disabled F(), (fixes) +" v0.7 b:searchfold fallback, s:foldtext check +" v0.6 (after v0.4) added customization vars (usestep, maxdepth, Zpost) +" reverting global fold settings adds to cmd-history +" v0.4 decreasing fold step always 1 +" maxdepth 7 (before: 6) +" v0.3 (after v0.1) added a modified F() from f.vim +" functions now with return values +" v0.2 (skipped) + +" Init Folklore: {{{1 +if exists("loaded_searchfold") + finish +endif +let loaded_searchfold = 1 + +if v:version<700 + echo "Searchfold: you need at least Vim 7.0" + finish +endif + +" Customization: {{{1 +if !exists("g:searchfold_maxdepth") + let g:searchfold_maxdepth = 7 +endif +if !exists("g:searchfold_usestep") + let g:searchfold_usestep = 1 +endif +if !exists("g:searchfold_postZ_do_zv") + let g:searchfold_postZ_do_zv = 1 +endif +if !exists("g:searchfold_foldlevel") + let g:searchfold_foldlevel = 0 +endif +if !exists("g:searchfold_do_maps") + let g:searchfold_do_maps = 1 +endif + +" s:variables {{{1 +let s:foldtext = "(v:folddashes.'').((v:foldend)-(v:foldstart)+(1))" +" use unique notation of 'foldtext' to identify active searchfold in a +" window + +func! s:FoldNested(from, to) " {{{1 + " create one fold from line a:from to line a:to, with more nested folds + " return 1 if folds were created + " return 0 if from > to + let nlines = a:to - a:from + if nlines < 0 + return 0 + elseif nlines < 3 + " range of 1 line possible + exec a:from.",".a:to. "fold" + return 1 + endif + + " calc folds, start with most outer fold + " - range of inner folds at least 2 lines (from0), don't create folds with few + " lines only (check to-from>step) + if g:searchfold_maxdepth < 1 || g:searchfold_maxdepth > 12 + let g:searchfold_maxdepth = 7 + endif + let depth = g:searchfold_maxdepth + let step = 1 " decstep:'' + let step1 = 1 " (const) decstep:'1' + let from = a:from + let to = a:to + " let decstep = exists("g:searchfold_usestep") && g:searchfold_usestep ? "" : "1" + let decstep = g:searchfold_usestep ? "" : "1" + let foldranges = [] + let lined = line("$") + while depth>0 && fromstep + call insert(foldranges, from.",".to) + let from += from>1 ? step : 0 + " let to -= to 0 + call s:FoldNested(1, matches[0]-1) + let imax = nmatches - 1 + let i = 0 + while i < imax + if matches[i]+1 < matches[i+1] + call s:FoldNested(matches[i]+1, matches[i+1]-1) + endif + let i += 1 + endwhile + call s:FoldNested(matches[imax]+1, line("$")) + endif + + let &l:foldlevel = g:searchfold_foldlevel + call cursor(sav_cur[1:]) + + return nmatches +endfunc + +func! SearchFoldEnable(inverse) "{{{1 + " return number of matches + if !search("", "n") + " last search pattern not found, do nothing + return 0 + endif + if (!exists("w:searchfold") || w:searchfold.bufnr != bufnr("")) + \ && &fdt != s:foldtext + " remember settings + let w:searchfold = { "bufnr": bufnr(""), + \ "fdm": &fdm, + \ "fdl": &fdl, + \ "fdt": &fdt, + \ "fen": &fen, + \ "fml": &fml } + " else: do not remember settings if already enabled + endif + setlocal foldmethod=manual + setlocal foldlevel=0 + let &l:foldtext=s:foldtext + setlocal foldenable + setlocal foldminlines=0 + normal! zE + if exists("w:searchfold") + let b:searchfold = w:searchfold + endif + return s:CreateFolds(a:inverse) +endfunc +func! SearchFoldRestore() "{{{1 + " turn off + if exists("w:searchfold") && w:searchfold.bufnr == bufnr("") + " restore settings; var has the right settings if exists, but + " doesn't survive window split or win close/restore + let &l:fdm = w:searchfold.fdm + let &l:fdl = w:searchfold.fdl + let &l:fdt = w:searchfold.fdt + let &l:fen = w:searchfold.fen + let &l:fml = w:searchfold.fml + if &fdm == "manual" + " remove all search folds (old folds are lost anyway): + normal! zE + endif + unlet w:searchfold + elseif exists("b:searchfold") && &fdt == s:foldtext + " fallback only, may have wrong settings if overwritten + let &l:fdm = b:searchfold.fdm + let &l:fdl = b:searchfold.fdl + let &l:fdt = b:searchfold.fdt + let &l:fen = b:searchfold.fen + let &l:fml = b:searchfold.fml + if &fdm == "manual" + normal! zE + endif + else + let choice = input("Revert to global fold settings? (y/[n]/(s)how):")[0] + let setargs = 'fdm< fdl< fdt< fen< fml<' + if choice == "y" + let cmd = 'setlocal '. setargs + echo ':'. cmd + exec cmd + " call histadd(':', cmd) + elseif choice == "s" + let setargs = tr(setargs, "<","?") + let cmd = 'setglobal '. setargs + echo ':'. cmd + exec cmd + let cmd = 'setlocal '. setargs + echo ':'. cmd + exec cmd + endif + return + endif + if g:searchfold_postZ_do_zv + normal! zv + endif +endfunc + +"" func! F() range "{{{1 +" " commented out 2010 Jun 01 +" " range arg: ignore range given by accident +" let pat = input("Which regexp? ", @/) +" if pat == "" +" if exists("w:searchfold") +" call SearchFoldRestore() +" endif +" return +" endif +" let @/ = pat +" call histadd("search", @/) +" call SearchFold() +" endfunc + +" :call F() only for backwards compatibility + +func! SearchFold(...) "{{{1 + let inverse = a:0>=1 && a:1 + if v:count >= 1 + let g:searchfold_foldlevel = v:count - 1 + endif + let nmatches = SearchFoldEnable(inverse) + " at most one match per line counted + if nmatches == 0 + echohl ErrorMsg + echomsg "Searchfold: Pattern not found:" @/ + echohl none + elseif nmatches == line("$") + echomsg "Searchfold: Pattern found in every line:" @/ + elseif nmatches == 1 + echo "Searchfold: 1 line found" + else + echo "Searchfold:" nmatches "lines found" + endif + " 2011 Feb 06 commented out: + " let &hls = &hls + " redraw +endfunc + +" Mappings: {{{1 +nn SearchFoldNormal :call SearchFold(0) +nn SearchFoldInverse :call SearchFold(1) +nn SearchFoldRestore :call SearchFoldRestore() + +if g:searchfold_do_maps + nmap z SearchFoldNormal + nmap iz SearchFoldInverse + nmap Z SearchFoldRestore +endif + +" Modeline: {{{1 +" vim:set fdm=marker ts=8 sts=4 sw=4 noet: