Skip to content

editor: Go to previous and next symbol actions#50777

Merged
SomeoneToIgnore merged 4 commits intozed-industries:mainfrom
nishanthkarthik:prev-next-symbol
Mar 16, 2026
Merged

editor: Go to previous and next symbol actions#50777
SomeoneToIgnore merged 4 commits intozed-industries:mainfrom
nishanthkarthik:prev-next-symbol

Conversation

@nishanthkarthik
Copy link
Copy Markdown
Contributor

Closes discussion #34890

This is similar to the vim prev/next method/section motion, but more flexible because this follows the items in editor's outline (Tree sitter or LSP provided).

Before you mark this PR as ready for review, make sure that you have:

  • Added a solid test coverage and/or screenshots from doing manual testing
  • Done a self-review taking into account security and performance aspects
  • Aligned any UI changes with the UI checklist

Release Notes:

  • Added actions editor::GoToPreviousSymbol and editor::GoToNextSymbol actions to go to the previous and next outline symbol. This is either the tree sitter outline, or the LSP provided outline depending on the configuration.

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Mar 5, 2026
@zed-community-bot zed-community-bot bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label Mar 5, 2026
Copy link
Copy Markdown
Contributor

@SomeoneToIgnore SomeoneToIgnore left a comment

Choose a reason for hiding this comment

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

As commented by @\RemcoSmitsDev too, new code definitely benefits from less operations invoked: besides snapshots, there's something suspicious in how we want to list all outlines and sort them, that might take a while for large files like editor.rs itself.

Another concern is that we don't use symbol that much and seem to have somewhat similar methods already?

Image

I'm particularly interested in SelectNextSyntaxNode and its Prev counterpart — how far it is from what's needed?
It seems that we can either rework it, or use a SyntaxNode-based name for the new action at least?
Ideally, we could try to reuse syntax_next_sibling and related methods to simplify the calculations.


Naming and approaches aside, the current implementation seems to loose track of its neighbours when placed on a blank line?

For example, here:

class A:
    def f(self):
        pass

    def g(self):
        pass
<CARET>

class B:
    def f(self):
        pass

    def g(self):
        pass


class C:
    def f(self):
        pass

    def g(self):
        pass

I cannot move anywhere using new actions, which looks like a bug worthy of a fix and a test.

Should we also allow wrapping over the editor's edge when we reach the first/last symbol?

@nishanthkarthik
Copy link
Copy Markdown
Contributor Author

nishanthkarthik commented Mar 13, 2026

Thanks for the feedback!

As commented by @\RemcoSmitsDev too, new code definitely benefits from less operations invoked: besides snapshots, there's something suspicious in how we want to list all outlines and sort them, that might take a while for large files like editor.rs itself.

I profiled large files (about thousand outline items) in my first version. The performance was not quite great, in the order of few hundred milliseconds. There are two ideas I want to implement in the future -

  • We already have primitives to navigate to previous and next nodes. Outline scm should provide us the same structure from buffer_outline_items. We should be able to do it in constant time instead of linear time. I'm thinking something built on top of BufferSnapshot::next_outline_item.
  • For really complex and large files, LSPs are likely better at incremental updates. Currently the outline panel refreshes itself (and fetches all outline items) on editor updates. I have not tested the performance of LSP provided outlines for large files. It would be nice to have an incrementally updated view of LSP provided symbols.

Another concern is that we don't use symbol that much and seem to have somewhat similar methods already?

I did not want to use syntax node because that's tree-sitter specific. It would be nicer to not tie this implementation to tree-sitter or LSP. LSPs have their own notion of syntax nodes, but syntax node actions specifically refer to tree sitter ones in Zed. I picked the name Symbols because the outline panel also uses the term "Search buffer symbols..." to filter outline items.

Naming and approaches aside, the current implementation seems to loose track of its neighbours when placed on a blank line?

Good catch! I reworked the implementation so it should be a lot simpler than my first version. Added one more test for this. I came across a similar dead zone bug in the outline panel. Once the selection is over ## bar, down arrow does not work anymore to go to the node below. I should file a bug...

image

Should we also allow wrapping over the editor's edge when we reach the first/last symbol?

One way I use this action is by pressing alt+down for a few seconds and I'm at the last symbol. Wrapping and jumping to the top might be unexpected. Not sure if this is worth a config option?

Copy link
Copy Markdown
Contributor

@SomeoneToIgnore SomeoneToIgnore 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, looks like the snapshot situation had become better.

Regarding the wrap around and large file implications, let's merge and see how things work for now.
Overall, both are good to improve: for the wrap around, we could add a parameter into actions.

@SomeoneToIgnore SomeoneToIgnore merged commit 9b5d170 into zed-industries:main Mar 16, 2026
28 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 first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants