Skip to content

Conversation

@vamsi10010
Copy link

@vamsi10010 vamsi10010 commented Oct 27, 2025

Closes #22349
Closes #14803

  • This PR introduces a syntax-aware navigation feature (using tree-sitter nodes) that enables fast cursor navigation within code structures. This PR adds two new components:
    • Adds two actions MoveToEndOfLargerSyntaxNode and MoveToStartOfLargerSyntaxNode. These actions can be bound to any keybinding if the user does not like the default smart tab settings.
    • Binds tab and shift-tab to perform the two actions respectively. In particular, tab will check if there is whitespace to the left of the cursor. If there is only whitespace, a regular tab is inserted, otherwise, the cursor will move to the end of its parent node. shift-tab will always move the cursor to the start of its parent node. This can be activated using a new setting called Smart Tab.
  • If smart tab is activated, the navigation will respect snippet tab stops, completions, and edit predictions. Tab and shift-tab also act normally when text is selected. Smart tab also does not activate in normal mode for vim (it does activate in insert mode). Additional settings are available to supersede accepting completions and edit predictions in the smart tab settings page.
  • This PR was heavily inspired by its namesake feature in Helix (Smart tab (aka tabout) helix-editor/helix#4443). It also provides the behavior users might expect when using albert.TabOut in VSCode (and more). There was also an attempt to do this in Tab-out feature #23412 which was rejected in favor of a more sophisticated approach. I took the feedback there and opted to use the builtin tree-sitter features for navigation.

Questions:

  1. I currently hooked the smart tab functionality into the existing editor::Tab and editor::Backtab actions. Is this approach preferred to making separate actions for binding to tab and shift-tab keys?
  2. Helix provides a setting where shift-tab can be used as a backup tab key. I believe they did so because not all terminals support shift-tab. However, since zed does not have that issue, I have mapped shift-tab to always move to the start of the parent node (if the setting is enabled). Do we want a setting where shift-tab can be configured as a tab backup?
  3. I'm not sure what the best place would be to document this feature in zed docs.
  4. Should this feature be enabled by default? I have it set to disabled.
  5. While I have settings to supersede completions and edit predictions, I would love some feedback on their design so that I don't introduce any code debt there.

Here is smart tab in action:

zed-smart-tab.mp4

This is my first contribution to zed, so I would really appreciate any feedback on this! I believe this feature could be very helpful for users coming from other IDEs like VSCode or JetBrains.

Release Notes:

  • Added new actions to move to start/end of tree-sitter nodes
  • Added settings to bind tab and shift-tab to those actions

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Oct 27, 2025
@zed-industries-bot
Copy link

zed-industries-bot commented Oct 27, 2025

Warnings
⚠️

This PR is missing release notes.

Please add a "Release Notes" section that describes the change:

Release Notes:

- Added/Fixed/Improved ...

If your change is not user-facing, you can use "N/A" for the entry:

Release Notes:

- N/A

Generated by 🚫 dangerJS against 38f335a

@vamsi10010 vamsi10010 marked this pull request as draft October 28, 2025 21:33
@vamsi10010 vamsi10010 marked this pull request as ready for review October 29, 2025 02:35
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.

Implement something like the VSCode TabOut extension Smart tab support

2 participants