Plug.kak rewrite

I’m planning on long going rewrite of plug.kak from scratch. This topic meant to get in touch with plug.kak users, to hear some ideas, and suggestions. The main reason of rewriting plug.kak is that it is hard to change and debug, but I’m also very open for new ideas and thinking about making it easier to plug into plug.kak to extend it with new keywords.

My main goals for plug.kak were and still are:

  • A plugin manager:
    Not only download plugins, but see git history, changelogs, revert to older versions, and so on;
  • A declarative configuration manager:
    Provide a sane way to encapsulate plugin configurations within plug command;
  • Sane way to interact with build tools that plugin use;
  • Easy installation of plugins from different repositories and git forges, as well as possibilities to load local plugins;
  • Be fast;

I’m thinking of rewriting this plugin from scratch, and I’m thinking of a better implementation language for it, rather than posix sh, maybe Perl. It seems that Perl should have less problems running on BSD or MacOS. There are some possibilities of speed problems though.

I welcome any ideas and suggestions, feel free to discuss features that you miss or want in plug.kak to be presented

5 Likes

I love plug.kak! Makes life so much easier.

I could not care less about this feature, I don’t think this at all the common use case for it. I think this is really almost an external plugin-developer tool, rather than a part of plug.kak (optional load?)

This would be amazing, but the current system of adding one line to a config is fairly great too.

Awesome!

Also great!

\o/


I think an improvement of the first run on a new box experience would be great, a few times I have checked out my config before running plug-install and been like “why is Kakoune broken” – so something like “Hey, I see you haven’t even run plug install, do you want to?” or “Hey, it has been 4 weeks since you did a plug update, do you want to?” would be great too.

2 Likes

I love plug.kak @andreyorst, so thanks for that :slight_smile:

I like how plugins are added and I like how their configuration can be encapsulated as part of the plug command.

The only thing where I think „hm, this should be easier,“ is updating all plugins.
Updating the plugins automatically on a regular basis or being reminded about it (like @robertmeta already suggested) would be of great help, too.

Cheers!

I don’t think we’ll need to load it until you open plug-list, or update a package. I had in mind ability to see git log and history in a more elaborate way than now, because currently, log shows only that there was successful pull and what file changed, but not what the commit messages were. Sometimes it is handy in a way that you can see how you might need to update your configuration.

Well, current system is pretty declarative already with config, defer and demand keywords, but I’m thinking if this could be extended or managed in a more sane way than it is done currently. One pain point for me is a do block, because it is hard to make complex recipes. Although this should probably be handed to plugin creators through Makefiles.

As for reminding to update, I feel the desperate need in good date comparison tool. But right now you can do

set-option global plug_always_ensure true

And plug.kak will install all plugins that are not installed already when you open Kakoune. It doesn’t add much to startup time, as far as I’m concerned.

um, plug-update updates all plugins. Am I missing something? I’m not a biggest fan of automatic updates, because those can break working system, but I guess, this feature is needed some times, so I’ll add this on my list.

1 Like

Andrey this plugin manager has just always worked for me. The below plug commands would be my only real request.

A plugin manager:

  • git log -1 HEAD
  • git reset --hard <previous-commit>
  • A formatted persistent log file

To get out of trouble quickly and safely with the ability to dig into the ‘issue’ when time permits.

Look forward to seeing what you come up with. Thanks Andrey.

1 Like

I agree that git history and changelogs don’t necessarily have to be a feature of plug.kak.
Currently I just use the terminal for that, and that’s fine for me.
Also, if a plugin breaks, I just check the problem in the terminal.

Now that I think of it, maybe opening the directory of a plugin in a terminal would be nice.

Thanks for the great work on this plugin. It works really nice!

2 Likes

I actually switched to plug.kak pretty recently (before I was just using a script to fetch scripts to autoload folder). Things I like are plug-list that shows a nice summary and the nice encapsulation of plugin configs, although I haven’t completely wrapped my head around config/defer/demand distinctions.

