feat: initial implementation

A first working, publishable version of colorsaver.nvim.

This plugin connects to the ColorScheme event to detect changes to the
colorscheme. Any time that changes, it saves the colorscheme's name to a
local file. In addition to that, it can watch that local file for
changes. This way, when one `nvim` process changes the colorscheme, all
other instances will automatically reload the colorscheme.
This commit is contained in:
swaits committed 2023-11-07 11:22:13 -07:00
commit 70f0ad0ab8
10 files changed
+835

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
#--------------------------------------------------#
# The following was generated with gitignore.nvim: #
#--------------------------------------------------#
# Gitignore for the following technologies: Lua, Vim
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
+3
View File
@@ -0,0 +1,3 @@
indent_type = "Spaces"
indent_width = 2
column_width = 100
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright © 2023 Stephen Waits <steve@waits.net>
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.
+158
View File
@@ -0,0 +1,158 @@
# colorsaver.nvim
colorsaver.nvim is a Neovim plugin designed to save and load your preferred
colorscheme persistently across sessions. With colorsaver, you can ensure your
aesthetic preferences are maintained automatically. Additionally, it can
automatically load colorscheme changes across all running instances of Neovim,
providing a consistent user experience.
## Features
- **Persistent Colorscheme**: Save your selected colorscheme and have it load
automatically on startup.
- **Automatic Updates**: Watch for changes and automatically apply them across
instances of Neovim.
## Installation
Install colorsaver using your favorite package manager.
### [lazy](https://github.com/folke/lazy.nvim) (recommended)
```lua
{
"https://git.sr.ht/~swaits/colorsaver.nvim",
lazy = true,
event = "VimEnter",
opts = {
-- your options here
},
}
```
Or, using [LazyVim](https://www.lazyvim.org/), which is built on top of
[lazy](https://github.com/folke/lazy.nvim), one example configuration might
look like this:
```lua
{
-- tell LazyVim to stop messing with colorschemes
{ "catppuccin/nvim", name = "catppuccin", enabled = false },
{ "folke/tokyonight.nvim", enabled = false },
{
"LazyVim/LazyVim",
opts = {
colorscheme = "default", -- just some random built-in scheme
},
},
-- load/save our last used colorscheme automatically
{
"https://git.sr.ht/~swaits/colorsaver.nvim",
event = "VimEnter",
opts = {},
dependencies = {
-- load colorschemes as a dependency of colorsaver
{ "AlexvZyl/nordic.nvim" },
{ "EdenEast/nightfox.nvim" },
{ "Shatur/neovim-ayu" },
{ "rebelot/kanagawa.nvim" },
},
},
}
```
### [pckr](https://github.com/lewis6991/pckr.nvim)
```lua
{
"https://git.sr.ht/~swaits/colorsaver.nvim",
config = function()
require("colorsaver").setup({
-- your options here
})
end
}
```
### [vim-plug](https://github.com/junegunn/vim-plug)
```vim
Plug 'https://git.sr.ht/~swaits/colorsaver.nvim'
lua require("colorsaver").setup({
-- your options here
})
```
## Configuration
To configure colorsaver, pass a table with your preferred settings to the
`setup` function. Here is the default configuration:
```lua
{
-- log_level: Sets the logging level for the module's output.
-- Acceptable values are "debug", "info", "warn", "error".
log_level = "warn",
-- debounce_ms: Sets the debounce time in milliseconds for file watching.
-- Accepts any integer greater than or equal to 50. If experiencing issues,
-- consider increasing this value.
debounce_ms = 100,
-- filename: The name of the file where the colorscheme will be saved.
-- Note that the file is always stored in the "data" directory, which is
-- usually ~/.local/share/nvim/
filename = "colorsaver",
-- auto_load: If true, any colorscheme changes from one instance of nvim
-- will be automatically loaded by all other instances of nvim.
auto_load = true,
}
```
### File Watching
If `auto_load` is enabled, colorsaver will watch for changes in the saved
colorscheme file and apply them to all running instances of Neovim.
### Logging
colorsaver features an integrated logging system. You can specify the log level
in the configuration options. For troubleshooting, set the `log_level` to
`"debug"` to receive verbose output.
## Usage
Once colorsaver is installed and configured, it works automatically. Your
current colorscheme will be saved upon change and reloaded when Neovim starts
or when any Neovim instance changes it (when `auto_load` is `true`).
## Contributing
Contributions to colorsaver are welcome! Please feel free to fork the
repository, make your changes, and submit a pull request.
## MIT License
Copyright © 2023 [Stephen Waits](https://swaits.com/) <steve@waits.net>
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.
+103
View File
@@ -0,0 +1,103 @@
-- autocommands.lua
--- AutocommandGroup module for managing groups of autocommands in Neovim.
-- This module encapsulates the creation and management of autocommand groups and their definitions.
local AutocommandGroup = {}
AutocommandGroup.__index = AutocommandGroup
--- Constructor for creating a new AutocommandGroup.
-- @param name string The name of the autocommand group.
-- @param definitions table A table of autocommand definitions.
-- @return table A new instance of AutocommandGroup.
function AutocommandGroup.new(name, definitions)
-- Validate that 'name' is provided and is a string.
assert(type(name) == "string", "Autocommand group name must be a string")
-- Create an instance of AutocommandGroup and set its properties.
local self = setmetatable({}, AutocommandGroup)
self.name = name
self.definitions = definitions or {}
-- Create a new autocommand group in Neovim, clearing any existing autocommands in the group.
self.group_id = vim.api.nvim_create_augroup(name, { clear = true })
-- Set or update the autocommand definitions for the group.
self:set_definitions(self.definitions)
return self
end
--- Sets or updates the autocommand definitions for the group.
-- @param definitions table The autocommand definitions to set or update.
function AutocommandGroup:set_definitions(definitions)
-- Validate that 'definitions' is a table.
assert(type(definitions) == "table", "Autocommand definitions must be a table")
-- Clear existing autocommands from the group to prepare for new definitions.
vim.api.nvim_clear_autocmds({ group = self.group_id })
-- Iterate over each definition and create an autocommand.
for _, def in ipairs(definitions) do
-- Perform checks to ensure the definition structure is valid.
assert(def.events, "Autocommand definition is missing 'events' key")
assert(
type(def.events) == "string" or type(def.events) == "table",
"'events' must be a string or a table"
)
assert(def.patterns, "Autocommand definition is missing 'patterns' key")
assert(
type(def.patterns) == "string" or type(def.patterns) == "table",
"'patterns' must be a string or a table"
)
assert(
def.callback or def.command,
"Autocommand definition must have either 'callback' or 'command'"
)
-- Check for 'callback' and 'command' specifics and validate their types.
if def.callback then
assert(type(def.callback) == "function", "'callback' must be a function")
end
if def.command then
assert(type(def.command) == "string", "'command' must be a string")
end
-- Validate optional keys if they are present.
if def.once then
assert(type(def.once) == "boolean", "'once' must be a boolean")
end
if def.nested then
assert(type(def.nested) == "boolean", "'nested' must be a boolean")
end
-- Create the autocommand in Neovim with the provided definition.
vim.api.nvim_create_autocmd(def.events, {
group = self.group_id,
pattern = def.patterns,
callback = def.callback,
command = def.command,
once = def.once,
nested = def.nested,
})
end
-- Update the stored definitions.
self.definitions = definitions
end
--- Clears the autocommand group, effectively disabling all its autocommands.
function AutocommandGroup:clear()
-- Clear all autocommands associated with the group in Neovim.
vim.api.nvim_clear_autocmds({ group = self.group_id })
end
--- Restores the autocommand group using the stored definitions.
function AutocommandGroup:restore()
-- Reapply the stored autocommand definitions.
self:set_definitions(self.definitions)
end
-- Module table for exporting the constructor.
local M = {
new = AutocommandGroup.new,
}
return M
+98
View File
@@ -0,0 +1,98 @@
-- config.lua
--- Configuration module for handling user settings and defaults.
-- This module provides validation and fallbacks for user-specified configuration.
local M = {}
--- Define default configuration values with inline documentation.
-- These defaults are used as a fallback if the user does not provide these settings or if they are invalid.
local defaults = {
--- log_level: Sets the logging level for the module's output.
-- @field log_level Acceptable values are "debug", "info", "warn", "error".
log_level = "warn",
--- debounce_ms: Sets the debounce time in milliseconds for file watching.
-- @field debounce_ms Accepts any integer greater than or equal to 50. If experiencing issues, consider increasing this value.
debounce_ms = 100,
--- filename: The name of the file where the colorscheme will be saved.
-- @field filename Note that the file is always stored in the "data" directory, which is usually ~/.local/share/nvim/
filename = "colorsaver",
--- auto_load: If true, any colorscheme changes from one instance of nvim will be automatically loaded by all other instances of nvim.
-- @field auto_load
auto_load = true,
}
--- Validates the logging level.
-- @param level string The log level to validate.
-- @return boolean Whether the log level is valid.
local function is_log_level_valid(level)
local valid_levels = { debug = true, info = true, warn = true, error = true }
return valid_levels[level:lower()] ~= nil
end
--- Validates the debounce time.
-- @param ms number The debounce time in milliseconds to validate.
-- @return boolean Whether the debounce time is valid.
local function is_debounce_ms_valid(ms)
return type(ms) == "number" and ms >= 50
end
--- Validates the filename.
-- @param name string The filename to validate.
-- @return boolean Whether the filename is valid.
local function is_filename_valid(name)
return type(name) == "string" and name ~= ""
end
--- Validates the auto_load value.
-- @param value boolean The auto_load value to validate.
-- @return boolean Whether the auto_load is valid.
local function is_auto_load_valid(value)
return type(value) == "boolean"
end
--- Checks for invalid keys in the user configuration and logs a warning for each.
-- @param user_config table The user configuration to check.
local function check_for_invalid_keys(user_config)
for key, _ in pairs(user_config) do
if defaults[key] == nil then
log:warn("Ignoring invalid configuration key '" .. key .. "'.")
user_config[key] = nil
end
end
end
--- Merges user configuration with defaults and validates the result.
-- @param user_config table The user-specified configuration.
-- @param logger table The logger instance to be used for logging messages.
-- @return table The validated and merged configuration.
function M.setup(user_config, logger)
-- Store the logger after ensuring it's provided.
assert(logger, "Logger instance must be provided for configuration setup.")
log = logger
-- Check if the provided user_config is a table.
if user_config ~= nil and type(user_config) ~= "table" then
log:error("Provided user_config must be a table")
return
end
-- Remove invalid keys from the user configuration.
check_for_invalid_keys(user_config or {})
-- Deeply merge the defaults with the user configuration, prioritizing user settings.
local config = vim.tbl_deep_extend("force", {}, defaults, user_config or {})
-- Validate and apply individual configuration settings.
config.log_level = is_log_level_valid(config.log_level) and config.log_level or defaults.log_level
config.debounce_ms = is_debounce_ms_valid(config.debounce_ms) and config.debounce_ms
or defaults.debounce_ms
config.filename = is_filename_valid(config.filename) and config.filename or defaults.filename
config.auto_load = is_auto_load_valid(config.auto_load) and config.auto_load or defaults.auto_load
-- Return the validated and potentially corrected configuration.
return config
end
return M
+50
View File
@@ -0,0 +1,50 @@
-- file_watcher.lua
--- FileWatcher module for watching file system events.
-- This module provides the ability to watch for changes in a specified file and execute a callback when changes occur.
local FileWatcher = {}
FileWatcher.__index = FileWatcher
--- Constructor for the FileWatcher object.
-- @param path string The file system path to watch.
-- @param callback function The callback function to execute when a change is detected.
-- @return table The constructed FileWatcher object.
function FileWatcher.new(path, callback)
-- Validate the input parameters to ensure correct types.
assert(type(path) == "string", "Path must be a string")
assert(type(callback) == "function", "Callback must be a function")
-- Set up the FileWatcher object.
local self = setmetatable({}, FileWatcher)
self.path = path
self.callback = callback
-- Initialize the file system watcher with libuv.
self.fs_watcher = vim.loop.new_fs_event()
return self
end
--- Starts watching the file system event.
-- This method activates the file watcher, which will invoke the callback on file changes.
function FileWatcher:start()
-- Ensure the file system watcher starts monitoring for changes.
-- Empty options table and vim.schedule_wrap to ensure the callback is called in the main loop.
self.fs_watcher:start(self.path, {}, vim.schedule_wrap(self.callback))
end
--- Stops watching the file system event.
-- This method deactivates the file watcher, preventing the callback from being invoked.
function FileWatcher:stop()
-- If the watcher is active, stop it.
if self.fs_watcher then
self.fs_watcher:stop()
end
end
--- Restarts watching the file system event.
-- This method stops and then restarts the file watcher.
function FileWatcher:restart()
-- Stop and then start the watcher to refresh the monitoring.
self:stop()
self:start()
end
return FileWatcher
+219
View File
@@ -0,0 +1,219 @@
local M = {}
-- load modules
local autocommands = require("colorsaver.autocommands")
local config = require("colorsaver.config")
local file_watcher = require("colorsaver.file_watcher")
local logger = require("colorsaver.logger")
local utils = require("colorsaver.utils")
-- our module local data (and these are just placeholder values, they're overwritten below)
local autocmd_group = nil
local color_file_path = vim.fn.stdpath("data") .. "/colorsaver"
local colorfile_watcher = nil
local log = logger.new("warn", "colorsaver")
--- save_colorscheme(new_scheme)
--
-- This function saves a new colorscheme to a file. If no new_scheme is provided, it saves the default colorscheme.
--
-- Parameters:
-- - new_scheme (string): The name of the new colorscheme to save.
--
-- Returns:
-- - success (boolean): true if the colorscheme was saved successfully, false otherwise.
--
-- Raises:
-- - None
--
-- Example usage:
-- save_colorscheme("my_colorscheme")
--
local function save_colorscheme(new_scheme)
local colorscheme_name = new_scheme
if not vim.tbl_contains(vim.fn.getcompletion("", "color"), colorscheme_name) then
log:warn("Didn't find " .. colorscheme_name .. " in the list of colorschemes")
return false
end
local file, err = io.open(color_file_path, "w")
if not file then
log:error("Failed to open " .. color_file_path .. " for writing: " .. err)
return false
end
local success, write_err = pcall(function()
file:write(colorscheme_name)
end)
local close_ok, close_err = pcall(function()
file:close()
end)
if not success then
log:error("Failed to write colorscheme to " .. color_file_path .. ": " .. write_err)
return false
elseif not close_ok then
log:error("Failed to close the file " .. color_file_path .. ": " .. close_err)
return false
end
return true
end
--- load_colorscheme()
--
-- This function loads a colorscheme for the current session in Neovim. It first
-- attempts to read the colorscheme from a specified file path. If the file exists
-- and is not empty, the content of the file is used as the colorscheme.
--
-- Parameters:
-- None
--
-- Returns:
-- success (boolean): true if the colorscheme was loaded successfully, false otherwise.
--
-- Raises:
-- None
--
-- Example usage:
-- load_colorscheme()
--
local function load_colorscheme()
local colorscheme = M.default -- Fallback to default colorscheme
local file, err = io.open(color_file_path, "r")
if not file then
log:warn("Failed to open " .. color_file_path .. " for reading: " .. err)
return false
end
local content, read_err = file:read("*a")
if read_err then
log:error("Failed to read from " .. color_file_path .. ": " .. read_err)
file:close()
return false
end
local close_ok, close_err = file:close()
if not close_ok then
log:error("Failed to close " .. color_file_path .. ": " .. close_err)
return false
end
colorscheme = content ~= "" and content or colorscheme
if not (colorscheme and colorscheme ~= "") then
log:error("Invalid colorscheme name found in " .. color_file_path .. ".")
return false
end
-- disable ColorScheme autocmd so we don't get into a bad loop; this is
-- because we're about to call `colorscheme` which will trigger ColorScheme
-- and cause us to write the file again, thus retriggering the
-- load_colorscheme function since the file changed... bad loop
if autocmd_group then
autocmd_group:clear()
end
log:info("Switching to '" .. colorscheme .. "'")
local ok, cmd_err = pcall(vim.api.nvim_command, "colorscheme " .. colorscheme)
if not ok then
log:error("Failed to apply colorscheme '" .. colorscheme .. "': " .. cmd_err)
return false
end
-- and re-enable the autocommands
if autocmd_group then
autocmd_group:restore()
end
return true
end
--- Callback function for file change events.
--
-- This function is called when a file change event is triggered. It handles
-- the event by reloading the colorscheme from the updated file. If there is an
-- error, it logs the error message and stops the event.
--
-- Parameters:
-- - err (string|nil) The error message, if any. If there is no error, this parameter is nil.
-- - filename (string) The name of the file that triggered the event.
-- - events (table) A table containing information about the events that occurred.
--
-- Returns:
-- None
--
-- Raises:
-- None
--
local function on_change(err, filename)
vim.schedule(function()
if err then
-- If there's an error, notify and stop the event
log:error("Error watching file " .. tostring(filename) .. ": " .. tostring(err))
return
end
-- Reload the colorscheme from the updated file
load_colorscheme()
end)
end
--- Sets up the ColorSaver module with the provided options.
--
-- Parameters:
-- - opts (table): A table containing the options for configuring the ColorSaver module. The following keys are supported:
-- - filename (string): The name of the file where the colorscheme will be saved.
-- - log_level (string): The log level for the ColorSaver module.
-- - debounce_ms (number): The debounce time in milliseconds for saving the colorscheme.
-- - auto_load (boolean): Whether to enable autoloading of the colorscheme file.
--
-- Returns:
-- None
--
-- Raises:
-- None
--
-- This function sets up the ColorSaver module by performing the following steps:
-- 1. Extracts and validates the options provided.
-- 2. Sets up local data, including the file path for saving the colorscheme and a logger instance.
-- 3. Loads the colorscheme at startup.
-- 4. Captures the new colorscheme and saves it on the "ColorScheme" event.
-- 5. Sets up autoloading of the colorscheme file if enabled.
--
function M.setup(opts)
-- Extract options and validate them
M.config = config.setup(opts, log)
-- Set up some local data
color_file_path = vim.fn.stdpath("data") .. "/" .. M.config.filename
log = logger.new(M.config.log_level, "colorsaver")
-- Load the colorscheme at startup.
load_colorscheme()
-- Capture the new colorscheme and save it on the ColorScheme event.
local debounced_save_colorscheme = utils.debounce(save_colorscheme, M.config.debounce_ms)
autocmd_group = autocommands.new("ColorSaverGroup", {
{
events = { "ColorScheme" },
patterns = { "*" },
callback = function(info)
vim.schedule(function()
debounced_save_colorscheme(info.match) -- info.match is the colorscheme parameter (i.e. name)
end)
end,
},
})
-- Setup autoloading if enabled
if M.config.auto_load then
local debounced_on_change = utils.debounce(on_change, M.config.debounce_ms)
colorfile_watcher = file_watcher.new(color_file_path, debounced_on_change)
colorfile_watcher:start()
end
end
return M
+65
View File
@@ -0,0 +1,65 @@
--- Logger module for neovim that provides a simple logging interface.
-- @module Logger
local Logger = {}
Logger.__index = Logger
--- Log levels with corresponding neovim's vim.log.levels.
local log_levels = {
debug = vim.log.levels.DEBUG,
info = vim.log.levels.INFO,
warn = vim.log.levels.WARN,
error = vim.log.levels.ERROR,
}
--- Constructor for Logger object.
-- @param min_level The minimum log level to output messages for.
-- @param prefix A prefix to prepend to all log messages.
-- @return A new Logger instance with specified level and prefix.
function Logger.new(min_level, prefix)
local self = setmetatable({}, Logger)
self.min_level = log_levels[min_level] or log_levels.info -- Fallback to info level if unspecified
self.prefix = prefix or "Logger" -- Default prefix if none provided
return self
end
--- Sets the minimum log level.
-- Only log messages at this level or higher will be output.
-- @param min_level The minimum log level string ("debug", "info", "warn", "error").
function Logger:set_level(min_level)
self.min_level = log_levels[min_level] or self.min_level -- Keep current level if the new level is invalid
end
--- Internal function to process the log message.
-- @param level The log level of the message.
-- @param message The log message.
function Logger:_log(level, message)
if level >= self.min_level then
vim.notify(self.prefix .. ": " .. message, level)
end
end
--- Logs a message at DEBUG level.
-- @param message The message to log.
function Logger:debug(message)
self:_log(log_levels.debug, "DEBUG: " .. message)
end
--- Logs a message at INFO level.
-- @param message The message to log.
function Logger:info(message)
self:_log(log_levels.info, "INFO: " .. message)
end
--- Logs a message at WARN level.
-- @param message The message to log.
function Logger:warn(message)
self:_log(log_levels.warn, "WARN: " .. message)
end
--- Logs a message at ERROR level.
-- @param message The message to log.
function Logger:error(message)
self:_log(log_levels.error, "ERROR: " .. message)
end
return Logger
+52
View File
@@ -0,0 +1,52 @@
--- Utility functions for debouncing and validating colorschemes.
-- @module util
local M = {}
--- Debounces a function call. This is useful to prevent a function from
-- being called too frequently, delaying its execution until after a certain
-- amount of time has elapsed since the last time it was invoked.
-- @param func function The function to debounce.
-- @param delay number The time delay in milliseconds.
-- @return function A new debounced function.
function M.debounce(func, delay)
assert(type(func) == "function", "Invalid argument 'func': function expected")
assert(type(delay) == "number", "Invalid argument 'delay': number expected")
local timer = nil
return function(...)
local args = { ... } -- Capture any arguments passed to the function.
if timer then
timer:stop() -- Stop any existing timer.
timer:close() -- Clean up the timer resources.
end
-- Create a new timer.
timer = vim.loop.new_timer()
-- Start the timer with the specified delay.
timer:start(
delay,
0,
vim.schedule_wrap(function()
func(unpack(args)) -- Call the original function with the captured arguments.
timer:stop() -- Stop the timer.
timer:close() -- Clean up the timer resources.
timer = nil -- Clear the timer variable.
end)
)
end
end
--- Validates whether the provided colorscheme name is available in Neovim.
-- This function checks against the list of valid colorschemes that Neovim knows about.
-- @param colorscheme string The colorscheme name to validate.
-- @return boolean True if the colorscheme is valid, false otherwise.
function M.is_colorscheme_valid(colorscheme)
assert(type(colorscheme) == "string", "Invalid argument 'colorscheme': string expected")
-- Check if the colorscheme exists in the list of completions for "color".
return vim.tbl_contains(vim.fn.getcompletion("", "color"), colorscheme)
end
return M