fix(ui): clamp cursor to last char after all NORMAL mode deletes#21973
fix(ui): clamp cursor to last char after all NORMAL mode deletes#21973jacob314 merged 2 commits intogoogle-gemini:mainfrom
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a cursor positioning bug in Vim's NORMAL mode where the cursor could end up past the last character of a line after a deletion. The changes introduce a clamping mechanism to correctly position the cursor and include updated and new test cases to validate this behavior, ensuring a more accurate emulation of Vim's cursor handling. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request correctly fixes an issue where the cursor could be positioned past the end of a line after deleting a character with x in Vim's NORMAL mode. The change introduces logic to clamp the cursor to the last valid character position. While the fix is correct for the vim_delete_char case, I've identified that the same underlying bug affects other delete/change commands like D and C. My review includes a suggestion to apply this fix more broadly to ensure consistent behavior.
74e6193 to
5e9a0d3
Compare
In NORMAL mode the cursor can never rest past the last character of a line. Several delete commands left the cursor one position past the new line end after shrinking the line: x (vim_delete_char) dw / dW (vim_delete_word_forward / vim_delete_big_word_forward) de / dE (vim_delete_word_end / vim_delete_big_word_end) D (vim_delete_to_end_of_line) df / dt (vim_delete_to_char_forward) Added a clampNormalCursor() helper in vim-buffer-actions.ts and applied it to every delete action that stays in NORMAL mode. Change actions (cw, C, cf, ...) are intentionally excluded since they immediately enter INSERT mode where the cursor is allowed past the last character. Flagged by @jacob314 in review of google-gemini#21932.
5e9a0d3 to
3665156
Compare
|
Great work on this! This correctly addresses the cursor out-of-bounds issue for I ran the test suite locally and noticed two small things that need to be addressed before we can merge: 1. Failing Tests
2. Missing clamping for You can fix this by wrapping the return state of // In packages/cli/src/ui/components/shared/vim-buffer-actions.ts (around line 1367)
- return { ...resultState, cursorCol: startCol, preferredCol: null };
+ return clampNormalCursor({ ...resultState, cursorCol: startCol, preferredCol: null });It would also be good to add a test case for Once the tests are updated and the backward delete clamping is added, this is good to go! |
|
Thanks for catching those! Fixed in the latest commit:
Good to go on your end? |

Follow-up to #21932, flagged by @jacob314 in review.
In NORMAL mode the cursor can't rest past the last character.
replaceRangeInternalleaves the cursor at the pre-delete column after any delete, which can be one past the new line end. Added aclampNormalCursor()helper that appliesmax(0, lineLen - 1)and hooked it up across all NORMAL-mode deletes that stay in NORMAL mode.Affected commands:
x,dw,dW,de,dE,D,df/dt(and their backward variants)Change commands (
cw,C,cf, etc.) are intentionally excluded — they immediately enter INSERT mode where off-the-end cursor is valid.dW,dE,dfcursor clamp behavior