regex - VIM - 当前缓冲区中视觉选择的 VIMGREP 热键

标签 regex vim vi vimgrep

我将如何设置热键(例如:CTRL+g)来执行 VIMGREP对当前缓冲区中的当前视觉选择进行操作?我的目的是在所有匹配搜索结果的“快速修复”窗口中显示一个行编号列表。

现在,如果我想获取正则表达式搜索的结果列表,我可以执行命令模式查询,如下所示:

:vimgrep /foo/ %

但是,这样做有两个问题:
  • 我不想输入整个查询。我总是可以做一个视觉选择,然后使用 CTRL+r、CTRL+w 将当前的视觉选择粘贴到命令缓冲区中,但我想要比这更简单的东西。
  • 上述方法要求当前缓冲区已经保存到文件中。我希望能够处理粘贴到 VIM 中的临时缓冲区,而不必每次都保存文件缓冲区。

  • 谢谢你。

    最佳答案

    低级解决方案

    试试 [I:ilist命令:

    [I                 " lists every occurrence of the word under the cursor
                       " in the current buffer (and includes)
    
    :ilist /foo<CR>    " lists every occurrence of foo in the current buffer 
                       " (and includes)
    

    :后跟一个行号和 <CR>跳到那条线。

    您可以通过简单的映射在视觉选择上使用它们:

    xnoremap <key> "vy:<C-u>ilist /<C-r>v<CR>:
    

    不过,您可能需要在插入时清理寄存器。

    :help :ilist .

    另一个更低级别的解决方案

    既然我们已经做到了,让我们更深入地挖掘并找到惊人的简单和优雅:

    :g/foo/#
    

    您可以使用与 :ilist 相同的方式以上:

    xnoremap <key> "vy:<C-u>g/<C-r>v/#<CR>:
    

    限制

    显然,上述解决方案不使用 quickfix 窗口,但它们允许您:
  • 以列表形式查看他们的结果,
  • 使用行号实际到达您想要的位置。

  • 但是,它们有局限性:
  • 该列表没有被缓存,所以如果你想找到一个不同的事件,你必须再次执行搜索,
  • 该列表不像 quickfix 列表那样是暂时的,所以你不能使用像 :cnext 这样的导航命令。或 :clast移动结果。

  • 更高层次的解决方案

    如果这些限制是一个阻碍,那么下面的函数改编自 justinmk 在 this /r/vim thread 中的回答。 ,给你一个几乎完整的解决方案:
  • [I在正常模式下在整个缓冲区中搜索光标下的单词,
  • ]I在普通模式下搜索当前行后光标下的单词,
  • [I在可视模式下在整个缓冲区中搜索选定的文本,
  • ]I在可视模式下搜索当前行之后的选定文本。

  • 当缓冲区与文件关联并回退到 [I 的常规行为时,下面的函数使用快速修复列表/窗口。和 ]I除此以外。它可能可以修改为用作 :Ilist 的一部分。命令。

    " Show ]I and [I results in the quickfix window.
    " See :help include-search.
    function! Ilist_qf(selection, start_at_cursor)
    
        " there's a file associated with this buffer
        if len(expand('%')) > 0
    
            " we are working with visually selected text
            if a:selection
    
                " we build a clean search pattern from the visual selection
                let old_reg = @v
                normal! gv"vy
                let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
                let @v = old_reg
    
                " and we redirect the output of our command for later use
                redir => output
                    silent! execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern
                redir END
    
            " we are working with the word under the cursor
            else
    
                " we redirect the output of our command for later use
                redir => output
                    silent! execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
                redir END
            endif
            let lines = split(output, '\n')
    
            " better safe than sorry
            if lines[0] =~ '^Error detected'
                echomsg 'Could not find "' . (a:selection ? search_pattern : expand("<cword>")) . '".'
                return
            endif
    
            " we retrieve the filename
            let [filename, line_info] = [lines[0], lines[1:-1]]
    
            " we turn the :ilist output into a quickfix dictionary
            let qf_entries = map(line_info, "{
                        \ 'filename': filename,
                        \ 'lnum': split(v:val)[1],
                        \ 'text': getline(split(v:val)[1])
                        \ }")
            call setqflist(qf_entries)
    
            " and we finally open the quickfix window if there's something to show
            cwindow
    
        " there's no file associated with this buffer
        else
    
            " we are working with visually selected text
            if a:selection
    
                " we build a clean search pattern from the visual selection
                let old_reg = @v
                normal! gv"vy
                let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
                let @v = old_reg
    
                " and we try to perform the search
                try
                    execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' .  search_pattern . '<CR>:'
                catch
                    echomsg 'Could not find "' . search_pattern . '".'
                    return
                endtry
    
            " we are working with the word under the cursor
            else
    
                " we try to perform the search
                try
                    execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
                catch
                    echomsg 'Could not find "' . expand("<cword>") . '".'
                    return
                endtry
            endif
        endif
    endfunction
    
    nnoremap <silent> [I :call Ilist_qf(0, 0)<CR>
    nnoremap <silent> ]I :call Ilist_qf(0, 1)<CR>
    xnoremap <silent> [I :<C-u>call Ilist_qf(1, 0)<CR>
    xnoremap <silent> ]I :<C-u>call Ilist_qf(1, 1)<CR>
    

    注意:<C-r><C-w>在光标下插入单词,而不是视觉选择,不幸的是没有这样的快捷方式。我们别无选择,只能猛拉。

    关于regex - VIM - 当前缓冲区中视觉选择的 VIMGREP 热键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26538875/

    相关文章:

    linux - 设置 Vim 背景颜色

    regex - Vim:将正则表达式匹配到+ clipboard

    linux - 限制每行编辑器vi linux的字符数

    java - 将文档分为段落

    vim - 为什么 vim 在选项卡的位置画下划线以及如何避免这种情况?

    bash - bash vi shell 模式下的 Tab 自动补全

    linux - SED - 删除后跟换行 (\n) 的字符串

    javascript - 正则表达式不能用作 HTML5 模式验证器

    java - 正则表达式检查长度

    regex - 将一系列日期中的 Grep 作为文件名