I will go against the grain a bit and say that I’d love to have “changelogs” with commit messages when plugins update, which is much more useful than seeing a diff --stat.

Another thing I’d like is to be able to checkout certain commits, tags or branches. Granted I haven’t really needed it so far, but if the community gets larger and plugins get bigger/more numerous, that kind of feature would be helpful. I noticed this is already supported, awesome :slight_smile:

:man_facepalming: of course, thanks.

I understand that automatic updates feel dangerous. But then again you can always roll back easily if something breaks. In any case, a reminder instead of doing it automatically would be absolutely sufficient.

If you want to write it in Lua/Fennel, I can help with some tips :smile:. It solves the problem of performance, but also could potencially help with the declarative part of the goals you established for plug.kak. since Lua can be used as a data modelling language (its syntax indeed took inspiration from Bibtex).

Regarding functionality, one think I miss from vim-plug is the possibility to see the commit messages of all updated plugins in a unified view when pressing the D key.

Do you have screenshot?

I’ve though about it, but this will mean that plugin manager depends on the plugin, which is not really feasible option :smiley:. Probably I could include luar as a part of source code, by using submodules, but this still feels a bit bloaty.

Although, this brings another topic - dependencies. I’ve tried to avoid this, as plugins in Kakoune are more or less self contained, but still though that it would be nice if plug.kak was able to install dependencies along to plugins. So if you write a plugin, that depends on your luar plugin, plug.kak could detect it, or had a recipe for handling this. This also implies that load order should not be defined by position of plug command in file, but allow use some keywords, like after.

Sure!

This is the result of a :PlugUpdate command. Unfortunately, this screenshot doesn’t show the message that is displayed in the status line just after a successful update: Press 'D' to see the changes.

Then, when you press D,

Overall, I really like the UI of vim-plug. I think it could be used a source of inspiration for plug.kak.

This a problem indeed.

got it, this is close to what was in my mind when I’ve wrote this:

One thing I’ve always wanted a plugin manager to do (and intended to do with minpac and neovim before I switched) was a lockfile that I can commit with my dotfiles, that simply has the commit hash of all the currently installed plugins. That way I could have consistent versions of different plugins across my machines, and when I update plugins on one machine (therefore updating the lockfile) when I start up kakoune on another machine with the new lockfile it would automatically update to that hash.

This would also benefit your aforementioned “revert” action, because then you wouldn’t even have to be on the same machine you performed the update on to revert to a previous version.

That said I think this feature could be something external to plug.kak, and would be adding more surface area for something to go wrong if it was added to the core plugin, especially if it’s not a feature everyone would use/appreciate. Maybe just making sure that plug.kak can be easily extended after the rewrite would be the best route?

not exactly a lockfile, but you’re able to specify commit "hash" as a plug keyword thus locking to specific commit. There’s also tag and branch keywords for similar purpose. Lockfile is interesting, but I don’t know why would you want to maintain external file instead of using your config. That’s common for build systems, but I don’t think it makes sense in context of plugin management. Although I get your point, I’ll ad this to the feature list

вт, 16 июн. 2020 г., 17:46 Brad via Kakoune Community Hub <noreply@discuss.kakoune.com>:

Yeah that make sense, I thought it might be pretty niche. For me it hits a happy medium between having to explicitly hunt down and set each plugin to the latest commit, and having no idea what the last version was that was working before it updated to master. I swap between 3 machines (2 of which are running NixOS) and commit my dotfiles religiously, so a lockfile makes a lot of sense for me.

I think that the best way to express dependencies in a declarative manner is by nesting declarations. So, for instance, if I have the following plugin dependencies:

plugin-a
|___ plugin-b
|___|___ plugin-c
|___ plugin-d

meaning that plugin-c depends on plugin-b that depends on plugin-a, then it could be expressed inside kakrc as:

plug "plugin-a" %{
    plug "plugin-b" %{
        plug "plugin-c"
    }
    plug "plugin-d"
}

With that setup, If for some reason I need to temporarily disable plugin-a, I can simply add a noload attribute to it and all its dependencies will be disabled with it:

