How do I search the open buffers in Vim?

后端 未结 6 542
陌清茗
陌清茗 2020-12-23 16:36

I\'d like to search for text in all files currently open in vim and display all results in a single place. There are two problems, I guess:

  • I can\'t pass the li
6条回答
  •  执念已碎
    2020-12-23 17:02

    An improved (on steroids) version of Waz's answer, with better buffer searching and special case handling, can be found below (The moderators wouldn't let me update Waz's answer anymore :D). A more fleshed out version with binds for arrow keys to navigate the QuickFix list and F3 to close the QuickFix window can be found here: https://pastebin.com/5AfbY8sm (When i feel like figuring out how to make a plugin i'll update this answer. I wanted to expedite sharing it for now)

    " Looks for a pattern in the buffers.
    " Usage :GrepBuffers [pattern] [matchCase] [matchWholeWord] [prefix]
    " If pattern is not specified then usage instructions will get printed.
    " If matchCase = '1' then exclude matches that do not have the same case. If matchCase = '0' then ignore case.
    " If prefix == 'c' then put results in the QuickFix list. If prefix == 'l' then put results in the location list for the current window.
    function! s:GrepBuffers(...)
        if a:0 > 4
            throw "Too many arguments"
        endif
    
        if a:0 >= 1
            let l:pattern = a:1
        else
            echo 'Usage :GrepBuffers [pattern] [matchCase] [matchWholeWord] [prefix]'
            return
        endif
    
        let l:matchCase = 0
        if a:0 >= 2
            if a:2 !~ '^\d\+$' || a:2 > 1 || a:2 < 0
                throw "ArgumentException: matchCase value '" . a:2 . "' is not in the bounds [0,1]."
            endif
            let l:matchCase = a:2
        endif
    
        let l:matchWholeWord = 0
        if a:0 >= 3
            if a:3 !~ '^\d\+$' || a:3 > 1 || a:3 < 0
                throw "ArgumentException: matchWholeWord value '" . a:3 . "' is not in the bounds [0,1]."
            endif
            let l:matchWholeWord = a:3
        endif
    
        let l:prefix = 'c'
        if a:0 >= 4
            if a:4 != 'c' && a:4 != 'l'
                throw "ArgumentException: prefix value '" . a:4 . "' is not 'c' or 'l'."
            endif
            let l:prefix = a:4
        endif
    
        let ignorecase = &ignorecase
        let &ignorecase = l:matchCase == 0
        try
            if l:prefix == 'c'
                let l:vimgrep = 'vimgrep'
            elseif l:prefix == 'l'
                let l:vimgrep = 'lvimgrep'
            endif
    
            if l:matchWholeWord
                let l:pattern = '\<' . l:pattern . '\>'
            endif
    
            let str = 'silent ' . l:vimgrep . ' /' . l:pattern . '/'
    
            for buf in getbufinfo()
                if buflisted(buf.bufnr) " Skips unlisted buffers because they are not used for normal editing
                    if !bufexists(buf.bufnr)
                        throw 'Buffer does not exist: "' . buf.bufnr . '"'
                    elseif empty(bufname(buf.bufnr)) && getbufvar(buf.bufnr, '&buftype') != 'quickfix'
                        if len(getbufline(buf.bufnr, '2')) != 0 || strlen(getbufline(buf.bufnr, '1')[0]) != 0
                            echohl warningmsg | echomsg 'Skipping unnamed buffer: [' . buf.bufnr . ']' | echohl normal
                        endif
                    else
                        let str = str . ' ' . fnameescape(bufname(buf.bufnr))
                    endif
                endif
            endfor
    
            try
                execute str
            catch /^Vim\%((\a\+)\)\=:E\%(683\|480\):/ "E683: File name missing or invalid pattern --- E480: No match:
                " How do you want to handle this exception?
                echoerr v:exception
                return
            endtry
    
            execute l:prefix . 'window'
        "catch /.*/
        finally
            let &ignorecase = ignorecase
        endtry
    endfunction
    

提交回复
热议问题