情况#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
Run Code Online (Sandbox Code Playgroud)
步骤(2) - (5)是直截了当的.我遇到麻烦(1).我使用" <"/">"标记重新创建从视觉选择中收集数字.但是,如果当前突出显示/活动的视觉选择,我只想这样做.
也许我的整个逻辑都是错误的,有更好的方法来设计这个功能?
如果你需要使用命令,我看到的唯一方法是检查a:firstline/a:lastline:
" Assuming that you have passed -range=% when defining command
if a:firstline==1 && a:lastline==line('$')
" Do something
endif
Run Code Online (Sandbox Code Playgroud)
但是当你选择整个缓冲区时,这并不成立.我建议你使用表达式映射:
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()
Run Code Online (Sandbox Code Playgroud)
更新:可视模式在命令模式下从不活动.决不.仅仅因为命令模式不是可视模式.使用映射是实现所需的唯一方法,这里有两种方法:对所有模式使用完全相同的expr映射并检查mode()此表达式中的某个位置,或者为不同的模式定义不同的映射,并使用这些差异来告诉函数模式它被称为.