2

One of the main usage I have for selection is replacement.

Suppose I have:

Jane: Hello foo1 & bar1
John: Hello
Jane: Hello foo2 and bar2
John: Hello
Jane: Hello foo3 or bar3
John: Hello

That I would like to transform into:

Jane: Hello foo1 & bar1
John: Hello
Jane: Hello foo1 & bar1
John: Hello
Jane: Hello foo1 & bar1
John: Hello

I do:

  • /foo1Enter
  • y$
  • /foo2Enter
  • vg_
  • P
  • /foo3Enter
  • vg_
  • P

But if I do: I do:

  • /foo1Enter
  • y$
  • /foo2Enter
  • v$
  • P
  • /foo3Enter
  • v$
  • P

I get:

Jane: Hello foo1 & bar1
John: Hello
Jane: Hello foo1 & bar1John: Hello
Jane: Hello foo1 & bar1John: Hello

y$ yank from the cursor till the end of the line but not including the new line.

v$ select from the cursor till the end of the line including the new line.

Does someone knows if there is a good reason for that?

Is the following mapping common?

xnoremap <expr> $ mode(1) != "\<C-v>" ? '$h' : '$'

What are the down sides of it?

2 Answers 2

2

The behaviour of the v$ command can be influenced by the 'selection' option. For this use case, you may want to set it to old before performing your operations to make sure to not include the newline.

I generally tend to keep more obscure options such as this at their default values, because I have to jump on different customer environments and more then the current inconsistent behaviour, I would it find even more inconsistent if Vim behaves differently from my customized environment. And I have become accustomed to the current behaviour and don't even notice such inconsistencies anymore 🤷‍♂️

2
  • Thanks @ChristianBranbandt. Do you know why the behavior has changed? What was the reason? Jul 14 at 7:18
  • 1
    The option was introduced with release of Vim 5.2 which is 25 years ago(!). I have no idea why (and it predates my involvement in Vim by several years), but I suppose there was some discussion around it Jul 14 at 7:32
3

I generally go by the following rule of thumb: operator-pending mode motions tend to be "exclusive" while visual mode motions tend to be "inclusive". As a result, I tend to use visual mode whenever I want to include the boundaries of the motion in the operation, like your v$y or the equally common dv0.

FWIW, Yanking the rest of the line without the EOL seems to be a more common use case.

As for your mapping, I often see similar mappings for ^ and 0 in people's vimrcs so that kind of idea may in fact be popular. g_ and $ have different semantics so I don't think lumping them together under a vague "end of line" concept is a particularly good idea. Moreover, the difference between g_ and $ is not in how they treat the EOL but in how they treat trailing whitespace, which is one more reason for not using such a mapping if one is concerned by EOL issues.

--- EDIT ---

My rule of thumb is just that, a useful (for me) simplification of what is really going on. Some operator+motion combos include this or that while some others exclude this or that. It's tiring to always think about all those minutiae so I simplify the problem as much as I can.

The main use I have for it is backward operations, like d0 or yB, where the character under the cursor is generally excluded for reasons that escape me:

lorem ipsum dolor sit amet
        ^                     " cursor starts here
      ^^                      " yb yanks 'ip'
        ^^^                   " ye yanks 'sum'

Here, I will use yvb to yank ips because it forces Vim to include the character under the cursor. It makes more sense to me that way. I find that lack of symmetry disturbing:

  • backward operation excludes current character
  • forward operation includes current character
  • move cursor right to include current character in backward operation
  • move cursor right to exclude current character in forward operation

The current system provides:

  • a way to operate backward that excludes current character
  • a way to operate forward that includes current character
  • visual mode hacks for including current character
  • obligations for the user to do unintuitive cursor movements

IMO, a better system would provide full symmetry:

  • a way to operate backward that includes current character, b
  • a way to operate backward that excludes current character, <prefix>b
  • a way to operate forward that includes current character, e
  • a way to operate forward that excludes current character, <prefix>e

with the simple one-letter command always defaulting to "inclusive". Or always defaulting to "exclusive", I don't really care as long as it is consistent. Using v as prefix (:help forced-motion) kind of gives us that, hence the rule of thumb, but not exactly.

I have resisted making custom operators for a long time, though, because I don't want to depend on non-standard stuff but that is certainly one approach to the problem. Here is how an inclusive b would look, for example:

onoremap b vb

But it would only "fix" one part of the problem.

In your example, visually selecting what you want to paste over makes the most sense, of course, and you have basically two ways to do it.

One is to select to $, which includes the EOL, and then move the cursor back to exclude the EOL:

v$h

The other is to select to the last printable character:

vg_

Both ways are equivalent, here, because there is no trailing space in your example, but g_ is not "$ without the EOL", it is "$ without trailing space", which happens to leave the EOL out. That is why I think lumping $ and g_ together is not such a good idea.

2
  • thanks for your expert answer, I always like to read you :-). Could you tell me more about your rule of thumb? I'll be glad to have examples and understand better the reasons behind the rule? Does the rule apply also to new line inclusiveness? Jul 14 at 4:27
  • Thanks for the edit I understand much better what you mean. It make sense. With the input of @ChristianBrabandt I understand that it is not a corner case but something that has a history and that has been thought off. Jul 14 at 9:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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