🦥 lz.n
A dead simple lazy-loading Lua library for Neovim plugins.
It is intended to be used
- by users of plugin managers that don't provide a convenient API for lazy-loading.
- by plugin managers, to provide a convenient API for lazy-loading.
Note
Should I lazy-load plugins?
It should be a plugin author's responsibility to ensure their plugin doesn't unnecessarily impact startup time, not yours!
See our "DO's and DONT's" guide for plugin developers.
Regardless, the current status quo is horrible, and some authors may not have the will or capacity to improve their plugins' startup impact.
If you find a plugin that takes too long to load, or worse, forces you to load it manually at startup with a call to a heavy
setupfunction, consider opening an issue on the plugin's issue tracker.
🌟 Features
- API for lazy-loading plugins on:
- Events (
:h autocmd-events) FileTypeevents- Key mappings
- User commands
- Colorscheme events
- Events (
- Works with:
- Neovim's built-in
:h packpath(:h packadd) - Any plugin manager that supports manually lazy-loading plugins by name
- Neovim's built-in
- Configurable in multiple files
🌔 Introduction
lz.n provides abstractions for lazy-loading Neovim plugins,
with an API that is loosely based on lazy.nvim,
but reduced down to the very basics required for lazy-loading only.
🌌 Philosophy
lz.n is designed based on the UNIX philosophy: Do one thing well.
💤 Comparison with lazy.nvim
lz.nis not a plugin manager, but focuses on lazy-loading only. It is intended to be used with (or by) a plugin manager.- The feature set is minimal, to reduce code complexity
and simplify the API.
For example, the following
lazy.nvimfeatures are out of scope:- Merging multiple plugin specs for a single plugin (primarily intended for use by Neovim distributions).
lazy.vimcompletely disables and takes over Neovim's built-in loading mechanisms, including adding a plugin's API (lua,autoload, ...) to the runtimepath.lz.ndoesn't. Its only concern is plugin initialization, which is the bulk of the startup overhead.- Automatic lazy-loading of Lua modules on
require. - Automatic lazy-loading of colorschemes.
lz.nprovides acolorschemehandler in the plugin spec. - Heuristics for determining a
mainmodule and automatically calling asetup()function. - Abstractions for plugin configuration with an
optstable.lz.nprovides simple hooks that you can use to specify when to load configurations. - Features related to plugin management.
- Profiling tools.
- UI.
- Some configuration options are different.
📝 Requirements
Neovim >= 0.10.0
🔧 Configuration
You can override the function used to load plugins.
lz.n has the following default:
vim.g.lz_n = {
---@type fun(name: string)
load = vim.cmd.packadd,
}
📚 Usage
require("lz.n").load(plugins)
- plugins: this should be a
tableor astringtable:- A list with your Plugin Specs
- Or a single plugin spec.
string: a Lua module name that contains your Plugin Spec. See Structuring Your Plugins
Tip
You can call
load()as you would calllazy.nvim'ssetup(). Or, you can also use it to register individual plugin specs for lazy loading.
Plugin spec
| Property | Type | Description | lazy.nvim eqivalent |
|---|---|---|---|
| [1] | string |
The plugin's name (not the module name). | name1 |
| enabled | boolean? or fun():boolean |
When false, or if the function returns false, then this plugin will not be included in the spec. |
enabled |
| beforeAll | fun(lz.n.Plugin)? |
Always executed before any plugins are loaded. | init |
| before | fun(lz.n.Plugin)? |
Executed before a plugin is loaded. | None |
| after | fun(lz.n.Plugin)? |
Executed after a plugin is loaded. | config |
| event | string? or {event?:string|string[], pattern?:string|string[]}\ or string[] |
Lazy-load on event. Events can be specified as BufEnter or with a pattern like BufEnter *.lua. |
event |
| cmd | string? or string[] |
Lazy-load on command. | cmd |
| ft | string? or string[] |
Lazy-load on filetype. | ft |
| keys | string? or string[] or lz.n.KeysSpec[] |
Lazy-load on key mapping. | keys |
| colorscheme | string? or string[] |
Lazy-load on colorscheme. | None. lazy.nvim lazy-loads colorschemes automatically2 . |
| priority | number? |
Only useful for start plugins (not lazy-loaded) to force loading certain plugins first. Default priority is 50 (or 1000 if colorscheme is set). |
priority |
| load | fun(string)? |
Can be used to override the vim.g.lz_n.load() function for an individual plugin. |
None. |
User events
DeferredUIEnter: Triggered whenload()is done and afterUIEnter. Can be used as aneventto lazy-load plugins that are not immediately needed for the initial UI3 .
Examples
require("lz.n").load {
{
"neo-tree.nvim",
keys = {
-- Create a key mapping and lazy-load when it is used
{ "<leader>ft", "<CMD>Neotree toggle<CR>", desc = "NeoTree toggle" },
},
after = function()
require("neo-tree").setup()
end,
},
{
"crates.nvim",
-- lazy-load when opening a toml file
ft = "toml",
},
{
"sweetie.nvim",
-- lazy-load when setting the `sweetie` colorscheme
colorscheme = "sweetie",
},
{
"vim-startuptime",
cmd = "StartupTime",
before = function()
-- Configuration for plugins that don't force you to call a `setup` function
-- for initialization should typically go in a `before`
--- or `beforeAll` function.
vim.g.startuptime_tries = 10
end,
},
{
"nvim-cmp",
-- load cmp on InsertEnter
event = "InsertEnter",
},
{
"dial.nvim",
-- lazy-load on keys. -- Mode is `n` by default.
keys = { "<C-a>", { "<C-x>", mode = "n" } },
},
}
paq-nvim example
require "paq" {
{ "nvim-telescope/telescope.nvim", opt = true }
{ "NTBBloodBatch/sweetie.nvim", opt = true }
}
require("lz.n").load {
{
"telescope.nvim",
cmd = "Telescope",
},
{
"sweetie.nvim",
colorscheme = "sweetie",
},
}
Nix (Home Manager) example
programs.neovim = {
enable = true;
plugins = with pkgs.vimPlugins [
lz-n
{
plugin = pkgs.vimPlugins.telescope-nvim;
config = ''
require("lz.n").load {
"telescope.nvim",
cmd = "Telescope",
}
'';
type = "lua";
optional = true;
}
{
plugin = pkgs.vimPlugins.sweetie-nvim;
config = ''
require("lz.n").load {
"sweetie.nvim",
colorscheme = "sweetie",
}
'';
type = "lua";
optional = true;
}
];
};
Structuring Your Plugins
As is the case with lazy.nvim, you can also split your plugin specs
into multiple files.
Instead of passing a spec table to load(), you can use a Lua module.
The function will merge specs from the module and any top-level sub-modules
together in the final spec, so it is not needed to add require calls
in your main plugin file to the other files.
Example:
~/.config/nvim/init.lua
require("lz.n").load("plugins")
~/.config/nvim/lua/plugins.luaor~/.config/nvim/lua/plugins/init.lua(this file is optional)
return {
{ "sweetie.nvim" },
{ "telescope.nvim", cmd = "Telescope" },
}
lz.nwill automatically merge any Lua file in~/.config/nvim/lua/plugins/*.luawith the main plugin spec4 .
Example structure:
── nvim
├── lua
│ └── plugins # Your plugin specs go here.
│ └── init.lua # Optional top-level module returning a list of specs
│ └── neorg.lua # Single spec
│ └── telescope/init.lua # Single spec
├── init.lua
Or
── nvim
├── lua
│ └── plugins.lua # Optional top-level module returning a list of specs
├── init.lua
💚 Contributing
All contributions are welcome! See CONTRIBUTING.md.
📖 License
This library is licensed according to GPL version 2 or (at your option) any later version.
-
In contrast to
lazy.nvim'snamefield, alz.n.PluginSpec'snameis not optional. This is becauselz.nis not a plugin manager and needs to be told which plugins to load. ↩︎ -
The reason this library doesn't lazy-load colorschemes automatically is that it would have to know where the plugin is installed in order to determine which plugin to load. ↩︎
-
This is equivalent to
lazy.nvim'sVeryLazyevent. ↩︎ -
It does not merge multiple specs for the same plugin from different files. ↩︎