From d4a2eebb84b1c000a8388e167be3cb8f9d1edfe4 Mon Sep 17 00:00:00 2001 From: Marc Jakobi Date: Mon, 10 Jun 2024 15:43:25 +0200 Subject: [PATCH] feat: handler for lazy-loading colorschemes --- README.md | 10 ++++++ lua/lz/n/handler/colorscheme.lua | 53 ++++++++++++++++++++++++++++++++ lua/lz/n/handler/init.lua | 2 ++ lua/lz/n/meta.lua | 4 +++ lua/lz/n/spec.lua | 17 +++++++++- spec/colorscheme_spec.lua | 20 ++++++++++++ 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 lua/lz/n/handler/colorscheme.lua create mode 100644 spec/colorscheme_spec.lua diff --git a/README.md b/README.md index 9838e91..bbe40c1 100755 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ but reduced down to the very basics required for lazy-loading only. (primarily intended for use by Neovim distributions). - Automatic lazy-loading of Lua modules on `require`. - Automatic lazy-loading of colorschemes. + This library provides a `colorscheme` handler in the plugin spec. - Heuristics for determining a `main` module and automatically calling a `setup()` function. - Abstractions for plugin configuration with an `opts` table. @@ -112,12 +113,16 @@ require("lz.n").load(plugins) | **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 automatically[^2]. | | **priority** | `number?` | Only useful for **start** plugins (not lazy-loaded) to force loading certain plugins first. Default priority is `50`. It's recommended to set this to a high number for colorschemes. | `priority` | [^1]: In contrast to `lazy.nvim`'s `name` field, `lz.n`'s `name` *is not optional*. This is because `lz.n` does is not a plugin manager and needs to be told which plugins to load. +[^2]: 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. #### Example @@ -138,6 +143,11 @@ require("lz.n").load { -- lazy-load when opening a toml file ft = "toml", }, + { + "sweetie.nvim", + -- lazy-load when setting the `sweetie` colorscheme + colorscheme = "sweetie", + }, { "vim-startuptime", cmd = "StartupTime", diff --git a/lua/lz/n/handler/colorscheme.lua b/lua/lz/n/handler/colorscheme.lua new file mode 100644 index 0000000..3e01d0e --- /dev/null +++ b/lua/lz/n/handler/colorscheme.lua @@ -0,0 +1,53 @@ +local loader = require("lz.n.loader") + +---@class lz.n.ColorschemeHandler: lz.n.Handler +---@field augroup? integer + +---@type lz.n.ColorschemeHandler +local M = { + pending = {}, + type = "colorscheme", + augroup = nil, +} + +---@param plugin lz.n.Plugin +function M.del(plugin) + for _, plugins in pairs(M.pending) do + plugins[plugin.name] = nil + end +end + +---@param name string +local function on_colorscheme(name) + if vim.tbl_contains(vim.fn.getcompletion("", "color"), name) then + return + end + loader.load(vim.tbl_values(M.pending[name])) +end + +local function init() + if M.augroup then + return + end + M.augroup = vim.api.nvim_create_augroup("lz_n_handler_colorscheme", { clear = true }) + vim.api.nvim_create_autocmd("ColorSchemePre", { + callback = function(event) + on_colorscheme(event.match) + end, + group = M.augroup, + }) +end + +---@param plugin lz.n.Plugin +function M.add(plugin) + if not plugin.colorscheme then + return + end + init() + for _, colorscheme in pairs(plugin.colorscheme) do + M.pending[colorscheme] = M.pending[colorscheme] or {} + M.pending[colorscheme][plugin.name] = plugin.name + end +end + +return M diff --git a/lua/lz/n/handler/init.lua b/lua/lz/n/handler/init.lua index 0df0bf6..13429f5 100644 --- a/lua/lz/n/handler/init.lua +++ b/lua/lz/n/handler/init.lua @@ -12,6 +12,7 @@ M.types = { event = "event", ft = "ft", keys = "keys", + colorscheme = "colorscheme", } local handlers = { @@ -19,6 +20,7 @@ local handlers = { event = require("lz.n.handler.event"), ft = require("lz.n.handler.ft"), keys = require("lz.n.handler.keys"), + colorscheme = require("lz.n.handler.colorscheme"), } ---@param plugin lz.n.Plugin diff --git a/lua/lz/n/meta.lua b/lua/lz/n/meta.lua index 42923ac..94ac857 100644 --- a/lua/lz/n/meta.lua +++ b/lua/lz/n/meta.lua @@ -22,6 +22,7 @@ error("Cannot import a meta module") --- @field event? lz.n.Event[] --- @field keys? lz.n.Keys[] --- @field cmd? string[] +--- @field colorscheme? string[] --- @class lz.n.PluginSpecHandlers --- @@ -36,6 +37,9 @@ error("Cannot import a meta module") --- --- Load a plugin on one or more |key-mapping|s. --- @field keys? string|string[]|lz.n.KeysSpec[] +--- +--- Load a plugin on one or more |colorscheme| events. +--- @field colorscheme? string[]|string --- @class lz.n.KeysBase: vim.keymap.set.Opts --- @field desc? string diff --git a/lua/lz/n/spec.lua b/lua/lz/n/spec.lua index de069a6..6ab5291 100644 --- a/lua/lz/n/spec.lua +++ b/lua/lz/n/spec.lua @@ -104,7 +104,22 @@ local function parse(spec) table.insert(result.cmd, _cmd_spec) end end - result.lazy = result.lazy or result.event ~= nil or result.keys ~= nil or result.cmd ~= nil + local colorscheme_spec = spec.colorscheme + if colorscheme_spec then + result.colorscheme = {} + end + if type(colorscheme_spec) == "string" then + table.insert(result.colorscheme, colorscheme_spec) + elseif type(colorscheme_spec) == "table" then + for _, _colorscheme_spec in pairs(colorscheme_spec) do + table.insert(result.cmd, _colorscheme_spec) + end + end + result.lazy = result.lazy + or result.event ~= nil + or result.keys ~= nil + or result.cmd ~= nil + or result.colorscheme ~= nil return result end diff --git a/spec/colorscheme_spec.lua b/spec/colorscheme_spec.lua new file mode 100644 index 0000000..5bdc822 --- /dev/null +++ b/spec/colorscheme_spec.lua @@ -0,0 +1,20 @@ +local colorscheme = require("lz.n.handler.colorscheme") +local state = require("lz.n.state") +local loader = require("lz.n.loader") +local spy = require("luassert.spy") + +describe("handlers.colorscheme", function() + it("Colorscheme only loads plugin once", function() + ---@type lz.n.Plugin + local plugin = { + name = "sweetie.nvim", + colorscheme = { "sweetie" }, + } + local spy_load = spy.on(loader, "_load") + state.plugins[plugin.name] = plugin + colorscheme.add(plugin) + pcall(vim.cmd.colorscheme, "sweetie") + pcall(vim.cmd.colorscheme, "sweetie") + assert.spy(spy_load).called(1) + end) +end)