Sublime Forum

Project based completions/snippets

#1

Firstly I’m going to assume that ST is simply not interested in implementing project based completions/snippets like found in some IDE that allow you to auto-complete function parameters. I say this because it was asked multiple years ago and there’s still no activity on it (devs even implied it’s not possible but IDE’s like Xcode can do it so…). Please let me know if I’m wrong and this is planned.

I’d like to make an attempt to implement this myself but I want to know if ST has the plugin hooks required. The basic plan is to make a background daemon which can be notified of changes in a document, parse the affected range of text and then insert the symbols into a SQL database. Then if possible using a command to open an auto-complete panel in ST and query that database based on the current word being typed.

Some questions:

  1. If there are changes to a range of text in a document can ST save that information in a variable which I can then access when the file is saved? I only want the daemon to be called when the file is saved but I need to know which range or ranges of text were changed since last save. The way I’ve seen ST plugins is that I couldn’t save a global variable which persisted across API calls.

If this isn’t possible how could I know which ranges of text were changed between saves?

  1. Can a plugin actually open an auto-complete panel and insert a snippet?
0 Likes

#2

The on_modified event tells you when a view has been modified; however it doesn’t tell you what was modified, only that it was. I would imagine that if you wanted to track exactly what changed each time a change happened you would have to keep a snapshot of what the file looked like prior to making any changes so that you could compare them and see what is different between the two,

On the other hand if you only want to ship changes to the back end when the file is saved, then you could do something like capture the state of the file in on_load and compare that to the state of the file in on_pre_save and not worry about intermediate modifications at all. Or alternatively the state of the file on disk is theoretically what it was at the point of the last save, so you could grab it from there.

It’s possible to save information between API calls in global variables if you like (there’s nothing special required to do so other than standard Python syntax). In addition, a TextCommand and WindowCommand instance is created for every view and window that exists and an instance of ViewEventListener is created for every view that it applies to, so instance variables in these classes can persist information between calls as well.

Doing this sort of thing is not without its pitfalls, though. For example the state of the interpreter memory isn’t saved with the session information, so a quit and restart doesn’t put the state of values the plugin is saving back to where they originally were. Similarly reloading the plugin would also discard the state.

The settings object associated with a window or a view can store arbitrary data and that data is persisted in the session, so that’s one potential way around that restriction.

I think the most robust solutions in this case are to have things work in a way that “degrades” gracefully if state is lost or perhaps to use some strategic custom settings to store enough state information to get back to a known good state after startup.

You can use view.run_command("auto_complete") to open the autocomplete popup anywhere that an autocomplete popup is allowed (this is the command bound to Ctrl+Space on Windows, for example).

If you used on_query_completions as well to inject your completions, then I think such a call would also automatically include any completions that were added and which also apply. I would guess that interactive performance of the editor may suffer if on_query_completions takes a non-trivial time to return completions though, which might be an issue in this case if you need to IPC to an external process to gather the data.

Similarly you can also run insert_snippet (or just insert) to add text to the buffer as well if needed.

You may be able to get some inspiration from the LSP package; it may also do what you want or need without having to do anything at all (I don’t use it personally though so I can’t say for sure).

1 Like

#3

Thanks for the ideas. on_modified seems to limited for what I want to do so I’ll need to find other options I think. It’s hard to believe there’s no event for a range of text changing though. Maybe a feature request?

I’m not a Python user but are memory mapped files the best way to communicate with my hypothetical daemon? Once the database is queried I need to return the results back to ST, maybe just a single line of text. Using a socket server would be an interesting option but not sure about if that’s feasible with ST.

0 Likes

#4

I’ve never tried playing with memory mapped files in Python so I’m not sure how that might rank as an approach to something like this. For a socket server, I think that’s what the LSP package is doing (though again I don’t use it personally).

I also have worked on a system in the past that uses a socket connection to an external process to ship files to another machine to build them and capture the build results, so it’s definitely possible. In my case I was using TCP sockets, but domain sockets or named pipes would probably also work quite well.

0 Likes