# vim: Fix selection motions when trailing newline is selected \(\#61253\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/d735d22c258a9d3573eeda317660c5537e6884c4)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: d735d22c258a9d3573eeda317660c5537e6884c4

Requested commit: d735d22c258a9d3573eeda317660c5537e6884c4

Commit: d735d22c258a9d3573eeda317660c5537e6884c4

Tree: 621cf9237dd8d04d181cc74af2991b5597a6727d

Author: Xin Zhao

Committer: GitHub

## Message

```
vim: Fix selection motions when trailing newline is selected (#61253)

# Objective

Closes #41743

When selecting text on the last line, excluding the trailing newline,
Vim and Helix modes behave differently from native Vim and Helix when
the file has a trailing newline:
1. We cannot use `l` (move right) to include the final `\n` in the
selection, while native Vim and Helix allow this.
2. By default, the rendered cursor should appear on the selected
character. When that character is the final `\n`, however, Zed renders
the cursor on the synthetic empty line after it rather than at the end
of the preceding line. This differs from native Vim and Helix, as well
as from Zed's behavior for newlines elsewhere in the file.
3. When the final `\n` is selected, it affects subsequent selection
motions, as reported in #41743.

The cause is several special-case guards for trailing newlines in Visual
and Select modes. These guards exist in the cursor rendering logic:

https://github.com/zed-industries/zed/blob/c9e8e611dbc279afa0914d28c4d37ad07f38c03b/crates/editor/src/element.rs#L201-L213

They also exist in the Visual motion logic for Vim mode and the Select
motion logic for Helix mode (the Helix implementation was adopted
directly from Vim in #43234):

https://github.com/zed-industries/zed/blob/c9e8e611dbc279afa0914d28c4d37ad07f38c03b/crates/vim/src/visual.rs#L254-L259

Finally, they exist in the selection extension logic for Vim and Helix
(the Helix logic was also adopted from Vim):

https://github.com/zed-industries/zed/blob/c9e8e611dbc279afa0914d28c4d37ad07f38c03b/crates/vim/src/visual.rs#L273-L284

These guards cause trailing-newline selections to behave inconsistently
with selections containing newlines elsewhere in the file.

## Solution

Remove all the guards mentioned above, including those in cursor
rendering, Visual and Select motions, and selection extension. And due
to the cursor rendering logic is also changed, an exsisting test is
updated.

After removing these guards, I could not reproduce the unexpected
behavior described in the existing comments:

https://github.com/zed-industries/zed/blob/c9e8e611dbc279afa0914d28c4d37ad07f38c03b/crates/vim/src/visual.rs#L247-L253

The only remaining difference is that, when the cursor is on the last
line in Visual mode, pressing `j` moves it to the final `\n` rather than
to the synthetic empty line after it. In comparison, native Vim and
Helix do nothing in this case.

## Testing

- Built and tested locally.
- Added new GPUI tests.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable


Release Notes:

- Improved Vim Visual and Helix Select modes when selections include a
trailing newline.
```

## Parents

- [8e807731b77b6ba52c7442a4818a147e6b19d1f6](https://git.cafe/gitcafe/zed/commit/8e807731b77b6ba52c7442a4818a147e6b19d1f6?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/d735d22c258a9d3573eeda317660c5537e6884c4?format=markdown)
