如何在Vim中所有打开的选项卡中搜索当前单词?


16

我已经开始使用*#当光标位于当前单词上时学习Vim单词搜索。但是此搜索仅限于当前文件缓冲区。

是否有命令或快捷方式可将搜索范围扩展到:

  1. 所有打开的标签页?
  2. 所有打开的缓冲区?

1
您可能会发现有关制表符和缓冲区的解释有趣而有用。
2016年

Answers:


4

对于您的问题,我没有确切的解决方案,希望比我的解决方案更好。但是,这就是我解决在所有缓冲区中查找单词的问题。

" 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

第一行创建一个Search以搜索模式作为参数的命令,该命令将结果写入快速修复列表中。另外两条线将(至少对我而言)无用的箭头键映射到了有用的东西。它们被映射为跳转到下一个/上一个Search或下一个/上一个编译错误等,它们只需通过quickfix列表即可。您可以如下使用它:

:Search foobar
<right>
<right>
…

我喜欢这个命令,但是添加了一些内容,因此它将更好地转义搜索词,并强制重绘。(在分割中使用silent可能导致vim ui出错)。命令!-nargs = 1搜索呼叫setqflist([])| 静默执行“ bufdo grepadd!'<args>'%” | 重绘!
Igorio 2014年

您也可以只键入:cn:cp切换到下一个文档。
phyatt

7

它实际上是默认行为,尽管可能很难注意到:尝试*然后更改为另一个选项卡,并在命令模式下使用nans N在搜索命中之间来回跳转。

如果首先为所有匹配打开突出显示,则可能更有意义:

:set hlsearch

1
+1只是因为hlsearch我不知道,我可能会搜索一天或另一天:-)。但是,默认情况下,我尝试使用*#,n和N,并且它不会跳到其他文件缓冲区 ...
Stephane Rolland 2013年

没有,n并且N不跳缓冲区(它们环绕),但他们的目标是搜索所有选项卡中的术语; 命中*与再循环突出通过你的标签-他们都将使用相同的术语突出,所以你可以使用nN不新鲜的本地搜索有。
goldilocks 2013年

2
关键不是要遍历选项卡即可找到所有匹配项。
Magnus 2014年

1
@Magnus虽然这可能是更好的选择,但实际上并没有在问题中明确说明,该问题询问如何“将搜索范围扩展到...所有缓冲区” ->扩展到所有缓冲区。我的回答的重点是要弄清楚这一点,因为它可能不是,特别是如果您没有hlsearch设置的话。
goldilocks 2014年


1

当我发现自己经常这样做时,我混搭了一个(可改进的)脚本。

您或其他人可能会发现它很有用。


简短说明:

基本上,它搜索缓冲区列表并在quickfix-window中显示结果。

添加了两个基本命令。

  1. Search <pattern> :在所有缓冲区中搜索<pattern>
  2. Search1 <pattern>:在所有缓冲区中搜索<pattern>,但仅显示每个缓冲区的第一个结果。通常用于列出所有foo使用函数,变量(或任何其他变量)的缓冲区。

使用爆炸(:Search! foo)追加到结果中。

另外GSearchGSearch1在与Search脚本添加regex分隔符的地方有所不同,并且添加了,例如:

foo -> /foo/

在哪里 GSearch预期的那样将其封闭。

j始终添加该标志以防止跳转。


码:

有一些技巧可以防止错误列表,同时保持代码简短。try / catch有点麻烦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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.