Skip to content

helix: Always offset cursor on selection#46311

Merged
SomeoneToIgnore merged 1 commit intozed-industries:mainfrom
jrobsonchase:helix-cursor-offset-on-selection
Mar 12, 2026
Merged

helix: Always offset cursor on selection#46311
SomeoneToIgnore merged 1 commit intozed-industries:mainfrom
jrobsonchase:helix-cursor-offset-on-selection

Conversation

@jrobsonchase
Copy link
Copy Markdown
Contributor

@jrobsonchase jrobsonchase commented Jan 8, 2026

#42837 added the cursor_offset_on_selection field, which displays the cursor after the end of the selection unless a vim visual mode is enabled, in which case it gets displayed at the end of the selection.

However, the real helix is effectively always in select mode, and will always display the cursor at the end of the selection, whether that selection is made via its visual mode, a movement key, or with the mouse.

This makes it so that the helix mode setting is taken into account regardless of the visual-ness of the vim mode in the sync_vim_settings method.

I also considered simply moving Mode::HelixNormal up to the true arm of the match in the is_visual method since helix is kinda always in visual mode, but I figured that could have some unintended consequences and chose to err on the side of caution.

Possibly related to #20121

Closes #46998

Release Notes:

  • Fixed the cursor offset in non-visual helix selections

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jan 8, 2026
@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from 0678444 to 34e770a Compare January 10, 2026 01:17
@nilskch
Copy link
Copy Markdown
Contributor

nilskch commented Jan 23, 2026

Hey, thanks for working on this!

The code was slightly refactored in #44284 yesterday, so you might want to change it to something like this:

diff --git a/crates/vim/src/state.rs b/crates/vim/src/state.rs
index f4c3af7131..86de2b0896 100644
--- a/crates/vim/src/state.rs
+++ b/crates/vim/src/state.rs
@@ -73,6 +73,10 @@ impl Mode {
             Self::Normal | Self::Insert | Self::Replace | Self::HelixNormal => false,
         }
     }
+
+    pub fn is_helix(&self) -> bool {
+        matches!(self, Self::HelixNormal | Self::HelixSelect)
+    }
 }
 
 #[derive(Clone, Debug, PartialEq)]
diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs
index 860af285c4..2d8380aca5 100644
--- a/crates/vim/src/vim.rs
+++ b/crates/vim/src/vim.rs
@@ -2041,7 +2041,7 @@ impl Vim {
             collapse_matches: !HelixModeSetting::get_global(cx).0,
             input_enabled: self.editor_input_enabled(),
             autoindent: self.should_autoindent(),
-            cursor_offset_on_selection: self.mode.is_visual(),
+            cursor_offset_on_selection: self.mode.is_visual() || self.mode.is_helix(),
             line_mode: matches!(self.mode, Mode::VisualLine),
             hide_edit_predictions: !matches!(self.mode, Mode::Insert | Mode::Replace),
         }

@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from 34e770a to d3edb88 Compare January 26, 2026 15:53
jrobsonchase added a commit to jrobsonchase/zed that referenced this pull request Jan 26, 2026
zed-industries#46311 added the
`cursor_offset_on_selection` field, which displays the cursor *after* the
end of the selection unless a vim visual mode is enabled, in which case
it gets displayed *at* the end of the selection.

However, the real helix is effectively *always* in select mode, and
will always display the cursor at the end of the selection, whether that
selection is made via its visual mode, a movement key, or with the mouse.

This makes it so that the helix mode setting is taken into account
regardless of the visual-ness of the vim mode in the `sync_vim_settings`
method.

Co-authored-by: Nils Koch <mail@nilskch.dev>
@jrobsonchase
Copy link
Copy Markdown
Contributor Author

Cool, thanks for the heads-up and suggested resolution! I applied it and noted you as a co-author @nilskch

