Modules, Plugins, and Provides Requires Lazy Loading

I want to discuss a new module system, and how we can use it for better plugin integration, and especially to make better integration between different plugins.

Today I’ve submitted my new plugin langmap.kak that uses module system to make Kakoune load faster, but also to allow integration with my another plugin powerline.kak. I’ve added a new langmap powerline module, but this time, it isn’t defined within the powerline.kak plugin, but within the langmap.kak plugin.

To be able to load these plugins in any order, I’ve wrapped the langmap powerline module into provide module langmap_powerline. But in order to require this module only when powerline.kak was actually loaded, I’ve added a new option to the end of powerline.kak: declare-option bool powerline_loaded true, and set up the hook hook -once global WinSetOption powerline_loaded=true %{ require-module langmap_powerline };. This way I can source langmap.kak before powerline.kak, and the langmap powerline module will be loaded after successful load of powerline.kak

Earlier I’ve proposed to provide this kind of a variable to allow lazy loading, but new provides requires model still can benefit from such approach.

My another plugin fzf.kak (this post isn’t an advertisement, trust me!), provides a module for a plugin called yank-ring.kak by @alexherbo2. It was introduced before the provides requires model were merged into Kakoune, so it’s using another approach. It tries to set the hidden yank_ring_history option, and if it faild, then module isn’t declared, but if it can do this, the module is provided. This is a cumbersome way to handle this, and I want to know @alexherbo2 what do you think about adding yank_ring_loaded option to the end of your script, so other plugins could declare their modules only after your plugin actually loaded by adding simple hook as I showed above.

What I want to say, is that I think that every script should provide a variable to identify if it was loaded or not. It is a common practice in Vim plugins, and Emacs packages, so I think if we want Kakoune plugins to integrate well, we should similar (yet appropriate for Kakoune) approach.

Instead of:

hook -once global WinSetOption powerline_loaded=true %{ }

…how about:

hook global ModuleLoad powerline %{ }

It’s a bit simpler, and works with Kakoune today.

that would be great, but the plugin may not provide a module, like in my case. I mean I don’t know if it is a good idea to provide a module and immediately require it after, because such plugin as powerline.kak has no reason to be lazy loaded, as it is UI plugin. Maybe I’m wrong

Also what would be a best practice to load a module that is a separate script?

For example. I have a script.kak and a supplement_script.kak files. The first one is a main script, but it is big, and I’ve decided to move some of it’s functionality to second file. First script is providing a script module. Would it be fine to use hook global ModuleLoad over whole body of supplement_script.kak to lazy load it only when main script is loaded? It works, but maybe it is better to provide a separate module in supplement_script.kak and require it with a hook instead of placing whole contents of the file in the hook? Won’t enormous amount of modules cause a problem?

Edit: Just realized I completely misread what you were asking. If the supplement file should always be loaded with the main file unconditionally, I would say place it somewhere where it doesn’t get loaded and source it from the script.

A large weakness of the current module system is that it is basically just a lazy loading system, with the added benefit that you could override some implementations from user scripts. No module should be loaded before all the support files have loaded, because otherwise the file that defines the module might not have been sourced yet. It might be a good idea to put all support files, including ones like comment.kak, in modules, and also have hook global KakBegin .* %{ require-module comment }.

If supplement_script.kak is a file that adds integration with another plugin, and that plugin provides a module, you could put it in a place where it wouldn’t get automatically loaded and add hook global ModuleLoad plugin-name %{ source supplement_script.kak } to script.kak. Adding another module would also work, the module internally is just a hash set so large amounts of modules wouldn’t be that bad (unless there starts being name overlapping). If it doesn’t provide a module, and cant just be loaded unconditionally then ¯\_(ツ)_/¯