nvim/util: report mload module errors

This commit unclobbers syntax and other errors that can occur when
loading a module.

Previously, we just pcall/2'd any inputs and silently assumed that any
error reported meant the module didn't exist. The changes within add a
third branch to the mix: EXISTS, NOT_FOUND, and LOAD_ERR.

We keep the previous behaviour of not throwing when an error is
detected, but we do print out a big, red, angry message now.

As a side note, this should also slightly improve performance, due to
less errors being thrown; on account of us manually detecting whether a
module exists or not.
This commit is contained in:
Paul Stemmet 2022-10-30 18:19:26 +00:00
parent 6e8bbd4e22
commit ff33cf52d9
Signed by: Paul Stemmet
GPG Key ID: EDEA539F594E7E75
1 changed files with 58 additions and 6 deletions

View File

@ -1,6 +1,29 @@
local M = {}
---@enum Code
local Code = { EXISTS = 1, NOT_FOUND = 0, LOAD_ERR = -1 }
--- Checks if the given module exists, and adds it to the preload
--- list if it does.
---@param module string
---@return boolean
local function module_exists(module)
if package.loaded[module] then return true end
for _, searcher in ipairs(package.loaders or package.searchers) do
local fn = searcher(module)
if type(fn) == 'function' then
package.preload[module] = fn
return true
end
end
return false
end
-- Reload a given module, returning the result of loading it.
function M.mreload(module)
if package.loaded[module] then
@ -10,9 +33,21 @@ function M.mreload(module)
return require(module)
end
-- Try reloading the given module, returning ok, module
--- Try reloading the given module, returning (code, module|error)
--- Returns enumerated:
--- - Code.EXISTS, module
--- - Code.NOT_FOUND, nil
--- - Code.LOAD_ERR, error
---@param module string
---@return Code, any|string
function M.try_mreload(module)
return pcall(M.mreload, module)
if module_exists(module) then
local ok, result = pcall(M.mreload, module)
return ok and Code.EXISTS or Code.LOAD_ERR, result
else
return Code.NOT_FOUND, nil
end
end
-- Try reloading the given config module, returning either
@ -25,8 +60,10 @@ end
-- 4. fn() --> table
--
-- It the latter cases, *configuration will not be reloaded*, this is
-- primaraily meant for inline, static configuration
-- primarily meant for inline, static configuration
function M.try_mconfig(module)
-- Check if we were handed a object or function
-- instead of a module string
if type(module) ~= "string" then
module = type(module) == "function" and module() or module
module = type(module) == "table" and module or {}
@ -34,10 +71,25 @@ function M.try_mconfig(module)
return module
end
local ok, config = M.try_mreload(module)
config = type(config) == "function" and config() or config
-- We definitely have a module string, try loading it
local c, config = M.try_mreload(module)
return (ok and type(config) == "table") and config or {}
if c == Code.NOT_FOUND then
return {}
elseif c == Code.EXISTS then
return type(config) == "function" and config() or config
elseif c == Code.LOAD_ERR then
local options = {
title = string.format('Module Load Error: %s', module),
timeout = 2000
}
vim.notify_once(config, vim.log.levels.ERROR, options)
return {}
end
-- Catch fall through in case we ever add another Code variant
error(string.format("try_mconfig/1: unhandled Code '%s'", c))
end
-- Retrieve the config table stored in the provided module,