如何设置热键(例如: CTRL + g )以对当前当前视觉选择执行VIMGREP
操作缓冲?我的目的是在" quickfix"中显示行号列表。所有匹配搜索结果的窗口。
现在,如果我想获得正则表达式搜索的结果列表,我可以像这样执行命令模式查询:
:vimgrep /foo/ %
然而,这有两个问题:
谢谢。
答案 0 :(得分:5)
尝试[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窗口,但它们允许您:
但他们有局限性:
:cnext
或:clast
等导航命令来移动结果。如果这些限制是一个限制,下面的函数改编自justinmk在this /r/vim thread中的答案,为您提供了几乎完整的解决方案:
[I
,在整个缓冲区中搜索光标下的单词,]I
,在当前行后面的光标下搜索单词,[I
以在整个缓冲区中搜索所选文字,]I
,在当前行后搜索所选文字。当缓冲区与文件关联时,下面的函数使用quickfix列表/窗口,否则回退到[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>
在光标下插入单词,而不是可视选择,遗憾的是没有这样的快捷方式。我们别无选择,只能猛拉。
答案 1 :(得分:4)
您可以使用:global
命令结合:caddexpr
将条目添加到当前的quickfix列表中。以下是:h :caddexpr
的示例:
:g/mypattern/caddexpr expand("%") . ":" . line(".") . ":" . getline(".")
这有一些问题:
'errorformat'
尚未更改要克服这些问题(除了每行多个匹配项外),请在~/.vimrc
文件中添加以下命令:
command! -nargs=1 -bar Cgrep
\ let s:errorformat = &errorformat |
\ try |
\ let &errorformat='%f:%l:%m' |
\ cexpr [] |
\ execute 'g'.<q-args>.'caddexpr expand("%").":".line(".").":".getline(".")' |
\ cc |
\ finally |
\ let &errorformat = s:errorformat |
\ endtry
现在您可以使用:Cgrep/foo/
来grep当前缓冲区。
为了使你能够做到这一点的可视化版本,你需要在所选文本中猛拉并通过:Cgrep
将其传递给我们的<c-r>
命令。以下是一个示例视觉映射g/
来执行此操作:
xnoremap g/ y:<c-u>Cgrep/<c-r>"/<cr>
此映射也存在一些问题:
@"
以下映射通过<c-r>=
使用表达式寄存器来修复映射,并且没有魔法\V
:
xnoremap g/ :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>Cgrep/\V<cr>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr>/<cr>
就个人而言,我会放弃映射并获得一个visual star插件(那里有一些插件)。关于这个问题有一个很好的Vimcast:Search for the selected text。然后我会使用我们刚刚通过:Cgrep
创建的:Cgrep//
命令,或者更好的xmap g/ *:Cgrep//<cr>
如需更多帮助,请参阅:
:h :caddexpr
:h :cexpr
:h :g
:h 'efm
:h registers
:h /\V
答案 2 :(得分:1)
通过热键 CTRL + g 搜索文件* .c中的视觉选定文本:
:vmap <silent> <unique> <c-g> y:vimgrep "<c-r>"" *.c<CR>
还存在两个问题:
至1: 据我所知,vimgrep只能搜索文件。解决方案是将缓冲区写入临时文件并在此文件中搜索并在不再需要时删除临时文件。此解决方案需要通过热键调用的脚本。 只是一个提示:要获得合适的文件名,可以使用VIM函数tempname()。例如:
let s:tmpfile = tempname()
(抱歉,我目前没有时间在这里显示脚本解决方案,也许我稍后再添加一个。也许其他人有更好的解决方案或者可以提供脚本?)
到2: 此命令将启用当前缓冲区中的行号:
:set number