feat: add breadcrumb navigation bar#15573
feat: add breadcrumb navigation bar#15573RoloEdits wants to merge 4 commits intohelix-editor:masterfrom
Conversation
802c0ab to
3c1fff2
Compare
|
Im actually not the biggest fan of the text coloring as, for example, impl blocks get returned with the It looks better than no colors, but pretty much every breadcrumb implementation I have seen has normal text colors, but has a colored icon. This comes across much better, but have to wait till #12369 is ready. |
37d985c to
ca93344
Compare
|
I'm not actually sure about the theme scopes here. Once I get some feedback I will add to the documentation. |
|
Yeah, looks much better with the themed icons (at least to me): helix_breadcrumbs_with_icons.mp4 |
|
I'm not sure why the tests are so slow. The tests are run with |
|
@dpc I thought this would come up as well, but wasnt sure how to handle truncation.
What would the ideal form of that As for the configuration, how does this look: [editor.breadcrumb]
enabled = true
# full: helix-term > src > commands > typed.rs > TypeableCommand > name
# file: typed.rs > TypeableCommand > name
# none: TypeableCommand > name
path = "full|file|none" |
I supposed this would be enough to control the path. As for the treesitter items maybe caping at certain length and replacing with |
|
How did you get icons? |
|
@lemonlambda From #12369, another PR I am working on. I am using a custom branch that has other PRs and misc changes that I daily drive. |
|
Implemented the changed configuration, but holding off on the truncation changes. Want to see if anyone else has input. |
File system operations are blocking IO, and I don't see |
|
Created a new type, Doing so introduces some additional allocations, one per symbol, but we get a 2.43x memory reduction. I think this is very worth the trade off. The smaller type also should cache better, with the tree walking only missing a cache hit when it begins to walk the next symbol, but which after it starts to walk, more types should fit it cache at once. |
485d749 to
6bbf9f5
Compare
b961286 to
f5304e7
Compare
|
Something I will need help with is figuring out which event I need to change so that when you use goto definition, for example, and a new document is opened at that definition, the breadcrumb is not updated until the cursor is moved at least once. You can see this using the global search as well, when it opens a new document. I would have thought that as this is a new document opening, this would be where you would update the breadcrumb, but it doesn't seem to be so. |
|
Been testing it on my fork - brilliant stuff. I've been wanting something like this for a long time! |
f30307f to
49a5c18
Compare
|
I did something similar to Zed but put the breadcrumbs path in the statusbar with my unmerged statusbar PR. For the syntax highlighting I just "reimplemented" some of the highlight query objects and matched them to the context using binary search but I'm sure there's a better way to make it more integrated using the actual highlight queries/tag queries. https://codeberg.org/gwid/context.hx is the repo. I should get around to remaking this with steel components as I'm unsure as to whether or not the statusbar PR is going to be merged. Edit: I see now that here the context is implemented with LSP so the method for highlighting is likely different as I'm unaware on how exactly the LSP protocol here works. We might be able to do some highlight query matching on top of the LSP protocol maybe(?) but not sure that would be implemented |
|
Is there a fallback to use the treesitter symbols if the LSP doesn't support document symbols or if an LSP isn't available? I wasn't able to find one when looking at the changes |
|
Yeah, this is just LSP. In a future PR we can probably support TS. Like how the symbol picker supports both. |
2b1c8dc to
42fda4c
Compare
|
This is what I dreamed of. 🥹 . I love it. |
|
My only feedback so far would be to make the breadcrumbs per-buffer instead of per-editor. It's current pretty disorienting to work with 2+ splits because you don't have the ability to glance at which function the unfocused splits are on. I've implemented this on my fork: iniw@7e37e77, feel free to use it as inspiration if you go on this direction. |









This PR implements a breadcrumb navigation bar at the top of the editor.
Breadcrumbs are common in other editors:
The main use for them is to help contextualize the current cursor scope, which can be hidden from all other context clues. For me personally, this alone can replace the statusline path information completely as well.
The commits should hopefully be re-viewable in order. I started by setting up the machinery in the event system to get the symbols for a document. I did need to add a new capability to tell LSPs that we support trees as a response. Without this setting, only a flat structure will be returned. I have testing this with
rust-analyzerand it works as I expect. There was care to hopefully properly cache the symbols in theDocumentwithout constantly spamming the server. The symbols are kept in a tree structure for later traversal. I did make a note that perhaps this can work with flat structures too, for LSPs that don't support the nested data return, but will leave this for later. This gets the symbols from the first LSP that supports it, as i'm not sure how we would even handle multiple symbols and which gets priority that wouldn't just be the first priority anyways. One unfortunate thing here is that theDocumentSymbolis quite large(136 bytes). When storing lots of symbols, this can take up a lot of memory unnecessarily. I would love to go over ways we can optimize the size and/or the use to try to get this down.I then set up the actual breadcrumb logic, but not yet add the UI element. This part is pretty straight forward. There are separate breadcrumbs for each view of the document, as is standard. After that, it was mainly just setting up an event that monitors the selection change, and then walks the tree to get the new symbols in the breadcrumb.
Breadcrumbwraps aVecand reuses the buffer so that allocations are kept to a minimum. One thing to be aware of is that I did not add a depth limit. This should be fine, with most nesting only being around 2 or 3, with some of the most common deep ones being 5-7, but this could hit a pathological situation, from generated code, for example. But it was simpler to implement this way. I added a configuration to enable the breadcrumb gathering. It defaults tofalse, meaning its disabled. There shouldn't be any extra overhead while disabled.Finally, I added the UI element. This part is also straight forward. Just access the document and traverse the symbols for the view. Inline with other common breadcrumb implementations, I have added the relative path at the beginning. This helps the goal of adding navigational context, as there could be similar code in multiple places, so the path really is part of where the cursor is. The theming is to help the symbols pop more when looking, and take from the already defined theme keys. Its not perfect, as seen in the examples showing an
implblock, but its better than just plain text. Extending this, I applied the directory theme to the path elements as well, fulfilling the visual expectation. Im also not sure if I matched up the themes to the items as they should, but this is easy to fix in followup PRs if anyone notices something strange.The documentation still needs to be fleshed out, but I need help figuring out how the theme structure should be. Once that is done, I can implement it and add to the documentation.
AI Disclosure: I needed help finding the LSP capabilities part that would enable the hierarchical symbol configuration. I didn't know what it would be called, though in hindsight its incredibly obvious.
Much of this was taken from @matoous in #15221. Thanks for your work!
Examples:
I did set this up in my daily driver, and added icons. This looks much better to me, but it waits on #12369 to be completed.
helix_breadcrumbs_with_icons.mp4
Related: #13492
Related: #8407
Related: #6118