4

What is the correct way get the column of the cursor after a visual selection was made?

As a simple example, consider the following command. It takes a range and I am trying to obtain the column to eventually pass both to a filter:

command! -range CursorColumn echo col('.')

and this buffer:

abc
def
ghi

If the cursor is on c and a visual line-wise selection is started and extended downwards to the third line, the cursor is on i. Switching to command-line mode and executing the command above, it echos 1. If the selection is started at i and extended upwards to c, then the command echos 3, which I would expect in both cases.

How do I get the column of the cursor independently of how the selection was made?

My use case is that I want to pass the selected lines to a filter. At the same time I would like to pass the column the cursor was on as an argument:

command! -range MyFilter exe <line1>.",".<line2>."!myfilter ".col('.')

Edit: Making the selection in visual mode, instead of linewise-visual, shows the behavior I want: I get the column the cursor was on when I execute the command no matter how I made the selection.

  • Welcome to Vi and Vim! Can you edit to clarify how what you want is different from what you presented? I'm not sure I follow your examples and how they relate to what you want to accomplish. It's an interesting question though! – D. Ben Knoble Oct 15 '19 at 15:03
  • 2
    It does print the position of the cursor, not of the selection. You may use the '< and '> marks for the bounds of the selection. – eyal karni Oct 15 '19 at 23:52
2

How do I get the column of the cursor independently of how the selection was made?

Let's make it clear: at this point you're already in the normal mode. All you can get is the selection range, not the cursor position at the time it was made. And so col('.') correctly returns the current cursor position, not the previous one.

Your confusion is based on an incorrect assumption that the cursor position is preserved on such transition from visual mode to normal. That's not true. The docs never say Vim should do this. And in fact, Vim normally moves the cursor into the topleft corner of the selection before executing a command. But not always, in particular, while in Visual-Line mode using only k and l to extend the selection, the cursor stays in place (the true conditions may be more complicated, of course).

However, the point is that such things are not documented and should be viewed as a kind of "undefined behaviour". You should not make any use of it, especially in linewise mode where the cursor column must be totally irrelevant.

  • Thank you, Matt. I admit I am not entirely clear on when mode transitions happen. If I'm in linewise-visual mode and press :, do I not then switch to command-line mode? – clearissimple Oct 16 '19 at 10:20
  • @clearissimple You do. Until you press enter or esc. Then you get into normal mode. There's no direct way from cmdline to visual though. See :h mode-switching. – Matt Oct 16 '19 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.