检查Vim中是否存在来自命令调用的函数的当前活动视觉选择

时间:2010-11-30 16:45:21

标签: vim

情况#1:我刚刚选择了一个文本块。然后我输入“:Command”,它会调用一些函数。

情况#2:目前没有视觉选择(尽管我之前在编辑会话中做过这样的选择)。我输入“:Command”,它调用(相同的)函数。

是否有(强大的)方法将上述两种情况与功能区分开来?我尝试了mode(),但问题是在两种情况下我都处于命令模式,尽管在第一种情况下我从可视模式进入命令模式,而在第二种情况下我从正常模式进入。也许是通过检查a:firstline / a:lastline / v:count


更新 - 用例示例:“:Sum”。如果存在当前视觉选择,例如,一列数字(块选择)或仅包含数字的一系列行,则该命令将回显数字的总和。否则,它需要一个以空格分隔的数字列表作为参数,并将回显这些数字的总和。基本框架:

command! -nargs="*" -range Sum :call CalcSum(<f-args>)
function! CalcSum(...) range
   " 1. collect numbers from visual selection if there is a current active selection
   " 2. otherwise, if len(args) > 0, collect numbers from args
   " 3. other cases (i.e., no selection and no args or both selection and args) handled reasonably
   " 4. sum collection of numbers
   " 5. return/echo result
endfunction 

步骤(2) - (5)是直截了当的。我遇到麻烦(1)。我使用“<"/"&gt;”用于重新创建的标记从视觉选择中收集数字。但是我只想这样做如果有一个视觉选择当前突出显示/活动。

也许我的整个逻辑都是错误的,有更好的方法来设计这个功能吗?

2 个答案:

答案 0 :(得分:6)

如果您需要使用命令,我看到的唯一方法是检查a:firstline / a:lastline

" Assuming that you have passed -range=% when defining command
if a:firstline==1 && a:lastline==line('$')
    " Do something
endif

但是当您选择整个缓冲区时,这并不成立。我建议你使用表达式映射:

function DoCommand()
    if mode()!~#"^[vV\<C-v>]"
        " Do something. For example, set global variable (and unset it in :Command)
    endif
    return ':Command'
endfunction
noremap <expr> {lhs} DoCommand()

更新:在命令模式下,可视模式从不处于活动状态。决不。仅仅因为命令模式不是可视模式。使用映射是实现所需的唯一方法,这里有两种方法:对所有模式使用完全相同的expr映射,并在此表达式中的某处检查mode(),或者为不同模式定义不同的映射并使用这些差异告诉函数从什么模式调用它。

答案 1 :(得分:0)

老问题。
通过DDG搜索来到这里。 有一个新函数 visualmode 旨在用于函数中。它返回上次使用的视觉模式。