3

I would like to use search in file with folded functions to search only in functions titles. But common vim search searches inside folding and unfolds any hidden text. Is there a way to search only in open text ignoring the rest?

  • 1
    If you :set foldopen-=search, then Vim will still search within the folds, but at least it won't unfold them. – Rich Feb 14 at 14:52
3

You could use :folddoopen to capture the addresses of the lines which are not in open folds, then build a sub-expression describing those lines (see :h \%l, :h \%>l, :h \%<l).

As an example:

cno <c-o> <c-r>=<sid>limit_search_to_open_folds(1)<cr><c-c>
fu s:limit_search_to_open_folds(step) abort
    if a:step == 1
        let s:pat = getcmdline()
        call timer_start(0, {-> s:limit_search_to_open_folds(2)})
    else
        let s:pat = get(s:, 'pat', '')..'\m\%('
        folddoopen let s:pat ..= '\%'..line('.')..'l\|'
        let s:pat = substitute(s:pat, '\\|$', '\\)', '')
        call feedkeys('/'..s:pat, 'in')
    endif
    return ''
endfu

Write your pattern, then press C-o. It should append a sub-expression which limits the search to the lines which are not in closed folds.


If the sub-expression is too long, try this:

cno <c-o> <c-r>=<sid>limit_search_to_open_folds(1)<cr><c-c>
fu s:limit_search_to_open_folds(step) abort
    if a:step == 1
        let s:cmdline = getcmdline()
        call timer_start(0, {-> s:limit_search_to_open_folds(2)})
    else
        let lnums = []
        folddoopen let lnums += [line('.')]
        let ranges = []
        for i in range(len(lnums))
            if i > 0 && lnums[i] == lnums[i-1] + 1
                if type(ranges[-1]) == type(0)
                    let ranges[-1] = [ranges[-1], ranges[-1]+1]
                else
                    let ranges[-1][1] += 1
                endif
            else
                let ranges += [lnums[i]]
            endif
        endfor
        call map(ranges, {_,v -> type(v) == type(0) ? '\%'..v..'l' : '\%>'..(v[0]-1)..'l\%<'..(v[1]+1)..'l'})
        let pat = get(s:, 'cmdline', '')
            \ ..'\m\%('
            \ ..join(ranges, '\|')
            \ ..'\)'
        call feedkeys('/'..pat, 'in')
    endif
    return ''
endfu
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.