diff options
| author | Tim Keller <tjk@tjkeller.xyz> | 2026-07-31 16:20:53 -0500 |
|---|---|---|
| committer | Tim Keller <tjk@tjkeller.xyz> | 2026-07-31 16:20:53 -0500 |
| commit | 56b1314c4470f35ee4511fa29f8e137636accb1a (patch) | |
| tree | f3d910ad17955708530f20b90be779f40a8b5777 | |
| download | lazy-like-loader.nvim-56b1314c4470f35ee4511fa29f8e137636accb1a.tar.xz lazy-like-loader.nvim-56b1314c4470f35ee4511fa29f8e137636accb1a.zip | |
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | README.md | 62 | ||||
| -rw-r--r-- | lua/lazy-like-loader.lua | 70 |
3 files changed, 153 insertions, 0 deletions
@@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Tim Keller <tjkeller.xyz> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ad2ca6 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# lazy-like-loader.nvim +Lazy-like-loader is a plugin-loading plugin utilizing the builtin `vim.pack` +package manager, but incorporating a module-per-plugin loading paradigm like +[lazy.nvim](https://lazy.folke.io/) (see the way lazy does it +[here](https://lazy.folke.io/usage/structuring)). + +Lazy-like-loader uses similar (not identical) idiomatic "plugin spec" +conventions to [lazy's plugin spec](https://lazy.folke.io/spec), making it +convenient for those moving from lazy to `vim.pack` or other plugin management +solutions (e.g. adding plugins via a separate package manager like Nix). + +The loader can also be used to hierarchical loading via the `dependents` and +`dependencies` options in the plugin spec, and arbitrary functions can be setup +to run after loading via `loadFn`. + +The entire loader is hyper-minimal at only ~70 lines of lua. + +## Usage +Install the plugin using `vim.pack` (or another package manager if you'd like), +then initialize it like so: + +```lua +require("lazy-like-loader").setup { + package = "tjk.plugins", +} +``` + +The `package` option is required. It will point to the package containing all +your plugin modules. In this case: `~/.config/nvim/lua/tjk/plugins` (or +wherever your nvim home is). + + +Plugin modules can then be defined using the `plugin spec`, for example: + +```lua +-- autoclose.lua +return { + "autoclose", + "https://github.com/m4xshen/autoclose.nvim", + setup = { + options = { pair_spaces = true }, + }, +} +``` + +If the plugin cannot be loaded, then `source` will be passed to `vim.pack.add` +by default which will prompt the user to optionally install the plugin. +This behavior can be disabled by setting `packAddMissing = false` in `setup`. + +More examples can be found as part of my [neovim config here](https://git.tjkeller.xyz/nvim/tree/lua/tjk/plugins) + +## Plugin spec + +| Property | Type | Description | +|-------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] or moduleName | `string` | plugin name loaded via `require(moduleName)` | +| [2] or source | `string?` | plugin source, added via `vim.pack.add { source }` | +| dependencies | `plugin[]?` | table of plugins loaded before the initial plugin. same spec is used recursively | +| dependents | `plugin[]?` | table of plugins loaded after the initial plugin. same spec is used recursively | +| enabled | `boolean?` | whether to attempt to initialize the plugin the loader | +| loadFn | `fun()?` | runs after plugin and dependencies are successfully loaded, but before dependents | +| setup | `table` or `boolean?` | table passed to setup function. if unset or `false` then setup will not be ran. if `true` then opts is set to `{}`. otherwise opts is set to the value of `setup` | diff --git a/lua/lazy-like-loader.lua b/lua/lazy-like-loader.lua new file mode 100644 index 0000000..d17c91e --- /dev/null +++ b/lua/lazy-like-loader.lua @@ -0,0 +1,70 @@ +local M = { + package = nil, + packAddMissing = true, +} + +-- fancy plugin loader +function require_plugin(moduleName, source, setup, loadFn) + local ok, mod = pcall(require, moduleName) + if not ok then + if M.packAddMissing then + if not source then + vim.notify("Failed to load plugin module without source " .. moduleName, vim.log.levels.ERROR) + return + end + -- TODO track and do these all at once + vim.pack.add { source } + end + ok, mod = pcall(require, moduleName) + if not ok then + vim.notify(mod, vim.log.levels.ERROR) + return + end + end + if setup and mod.setup then + mod.setup(setup == true and {} or setup) + end + if loadFn then + loadFn() + end +end + +-- helper for handling dependencies and parsing module +function require_plugin_from_module(mod) + -- mod == true means it returned nothing + if mod == true or mod.enabled == false then + return + end + for _, dMod in ipairs(mod.dependencies or {}) do + require_plugin_from_module(dMod) + end + require_plugin(mod.moduleName or mod[1], mod.source or mod[2], mod.setup, mod.loadFn) + for _, dMod in ipairs(mod.dependents or {}) do + require_plugin_from_module(dMod) + end +end + +-- setup +local setup = function(opts) + -- handle missing opts + if not opts or not opts.package then + vim.notify("lazy-like-loader.setup invoked without required options ({ package = '' })", vim.log.levels.ERROR) + end + + -- handle opts + for k, v in pairs(opts) do + M[k] = v + end + + -- loop over plugins + local pluginsPath = vim.fn.stdpath("config") .. "/lua/" .. M.package:gsub("%.", "/") + for _, f in ipairs(vim.fn.glob(pluginsPath .. "/*.lua", false, true)) do + local name = vim.fn.fnamemodify(f, ":t:r") + local modName = M.package .. "." .. name + require_plugin_from_module(require(modName)) + end +end + +return { + setup = setup +} |
