Skip to content

vim: Change logic in subword motion subword_start calculation#45341

Merged
dinocosta merged 8 commits intozed-industries:mainfrom
VVill-ga:vvill-ga/fix_subword_punctuation
Jan 13, 2026
Merged

vim: Change logic in subword motion subword_start calculation#45341
dinocosta merged 8 commits intozed-industries:mainfrom
VVill-ga:vvill-ga/fix_subword_punctuation

Conversation

@VVill-ga
Copy link
Contributor

@VVill-ga VVill-ga commented Dec 19, 2025

Closes #23344

Previous logic would consume a subword until it left a non-alphanumeric character (consuming any punctuation). With the new logic, the only punctuation we consume is _ for snake_case, and should immediately exit after leaving - consuming only trailing underscores. This new behavior resolves the inconsistencies pointed out in the issue above, and matches what I've experienced with the CamelCaseMotion vim extension.

Screencast.From.2025-12-18.23-40-15.webm
Screencast.From.2025-12-18.23-47-14.webm

Release Notes:

  • Fixed vim mode's subword motions to properly stop at punctuation and handle snake_case, camelCase, and dot.separated identifiers consistently, matching vim's CamelCaseMotion behavior

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Dec 19, 2025
Update `crates/vim/src/motion.rs` with two tests,
`test_next_subword_start` and `test_previous_subword_start`, in order to
verify that our implementation matches the behavior of vim's
CamelCaseMotion script – https://github.com/bkad/CamelCaseMotion .

At the moment these tests are failing and are meant to serve as a
guideline for us to fix the implementations so that the tests pass.
Copy link
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 @VVill-ga! 👋

Thanks for taking a stab at this. I think we need a bit more work to match CamelCaseMotion’s behavior. While reviewing your changes, I tested a range of scenarios and noticed that in some cases Zed doesn’t behave the same. I’ve added tests with the expected behavior; they’re currently failing so we can adjust the implementation to make them pass. Please feel free to run through these scenarios too and let me know if I’ve misunderstood anything.

If you’re available to keep iterating, or if you need help, let me know. Otherwise, I can take a pass at fixing 🙂

Lastly, I merged main into this branch. Recent migrations meant you couldn’t cargo run here if you’d already compiled a more recent version. Thanks!

@VVill-ga
Copy link
Contributor Author

VVill-ga commented Jan 9, 2026

Thank you @dinocosta!

When I made this, I was actually testing against the functionality in the vscode vim extension since I had it open, and it would actually stop at the period in foo.bar - I hadn't noticed that difference. Just pushed some changes to handle subwords separators equally in this way (., -, _) and stop at some semantic punctuation like CamelCaseMotion does (", ', [, ], {, }, (, ), <, >).

With this behavior change, I updated subword object handling and subword ends as well, which I think make sense to have. I was trying to keep the diff minimal in the initial commit as it didn't seem like the feature was intended to 100% mimic CamelCaseMotion. This'll feel more consistent I think, let me know if you want me to (or feel free to) add test on these operators or centralize some of this logic.

Add two new tests, `test_previous_subword_end` and
`test_next_subword_end`, to ensure that those motions are also being
tested against vim's CamelCaseMotion implemenentation.

Since the updated code was not yet passing those tests, the
implementation has also been updated to ensure that those tests now
pass.
- Update `in_subword` and `around_subword` in object.rs to use the
  shared `is_subword_start` and `is_subword_end` helpers from motion.rs
- Add comprehensive test for subword text objects covering `c i w`, `d i
  w`, `c a w`, and `d a w` with snake_case, camelCase, and dot.separated
  identifiers
@dinocosta
Copy link
Member

Hey @VVill-ga ! Thanks for the updates 🙌

I've pushed a few more commits on top of your changes:

  • Added tests for both next_subword_end and previous_subword_end to ensure that we behave the same as CamelCaseMotion for those motions too. Since the tests were not yet passing, I've updated the implementation.
  • Introduced some helper functions for is_subword_start and is_subword_end.
  • Updated vim::object::around_subword to also reflect these new changes and leverage the next helper functions.

Let me know if you have any other suggestions or feel like there's something here we shouldn't ship, otherwise I'll merge this 🚢

@VVill-ga
Copy link
Contributor Author

Great thank you @dinocosta, that all looks good to me!

@dinocosta dinocosta merged commit 5a8a7d8 into zed-industries:main Jan 13, 2026
23 of 24 checks passed
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.

Vim mode: delete subword deleting beyond the first punctuation

2 participants