Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have started learning Vim word-search using * and # while the cursor is over the current word. But this search is limited to the current file buffer.

Is there a command or a shortcut to extend this search to:

  1. all opened tabs?
  2. all opened buffers?
share|improve this question

4 Answers 4

up vote 3 down vote accepted

I don't have an exact solution for your problem, hopefully a better answer than mine will come up. But this is how I tackled the problem of finding a word in all buffers.

" enables to search in all open buffers with :Search <pattern>
command! -nargs=1 Search call setqflist([]) | silent bufdo grepadd! <args> %

nnoremap <left>  :cprev<cr>zvzz
nnoremap <right> :cnext<cr>zvzz

The first line creates a command Search with the search pattern as argument, which writes the results in a quickfix list. The two other lines map the (at least for me) useless arrow keys to something useful; they are mapped to jump to the next/previous Search or to the next/previous compile error, etc., they simply step throu the quickfix list. You can use this as follows:

:Search foobar
<right>
<right>
…
share|improve this answer
    
I love this command, but added a few things so it will escape search terms better, and force a redraw. (using silent with splits can cause vim ui to bug out). command! -nargs=1 Search call setqflist([]) | silent execute "bufdo grepadd! '<args>' %" | redraw! –  Ross Charette Jul 21 at 4:30

As I've found myself frequently doing this I mashed up an (improvable) script.

You or someone else might find it useful.


Short explanation:

Basically it searches buffer list and show result in quickfix-window.

Two basic commands is added.

  1. Search <pattern> : Search all buffers for <pattern>.
  2. Search1 <pattern> : Search all buffers for <pattern>, but only show first result for each buffer. Typically useful for listing all buffers where function, variable foo is used, (or what ever).

Use bang (:Search! foo) to append to results.

Additionally GSearch and GSearch1 is added where difference is that with Search the script add regex delimiter, e.g.:

foo -> /foo/

Where as GSearch expect it to be enclosed.

The j flag is always added to prevent jump.


Code:

There are some hacks to prevent error listing while at the same time keeping the code short. try / catch was a bit cumbersome on bufdo.

let s:not_idents = split("/!#$%&\"`´¨'¯()*+,-.:;<=>?¿@[\]^{|}µ¶·¸~±×÷®©«»¬­ª°º¹²³¼½¾", '\zs')
" Create a delimited pattern. "
fun! s:Parse_pat(pat)
    for c in s:not_idents
        if stridx(a:pat, c) == -1
            return c . a:pat . c
        endif
    endfor
    echohl Error
    echom "Could not delimit pattern '". a:pat ."'"
    echohl None
    return ''
endfun

fun! s:AllBufSearch(pat, bang, uno, isg)
    if a:isg
        let pat = a:pat
    else
        let pat = s:Parse_pat(a:pat)
    endif
    if pat == ''
        return
    endif
    cclose
    let [_buf, _view] = [bufnr("%"), winsaveview()]
    let _foldenable = &foldenable
    set nofoldenable

    " Copy of current qflist. "
    let qfc = getqflist()
    " Hack to prevent error if no matches. "
    call setqflist([{}])
    silent execute "bufdo vimgrepadd! " . pat . "j %"
    " Restore "
    exec "buffer " . _buf
    let &foldenable = _foldenable
    call winrestview(_view)
    " Fix "
    let qf = getqflist()
    call remove(qf, 0)
    " Only one listing per buffer. "
    if a:uno
        let bn = {}
        let i  = 0
        for m in qf
            if has_key(bn, m["bufnr"])
                call remove(qf, i)
            else
                let bn[m["bufnr"]] = 1
                call remove(qf[i], "valid")
                let i += 1
            endif
        endfor
    endif
    if a:bang == "!"
        let qf = qfc + qf
    endif
    " If any matches, copen. "
    if len(qf)
        call setqflist(qf)
        copen
    endif
endfun

command! -nargs=1 -bang Search   call s:AllBufSearch(<q-args>, "<bang>", 0, 0)
command! -nargs=1 -bang Search1  call s:AllBufSearch(<q-args>, "<bang>", 1, 0)
command! -nargs=1 -bang GSearch  call s:AllBufSearch(<q-args>, "<bang>", 0, 1)
command! -nargs=1 -bang GSearch1 call s:AllBufSearch(<q-args>, "<bang>", 1, 1)
share|improve this answer
 :bufdo vimgrepadd yoursearchterm % | copen
share|improve this answer

It's actually the default behaviour although it may be hard to notice: try * then change to another tab and use n ans N in command mode to jump forward and backward between search hits.

This may make more sense if first you turn highlighting on for all hits:

:set hlsearch
share|improve this answer
    
+1 only because of hlsearch that I didn't know, and which I would have search for one day or another :-). However, by default I have tried * #, n and N, and it doesn't jump to other file buffers... –  Stephane Rolland Jan 3 '13 at 15:10
    
No, n and N do not jump buffers (they wrap around), but the term they target is searched for in all tabs; hit * with the highlighting on then cycle thru your tabs -- they will all be highlighted with the same term, so you can use n and N locally there without a fresh search. –  goldilocks Jan 3 '13 at 15:28
    
The whole point is NOT to have to cycle through your tabs to find all the matches. –  Magnus Jun 26 at 18:16
    
@Magnus While that may be preferable, it's actually not explicitly stated in the question, which asks how to "extend this search to...all buffers" -> it is extended across all buffers. The point of my answer was to make this clear, since it might not be, especially if you do not have hlsearch set. –  goldilocks Jun 26 at 18:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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