Sublime Forum

Complete on project symbols

#1

It’s easy to go to a symbol in your project and to use completion when looking up the symbol you want to go to.

However, I want to be able to complete at point (on_query_completions) from the set of symbols in the project. In order to do that, we need a sublime function to get the list of completions that match the prefix (like view.extract_completions does with words in the buffer) or at the very list a list of all the symbols in the project.

Neither of those exists but I am surprised because it would be a really simple way to do something that we apparently need super powerful plugins with deep understanding of the language being edited, etc), whereas sublime uses language definitions to define symbols automatically and in real time.

Am I confused?

1 Like

Syntax Scopes Q: `meta.path` and `meta.generic`
#2

I think you are probably looking for Window.lookup_symbol_in_index() and Window.lookup_symbol_in_open_files() at http://www.sublimetext.com/docs/3/api_reference.html.

We are probably going to play around with adding an option for the default config to complete based on symbols in open files. Our concern over completing on the whole project is the sheet number of symbols many projects have, and the signal to noise ratio.

1 Like

Goto Symbol in Project completions?
#3

Hi again,

What would probably be best is something like:

Window.find_symbols_in_index(prefix | regex)

which can be optionally used by some form of auto completion code. It would be preferable if it returned an enumeration of symbols that match the specified prefix w/out allocating any memory for an array. Or, if there were just a way to enumerate an array of symbols again without copying the array, we could do the search however we want (although probably somewhat slower).

0 Likes

#4

I’m curious to know the status of this. Would love to see complete on project symbols make it into the main build but I’m happy to write a plugin if we could get better access to the project symbol list.

0 Likes

#5

Such a function should be able to filter the suggestions based on the active view’s scope and/or a syntax-specific ´"completion_selector"` setting.

A Window.find_symbols_in_index(selector) and Window.find_symbols_in_open_files(selector), which could be used by packages would be nice, too, as it would allow to add per scope hints and custom snippet contents to add on completions.

0 Likes

#6

I think you could do it already. Maybe a bit inelegant, but it could work. Something like:

  • Window.lookup_symbol_in_index() and you get the locations in files
  • open each file you want to index and extract the string at the location for each element of the index. If it matches the selected scope, you add it to the completions list.I would bind it to a palette command like Index symbols in project for completions, so that the work isn’t done in the background, just once on demand.
  • After that, every time you save a file in the project you scan the file for new symbols, and add them to the same list, so that they will be available for other files.
  • You could save all current lists for your indexed projects in the same json file, so that when ST is restarted you can run another command, like Reload indexed symbols for project, without re-indexing everything. If you run the other command again, the list for that project would be updated and saved again to file.

Maybe if location

http://www.sublimetext.com/docs/3/api_reference.html#type-location

returned also the selector and the string, it would be much simpler.

Location:
(str, str, (int, int), str, str), with last being selector and symbol string.

0 Likes

#7

You seriously suggest to create another index, just because there is no API to access the existing one? I don’t think this is a good idea for modern HTML/JS projects with probably hundreds/thousands of files. Opening each one for indexing would cause significant performance issues.

I already tried to such things to provide a global completion list for one of my projects but abandoned it very quickly. It might work for little projects with 10 or 20 files but is a mess with larger projects.

0 Likes

#8

I have to say I never worked with very big projects. Still I think that having an expanded selective index wouldn’t be useless, you can achieve a lot by creating a selective index(filtered for chosen selectors), built from the Sublime index, but with additional informations that you retrieve directly from files, especially if files are indexed one by one (with an on_save listener for example). Also, having all symbols in autocomplete without some kind of filtering isn’t something I’d like, personally.

To make it in a way that it doesn’t cause performance issues, I was thinking something like this could work. Assuming you have a json file where you will store all indexes, initially empty.

  • palette command: Project Autocomplete: Track current project. It will then look the symbol index and extract the ones that are present in the current file. It will then build a list of selectors from this list of symbols(checking the selector of the row/col point stored in the index), and prompt you to choose which selectors you would like to index for this project. So you’re starting to index this project, and only the words that match the chosen selectors.

  • the command would write to the json file: the name of the project and the chosen selectors, adding already the strings of the symbols in the file that match the chosen selectors, excluding all others.

  • after that, the only work done in the backgroung would be in an on_save listener: when a file is saved, ST index is searched for symbols that belong to the current file, the string is extracted from the view for symbols that match the chosen selectors, they are added to the project autocomplete list, and the json file is also updated (so that on Sublime restart your index is still there). If you want to index files with a certain extension and exclude others, you could do it, and further decrease performance impact.

  • you could have another palette command like: Project Autocomplete: Add selectors from current file. A similar job as in the other command would be done, but it would only add from the current file, also for extensions/selectors that you don’t want for other files.

This index would be expanded as you work on the project, edit and save files. It would be a partial index unless you open and save all files, but I don’t think it would affect performance much or at all, the on_save listener would run a command that scans the current file asynchronously. It wouldn’t be like having the same from the API, but it’s something that can be done already. Moreover, it’s not guaranteed that an expanded built-in indexing wouldn’t cause performance issues less than a plugin.

If you do it by plugin, you have an initial limitation (partial index) but you could restrict autocomplete to chosen selectors (much lighter for a big project) and could do some more stuff. For example, if you index functions you can store parameters as well, and then have parameters autocompletion with a special keybinding (as ctrl+tab), snippet-like. I’m doing something like this in a plugin, and it works well but only from a pre-built file with all autocompletions.

For example if I set the autocompletion string to:

score_selector(${1:scope}, ${2:selector})

autocomplete would only show score_selector and complete that word with tab, but if I hit ctrl+tab it would launch a snippet with the whole string as content. The snippet string would be built from extracted string and accompanying parameters in the case of functions.

I don’t know if there’s some Python library to extract scopes/selectors from a file position, if there is, you could index the whole project in one go, starting from ST index, without actually opening the files in ST.

0 Likes

#9

I;m with deathaxe although it took me a while to remember what this was all about. I had to give up and write my own completion by literally searching all the buffers for regular expressions of my own form to try to create a list of completions I am happy with.

And I mostly am.

But, as I said originally, I want a list of known symbols which I can iterate over looking for matches, when I am hoping to complete what is by definition a symbol. So I cannot lookup a WHOLE symbol because I have only partially typed it.

Sometimes I want to complete words that are not symbols, I admit, but I could augment the list of symbols with words from other scopes in the existing buffers for example.

Ah - I see deathaxe has basically represented my case better than I can. The indexes already exist. All we need is a way to enumerate them. I worked around it by using regex in all my open buffers, and it works surprisingly well for me, but it would be a lot faster to access the existing index. If I could pass in a regex and get back an enumeration of matching (symbol, file, position), well I’d be done. And it would scale. And it would be more accurate than what I have.

What I really want, though, is more control over the order of completions that is presented to the user. If there’s a possibly completion right next to my cursor, I want that to be the first choice. But I don’t have that kind of control.

1 Like

#10

This plugin says it does what it seems you want to do. Maybe you can find some answers there.

0 Likes

#11

No - that plugin attempts to implement its own completion outside the whole completion infrastructure of sublime.

Not to worry.

0 Likes

#12

Thanks for the suggestions mg979. I’m not really looking to build something that maintains its own symbol index. I’ve never been quite satisfied with ctag-based plugins, and in my experience Sublime has been really great at maintaining it’s index and keeping it up to date. I would love to be able to build something off of it.

1 Like