Search 如何在Vim中搜索打开的缓冲区?

Search 如何在Vim中搜索打开的缓冲区?,search,vim,Search,Vim,我想在vim中当前打开的所有文件中搜索文本,并在一个地方显示所有结果。我想有两个问题: 我无法将打开的文件列表传递给:grep/:vim,尤其是磁盘上没有的文件名 :grep-c1 text的结果在quickfix窗口中看起来不太好 下面是Sublime Text 2中多文件搜索的一个很好的示例: 有什么想法吗?并巧妙地处理这个问题。您还可以使用:help:vimgrep。例如: :bufdo AckAdd -n threading 将创建一个很好的快速修复窗口,让您跳到光标位置。或 :b

我想在vim中当前打开的所有文件中搜索文本,并在一个地方显示所有结果。我想有两个问题:

  • 我无法将打开的文件列表传递给
    :grep
    /
    :vim
    ,尤其是磁盘上没有的文件名
  • :grep-c1 text
    的结果在quickfix窗口中看起来不太好
下面是Sublime Text 2中多文件搜索的一个很好的示例:

有什么想法吗?

并巧妙地处理这个问题。您还可以使用
:help:vimgrep
。例如:

:bufdo AckAdd -n threading
将创建一个很好的快速修复窗口,让您跳到光标位置。

:bufdo vimgrepadd threading % | copen

quickfix窗口对您来说可能不太合适,但它比ST2的“结果面板”功能强大得多,因为您可以在跳转到位置时保持其打开和可见,并在不存在的情况下与之交互。

我很久以前就实现了此功能,我猜它可能不是最干净的解决方案,但它对我很有用:

" 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')
“在打开的缓冲区中查找模式。
“如果列表=='c',则将结果放入快速修复列表中。
“如果list='l',则将结果放入位置列表中。
函数!GrepBuffers(模式、列表)
设str=''
如果(a:list='l')
设str='l'
恩迪夫
设str=str.'vimgrep/'。a:模式。'/'
对于范围内的i(1,bufnr(“$”))
设str=str.''.fnameescape(bufname(i))
外循环
执行str
执行:列表“w”
端功能
“:GrepBuffers('pattern')将结果放入快速修复列表中
命令-nargs=1个grepbuffer调用grepbuffer(,'c')
“:GrepBuffersL('pattern')将结果放入位置列表中
命令!-nargs=1 GrepBuffersL调用GrepBuffers(,'l')

就像Waz的答案一样,我已经为此编写了自定义命令,发布在my中。它允许在缓冲区(
:BufGrep
)、可见窗口(
:WinGrep
)、选项卡和参数上搜索

(但和所有其他答案一样,它还不能处理未命名的缓冲区。)

下面是Waz答案的改进版(使用类固醇),具有更好的缓冲区搜索和特殊情况处理功能(版主不允许我再更新Waz的答案:D)。 可以在此处找到一个更丰富的版本,其中包含箭头键绑定,用于导航快速修复列表,F3用于关闭快速修复窗口: (当我想弄清楚如何制作插件时,我会更新这个答案。我现在想加快分享速度)

“在缓冲区中查找模式。
用法:GrepBuffers[pattern][matchCase][matchWholeWord][prefix]
“如果未指定图案,则会打印使用说明。
“如果matchCase='1',则排除不具有相同大小写的匹配项。如果matchCase='0',则忽略大小写。”。
“如果前缀=='c',则将结果放入快速修复列表中。如果prefix=='l',则将结果放入当前窗口的位置列表中。
功能!s:GrepBuffers(…)
如果a:0>4
抛出“太多的论点”
恩迪夫
如果a:0>=1
设l:pattern=a:1
其他的
echo'用法:GrepBuffers[pattern][matchCase][matchWholeWord][prefix]'
返回
恩迪夫
设l:matchCase=0
如果a:0>=2
如果a:2!~'^\d\+$a:2>1 | a:2<0
抛出“ArgumentException:matchCase值”。a:2。“'不在界限[0,1]内。”
恩迪夫
设l:matchCase=a:2
恩迪夫
设l:matchWholeWord=0
如果a:0>=3
如果a:3!~'^\d\+$a:3>1 | a:3<0
抛出“ArgumentException:matchWholeWord值”。a:3。“'不在界限[0,1]内。”
恩迪夫
设l:matchWholeWord=a:3
恩迪夫
让l:前缀='c'
如果a:0>=4
如果a:4!='c&a:4!='我是
抛出“ArgumentException:前缀值”。a:4。“'不是'c'或'l'。”
恩迪夫
设l:prefix=a:4
恩迪夫
让ignorecase=&ignorecase
让&ignorecase=l:matchCase==0
尝试
如果l:前缀=='c'
让l:vimgrep='vimgrep'
elseif l:前缀=='l'
让l:vimgrep='lvimgrep'
恩迪夫
如果我是matchWholeWord
设l:pattern='\'
恩迪夫
让str='silent'。l:vimgrep.“/”。l:图案
对于getbufinfo()中的buf
if buflisted(buf.bufnr)“跳过未列出的缓冲区,因为它们不用于正常编辑
if!bufexists(buf.bufnr)
抛出“缓冲区不存在:”。buf.bufnr"'
elseif empty(bufname(buf.bufnr))&getbufvar(buf.bufnr,&buftype')!='quickfix'
如果len(getbufline(buf.bufnr,'2'))!=0 | | strlen(getbufline(buf.bufnr,'1')[0])!=0
echohl warningmsg | echomsg'跳过未命名的缓冲区:['.buf.bufnr.]'| echohl正常
恩迪夫
其他的
设str=str.''.fnameesce(bufname(buf.bufnr))
恩迪夫
恩迪夫
外循环
尝试
执行str
catch/^Vim\%(\a\+)\=:E\%(683\\;480\):/“E683:文件名丢失或模式无效---E480:不匹配:
“您希望如何处理此异常?
第五章:例外
返回
末日
执行l:前缀。“窗口”
“捕获/*/
最后
let&ignorecase=ignorecase
末日
端功能

我真的很喜欢Romaill的答案,但其中有一些难以理解的地方,使得它在实践中难以使用

在.vimrc文件中,下面介绍了一个用户命令
Gall
(Grep all),它解决了我发现的一些令人讨厌的问题

funct! GallFunction(re)
  cexpr []
  execute 'silent! noautocmd bufdo vimgrepadd /' . a:re . '/j %'
  cw  
endfunct

command! -nargs=1 Gall call GallFunction(<q-args>)
不区分大小写:

:Gall error
和空格:

:Gall fn run
赞成的意见
  • 它只会打开“快速修复”窗口,而不会打开其他窗口
  • 在从每个缓冲区读取结果之前,它将首先清除Quickfix窗口
  • “快速修复”窗口将包含该位置
    :Gall error
    
    :Gall fn run
    
    :[count]cn
    
    :[count]cp
    
    Ctrl-w w "next window (you'll need this at a bare minimum)
    
    Ctrl-w t Ctrl-w o "go to the top window then close everything else
    
    Ctrl-w c "close the current window, i.e. usually the Quickfix window
    
    :ccl "close Quickfix window
    
    :cw
    
    :copen