Skip to content

helix: Fix insert line above/below with selection#46492

Merged
dinocosta merged 7 commits intozed-industries:mainfrom
jrobsonchase:fix-helix-insert-line
Mar 26, 2026
Merged

helix: Fix insert line above/below with selection#46492
dinocosta merged 7 commits intozed-industries:mainfrom
jrobsonchase:fix-helix-insert-line

Conversation

@jrobsonchase
Copy link
Copy Markdown
Contributor

@jrobsonchase jrobsonchase commented Jan 10, 2026

In addition to the visual offset of the cursor as addressed in the #46311, this also fixes its behavior. Even though the cursor displays at the end of the line per #46311, it's treated as at the beginning of the next line since selections are end-exclusive. This caused the vim: insert line above/below commands to behave strangely, either leaving the cursor at the end of the first line of the selection after inserting a line above, or inserting a line below the next line.

The fix for each case is slightly different. The "above" case switches from move_cursors_with to move_with for tighter control over which part of the selection the cursor gets collapsed to. In move_cursors_with, it's always the head/end, but when inserting a line above the selection, we actually want to use the tail/start.

The "below" case checks for a non-empty selection ending at column zero, which is semantically a "to the end of the row" selection. In this situation, the "previous row" is actually the row before the selected row, not the row of the end of the selection.

Closes #43210

Release Notes:

  • helix: Fixed insert line above/below behavior when using selections

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jan 10, 2026
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch from f28fe7e to 53c7a94 Compare January 10, 2026 01:17
@jrobsonchase
Copy link
Copy Markdown
Contributor Author

jrobsonchase commented Jan 13, 2026

Had a thought on this. Maybe cursor_offset_on_selection should actually be a property of the selection, not the editor as a whole. It might even make sense to treat it like Range and have inclusive/exclusive variants (or just a boolean flag). Either approach would reduce the plumbing I had to do to make this change happen, and would also prevent the Editor from having to track the vim/helix select mode, whether implicitly or explicitly.

Still mulling it over, but I might attempt one of these approaches and see where it gets me.

@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Ok, got most of the way through refactoring the cursor offset boolean to live on Selection before deciding that it was way more trouble than it was worth, and didn't even solve the real problem with InsertLineAbove, which was that it was considering the selection head for the new cursor position rather than the tail as it should.

So I got to rip out the plumbing and duplicate logic that was bugging me, and the fix is now much simpler.

@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch 3 times, most recently from 5c0367f to 7a35f31 Compare January 16, 2026 15:46
@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Since this no longer needs the cursor offset boolean, I've rebased it to not depend on the PR that fixes the visible cursor offset.

@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Ugh, still a bug with cursor placement post-insert-after. I think I need to write some actual tests for this.

@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch 3 times, most recently from 73c935a to 137cb0f Compare January 16, 2026 18:35
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch 2 times, most recently from aa86d99 to fadf351 Compare January 30, 2026 14:17
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch from fadf351 to f67bafe Compare February 2, 2026 19:10
@jrobsonchase jrobsonchase requested a review from a team as a code owner February 18, 2026 15:22
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch from 6cdf5ca to 1ad1804 Compare March 6, 2026 17:08
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch from 1ad1804 to aed38e1 Compare March 19, 2026 15:25
@jrobsonchase
Copy link
Copy Markdown
Contributor Author

@kubkon Can I get a review on this?

Copy link
Copy Markdown
Member

@dinocosta dinocosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jrobsonchase 👋

Thank you for picking this one up and trying to improve it!

I've tested your changes locally and it fixes when x is used to select lines, but it doesn't seem to tackle the scenario where HelixSelect mode is used, as in, making a selection using v. I believe that's already not working today, so it's not like it breaks anything, just though I should point that out as it's mentioned in the original issue 🙂

@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Oh, huh, good catch! Seems like insert line above/below simply does nothing when in helix select mode currently, both in this branch and on stable. I'll see if I can get that fixed!

@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Alright, added a test and fixed it, but not convinced that I haven't broken something else in the process that just isn't tested. Going to run it myself for a day or two to see if I notice anything amiss.

@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Been running this for a few days and haven't noticed anything amiss! Should be good to go.

jrobsonchase and others added 5 commits March 25, 2026 11:58
Setting the selection with `set_state` instead of using
`simulate_keystrokes` appears to not have been correctly setting the
selection in a state to trigger the path where the previous row had to
be selected (`!selection.is_empty() && selection.end.column == 0`), so
this commit refactors the test to ensure that, if we change the code in
`vim::normal::Vim::insert_line_below` from:

```
.map(|selection| {
    if !selection.is_empty() && selection.end.column == 0 {
        selection.end.row.saturating_sub(1)
    } else {
        selection.end.row
    }
})
```

back to:

```
.map(|selection| selection.end.row)
```

The test actually fails.
@jrobsonchase jrobsonchase force-pushed the fix-helix-insert-line branch from bd68978 to 78d2cea Compare March 25, 2026 15:58
@github-actions github-actions bot added Size M and removed Size S labels Mar 26, 2026
Copy link
Copy Markdown
Member

@dinocosta dinocosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for tackling the provided feedback @jrobsonchase ! 🙌

I'm going to merge this as it fixes the reported issue but, if you wish, you can also open a different Pull Request tackling the scenario where there's multiple cursors in the same line, where Helix actually inserts the same number of lines as cursors.

For example, given the following state:

ˇline ˇone

Pressing o would insert two lines below the one where the cursors are:

line one
ˇ
ˇ

Which Zed doesn't yet support 🙂

@dinocosta dinocosta enabled auto-merge (squash) March 26, 2026 16:20
@dinocosta dinocosta merged commit be6cd3e into zed-industries:main Mar 26, 2026
32 checks passed
@jrobsonchase jrobsonchase deleted the fix-helix-insert-line branch April 9, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Helix Mode: incorrect new line above/below behavior

4 participants