Situation #1: I have just selected a block of text. I then type ":Command", which invokes some function.
Situation #2: There is no current visual selection (though I may have made such a selection previously in the edit session). I type ":Command", which invokes (the same) function.
Is there a (robust) way to distinguish the above two situations from within the function? I tried mode()
, but the problem is that in both cases I am in command mode, though in the first case I got into command mode from visual mode while in the second it was from normal mode. Maybe through inspection of a:firstline
/a:lastline
/v:count
?
Update -- Use Case example: ":Sum
". If there is a current visual selection, e.g., a column of numbers (block selection) or a range of lines containing just numbers, this command will echo the sum of the numbers. Otherwise, it expects a list of space-separated numbers as arguments, and will echo the sum of those numbers. Basic framework:
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
Steps (2)-(5) are straightforward. I'm having trouble with (1). I use the "<"/"
>" markers to recreate the collect the numbers from a visual selection. But I only want to do this if there is a visual selection currently highlighted/active.
Maybe my entire logic is wrong and there is a better way to design this functionality?
If you need to use command, the only way I see is to inspect a:firstline
/a:lastline
:
" Assuming that you have passed -range=% when defining command
if a:firstline==1 && a:lastline==line('$')
" Do something
endif
but this does not hold the case when you selected the whole buffer. I suggest you use expression mappings:
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()
Update: Visual mode is never active in command mode. Never. Just because the command mode is not the visual mode. Using mappings is the only way to achieve what you want and here are two approaches: you use exactly the same expr mapping for all modes and check mode()
somewhere in this expression or you define different mappings for different modes and use these differences to tell function from what mode it is called.
Old question.
Came here via DDG search.
There is a new function visualmode that's meant to be used in functions. It returns the last used visual mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With