martanne / vis

A vi-like editor based on Plan 9's structural regular expressions
Other
4.19k stars 259 forks source link

y% when positioned over right-hand bracket omits the right-hand bracket #1072

Open donaldcallen opened 1 year ago

donaldcallen commented 1 year ago

If the cursor is positioned on the right-hand bracket of

{foobar}

and you execute 'y%', '%' and then 'p', you will get

{foobar}{foobar

This is not consistent with vim.

If you start with the cursor positioned on the left-hand bracket and do the same, you will get

{foobar}{foobar}

Similarly, if you start with the cursor on the right-hand bracket and execute 'v', '%', 'y', '%', 'p', you will get

{foobar}{foobar}
ninewise commented 1 year ago

This may not be consistent with vim, but it is expected behaviour. The current column is never included when yanking or deleting with a backwards movement (think y0 and v0). Use ya{ to yank the brackets and their contents.

donaldcallen commented 1 year ago

Yes, when positioned on the right bracket in my example, y0 will yank "{foobar". But v0 will select the current column back to the first. If you then yank and then paste, you will get "{foobar}". So your suggestion for understanding this is only partially correct.

The above behavior of y0 and v0 is consistent with vim. But the backward bracket movement is not. And because it isn't documented, I don't have a clear mental model of how movement results in selection in vis. I would argue that this issue, how movement produces selection, is one of the fundamental properties of any vi-like editor that is trying to improve upon the original and needs to be clearly documented.

ninewise commented 1 year ago

I was unclear: I should have written y0 versus v0. It makes no sense (in vim) that behaviour between d% and d0 differs if the left bracket is on column zero. They are the same action on a movement to column zero.

I think the model is fairly straightforward. Consider the current cursor as a bar on the left of the current column. Any action on a movement will be applied on any character this bar moves through to reach the destination. Selections are a bit different: they always include the archored character no matter in which direction you extend. Perhaps this should be clarified in the documentation though.

donaldcallen commented 1 year ago

Good explanation.

But ... if we accept your assertion that the cursor should be thought of as a bar to the left of the character it is over, then "Any action on a movement will be applied on any character this bar moves through to reach the destination." still isn't quite right.

For example, if you have the line 'abcdef' and the cursor is over the 'a', then the command fd will leave the cursor over the 'd'. Your bar started to the left of the 'a' and traversed -- passed over -- the a, b, and c. But if, with the cursor over the 'a', you do yfd and then a p command somewhere, 'abcd' will be "put". The bar never passed over the 'd'.

Similarly, starting again at the 'a', td will leave the cursor over the 'c'. ytd followed by a p somewhere will put "abc".

So I think your definition needs to be modified to say something like "Any action on a movement will be applied to any character this bar moves through to reach the destination, plus the destination character".

Another way to handle this might be to think of the cursor as over the character it is .... over. Then the characters affected by an action-motion are the half-closed interval (source, destination]. Whereas the characters affected by visual-action are the closed interval [source, destination].

I think this is a useful discussion and one way or another, something should be extracted from what we've been talking about and added to the documentation (man page). I'm happy to submit a pull request once we're done talking about this and at least think we know what we're doing :-)

donaldcallen commented 1 year ago

I didn't get this quite right this time. When I said "Another way to handle this might be to think of the cursor as over the character it is .... over. Then the characters affected by an action-motion are the half-closed interval (source, destination]. Whereas the characters affected by visual-action are the closed interval [source, destination].", I was referring to backward action-motion and it needs another sentence for forward action-motion, which is a closed interval.

If you think of this as the cursor over the current character, I question why backward action-motion is different from forward and also different from visual backward. And forgetting for a moment about these descriptions, it does not make sense to me that action-forward-bracket-match behaves differently than the backward case. I don't think the editor should be designed so the pseudo mathematical descriptions are consistent. What needs to be consistent is the behavior the user sees and I don't think that's the case with bracket matching combined with action differing forward and backward and backward matching differing from using visual and motion to select.