从函数中以可视模式获取当前行

时间:2010-12-02 18:02:24

标签: vim

我有一个简单的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"),该函数可以正常工作,但如果可以,我想避免使用此解决方案,因为它可能与用户的映射。

在光标返回到可视块的开头之前,有没有办法在函数内获取可视块的当前行?

1 个答案:

答案 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(选择开始的行可能位于选择结束的行之后),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')。但是,您仍将使用:退出视觉模式。