从函数中获取视觉模式下的当前行

3

我有一个简单的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("'Z")替换line('v')line('.'),该函数可以正常工作,但如果可能的话,我想避免使用这种解决方案,因为它可能会与用户的映射冲突。

在光标返回可视块的开头之前,在函数中有没有一种方法可以获取当前可视块的当前行?

1个回答

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(选择开始的行可能在选择结束的行之后),vnoremapline(“v”)仅在可视模式下运行),returnexpr映射返回值被执行,但你不需要它,你只需要副作用)。你可以将第二行替换为:
    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”)。 但是,您仍然会使用:退出可视模式。

sort存在的问题是它按字母顺序排序,因此如果您跨越第5-12行进行排序,它将返回[12,5]到[firstline,lastline]。如果您跨越100s边缘,1000s边缘等,则会出现相同的问题。 - bobpaul
@bobpaul 谢谢。我现在知道这个问题,但我还没有找到所有使用这种方式的排序的地方。 - ZyX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接