sublimehq / sublime_text

Issue tracker for Sublime Text
https://www.sublimetext.com
809 stars 39 forks source link

Extend Goto Symbol In Project query patterns #3687

Open deathaxe opened 4 years ago

deathaxe commented 4 years ago

Problem description

Large projects may contain symbols of the same name but different kinds in different syntaxes.

In the past some syntaxes used symbol transformations to add some additional hints to labels, which could easily be used to filter certain kinds of symbols (e.g.: CSS:, ID:, import:, export:, etc.).

Those transformations are removed step by step in favor of kind info icons being available on the left and a hint of the syntax on the right.

While that results in cleaner look it is a step backward with regards to querying certain kinds of symbols.

Preferred solution

A certain kind of query syntax might be introduced to be able to include kind and syntax.

Something like we have in Sublime Merge, maybe:

As the kind icon can be an arbritary unicode code point, both the kind name function and the icon f should be supported in the query, so that the short f can be used in case the icon is a normal letter with the alternative of the long name if needed.

Alternatives

??

Additional Information (optional)

The following screenshot should illustrate the current situation when looking for a symbol of a very general name.

grafik

mitranim commented 3 years ago

Would appreciate a solution to this. I currently have symbol overrides that prepend keywords like func X, var X and so on, for the languages I commonly use. This allows to filter them by type in local search (⌘R). Not only does it require special knowledge and effort to set up, it also can't be applied to indexed search, because symbolIndexTransformation is not cosmetic and breaks goto_definition.

Unfortunately I don't have a good suggestion at this time.

mitranim commented 3 years ago

Just realized that in ST4, global symbol search may show several entries for the same symbol, one entry per type, and selecting one of them will search only for entries of that type. For example, on this screenshot, selecting t Header will show only functions, t Header only types, and v Header will jump to the only root constant with that name.

image

Handy feature. Leaving it here since it's relevant and some users may be unaware.

wbond commented 3 years ago

I've spent time thinking about this before we decided to remove the symbol transformations. Here is what I've considered:

  1. The previous behavior of adding the "kind" to the filter text was a quick solution, but had downsides, such as introducing false positive matches. Plus it made it harder to read the symbol names since you had to mentally strip the prefix.
  2. There are two primary use cases:
    1. Wanting a list of all symbols of a certain kind, like "functions"
    2. Knowing the name of the symbol you want to navigate to, but there being multiple kinds, such as a "class" and "function" in C++ for the class and constructor
  3. For use case number 2, adding a suffix would make the most sense. For instance something like :c for class, or :f for function. However, in all likelyhood there aren't going to be 3+ options, but usually perhaps 2. Typing :c instead of pressing the down arrow would be two key presses instead of one.
  4. For a list of all symbols of a kind, I think it probably makes sense for it to be possible to bring up a quick panel with just symbols of one kind. This is currently possible via the API. There is view.symbol_regions() and view.show_quick_panel() can now provide rich kind info. I think there will need to be some experimentation around the usability of this. The API docs may not have the latest additions yet, but will in the near future.
wbond commented 3 years ago

In order to provide a simple way to navigate back and forth between symbol lists of different kinds, a list input handler combined with the command palette would allow selecting a certain symbol kind, but then hitting backspace to switch to a different kind would probably be a fairly usable solution.

deathaxe commented 3 years ago

For use case number 2, adding a suffix would make the most sense.

I don't think that's better than the several prefixes which exist(ed) for custom symbols. The major improvement of kind info is to have a separate column with hints about the symbol type while keeping all labels aligned and clean.

The fact such symbol transformations may cause false positives or sombols not to be recognized is a more important argument to avoid them, though.

... aren't going to be 3+ options, but usually perhaps 2. Typing :c instead ...

This may not be so easy if there are hundrets of symbols. Instead of assuming the full symbol to have been entered leaving 3 options, the more important question was, how much of a symbol and its kind needs to be known/entered to get to the desired result. If a 30 chars long java identifier needs to be fully entered to get a valuable short list of symbols to select from, it might not help much.

... This is currently possible via the API. ...

Wouldn't work for Goto Symbol in Project, would it?

a list input handler combined with the command palette would allow selecting a certain symbol kind

