-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more context to the symbol picker #2452
Conversation
This adds the symbol kind along with its direct parent symbol. So: ```rust mod foo { fn bar() {} } ``` will show symbols like ``` module : foo function : foo → bar ``` This lets you quickly filter by the symbol kind, containing symbol or symbol name.
Some personal feedback, take it with a grain of salt: The display of namespaces/modules with an arrow looked a little odd at first glance. I like that the module is shown, though. Would it be possible to have the item type (function/enum/etc.) aligned to the right or does this break searching for |
Hi @CptPotato, thanks for the feedback!
Yea I played around with some other possibilities like
Unfortunately the symbol only contains the direct parent and didn't find a good way to get the rest of the hierarchy. I played around with building up a hash map but ran into some problems when there are symbols with the same name. It feels like this is something that should be solvable with tree-sitter (though admittedly I haven't played with that). If you have any specific ideas on how to get this I'm happy to play with this further (otherwise can very much put a TODO here).
Could be. I'll play around with this in the next day or so. I agree it'd be kinda nice to have it right aligned if it doesn't make filtering more difficult. |
Thanks for elaborating! I personally don't have a strong preference for how to separate the namespace from the symbol name. Different languages have different conventions here (like I also don't think it's a big issue that only the parent namespace is shown in the list for now. If a project has a very deep structure, it might clutter up the window and make it harder to see the actual symbol name on smaller screen sizes. |
The problem with only showing the immediately containing symbol is pretty well shown in this would show up something like:
Definitely an improvement over the current output but it'd be much nicer to have the full nested structure (albeit truncating long names to make the length reasonable). (FWIW this is the exact example that broke my initial implementation 😛 ) All that to say, this still feels like a problem that should be solved (though maybe outside the scope of this PR). I suspect that this would be more problematic in some languages than others. |
@CptPotato - Ok, so after digging in a bit more....
This isn't possible without significantly reworking how the picker is implemented. In the PR you linked the right alignment is done by using two That said, right aligning also makes filtering by symbol kind pretty awkward as the filtering is from left to right, so you'd have to do something like I think there'd be a lot of value to reworking the picker to support style information to use color to differentiate pieces of information in the picker. Even before this PR, the workspace symbol picker has the symbol and file path, it'd be really great to have them styled differently to make it easy for the eye to parse the different pieces of information. (if there is general agreement on that direction I'd be happy to spend some time on it at some point) I added a TODO for adding ancestor symbols. For the separating symbol, my view is that a simple Any thoughts? |
I think reworking the picker to make alignment, coloring or searching work better is out of scope for this PR. It might be worth revisiting in the future, but for now I think having the item types added to the symbol picker is already a nice addition. 👍 |
helix-term/src/commands/lsp.rs
Outdated
let kind = match symbol.kind { | ||
lsp::SymbolKind::FILE => "file ", | ||
lsp::SymbolKind::MODULE => "module ", | ||
lsp::SymbolKind::NAMESPACE => "namespace ", | ||
lsp::SymbolKind::PACKAGE => "package ", | ||
lsp::SymbolKind::CLASS => "class ", | ||
lsp::SymbolKind::METHOD => "method ", | ||
lsp::SymbolKind::PROPERTY => "property ", | ||
lsp::SymbolKind::FIELD => "field ", | ||
lsp::SymbolKind::CONSTRUCTOR => "construct ", | ||
lsp::SymbolKind::ENUM => "enum ", | ||
lsp::SymbolKind::INTERFACE => "interface ", | ||
lsp::SymbolKind::FUNCTION => "function ", | ||
lsp::SymbolKind::VARIABLE => "variable ", | ||
lsp::SymbolKind::CONSTANT => "constant ", | ||
lsp::SymbolKind::STRING => "string ", | ||
lsp::SymbolKind::NUMBER => "number ", | ||
lsp::SymbolKind::BOOLEAN => "boolean ", | ||
lsp::SymbolKind::ARRAY => "array ", | ||
lsp::SymbolKind::OBJECT => "object ", | ||
lsp::SymbolKind::KEY => "key ", | ||
lsp::SymbolKind::NULL => "null ", | ||
lsp::SymbolKind::ENUM_MEMBER => "enum mem ", | ||
lsp::SymbolKind::STRUCT => "struct ", | ||
lsp::SymbolKind::EVENT => "event ", | ||
lsp::SymbolKind::OPERATOR => "operator ", | ||
lsp::SymbolKind::TYPE_PARAMETER => "type param", | ||
_ => "", | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see much benefits of aligning this, since they have a different group.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't that be solved if we just reorder the appearance? Or maybe the order is somehow useful?
/// the result will be: `function : foo → bar` | ||
fn get_symbol_string(symbol: &lsp::SymbolInformation) -> String { | ||
let kind = match symbol.kind { | ||
lsp::SymbolKind::FILE => "file ", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some idea but not sure if it's good or not. Why not do [file]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The downside of [symbol kind]
is that it would take more horizontal space. It also feels a bit more cluttery (at least in my view). I think the ideal would be to eventually differentiate with color (which would also remove the need for the →
separator altogether).
helix-term/src/commands/lsp.rs
Outdated
lsp::SymbolKind::EVENT => "event ", | ||
lsp::SymbolKind::OPERATOR => "operator ", | ||
lsp::SymbolKind::TYPE_PARAMETER => "type param", | ||
_ => "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better if we log this out in case we missed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great callout! Will add this.
2611c36
to
1f29d08
Compare
lsp::SymbolKind::FILE => "file ", | ||
lsp::SymbolKind::MODULE => "module ", | ||
lsp::SymbolKind::NAMESPACE => "namespace ", | ||
lsp::SymbolKind::PACKAGE => "package ", | ||
lsp::SymbolKind::CLASS => "class ", | ||
lsp::SymbolKind::METHOD => "method ", | ||
lsp::SymbolKind::PROPERTY => "property ", | ||
lsp::SymbolKind::FIELD => "field ", | ||
lsp::SymbolKind::CONSTRUCTOR => "construct ", | ||
lsp::SymbolKind::ENUM => "enum ", | ||
lsp::SymbolKind::INTERFACE => "interface ", | ||
lsp::SymbolKind::FUNCTION => "function ", | ||
lsp::SymbolKind::VARIABLE => "variable ", | ||
lsp::SymbolKind::CONSTANT => "constant ", | ||
lsp::SymbolKind::STRING => "string ", | ||
lsp::SymbolKind::NUMBER => "number ", | ||
lsp::SymbolKind::BOOLEAN => "boolean ", | ||
lsp::SymbolKind::ARRAY => "array ", | ||
lsp::SymbolKind::OBJECT => "object ", | ||
lsp::SymbolKind::KEY => "key ", | ||
lsp::SymbolKind::NULL => "null ", | ||
lsp::SymbolKind::ENUM_MEMBER => "enum mem ", | ||
lsp::SymbolKind::STRUCT => "struct ", | ||
lsp::SymbolKind::EVENT => "event ", | ||
lsp::SymbolKind::OPERATOR => "operator ", | ||
lsp::SymbolKind::TYPE_PARAMETER => "type param", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think even if you want to align, it is better to remove the spaces, then use left align format specifier to do the spacing rather than having to do that manually. Doing it manually will cause changing the largest variant require changing all the lines, bad for git diff.
.clone() | ||
.container_name | ||
.map_or(String::new(), |name| format!("{} → ", name)); | ||
format!("{}: {}{}", kind, prefix, symbol.name.clone()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this look bad for the case in which we don't match? Given that now it will show : .....
.
I think this is a good change, but rather than formatting the text by hand the picker UI needs to use the table component instead, so we can add a bunch of automatically aligned columns. #2013 is working towards that goal so let's park this PR for a bit |
this will be covered by #9647 |
The symbol picker functionality is really useful; however, it can be annoying when you want to do something like only see the
function
symbols, or maybe onlystruct
orenum
kinds. It'd also be convenient to be able to filter by the containing symbol name.This adds the symbol kind along with its direct parent symbol. So:
will show symbols like
This lets you quickly filter by the symbol kind, containing symbol or
symbol name.
Here is how this looks before (top) and after (bottom):
The nice thing about this is that you can search by the symbol type (like function) to more quickly narrow in on what you want.
By showing the containing symbol (if it exists) it becomes easy to search only symbols in the
test
module as well.This also addresses a TODO and a bit of minor formatting cleanup.