Open GaetanLepage opened 1 year ago
A (relatively) easy way to do this, compared to lazy.nvim
's approach of basically redoing the whole lazy-loading machinery in neovim, is to make use of optional plugin loading - this is supported, I don't really remember how, but it's a matter of checking how wrapNeovim
works.
This way, we can :packadd
the packages only when they're needed - AFAIK this is basically how plugin lazy-loading has been done in the past.
Second, probably easier, option - the vast majority of the plugins we support are lua-based plugins. The majority of the loading time there is spent on the setup
function. What if we just avoid calling that function until it's needed?
Either way, I will be looking into how lazy-loading in neovim has been traditionally done, since I don't have much experience with it, and will try to come up with some way it could work.
Also, another feature lazy.nvim
supports is bytecode pre-compilation. This is actually totally something we could do! Basically just need to wrap the plugin's derivations to add that. Something to look into, but I'd say this is better off as a separate feature.
Some references:
:packadd
the plugin when they're called, or wait for an autocommand to load them.Either way, I will be looking into how lazy-loading in neovim has been traditionally done, since I don't have much experience with it, and will try to come up with some way it could work.
Great ! Thanks and good luck :) Feel free to open a PR as soon as you have a draft so that I can help and provide feedback :)
Yesterday I found out about nixvim. I'm already using home-manager. I'm not sure I would migrate though. I do some customization for neovim loading to greatly improve startup time and I'm not sure I can insert nixvim in that process. But the project looks interesting. Still I wanted to comment about lazy loading. What I think is most important for startup time are:
1) Reducing vim.api.nvim_list_runtime_paths()
. It's an actual search path where neovim will look for files. More plugins, longer the list. What is even worse in nix ecosystem is that every tree-sitter parser is actually a separate plugin. So when you are installing all parsers, your list_runtime_paths
contains hundreds of entries. It's very bad for startup time. Just merging all parsers to a single plugin with symlinkJoin
can greatly reduce startup time. But I went even further. I merged all plugins into one plugin pack with buildEnv
. So my list_runtime_paths
contains only 6 entries (.config/nvim
, vim-pack-dir
, vim-pack-dir/pack/myNeovimPackages/start/plugin-pack
, nvim/runtime
, vim-pack-dir/pack/myNeovimPackages/start/plugin-pack/after
, .config/nvim/after
).
vim.loader
can alleviate a long search path, because it caches directories, so nvim will not search in very directory. But vim.loader
is only for lua files. Neovim also scan all directories for plugins, ftplugins, syntax and so on. So reducing list_runtime_paths
improves things every time you load a buffer (because of autocommands scanning for ftplugin, syntax, indent).
Overall reducing vim.api.nvim_list_runtime_paths()
gave me the biggest impact. But unfortunately it's not an universal solution, because of file collisions. I'm currently removing help tags in every plugin and generating a new one for the entire pack. Also I'm limiting linked directories with pathsToLink
.
2) Byte-compiling every lua file. With nix we have a build step, so it's better to do a compilation beforehand, and not cache during startup. I compile every lua file: every file in every plugin, every file in my .conf/nvim
directory, init.lua
, and nvim runtime directory. I have a build hook that does that. As a result I have a fast startup time even on first startup and I don't pollute .cache/nvim
with thousands of compiled lua files (with nix every new configuration has different path, so there are a lot of old files there). I don't use vim.loader
at all. With both 1 and 2 I have even faster startup time than vim.loader
. There is one caveat: lua-language-server
can't parse compiled files. As a workaround I save a list of directories with original files in json and load it to lua_ls
config.
3) Reduce a number of required lua files. Usually it means not using heavy functions as callbacks for mappings. I mean do something like callback = function() require("plugin.functions").do_something() end
. But you don't need to do it if require("plugin").setup()
already pulling all relevant files, you won't improve speed in that case, rather the opposite (every time you use that binding).
4) I don't do it personally, but it's possible to defer plugin setup on some event (like mapping or command). packadd
will increase vim.api.nvim_list_runtime_paths()
for my case, so I never use optional plugins.
So even not doing any lazy-loading I have a decent startup time. Without all these optimizations vim.loader
greatly improves things. But 1) improves it even further. Maybe some of it can be implemented in nixvim. For example merging treesitter parsers in one plugin (minus 200 to vim.api.nvim_list_runtime_paths()
) and byte-compiling init.lua
(vim.loader
doesn't compile it, because it's enabled after).
Thank you so much @stasjok for this great insight of your config ! This will surely help once we will tackle the performance issue seriously.
I'm not using nixvim either because I need the lazy-loading but I'd like to chip in an idea. If you're willing to outsource some of the code, I'd suggest using lazy.nvim seeing as it's pretty good at lazy-loading + it would reduce the maintenance burden for developing nixvim. Its variety of options and features could come in handy. It even has async execution and automatic caching and bytecode compilation of Lua modules for improved performance. You could provide options to configure it in nix and then translate that to lua like you do with the rest of nixvim. Lazy's dir
option could be used to specify the path to the plugin in the nix store. For plugins not available in the nix repos, you could generate packages (see how they do it in the nix repos) or even just let lazy.nvim handle it internally (using git) if you don't mind installing stuff outside of the nix store.
I've written some examples below to illustrate the idea.\ The nix file:
{
plugins.lazy = {
enable = true;
# install any plugin available in the nix repos
nix = {
# this installs vimPlugins.neorg
neorg = {
build = ":Neorg sync-parsers";
dependencies = [
# these are all from the nix repos too
# they load when Neorg loads
plenary-nvim
nvim-treesitter
neorg-telescope = {
dependencies = [ telescope-nvim ];
config = ''
-- this is lua code
-- it does not get loaded until neorg-telescope is loaded
vim.wo.foldlevel = 99
'';
};
];
cmd = "Neorg";
ft = "norg";
keys = "<c-t>n";
# sometimes we like to keep the config in a different file
# so source it from elsewhere
config = import ./neorg.nix;
};
nvim-colorizer-lua = {
cmd = "ColorizerToggle"; # only load colorizer when I use :ColorizerToggle
config = ''
-- more lua code
vim.g.termguicolors = true,
require("colorizer").setup()
'';
};
};
# obscure plugin that isn't available in the nix repos
git."Vonr/align.nvim" = {
branch = "v2";
# only load align.nvim when the user presses <leader>a in visual mode
keys = [
{ "<leader>a"; mode = "v"; };
];
config = ''
vim.keymap.set(
'v',
'<leader>a',
function()
require'align'.align_to_string({
preview = true,
})
end,
{ noremap = true, silent = true }
)
'';
};
};
}
This would install pkgs.vimPlugins.lazy-nvim
, pkgs.vimPlugins.neorg
, pkgs.vimPlugins.nvim-colorizer-lua
, pkgs.vimPlugins.plenary-nvim
, pkgs.vimPlugins.nvim-treesitter
, pkgs.vimPlugins.neorg-telescope
and pkgs.vimPlugins.telescope-nvim
.
It would also generate a lua file that looks something like this:
-- add lazy.nvim to the runtime path
vim.opt.rtp:prepend("/nix/store/rjkwbzdmdfp9gfrvi0rch5g5illqwbgf-vimplugin-lazy.nvim-2023-08-26")
require("lazy").setup({
{
name = "neorg",
dir = "/nix/store/iwxg2w4blbphyk7yvf7drqkmf8qfyv4x-vimplugin-neorg-2023-09-15",
build = ":Neorg sync-parsers",
dependencies = {
{ name = "plenary.nvim", dir = "/nix/store/4f17ss3v7lv580hmca8pc2q3zn33lqk4-lua5.1-plenary.nvim-2023-09-12" },
{ name = "nvim-treesitter", dir = "/nix/store/vp0lhrdzvknz7rb8pc6ndvv28cgsfy14-vimplugin-nvim-treesitter-2023-09-16" },
{
name = "telescope.nvim",
dir = "/nix/store/1ldgn56d6sgmk42n6dna3b91w3si3sn7-lua5.1-telescope.nvim-2023-09-16",
dependencies = { name = "neorg-telescope", dir = "/nix/store/rvg763iaqbx3czb52ghrsxhidvqqgwbk-vimplugin-neorg-telescope-2023-08-06" },
config = function()
-- this is lua code
-- it does not get loaded until neorg-telescope is loaded
vim.wo.foldlevel = 99
end,
},
},
cmd = "Neorg",
ft = "norg",
keys = "<c-t>n",
config = function()
require("path.to.neorg.config")
end,
},
{
name = "nvim-colorizer.lua",
dir = "/nix/store/03k72h7x4m543z7vrqjwbvqjx6j789qg-vimplugin-nvim-colorizer.lua-2023-02-27",
cmd = "ColorizerToggle",
config = function()
-- more lua code
vim.g.termguicolors = true,
require("colorizer").setup()
end,
},
{
"Vonr/align.nvim",
branch = "v2",
keys = {{ "<leader>a", mode = "v" }},
config = function()
vim.keymap.set(
'v',
'<leader>a',
function()
require'align'.align_to_string({
preview = true,
})
end,
{ noremap = true, silent = true }
)
end,
},
})
Note that you shouldn't try to lazy-load lazy.nvim or the colourscheme. These should be loaded on startup.
As a related sidenote, you can install stuff with lazy.nvim without lazy-loading them by using the lazy = false
option. If you choose to load the colourscheme plugin using lazy, it's also good practise to use priority = 1000
to make sure it loads before all other plugins.
Cut me some slack if any of the nix or lua code above has mistakes. I'm pretty new to both languages and have so far not used them for anything besides configuring NixOS/home-manager and Neovim.
Oh btw, I came across another project called nixneovim, which seems to have pretty much the same goal as you. I don't believe they do lazy-loading but maybe some of their stuff would interest you, such as their auto-updated plugins repo.
Thanks for the link @koalagang ! I knew that this project existed (it was forked from nixvim a while ago). However, I wasn't aware that they had their own repo. We used to have an infrastructure to package plugins ourselves within nixvim but we have removed it at some point. Indeed, we now prefer the approach of upstreaming all missing plugins to nixpkgs. This makes the user experience a smoother. The only downside is that the users of the stable branch might not get the new/updated plugins. I am not aware of any backporting of the plugins by nixpkgs maintainers... (@teto am I right here ?). Anyway, we don't backport our updates to the nixvim stable branch.
I am not aware of any backporting of the plugins by nixpkgs maintainers... (@teto am I right here ?).
you are right, no backporting. It's not critical software + we usually dont run the tests (when there are tests !) so backporting would be tricky. Plus the tooling is not great.
auto-updated plugins repo.
I am glad to learn about this, I've wanted to see this (not use it though) so that users can contribute to the nixpkgs plugin updater. Haven't seen much contribution from the usual contributors sadly.
@teto if you are interested I have a different approach for my plugin management:
plugins repo uses their own updater so I better understand why they dont contribute to upstream. Would be interesting to compare the features of both and see if we can merge both approaches.
@traxys > I've seen that approach before. it's LGTM and to some extent, I wish we would leverage nix flake archive in the upstream updates like it's done for treesitter grammars already. Configuring neovim via nix is a bit tedious for most things so I use it only when the trade off is positive (plugins with complex dependencies and that) so I maintain a hybrid config with lazy to install hte other half of my plugins.
@GaetanLepage I definitely agree that upstreaming plugins is ideal but surely users should have access to a way of installing plugins that haven't been upstreamed? If one wants a plugin immediately and said plugin is not in the nix repos then what would one do? Of course, you should then ask for this to be added and upstreamed so that all users can benefit but I don't think users should be forced to do this, especially considering that, like you rightfully said, those not on the unstable channel would have to wait for a whole new release to install those plugins. There should be some way of grabbing it straight from a git repo just like traditional vim plugin managers do. I think perhaps pkgs.fetchFromGitHub
like how zsh's home-manager module does it could work well, though having to specify the revision and sha256 might be annoying if you regularly update your plugins (which I assume most Neovim users do).
Anyway, this might be diverging slightly from the topic of how Nixvim is going to handle lazy-loading.
though having to specify the revision and sha256 might be annoying if you regularly update your plugins
If you're okay with having flakes as a requirement, you can use builtins.fetchTree
instead. It allows you to fetch repos with only the commit hash.
But I do like the idea of generating lazy.nvim
configuration though. Might be worth exploring.
@musjj Haha I just discovered like 15 minutes after posting my comment that this is what flakes do 😅 I have my entire NixOS/home-manager setup inside a flake so no worries about adding that as a dependency for me personally, though perhaps others might be hesitant.
But yeah, again I like the idea of using lazy.nvim. It should possible be to do it with home-manager rather than with nixvim, which I am considering. If, instead of using programs.neovim.plugins
, you use programs.neovim.extraLuaConfig
then you could pass in a lua config that uses lazy.nvim but inside the dir
option use ${pkgs.vimPlugins.yourplugin}
.
So for example:
{ pkgs, ... }:
{
programs.neovim.extraLuaConfig = ''
-- this is lua code
vim.opt.rtp:prepend(${pkgs.vimPlugins.lazy-nvim})
require("lazy").setup({
{
name = "nvim-colorizer.lua",
dir = "${pkgs.nvim-colorizer-lua}",
cmd = "ColorizerToggle",
config = function()
vim.g.termguicolors = true,
require("colorizer").setup()
end,
},
})
'';
}
Note that name
is optional. It's just nice to have because otherwise the Lazy UI will show /nix/store/03k72h7x4m543z7vrqjwbvqjx6j789qg-vimplugin-nvim-colorizer.lua-2023-02-27
as the plugin's name.
The only difference between this and my suggestion earlier was basically that nixvim could do this but allowing the user to write it directly in nix rather than embedding lua code into a nix file.
P.s. I've never done this nor have I seen it being done. It's just something that, logically, I think would work.
There should be some way of grabbing it straight from a git repo just like traditional vim plugin managers do. I think perhaps
pkgs.fetchFromGitHub
like how zsh's home-manager module does it could work well, though having to specify the revision and sha256 might be annoying if you regularly update your plugins (which I assume most Neovim users do).
If, instead of using
programs.neovim.plugins
, you useprograms.neovim.extraLuaConfig
then you could pass in a lua config that uses lazy.nvim but inside thedir
option use${pkgs.vimPlugins.yourplugin}
.P.s. I've never done this nor have I seen it being done. It's just something that, logically, I think would work.
Are plugin versions locked with lazy.nvim
like with pure Nix?
lazy.nvim has a json lockfile that stores the branch and commit for each dependency that it pulls via git. I'm not sure how it handles local directory dependencies.
@trueNAHO
As @bmanuel rightfully said, if pulling via git then it will use its own lockfile implementation (lazy-lock.json
). If you're pulling the plugins via nix as I demonstrated above, it will save this to your flake.lock
if you're a flakes user. If you're using nix for installing the plugins but but you're not using a flake then there will be no lockfile.
@koalagang I agree, the goal is not to force the user to upstream packages. Right now there exists two ways of using plugins in nixvim that are not packages in nixpkgs:
buildPluginFromNix
in your config to create a package for the missing pluginsplugins.packer
plugin manager to manage your plugins the traditional way (like you would do on another distro)if pulling via git then it will use its own lockfile implementation (
lazy-lock.json
). If you're pulling the plugins via nix as I demonstrated above, it will save this to yourflake.lock
if you're a flakes user. If you're using nix for installing the plugins but but you're not using a flake then there will be no lockfile.
This sounds like we could encapsulate the entire lazy.nvim
plugin as a Nixvim module without any reproducibility issues.
A lazy.nvim module sounds great, although I still think the original proposal of doing as much as possible in nix (at build time) is the ideal.
That said, perfection is the enemy of good...
Just popping back in here to add a datapoint for lazy.nvim:
We used to have a module for a popular nvim package manager (packer? I forget...). It's what was used before to install packages outside of Nix, but had some issues.
Either way, I'm not particularly opposed to having lazy.nvim
as a module, but IMO that's orthogonal to this issue. We have the opportunity to have this done reproducibly at build time, and IMO we should try to do that.
I don't really see a reason not to have both.
I still think the original proposal of doing as much as possible in nix (at build time) is the ideal.
Indeed! Otherwise, IIRC lazy.nvim
downloads and installs unavailable plugins only when launching nvim
, which is opposed to Nix' build time. Personally, I prefer a fully reproducible all-inclusive Nix installation over a redeployable Nix installation that partially relies on bootstrapping.
I don't really see a reason not to have both.
We could trigger lazy.nvim
's installation command during Nix' build time to ensure plugins are downloaded and installed at build time.
We could trigger
lazy.nvim
's installation command during Nix' build time to ensure plugins are downloaded and installed at build time.
Not sure that's easily done given Nix's sandboxing. However we can definitely look at how lazy.nvim works under the hood, and even try to use some of its code.
@trueNAHO
Indeed! Otherwise, IIRC
lazy.nvim
downloads and installs unavailable plugins only when launchingnvim
, which is opposed to Nix' build time. Personally, I prefer a fully reproducible all-inclusive Nix installation over a redeployable Nix installation that partially relies on bootstrapping.
The original proposal was to use a nix config (with builtins.fetchTree
, etc.) which is then converted into a lazy.nvim config. The plugins will be retrieved by nix itself, so no run-time bootstrap will be required.
Though I do agree that a pure nix solution would be the most ideal.
@pta2002
I'd like to clarify the idea more explicitly. The proposal with lazy.nvim was not for it to install plugins (although that certainly could be exposed as an option for those who want it). Plugins can be installed by nix at build time (including lazy.nvim itself using pkgs.vimPlugins.lazy-nvim
) without the help of lazy. So you might then ask "well what's the point in a plugin manager if you're not using it to install plugins?". The reason to do this is that lazy.nvim does more than just installing plugins. It allows the user to configure Neovim to only load plugins into memory after particular conditions are met, e.g. load Neorg when opening .norg
files; load hop.nvim when you press the f
key; load oil.nvim when you use the :Oil
command; etc.
Additionally, lazy.nvim's config
option allows you to pass in configurations specific to the plugins and these configurations will only be loaded when the plugins are loaded. We could actually do this in a nice nix way by having the nixvim plugin options people use placed into this at build time.
For example, if the user sets plugins.nvim-colorizer.fileTypes
to css and javascript then the following would be generated:
{
name = "nvim-colorizer",
-- path to plugin in the nix store (installed at build time)
dir = "/nix/store/03k72h7x4m543z7vrqjwbvqjx6j789qg-vimplugin-nvim-colorizer.lua-2023-02-27",
config = function()
-- config generated by nixvim's nvim-colorizer module
require 'colorizer'.setup {
'css';
'javascript';
}
end,
},
As you can see, we're installing the plugin using nix and then just pointing lazy.nvim to the location of the plugin in the nix store so that it can handle the lazy-loading and we're generating the plugin's lua configuration at build time. If the user, for instance, wants to lazy-load it with the :ColorizerToggle
command, we could expose lazy's cmd
option to nix. Perhaps the user can set plugins.nvim-colorizer.cmd = "ColorizerToggle"
and then this will be added in the appropriate part of the generated lua file.
I'm not sure if there's a more pure nix way of doing it since you'll have to generate the lua code anyway as Neovim doesn't natively understand nix but I agree with everyone that we should use as much nix as possible.
I'm not sure if there's a more pure nix way of doing it since you'll have to generate the lua code anyway as Neovim doesn't natively understand nix but I agree with everyone that we should use as much nix as possible.
I'm not really sure there's any need for that in that case. Seems like we're just using lazy.nvim as a library at this point, which I have no real objection to, though in that case it might be better to fork it ourselves and create a more special-purpose thing.
Still though, as was said before, perfect is the enemy of good. If we go with this approach I don't really have any objections, especially considering it can be spun off later fairly transparently to the end-user.
IMO the course of action for this would therefore be:
lazy.nvim
module.lazy.nvim
lazy.nvim
CC: @nix-community/nixvim. If everyone agrees, I can create a project board and the required issues.
Perhaps we could have a "loading method" option which is an enumeration of:
default
- use vim's default plugin loadinglualoader
- replaces the existing lualoader.enable
optionlazy.nvim
- use lazy.nvim to load pluginslazy.nixvim
(placeholder name) - use custom lazy loading, mostly defined at build timeThis approach means we have a central way of selecting how plugins are loaded, seeing as (I assume) each approach will conflict the others.
Alternatively, these could each be separate enable options, and we could panic if more than one is enabled.
The proposed cmd
plugin option could be documented as "only support when loading.method
is set to lazy.nvim
or lazy.nixvim
". A trace warning could be printed if used without a supported loading method.
Having a centralised way of specifying the loading backend means supporting one method (lazy.nvim
) does not block later supporting another.
I agree with the enum, IMO it's the best option. Removes a lot of need for assertions.
@pta2002
I'm not really sure there's any need for that in that case. Seems like we're just using lazy.nvim as a library at this point, which I have no real objection to, though in that case it might be better to fork it ourselves and create a more special-purpose thing.
Entirely possible, though as you stated further down in the comment, we should probably wait until later before forking. I'd suggest taking a look at lazy's plugin spec for ideas. The most important options for lazy-loading imho are cond
, dependencies
, config
, event
, cmd
, ft
and keys
.
From lazy.nvim's README:
[Dependenices are a] list of plugin names or plugin specs that should be loaded when the plugin loads. Dependencies are always lazy-loaded unless specified otherwise. When specifying a name, make sure the plugin spec has been defined somewhere else.
Note that, traditionally, the user has to manually mark plugins as dependencies but you could perhaps make nixvim aware of what plugins are dependencies of other plugins. I would suggest also making it possible to manually mark dependencies though as this can be useful in some situations where a plugin isn't necessarily an actual dependency of another. For example, in my config I have oil.nvim marked as a dependency of telescope-zoxide so that oil loads when I load telescope-zoxide. You could argue that this is a bit of a hack, though, and that this should be handled differently.
Useful lazy.nvim options that are unrelated to lazy-loading but more so about how to install plugins include build
, branch
, tag
, commit
and version
, though I'm not sure how this would be handled in a nix fashion. I don't believe nixvim could make use of these lazy.nvim options if we're installing plugins with nix but nix has its own options for these, doesn't it? (Again, I'm quite new to nix yet so excuse my ignorance.) It is important to implement these somehow, though. build
is important for build options, though this is usually something like compiling treesitter parsers or installing a nodejs package, which can all just be installed by nix at build time. However, it should perhaps be made possible to use even for packages not available in the nix repos, such as for installing telescope-fzf-native's C implementation of the fzf algorithm. branch
, tag
and version
are important for choosing particular versions of a plugin; for example, telescope's main branch is used for development and is, thus not as stable so it's recommended to use the 0.1.x
branch.
Edit: come to think of it, maybe these options are handled by upstream, at least branch
, tag
, commit
and version
.
@MattSturgeon
This approach means we have a central way of selecting how plugins are loaded, seeing as (I assume) each approach will conflict the others.
Yup. It would also modularise and future-proof the project more because you can really easily just keep adding more methods if you want to / if particular methods are requested.
Also, remember that, regardless of what method the user goes for, you should set the colourscheme plugin to be the first plugin (other than the plugin manager itself) to load to avoid race conditions where some plugins are loaded before the colourscheme, causing them not to have the right colours. With lazy.nvim this can be done by setting priority = 1000
for the colourscheme plugin.
I'm not really sure there's any need for that in that case. Seems like we're just using lazy.nvim as a library at this point, which I have no real objection to, though in that case it might be better to fork it ourselves and create a more special-purpose thing.
Entirely possible, though as you stated further down in the comment, we should probably wait until later before forking.
Keeping a special-purpose lazy.nixvim
(name subject to change) fork introduces an additional layer of maintainance. Unless this adds tremendous value, we might want to avoid forking it.
Alternatively, we could try to merge our required features into lazy.nvim
. Although, it seems doubtful whether lazy.nvim
should support alternative frameworks in the first place.
Keeping a special-purpose
lazy.nixvim
(name subject to change) fork introduces an additional layer of maintainance. Unless this adds tremendous value, we might want to avoid forking it.
That item in the enum wasn't supposed to hint at a fork (poor naming on my part).
Rather it was supposed to represent the original proposal of this issue; lazy loading without using a plugin management plugin, or in other words a solution implemented at build time.
As has been discussed above, this should be possible with minimal lua code. It'll just take a fair bit more time & effort than a solution that utilizes lazy.nvim
lazy.nvim [has] options that are unrelated to lazy-loading but more so about how to install plugins, [...] though I'm not sure how this would be handled in a nix fashion.
All installation should be handled by nix, not at runtime. Therefore these options wouldn't be used. Instead the dir
option would be used to tell lazy.nvim where nix installed the plugin. As per this comment and this one.
Rather it was supposed to represent the original proposal of this issue; lazy loading without using a plugin management plugin, or in other words a solution implemented at build time.
But what do you mean by lazy-loading at build time? You need a plugin of some sorts to listen for input (such as commands, keys, etc.) whilst the user is using Neovim. That's not something you can do at build time. Do you mean like generating autocmds?
lazy.nvim [has] options that are unrelated to lazy-loading but more so about how to install plugins, [...] though I'm not sure how this would be handled in a nix fashion.
All installation should be handled by nix, not at runtime. Therefore these options wouldn't be used. Instead the
dir
option would be used to tell lazy.nvim where nix installed the plugin. As per this comment and this one.
Yes, I agree that it should be handled by nix. The point I was making was not that we should use those lazy.nvim options but I was just suggesting that perhaps the user being able to choose, for example what branch they want, could perhaps be a good thing. This would likely require them to use buildPluginFromNix
though if they wanted to change it, as upstream nixpkgs chooses the branch.
Anyway, regardless of which route nixvim ultimately takes, it might be best to start with a lazy.nvim module that provides all of its options and then aim to develop an in-house method later down the line if it's deemed necessary.
Seeing how this is going, I'm going ahead and creating an issue for lazy.nvim
to be added as a module.
Even if we end up going with another route, it's still a nice to have.
@pta2002 I take it that all new discussion regarding lazy.nvim should happen in #797 now but this issue will remain open for nixvim's in-house lazy-loading implementation then?
Yes!
Btw, in regards to lazy.nixvim (I'm assuming that's the placeholder name we're going with for nixvim's in-house lazy-loading) do you believe it would make sense to have some sane defaults? I'm thinking perhaps there could be some option like lazy.saneDefaults
for this which is false
by default so that users don't experience unexpected behaviour but it could help for those who aren't experienced with configuring lazy-loading or can't be bothered to configure it (which there seems to be a lot of judging by how many dotfiles I've seen which load all their plugins on startup). For example, setting Neorg to load on .norg
filetypes or when using :Neorg
, as well as loading nvim-cmp on the InsertEnter
event (when you enter insert mode) seems sensible to me.
I know this feature isn't exactly the next step in the plan but I figured I may as well post it here now since I just had the thought and perhaps you could look back on the issue later down the line.
When it comes to the sane defaults, yeah, not really oposed to that. Honestly I think some plugins already sort of do that, with an option to disable it per-plugin, so maybe we could do it that way. Don't know, though.
I have just came across this: https://github.com/b-src/lazy-nix-helper.nvim I haven't really looked at what it does though.
I have just came across this: https://github.com/b-src/lazy-nix-helper.nvim I haven't really looked at what it does though.
It is a neovim plugin that provides a function to search the /nix/store
for a specified neovim plugin.
Essentially you set dir = require("lazy-nix-helper").get_plugin_path("my-cool-plugins-dep")
in your lazy.nvim config and get_plugin_path
will try and find my-cool-plugins-dep
in the nix store.
If get_plugin_path
can't find my-cool-plugins-dep
, it'll return nil
and lazy.nvim will install the plugin itself.
If my-cool-plugins-dep
was found, then get_plugin_path
returns the path where it is installed. lazy.nvim will use that instead of installing the plugin itself.
All this happens at runtime (in lua), so it isn't the approach nixvim would take. It is useful for people who want to maintain a neovim config that can be used with or without a nix installation.
Ok, I see. Thank you for the explanation. Not really what we look for, because we would know in advance the paths to the different plugins.
I've been experimenting after finding this: https://github.com/azuwis/lazyvim-nixvim/blob/master/flake.nix. It uses the full blown lazy distro though, which isn't what I am interested in. I've gotten a PoC working that loads the plugins via lazy, also added the ability to add a setup config that can be passed on, but, I cannot use any of the prebuilt configuration options as they need the plugin activated, which then uses the default plugin loading mechanism, which defeats the purpose... who'd be willing to walk me through the setup of this project so I can determine where the best place would be to add a configurable hook that allows overriding the default loading mechanism?
Have done some more digging through the code base, I'm assuming this is where we could hook into ensuring only the plugin-manager is passed on. Obviously we'd have to then still use the list to ensure the configurations are applied however the chosen plugin-manager needs them...
Recently we introduced new helpers to create plugin modules (mkVimPlugin
/ mkNeovimPlugin
).
Although it was not the primary intent, they will surely make it easier to draft an implementation of lazy loading.
Indeed, it now gets quite easy to isolate the configuration of each plugin and to add new options to all plugins directly (lazyLoad.enable
, lazyLoad.event
...).
So... it looks like to use the new lazy module we ("we" being me, someone just using nixvim who doesn't really know what's going on) have to re-do how we setup plugins so they can be loaded with lazy? Is that something I should be doing, or is it going to change soon and we're in kindof an interim state at the moment?
to use the new lazy module we have to re-do how we setup plugins?
Currently, yes.
Is that something I should be doing,
If you want to try out lazy loading now, yes. If you don't like re-doing your config, no.
or is it going to change soon and we're in kindof an interim state at the moment?
The plan is to add a lazy
options set to all the plugin modules. When that'll happen is up in the air. Currently nobody has enough time/interest, but hopefully soon someone will.
to use the new lazy module we have to re-do how we setup plugins?
Currently, yes.
Is that something I should be doing,
If you want to try out lazy loading now, yes. If you don't like re-doing your config, no.
or is it going to change soon and we're in kindof an interim state at the moment?
The plan is to add a
lazy
options set to all the plugin modules. When that'll happen is up in the air. Currently nobody has enough time/interest, but hopefully soon someone will.
I had an idea what if lazy.nvim had an option that affects all plugins to lazy load the option could be programs.lazynvim.loadlazy
This library could be useful: https://github.com/nvim-neorocks/lz.n
I had an idea what if lazy.nvim had an option that affects all plugins to lazy load the option could be
programs.lazynvim.loadlazy
I was just thinking this actually; if I could just enable it then set lazy loading options based on filetype or something and then just enable plugins.lazy
and have all the plugins automatically use lazy.nvim, that'd be awesome.
-->Summary: https://notes.glepage.com/rA_fyfKESvC9OxGGNHOYXw#Lazy-Loading <--
Currently, nixvim relies on the neovim built-in way of loading plugins. This is implemented by nixpkgs neovim's module. It has the advantage of existing and leveraging the collection of plugins packaged in nixpkgs.
With that said, the very popular
lazy.nvim
plugin manager proposes a more performant way of loading plugins. Imitating their lazy loading process could be a very valuable addition to nixvim. I would guess that this feature should be optional so that conventional loading would stay the default.As of today, no-one has started to work on this issue. Feel free to go and make a PR, even if the work is in draft-stage. I will personally be glad to review and discuss a proposed implementation.