emacs-evil / evil

The extensible vi layer for Emacs.
GNU General Public License v3.0
3.38k stars 281 forks source link

'at' and 'it' motions for working with tags doesn't behave similar to vim #1815

Open ankitshahit opened 1 year ago

ankitshahit commented 1 year ago

Issue type

Issue with core feature of vim, changing and deleting text between tags

Environment

Emacs version: 28.2 (Build 2 x86_64-w64-mingw32) of 2022-09-13 Operating System: Windows 10 Evil version: evil-git-477807f Evil installation type: ELPA Graphical/Terminal: graphical Tested in a make emacs session (see CONTRIBUTING.md): No

Reproduction steps

Expected behavior

When using command such as cit and dit.

Scenario 1: the cursor is at the start of line (using 0 shortcut) When there is no text between tags, and the cursor is at the start of line (using 0 shortcut). Evil mode deletes the parent tag. Though vim jumps the cursor between the tag (VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Oct 25 2020 11:44:06)

Assume **|** to be the cursor for demonstration purposes.

Originally cursor is the pipe - **|** <label for="edit"></label> Expected cursor is the pipe - <label for="edit">**|**</label> after cit

Scenario 2: the cursor is at the start of tag Evil mode deletes the parent tag. Though vim jumps the cursor between the tag (VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Oct 25 2020 11:44:06)

Assume pipe to be the cursor Originally cursor is the pipe - <**|** label for="edit"></label> Expected cursor is the pipe - <label for="edit">**|**</label> after cit

Actual behavior

While running for scenario 1

  1. When at start of the line using 0 shortcut, the entire tag and other child element are deleted.

While running for scenario 2

  1. If there is no text and the cursor is in tag, entire line gets deleted. <**|**label for="edit"></label>

  2. When the cursor is at start of the line and no text is provided, entire line gets deleted. (using 0 shortcut) **|** <label for="edit"></label>

  3. If there is text between tag and cursor is at the start of line (again using 0 shortcut) still the entire line gets deleted. **|** <label for="edit">text</label>

  4. When cursor is at the tag, and tag has some text. When cit is pressed, the line works as expected.

Further notes

tomdl89 commented 1 year ago

Thanks for the bug report @ankitshahit . I've fixed 2.1 (If there is no text and the cursor is in tag, entire line gets deleted) in master - please check if this works as expected. For the other points, I can replicate the fact that they behave differently to vim. I'm not in as much of a rush to fix these as I personally think their behaviour makes more sense, but I'm open to a PR and may get around to it myself at some point.

Tekki commented 1 year ago

When using command such as cit and dit.

The same difference is with ci" and di", with single and double quotes. Vim always looks first in the current line, even if we have a multiline text that is itself quoted.

tomdl89 commented 1 year ago

@Tekki it's not really comparable to " because they are not commonly nested. The usual practice in English prose is to nest alternating " and ' so you'd need two layers of testing for this to be an issue, which is very rare. In code, string delimiters are escaped when inside strings, so it's not an issue there. But yeah, I am aware of what Vim does, I'm just saying in this specific instance, I can see why the way Evil handles it may make more sense. Not that it 100% does, but that it may.

tomdl89 commented 1 year ago

Furthermore, if you take an example like this:

(
f|oo (bar)
)

with the cursor at |, you may expect ci( to delete what is (bar) but it doesn't, it deletes what's in it's parent, even on a different line. I think I'd go as far as saying Vim hasn't made it's mind up on a blanket rule on this sort of stuff. Another reason why I'm not in a rush to "fix" this.

edit: the correct analogy would be with the foo in this example replaced with whitespace. It seems that vim treats tags with only children tags (no direct content) differently. It doesn't change my point, but it's a technicality worth being aware of.

ankitshahit commented 1 year ago

Thanks for the bug report @ankitshahit . I've fixed 2.1 (If there is no text and the cursor is in tag, entire line gets deleted) in master - please check if this works as expected. For the other points, I can replicate the fact that they behave differently to vim. I'm not in as much of a rush to fix these as I personally think their behaviour makes more sense, but I'm open to a PR and may get around to it myself at some point.

Hey @tomdl89 Thanks a lot for quick fix! It works for 2.1, appreciate it. I would love to explore and see if I can fix it, will raise a PR if possible

Tekki commented 1 year ago

@Tekki it's not really comparable to " because they are not commonly nested.

I just wanted to show that the behavior of Vim is the same, not that it makes sense. Your example with ci( shows that it's not even consistent. If in HTML you're inside a node, it's rather illogical to jump into the next child node to execute the command.

tomdl89 commented 1 year ago

Sorry @Tekki I think I misunderstood you.