@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from d3edb88 to 7ad6b33 Compare January 30, 2026 14:17
jrobsonchase added a commit to jrobsonchase/zed that referenced this pull request Feb 18, 2026
zed-industries#46311 added the
`cursor_offset_on_selection` field, which displays the cursor *after* the
end of the selection unless a vim visual mode is enabled, in which case
it gets displayed *at* the end of the selection.

However, the real helix is effectively *always* in select mode, and
will always display the cursor at the end of the selection, whether that
selection is made via its visual mode, a movement key, or with the mouse.

This makes it so that the helix mode setting is taken into account
regardless of the visual-ness of the vim mode in the `sync_vim_settings`
method.

Co-authored-by: Nils Koch <mail@nilskch.dev>
@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from 7ad6b33 to 45a3039 Compare February 18, 2026 15:28
@jrobsonchase jrobsonchase requested a review from a team as a code owner February 18, 2026 15:28
@kubkon kubkon enabled auto-merge (squash) March 3, 2026 10:34
@kubkon kubkon disabled auto-merge March 3, 2026 10:35
@kubkon
Copy link
Copy Markdown
Member

kubkon commented Mar 3, 2026

@jrobsonchase would you mind rebasing/merging main please?

@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from 45a3039 to c757bd4 Compare March 3, 2026 15:38
jrobsonchase added a commit to jrobsonchase/zed that referenced this pull request Mar 3, 2026
zed-industries#46311 added the
`cursor_offset_on_selection` field, which displays the cursor *after* the
end of the selection unless a vim visual mode is enabled, in which case
it gets displayed *at* the end of the selection.

However, the real helix is effectively *always* in select mode, and
will always display the cursor at the end of the selection, whether that
selection is made via its visual mode, a movement key, or with the mouse.

This makes it so that the helix mode setting is taken into account
regardless of the visual-ness of the vim mode in the `sync_vim_settings`
method.

Co-authored-by: Nils Koch <mail@nilskch.dev>
zed-industries#46311 added the
`cursor_offset_on_selection` field, which displays the cursor *after* the
end of the selection unless a vim visual mode is enabled, in which case
it gets displayed *at* the end of the selection.

However, the real helix is effectively *always* in select mode, and
will always display the cursor at the end of the selection, whether that
selection is made via its visual mode, a movement key, or with the mouse.

This makes it so that the helix mode setting is taken into account
regardless of the visual-ness of the vim mode in the `sync_vim_settings`
method.

Co-authored-by: Nils Koch <mail@nilskch.dev>
@jrobsonchase jrobsonchase force-pushed the helix-cursor-offset-on-selection branch from c757bd4 to e5833ee Compare March 6, 2026 17:08
@NewtonChutney
Copy link
Copy Markdown
Contributor

@kubkon CI needs approval here!

@SomeoneToIgnore SomeoneToIgnore enabled auto-merge (squash) March 12, 2026 08:57
@SomeoneToIgnore SomeoneToIgnore merged commit 81da953 into zed-industries:main Mar 12, 2026
28 checks passed
tommyming pushed a commit to tommyming/zed that referenced this pull request Mar 13, 2026
zed-industries#42837 added the
`cursor_offset_on_selection` field, which displays the cursor *after*
the end of the selection unless a vim visual mode is enabled, in which
case it gets displayed *at* the end of the selection.

However, the real helix is effectively *always* in select mode, and will
always display the cursor at the end of the selection, whether that
selection is made via its visual mode, a movement key, or with the
mouse.

This makes it so that the helix mode setting is taken into account
regardless of the visual-ness of the vim mode in the `sync_vim_settings`
method.

I also considered simply moving `Mode::HelixNormal` up to the `true` arm
of the match in the `is_visual` method since helix is kinda *always* in
visual mode, but I figured that could have some unintended consequences
and chose to err on the side of caution.

Possibly related to zed-industries#20121

Closes zed-industries#46998

Release Notes:

- Fixed the cursor offset in non-visual helix selections

Co-authored-by: Nils Koch <mail@nilskch.dev>
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: cursor is off-by-one when something is selected outside of visual mode

6 participants