Files
dep/lua/dep/spec.lua

213 lines
6.1 KiB
Lua

local logger = require("dep.log")
---@class specmodules
---@field prefix string prefix to prepend to the modules
---@field [integer] string list of all modules to load
---@class speclist
---@field modules specmodules? a list of modules
---@field base_dir string? the base directory for all plugins
---@field sync ("new"|"always")? when to sync (defaults to new)
---@field [integer] spec a spec
---@class spec
---@field [1] string id
---@field setup function? code to run before the package is loaded
---@field load function? code to run after the package is loaded
---@field config function? code to run after the package is installed/updated
---@field lazy function|true? code to run which determines when the package is loaded
---@field as string? overrides the short name of the package which is usually set
--- to a substring of all the chars after "/" in spec[1]
---@field url string? the url to the git repository hosting the package
---@field path string? path to local version of plugin, overrides the url
---@field branch string? the branch which the version of the package resides
---@field commit string? the commit which the version of the package resides
---@field disable boolean? if true disables the package from being loaded
---@field pin boolean? if true disables the package from being installed/updated
---@field reqs spec|spec[]|string? packages that this package requires
---@field deps spec|spec[]|string? packages that depend on this package
local spec = {}
--- check if a string seems to be a url
---@param url string the "url" to check
---@return boolean is_url
local function is_url(url)
if url:sub(1, 8) == "https://" or
url:sub(1, 7) == "http://" then
return true
end
return false
end
--- get the proper name of a spec
---@return string spec.name
function spec:get_name()
return self[1]:match("^[%w-_.]+/([%w-_.]+)$")
end
--- attempt to correct a spec
---@param self table|string spec to check
---@return spec spec
function spec:correct_spec()
if type(self) == "string" then
return { self }
elseif type(self) == "table" then
repeat
if type(self[1]) ~= "string" then
self = self[1]
elseif self[1] == nil then
break
end
until type(self[1]) == "string"
end
return self
end
-- store the logger temporarily to prevent any logs from being printed when
-- being run in silent mode
local __logger
--- check a spec to see if it's correct
---@param self table spec to check
---@param silent boolean? should the checker report errors
---@return spec|false spec if the spec is ok or false
function spec:check(silent)
if silent == true then
__logger = logger
logger = { log = function() end }
end
-- make sure all the data is correct
do -- spec[1]
if type(self[1]) ~= "string" then
logger:log("spec", "spec[1] must be a string")
return false
end
local name = spec.get_name(self)
if not name then
logger:log("spec", 'invalid name "%s"; must be in the format "user/package"', self[1])
return false
end
end
if self.setup ~= nil then -- spec.setup
if type(self.setup) ~= "function" then
logger:log("spec", "spec.setup must be a function in %s", self[1])
return false
end
end
if self.load ~= nil then -- spec.load
if type(self.load) ~= "function" then
logger:log("spec", "spec.load must be a function in %s", self[1])
return false
end
end
if self.config ~= nil then -- spec.config
if type(self.config) ~= "function" then
logger:log("spec", "spec.config must be a function in %s", self[1])
return false
end
end
if self.lazy ~= nil then -- spec.lazy
if type(self.lazy) ~= "function" and self.lazy ~= true then
logger:log("spec", "spec.lazy must be a function or boolean in %s",
self[1])
return false
end
end
if self.as ~= nil then -- spec.as
if type(self.as) ~= "string" then
logger:log("spec", "spec.as must be a string in %s", self[1])
return false
end
end
if self.url ~= nil then -- spec.url
if type(self.url) ~= "string" then
logger:log("spec", "spec.url must be a string in %s", self[1])
return false
elseif not is_url(self.url) then -- more strict checking on urls
logger:log("spec", "spec.url must be a properly formatted url in %s",
self[1])
return false
end
end
if self.path ~= nil then -- spec.path
if type(self.path) ~= "string" then
logger:log("spec", "spec.path must be a string in %s", self[1])
return false
elseif not vim.fn.isdirectory(self.path) then
logger:log("spec", "spec.path must be a valid directory in %s", self[1])
return false
end
end
if self.branch ~= nil then -- spec.branch
if type(self.branch) ~= "string" then
logger:log("spec", "spec.branch must be a string in %s", self[1])
return false
end
end
if self.commit ~= nil then -- spec.commit
if type(self.commit) ~= "string" then
logger:log("spec", "spec.commit must be a string in %s", self[1])
return false
end
end
if self.disable ~= nil then -- spec.disable
if type(self.disable) ~= "boolean" then
logger:log("spec", "spec.disable must be a boolean in %s", self[1])
return false
end
end
if self.pin ~= nil then -- spec.pin
if type(self.pin) ~= "boolean" then
logger:log("spec", "spec.pin must be a boolean in %s", self[1])
return false
end
end
if self.reqs ~= nil then -- spec.reqs
local is = type(self.reqs)
if is ~= "table" and is ~= "string" then
logger:log("spec", "spec.reqs must be a table or a string in %s", self[1])
return false
end
-- turn an id into a spec
if (is == "string") then
self.reqs = { self.reqs }
end
end
if self.deps ~= nil then -- spec.deps
local is = type(self.deps)
if is ~= "table" and is ~= "string" then
logger:log("spec", "spec.deps must be a table or a string in %s", self[1])
return false
end
-- turn an id into a spec
if (is == "string") then
self.deps = { self.deps }
end
end
if silent == true then
logger = __logger
end
return self
end
return spec