I had an idea for a snippet plugin, and right now the idea mostly relies on python(and potentially rust via pyO3), though I’m not sure how much of it is necessary, in the sense that I could be duplicating some functionality built into kakoune.
few features worth mentioning.
the snippet syntax would be a superset of the accepted snippet syntax making it easy to migrate from standard text editors, and would would be specified in a json or toml file.
- If json is used, this means that they could literally copy over their vscode snippets to use in kakoune.
snippets could be set to autotrigger via the snippet definition, but the default is to be manually completed.
my hope is also to conditionally change completion order, the kak autocompletion menu should set snippets as the lowest priority unless it’s an exact match, then it should be at the top. I’m not sure how to do this in kakoune though.
since all input is being piped to the daemon, snippet completion could be a bit smarter, only checking for snippets if it makes sense, for example not in a comment, or only in a comment.
each language would have multiple sets of snippets, a base set, which is always loaded, and conditional sets which are either user specified or loaded if certain snippet is triggered( for example
import opencvwould load opencv related snippets into the trie(or set of contextual tries) for that window.
related to the last 3 points, it uses tries as the data structure for storing snippets. easily updated if not compressed, from my understanding as fast as a dictionary (keys still have to be parsed char by char to check if match), and can tell if the current word is a valid prefix.
the autotrigger snippets should be there for the completion of unambiguous syntax. while loops tend to be unambiguous whereas for loops could be range based or iterable based. the former should autotrigger, the latter should not.
the rough sketch of the program
- start the snippet daemon
- the daemon creates a trie(or set of tries for different contexts) of all the relevant snippets for the window
- if insertion mode pipe either all input or current word boundary to the daemon
- if snippet is recieved, insert at start of word boundary
- else if completion option recieved add to menu based on priority
in the python daemon
- creates a trie(or set of tries for different contexts) of all the relevant snippets for the window
- monitor for context(comments, newlines, first word, etc)
- if given context is true then check if current word is a trigger
- if not return all snippets/triggers that current word is a prefix for and send to the completion menu with low priority
- if it is then return snippet/subsnippets if type is autotrigger else send to the completion menu with high priority.
- in last step if snippet is has attached snippets then update the trie(s).
Part of the reason I’m doing the majority of the work in python, besides being turing complete, is because I’m still not comfortable with the internal kakoune stuff. I don’t know what would be simpler(in terms of writing) or more performant to handle via kakoune itself. based on the rough sketch of the execution, what do you think that kakoune should handle?
How would I go about setting priority for completion items?
I don’t want to depend on the lsp, but how could I integrate it if it is available, and what could it offer that I couldn’t get from monitoring the input.
do you think making the syntax a superset of the standard syntax (where snippets set via the standard will work with the plugin, but plugin snippets won’t likely work with another editor) is advisable? what is an alternative if you think that isn’t a good idea?
right now, I’m thinking of a design using a daemon per window, rather than per session, because a session could be per project, and include multiple file types. Do you think this is better or worse. It would use more memory, especially if you have 10+ text editors open(I using tiling wms and it’s common enough to be a concern), but having a single daemon with multiple filetypes, seems like that could add a layer of complexity that is unnecessary in most use cases.
I appreciate any help you can provide, this will be a first for me in a couple of ways(monitoring input, kakoune plugin, implementing a trie actually meant to be used, etc).