plug "plugin-a" noload %{
    plug "plugin-b" %{
        plug "plugin-c"
    }
    plug "plugin-d"
}

Regarding temporarily disabling a plugin, I’d like to suggest the definition of a specific noop command: unplug, which would do nothing (not even parsing the arguments); it would be useful just as a means to avoid having to comment several lines when we need to disable some plugin temporarily:

plug "plugin-a" %{
    unplug "plugin-b" %{
        plug "plugin-c"
    }
    plug "plugin-d"
}

In the above example, both plugin-b and plugin-c would be disabled. It would act more or less like the noload attribute, but with the added benefit that it would skip parsing the arguments, thus improving Kakoune’s loading time.

this should currently work, but there’s a problem, let’s take luar as an example:

plug "plugin-1-that-depends-on-luar" %{
    plug "luar"
}

plug "plugin-2-that-depends-on-luar" %{
    plug "luar"
}

First thing, we have a plug for luar twice. This is not a problem, as plug.kak checks if plugin was already loaded. However this is boilerplate, and unnecessary duplication.

One could decide to leave luar only in first plugin:

plug "plugin-1-that-depends-on-luar" %{
    plug "luar"
}

plug "plugin-2-that-depends-on-luar"

But this is going to break once you’re remove that first plugin from Kakoune for any reason, and try to set up Kakoune on a fresh PC.

Another way is to explicitly state that luar has to be installed:

plug "luar"
plug "plugin-1-that-depends-on-luar"
plug "plugin-2-that-depends-on-luar"

This will work just fine, but that’s not what I’m after. What I’m thinking is something that will allow plug.kak to detect missing dependencies automatically, but that’s not an easy task.

Hmm… it seems that I didn’t explain it clearly enough :sweat_smile:. My suggestion was the opposite actually:

plug "luar" %{
    plug "plugin-1-that-depends-on-luar"
    plug "plugin-2-that-depends-on-luar"
}

This way you express the dependency clearly and avoids duplication.

Do you mean without any explicit reference to a dependency in a user’s kakrc (e.g. without referencing the luar plugin as in the above example)? That would be something really interesting!

Perhaps if plugin authors make their plugins aware of plug.kak… For example,
the author of plugin-1-that-depends-on-luar could add the following line somewhere in plugin-1-that-depends-on-luar.kak:

try %{
    plug "luar"
}

This way, when the file is parsed, it informs plug.kak about its dependency on luar. But, if the user opts to not use plug.kak, then it simply fails graciously (the user then needs to manage dependencies manually though). Isn’t it enough?

Whoops! :upside_down_face:

Yes. I’m currently thinking if we could really use exceptions as exceptions. This way we would do this:

plug "plugin_that_depends_on_luar"

plug will install plugin, and load it, but upon load the runtime error will occur, when the plugin will try to require luar module. try will fail and send the error to the upper caller, which is plug command, and I will have a special handler, that uses infromation from the exception, and installs the dependency.

This has several problems though. First, we don’t really have exceptions, but we have only try catch that can be used together. This can still work, because plug wraps loading each package with try and catches everything preventing your editor from error state at loading of plugins. So theoretically, if you just do require-module luar my plug will catch unable to require module luar error and will know what to do. However it is good to wrap error prone things in try block, so you might do this try %{ require-module luar; your-entire-plugin-code } catch %{ echo -debug "can't load for %val{error} reason } thing, and plug kak will simply do nothing in this case, and will be unable to detect missing dependency.

So we need a way to reason about dependencies.

The other problem is, that plugins should either specify a full URL to the plugin they depend on, so plug could use it to download plugin (which is dangerous and malicious), or we would need a central repository for plugins, like MELPA or ELPA for Emacs, or AUR in Arch Linux, which is harder and needs maintainers.

I’d like to make this as general and future proof as it can be. I’m not sure if plug.kak will be around in 5 years for example :slight_smile: but Kakoune, presumably, should be available, and plugins will still be made and depend on each other.