Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib/neovim-plugin: Add lazyLoad option to plugins #1875

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

psfloyd
Copy link
Contributor

@psfloyd psfloyd commented Jul 16, 2024

This PR is the second split of PR #1866, it works on a solution for the issue #421.
This PR depends on PR #1874.
All suggestions from the original PR are included.

Design description

The idea is to automatically create lazyLoad option for all plugins that are defined with mkNeovimPlugin.
lazyLoad is conformed by triggers (e.g. filetype, event, key, command) and actions (e.g. functions to run before/after loading the plugin). mkNeovimPlugin would also generate default values for some of these options (e.g. the setup).

Plugin maintainers can decide to not create the lazyLoad option, by setting allowLazyLoading to false when defining the plguin.

Plugin maintainers can provide sensible default values to lazyLoad when defining a plugin. For example, if defining telescope.nvim, set Telescope as a command trigger. Also defining a custom setup function if they are setting callSetup as false.

Finnally users can :

  • Enable lazy-loading (globally or on a per-plugin basis)
  • Add to these triggers (or override them with mkForce) on a per-plugin basis.
  • Override actions on a per-plugin basis.

Progress

  • Adding mkLazyLoadOption to generate lazyLoad options for plugins.
  • Conditionally enabling lazy or regular loading depending on user settings in mkNeovimPlugin.
  • Adding and implementing a lazy-loading mechanism using lz.n.
  • Adding and implementing a lazy-loading mechanism using lazy.nvim.
  • Assert that only one of the backends is enabled.
  • Conditionally enabling lazy or regular loading depending on user settings in mkVimPlugin.

@MattSturgeon MattSturgeon mentioned this pull request Jul 16, 2024
Copy link
Member

@MattSturgeon MattSturgeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my initial thoughts. Again, thanks for working on this!

plugins/languages/qmk.nix Outdated Show resolved Hide resolved
plugins/languages/qmk.nix Outdated Show resolved Hide resolved
lib/options.nix Outdated Show resolved Hide resolved
lib/neovim-plugin.nix Outdated Show resolved Hide resolved
lib/neovim-plugin.nix Outdated Show resolved Hide resolved
lib/helpers.nix Outdated Show resolved Hide resolved
@psfloyd
Copy link
Contributor Author

psfloyd commented Jul 17, 2024

To keep things organized i am going to wait for PR #1874 to be stabilised to keep working on this.
Also I updated the top comment with a design description, to review the general concept.

@MattSturgeon
Copy link
Member

Add to these triggers (or override them with mkForce) on a per-plugin basis.

Probably better to have our defaults set with mkDefault, allowing users to override without needing to resort to mkForce.

That's only a guideline though, not a rule. There may be times where a default is so sensible that it makes sense not to use mkDefault?

@arunoruto
Copy link

Seems like #1874 got morgen! I am hyped for this feature 🙌🏻
I hope I can move from helix back to neovim when this is implemented!

@psfloyd
Copy link
Contributor Author

psfloyd commented Aug 8, 2024

Now that #1874 has been merged I am going to rework this PR to work with that implementation. While working on #1874 I discovered some flaws in the draft implementation of this PR, that need to be addressed.
Later today I am going to update the first comment to better reflect the tasks that need to be done.

I am also going to integrate with the new helpers implementation from #1948.

It also would be nice to integrate lazyLoad options with configLua from #1876, when/if that gets merged.

@psfloyd
Copy link
Contributor Author

psfloyd commented Aug 9, 2024

I refactored the lazyLoad options, decupling them from the specific lz-n backend.
The first commit 894e190 is just for testing purposes. It can be removed at the end.

Copy link
Member

@MattSturgeon MattSturgeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is still a draft, so some of my feedback may be irrelevant. But here's some early feedback in the hopes it helps.

Thank you for your continued efforts!

@@ -47,6 +48,8 @@ let
dontRun ? false,
}:
lib.optionalString (!dontRun) ''
ln -s ${derivation} $out/${name}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this is a temporary debugging change, but I think this highlights another reason we should probably move back to using linkFarm instead of a custom derivation, even if it's still grouped on a per-test-file basis.

#1989 does this, among other things.

We could of course add the package being tested to passthru manually, but linkFarm does that for us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old implementation also didn't work for this kind of test. Because the linkFarm was of all the tests.
With this change I can build a specific test and run that nixvim instance to test functionallity inside neovim.

Maybe I missed a better way to achieve this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change I can build a specific test and run that nixvim instance to test functionality inside neovim.

I think what we want here is to be able to build a test's passthru to debug it. If the test fails, that's because it can't be built.

