web-dev-qa-db-fra.com

Comment rechercher les tampons ouverts dans Vim?

Je souhaite rechercher du texte dans tous les fichiers actuellement ouverts dans vim et afficher tous les résultats au même endroit. Il y a deux problèmes, je suppose:

  • Je ne peux pas transmettre la liste des fichiers ouverts à :grep/:vim, en particulier les noms des fichiers qui ne sont pas sur le disque;
  • Le résultat de :grep -C 1 text ne semble pas bon dans la fenêtre de correction rapide.

Voici un bel exemple de recherche de fichiers multiples dans Sublime Text 2:enter image description here

Des idées?

36
squirrel

Ou

:bufdo vimgrepadd threading % | copen

La fenêtre de correction rapide ne vous convient peut-être pas, mais elle est beaucoup plus fonctionnelle que le "panneau de résultats" de ST2, ne serait-ce que parce que vous pouvez la garder ouverte et visible lorsque vous vous déplacez et que vous pouvez interagir avec elle si elle n'y est pas.

36
romainl

ack et Ack.vim gèrent ce problème à merveille. Vous pouvez également utiliser :help :vimgrep. Par exemple:

:bufdo AckAdd -n threading

créera une fenêtre de correction rapide Nice qui vous permet de sauter à la position du curseur.

6
Conner

Comme la réponse de Waz, j’ai écrit pour cela des commandes personnalisées, publiées dans mon plugin GrepCommands . Il permet de rechercher dans les tampons (:BufGrep), les fenêtres visibles (:WinGrep), les onglets et les arguments.

(Mais comme toutes les autres réponses, il ne gère pas encore les tampons non nommés.)

3
Ingo Karkat

J'ai créé cette fonction il y a longtemps, et j'imagine que ce n'est probablement pas la solution la plus propre, mais elle m'a été utile:

" Looks for a pattern in the open buffers.
" If list == 'c' then put results in the quickfix list.
" If list == 'l' then put results in the location list.
function! GrepBuffers(pattern, list)
    let str = ''

    if (a:list == 'l')
        let str = 'l'
    endif

    let str = str . 'vimgrep /' . a:pattern . '/'

    for i in range(1, bufnr('$'))
        let str = str . ' ' . fnameescape(bufname(i))
    endfor

    execute str
    execute a:list . 'w'
endfunction

" :GrepBuffers('pattern') puts results into the quickfix list
command! -nargs=1 GrepBuffers call GrepBuffers(<args>, 'c')

" :GrepBuffersL('pattern') puts results into the location list
command! -nargs=1 GrepBuffersL call GrepBuffers(<args>, 'l')
2
Waz

Une version améliorée (sur les stéroïdes) de la réponse de Waz, avec une meilleure recherche dans la mémoire tampon et un traitement spécial des cas, se trouve ci-dessous (les modérateurs ne me permettraient plus de mettre à jour la réponse de Waz: D). Une version plus détaillée. avec des liens pour les touches de direction pour naviguer dans la liste de corrections rapides et F3 pour fermer la fenêtre de corrections rapides peut être trouvé ici: https://Pastebin.com/5AfbY8sm (Quand j’ai envie de trouver comment faire un plugin je vais mettre à jour cette réponse. Je voulais accélérer le partage pour le moment)

" 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
0
FocusedWolf