VimScript 执行搜索不再起作用
VimScript execute search does not work anymore
不知道从什么时候开始,我的视觉选择搜索功能不再起作用了。我将问题分解为这个最小的例子。
假设以下缓冲区:
word
word
word
当我运行/word
时,我找到了所有结果并且可以在它们之间跳转。
当我 运行 :execute '/word'
这和以前一样工作。
当我编写一个简短的自动加载函数时,它只是做同样的事情,但它却不一样:
~/.config/nvim/autoload/utils/search.vim
:
function! utils#search#visual_selection() abort
execute '/word'
endfunction
执行:call utils#search#visual_selection()
使光标停留在第一个结果上,但没有结果突出显示。此外,它使用旧的搜索模式而不是新的搜索模式。因此,如果我首先搜索 foo
等不存在的内容,然后执行此功能,按 n
会给我错误消息 Pattern not found: foo
.
发生了什么变化。这里有什么区别?
这实际上是 Vim 和 NeoVim 的记录行为。它与 :execute
的使用并没有真正相关(您可以直接使用 /word
重现它),但与搜索(和重做)在函数中的工作方式有关。
参见 :help function-search-undo
,其中指出:
The last used search pattern and the redo command ".
" will not be changed by the function. This also implies that the effect of :nohlsearch
is undone when the function returns.
您可以通过显式设置 search pattern register 来解决这个问题,您可以使用 let
命令来完成。
function! utils#search#visual_selection()
let @/ = 'word'
execute "normal /\<cr>"
endfunction
第二个命令从正常模式执行一个简单的 /
,这足以搜索单词,因为它将查找现在设置为您想要的最后一个搜索模式。
函数完成后,搜索模式将保持其值,这意味着通过 'hlsearch'
突出显示将起作用,n
命令也将找到下一个匹配项。
上述方法的一个限制是您不能真正设置 n
重复的搜索方向。即使可以设置 v:searchforward
,该变量也会在作为 :help function-search-undo
效果的一部分的函数后重置。对于那个你似乎无能为力...
如果此函数的目的是用于键映射,您可能会考虑一种完全不同的方法,使用 nnoremap <expr>
并使用函数 return 作为搜索的正常模式命令一个字符串,这样实际搜索发生在函数之外,function-search-undo
的限制将不适用。
例如:
function! utils#search#visual_selection(searchforward)
let pattern = 'word'
if a:searchforward
let dir = '?'
else
let dir = '/'
endif
return dir.pattern."\<cr>"
endfunction
然后:
" Mappings for next-word and previous-word
nnoremap <expr> <leader>nw utils#search#visual_selection(1)
nnoremap <expr> <leader>pw utils#search#visual_selection(0)
这完全避免了 :help function-search-undo
的问题,因此如果可能的话,请考虑类似这种方法。
不知道从什么时候开始,我的视觉选择搜索功能不再起作用了。我将问题分解为这个最小的例子。
假设以下缓冲区:
word
word
word
当我运行/word
时,我找到了所有结果并且可以在它们之间跳转。
当我 运行 :execute '/word'
这和以前一样工作。
当我编写一个简短的自动加载函数时,它只是做同样的事情,但它却不一样:
~/.config/nvim/autoload/utils/search.vim
:
function! utils#search#visual_selection() abort
execute '/word'
endfunction
执行:call utils#search#visual_selection()
使光标停留在第一个结果上,但没有结果突出显示。此外,它使用旧的搜索模式而不是新的搜索模式。因此,如果我首先搜索 foo
等不存在的内容,然后执行此功能,按 n
会给我错误消息 Pattern not found: foo
.
发生了什么变化。这里有什么区别?
这实际上是 Vim 和 NeoVim 的记录行为。它与 :execute
的使用并没有真正相关(您可以直接使用 /word
重现它),但与搜索(和重做)在函数中的工作方式有关。
参见 :help function-search-undo
,其中指出:
The last used search pattern and the redo command "
.
" will not be changed by the function. This also implies that the effect of:nohlsearch
is undone when the function returns.
您可以通过显式设置 search pattern register 来解决这个问题,您可以使用 let
命令来完成。
function! utils#search#visual_selection()
let @/ = 'word'
execute "normal /\<cr>"
endfunction
第二个命令从正常模式执行一个简单的 /
,这足以搜索单词,因为它将查找现在设置为您想要的最后一个搜索模式。
函数完成后,搜索模式将保持其值,这意味着通过 'hlsearch'
突出显示将起作用,n
命令也将找到下一个匹配项。
上述方法的一个限制是您不能真正设置 n
重复的搜索方向。即使可以设置 v:searchforward
,该变量也会在作为 :help function-search-undo
效果的一部分的函数后重置。对于那个你似乎无能为力...
如果此函数的目的是用于键映射,您可能会考虑一种完全不同的方法,使用 nnoremap <expr>
并使用函数 return 作为搜索的正常模式命令一个字符串,这样实际搜索发生在函数之外,function-search-undo
的限制将不适用。
例如:
function! utils#search#visual_selection(searchforward)
let pattern = 'word'
if a:searchforward
let dir = '?'
else
let dir = '/'
endif
return dir.pattern."\<cr>"
endfunction
然后:
" Mappings for next-word and previous-word
nnoremap <expr> <leader>nw utils#search#visual_selection(1)
nnoremap <expr> <leader>pw utils#search#visual_selection(0)
这完全避免了 :help function-search-undo
的问题,因此如果可能的话,请考虑类似这种方法。