If I understand passthru correctly, it would allow us to bypass building the test derivation and instead use the derivation that was being tested.

In the case of a linkFarm we'd probably be building a passthru of a passthru, russian doll style.

This is something we ought to tackle in another PR, especially as our test infrastructure is somewhat in flux currently: #2015 #1989 #1986 etc

tests/test-sources/modules/lazy-load.nix Outdated Show resolved Hide resolved
lib/options.nix Outdated Show resolved Hide resolved
lib/options.nix Outdated Show resolved Hide resolved
lib/options.nix Outdated Show resolved Hide resolved
@psfloyd
Copy link
Contributor Author

psfloyd commented Aug 14, 2024

I just pushed an implementation for lazy loading with lz-n.
Because of the complexity and amount of lines, would it be better to split lazy loading implementations into a new file? Perhaps lib/lazy-load? What do you think?

Copy link
Member

@MattSturgeon MattSturgeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions and attempts to understand the changes 🙂

Comment on lines +144 to +147
(lib.removeAttrs (extraConfig cfg) [
"extraConfigLua"
"extraConfigLuaPre"
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a robust solution, we really need something like #1876 so that we can assign plugin-config to an option and then decide here how to use that option.

The problem is we're assuming extraConfig returns a "plain" attrset, instead of something like a mkIf, mkOverride, mkMerge, etc.

It's also kinda "pulling the rug out" from the module definition, which is expecting a config definition to actually add a definition to the respective option.

If we have an intermediate, plugin-specific option, this is more transparent and also exposes better hooks to end-users.

Comment on lines +157 to +164
if cfg.lazyLoad.after == null then
mkFn (
(extraConfig cfg).extraConfigLuaPre or ""
+ optionalString callSetup ''require('${luaName}')${setup}(${
optionalString (cfg ? settings) (helpers.toLuaObject cfg.settings)
}) ''
+ (extraConfig cfg).extraConfigLua or ""
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be the after option's default, instead of null? This if then else is effectively setting a default.

Don't mind too much if it is set with default in mkOption, or if we use lib.mkDefault in a config definition. We should probably also have a defaultText = literalExpression "" too, for transparency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is more complex because mkLazyLoadOption isn't given an actual option path, so it can't (truly) know which extraConfigLua definitions are being used, etc. Same for luaName, setup, etc.

We can still implement it as a ${namespace}.${name}.lazyload.after = mkDefault (mkFn ""), we just would struggle to document this in defaultText

Comment on lines +372 to +373
originalName,
lazyLoadDefaults ? { },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
originalName,
lazyLoadDefaults ? { },
pluginName,
defaults ? { },

@@ -47,6 +48,8 @@ let
dontRun ? false,
}:
lib.optionalString (!dontRun) ''
ln -s ${derivation} $out/${name}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change I can build a specific test and run that nixvim instance to test functionality inside neovim.

I think what we want here is to be able to build a test's passthru to debug it. If the test fails, that's because it can't be built.

If I understand passthru correctly, it would allow us to bypass building the test derivation and instead use the derivation that was being tested.

In the case of a linkFarm we'd probably be building a passthru of a passthru, russian doll style.

This is something we ought to tackle in another PR, especially as our test infrastructure is somewhat in flux currently: #2015 #1989 #1986 etc

@@ -43,9 +43,14 @@ with lib;
extraPackages ? [ ],
callSetup ? true,
installPackage ? true,
# lazyLoad
allowLazyLoad ? true,
packageName ? originalName, # Name of the package folder created in {runtimepath}/pack/start or {runtimepath}/pack/opt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not the same as luaName?

optionalPlugin =
x:
if isColorscheme then x else ((if x ? plugin then x else { plugin = x; }) // { optional = true; });
mkFn = str: if str != "" then "function()\n" + str + "end" else null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mkFn feels like an over-abstraction

Comment on lines +142 to +143
# Lazy loading with lz-n
(mkIf (lazyLoaded && config.plugins.lz-n.enable) (mkMerge [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it actually matters whether lz-n is enabled; we can define the config either way, it'll just have no effect, right?

We should probably assert somewhere that a supported lazy loading backend is enabled if the user has enabled lazyloading globally though.

@MattSturgeon
Copy link
Member

Because of the complexity and amount of lines, would it be better to split lazy loading implementations into a new file? Perhaps lib/lazy-load? What do you think?

I'm not sure. The stuff in lib/options.nix could be in its own file if you prefer.

I don't think the stuff in mkNeovimPlugin can be moved without major changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants