Check if there is currently active visual selection in Vim from the function called by the command

Case # 1: I just selected a block of text. Then I type the command: Command, which calls some function.

Situation # 2: there is no current visual selection (although, perhaps, I made this choice earlier in the editing session). I type the command β€œ: Command”, which calls the (same) function.

Is there a (reliable) way to distinguish the above two situations from a function? I tried mode() , but the problem is that in both cases I am in command mode, although in the first case I got into command mode from the visual mode, and in the second from normal mode. Maybe through checking a:firstline / a:lastline / v:count ?


Refresh . Use an example example: " :Sum ". If there is a current visual selection, such as a column of numbers (block selection) or a range of rows containing only numbers, this command will recalculate the sum of the numbers. Otherwise, he expects a list of numbers separated by spaces as arguments and will recount the sum of these numbers. Basic structure:

 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 (ie, 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 simple. I have problems with (1). I use the markers " <"/" >" to recreate a set of numbers from the visual selection. But I want to do this only if visual selection is currently selected / active.

Perhaps all my logic is wrong, and is there a better way to develop this functionality?

+7
vim
source share
1 answer

If you need to use the command, the only way I can see is to check 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 apply when you select the entire buffer. I suggest you use expressions:

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

Refresh . Visual mode is never active in command mode. Never. Just because command mode is not visual. Using mappings is the only way to achieve what you want, and here are two approaches: you use exactly the same expr mappings for all modes and check mode() somewhere in this expression or you define different mappings for different modes and use these differences to say the function from which it is called.

+6
source share

All Articles