我有一个简单的vim脚本,它采用可视化的文本块并将其存储为列表。函数VtoList()
的问题在于它在之后执行,光标返回到可视块的开头,而不是之前。因此,我无法获得视觉块结束的行。
nn <F2> :call VtoList()<CR>
func! VtoList()
firstline = line('v') " Gets the line where the visual block begins
lastline = line('.') " Gets the current line, but not the one I want.
mylist = getline(firstline, lastline)
echo mylist
endfunc
问题在于line('.')
。它应返回游标的当前行,但在调用该函数之前,游标已经返回到可视块的开头。因此,我只获得一行而不是一系列行。
我整理了一个解决方案,每当用户点击 V 时设置一个标记,并在调用该函数之前设置另一个标记。
nnoremap V mV
nnoremap <F2> mZ:call VtoList()<CR>
如果我用line('v')
和line('.')
替换line("'V")
和line("'Z")
,该函数可以正常工作,但如果可以,我想避免使用此解决方案,因为它可能与用户的映射。
在光标返回到可视块的开头之前,有没有办法在函数内获取可视块的当前行?
答案 0 :(得分:4)
请勿使用:
,请使用<expr>
:
function! s:NumSort(a, b)
return a:a>a:b ? 1 : a:a==a:b ? 0 : -1
endfunction
func! VtoList()
let [firstline, lastline]=sort([line('v'), line('.')], 's:NumSort')
let mylist = getline(firstline, lastline)
echo mylist
return ""
endfunc
vnoremap <expr> <F2> VtoList()
请注意其他更改:let
(您忘了),sort
(选择开始的行可能位于选择结束的行之后),vnoremap
(line("v")
正常工作仅在视觉模式下),return
(expr
映射返回值被执行,但您不需要它,您只需要副作用)。您可以用
if mode()=~#"^[vV\<C-v>]"
let [firstline, lastline]=sort([line('v'), line('.')], 's:NumSort')
else
let [firstline, lastline]=sort([line("'<"), line("'>")], 's:NumSort')
endif
您的解决方案无效的原因是当映射中出现:
时,您会立即退出可视模式并进入命令模式。 line("v")
仅适用于可视模式。
其他注意:vnoremap {lhs} :
将生成已填充'<,'>
的命令行。您可能已将range
添加到函数定义中并使用let [firstline, lastline]=sort([a:firstline, a:lastline], 's:NumSort')
。但是,您仍将使用:
退出视觉模式。