Yes, it would, but it feels a bit strange to duplicate some of the goto symbol functionality in another overlay. Can't use the used key binding then and would always need to go through two steps of selecting a kind first and then look for a symbol loosing fuzzy search being applied on both kind and symbol at the same time.

If the command palette may be used for goto ... features, why not moving all of it into a command palette command then? So removing : or @ from the beginning would bring us back to the normal Command Palette and typing @ back to goto symbol then. As it makes it harder to quickly switch between the goto features, maybe. Therefore they should keep where they are.

wbond commented 3 years ago

Wouldn't work for Goto Symbol in Project, would it?

Goto Symbol in Project already uses such functionality. The global symbol list is segmented by kind, and when you select a symbol/kind you get a quick panel with just that.

deathaxe commented 3 years ago

view.symbol_regions() returns result from the current view only, no? So how would it drive Goto Symbol in Project functionality then?

Current GSIP lists elements in "kind label syntax". The second step is to choose one match from all possible locations. So even if the API approach via Command Palette and InputHandlers work, it would even mean to have 3 steps to get to the symbol.

wbond commented 3 years ago

view.symbol_regions() returns result from the current view only, no? So how would it drive Goto Symbol in Project functionality then?

window.symbol_locations() brings up a list of locations for a given symbol. The master quick panel is written in C++ for performance. Trying to ship all of the symbol data to the plugin host and then send it back to core would be a huge waste.

Once the user selects a symbol/kind, then the API is used in Default/symbol.py to bring up the quick panel and allow the user to navigate to the various definitions.

Current GSIP lists elements in "kind label syntax". The second step is to choose one match from all possible locations. So even if the API approach via Command Palette and InputHandlers work, it would even mean to have 3 steps to get to the symbol.

I'm not quite sure what you mean here.

My idea for dealing with searching by kind would be to allow users who want only symbols of a certain kind to execute a command such as "Symbols by Kind" where you'd first selection a kind (from the list of kinds in the current document) and then you'd get a list of them. If an input handler was used, the user could back out to the list of kinds and pick a different kind.


Overall I was just dumping some of my thoughts I had previously thought about. At this point I'm not committed to anything, although I'm fairly sure that further tweaks to the navigation of symbols will be in a future dev cycle.

deathaxe commented 3 years ago

I understood your ... This is currently possible via the API. ... statement so that we already would have the ability to write a plugin, which brings up the Command Palette with InputHandler to

  1. List all kinds available to let the user choose one
  2. use the result of (1) to display a list with all symbols of that kind in the project
  3. display a list with all locations of the selected symbol.

This would require the API to provide all symbols in a project, which I am very aware of being not implemented for very good reasons. In other words: I don't think the API approach can help to implement an alternative Goto Symbol in Project quick panel which allows a sane way to include kinds into the query.

The one and only request is to do something like prepending the kind info to the labels behind the scenes when doing a query, so that they are included into the fuzzy search as if they were added via symbol transformation.

With regards to my screenshot it would mean to at least treat those items when fuzzy searching as if their label would be:

class: bar type: bar function: bar namespace: bar

Hope this makes sense.

Fuzzy search would automatically filter all classes when typing c: or class: even though it is not visible in a label. Or I could type c: f to shorten the list to all classes beginning with f. etc.

I don't want another panel, nor do I want a plugin for it. Just a tweak to the way fuzzy search works in case of presence of kind info. It should prepend the "long name" as the icon may be any unicode code point which can't be easily typed.


Overall I appriciate your dumps and fully understand if that is something for the future.

Basically this issue is a dump of my thoughts about the new kind info without symbol transformation situation, too. It just came up, as I found the type prefixes useful in Erlang, when doing the rewrite. Some still exist ;-) Removing them feels like a step backward. That's the reason for opening this issue up.

It just have a feeling it may be considered to probably be relevant for some guyes.

wbond commented 3 years ago

At a high level, I’m personally not keen on the idea of trying to build a pseudo query language into the fuzzy input panels. I feel like having them as separate steps would be easier to implement and easier for users to reason about.

deathaxe commented 3 years ago

Just had the search functionality of Sublime Merge in mind when thinking about that, but I haven't done any case studies to say what a good solution would look like. I guess we just might need a way to further filter a list like in the initial screenshot, when a huge project with multiple languages may return a huge list of symbols. These are situations filtering for kind and/or syntax might be useful somehow.