aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/shared.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/shared.lua')
-rw-r--r--runtime/lua/vim/shared.lua93
1 files changed, 60 insertions, 33 deletions
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 6e427665f2..995c52e8ed 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -190,10 +190,10 @@ function vim.tbl_contains(t, value)
return false
end
--- Returns true if the table is empty, and contains no indexed or keyed values.
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
+--- Checks if a table is empty.
+---
+--@see https://github.com/premake/premake-core/blob/master/src/base/table.lua
+---
--@param t Table to check
function vim.tbl_isempty(t)
assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
@@ -347,13 +347,11 @@ function vim.tbl_flatten(t)
return result
end
---- Determine whether a Lua table can be treated as an array.
+--- Tests if a Lua table can be treated as an array.
---
---- An empty table `{}` will default to being treated as an array.
---- Use `vim.emtpy_dict()` to create a table treated as an
---- empty dict. Empty tables returned by `rpcrequest()` and
---- `vim.fn` functions can be checked using this function
---- whether they represent empty API arrays and vimL lists.
+--- Empty table `{}` is assumed to be an array, unless it was created by
+--- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result,
+--- for example from |rpcrequest()| or |vim.fn|.
---
--@param t Table
--@returns `true` if array-like table, else `false`.
@@ -479,48 +477,77 @@ end
--- 2. (arg_value, fn, msg)
--- - arg_value: argument value
--- - fn: any function accepting one argument, returns true if and
---- only if the argument is valid
+--- only if the argument is valid. Can optionally return an additional
+--- informative error message as the second returned value.
--- - msg: (optional) error string if validation fails
function vim.validate(opt) end -- luacheck: no unused
-vim.validate = (function()
+
+do
local type_names = {
- t='table', s='string', n='number', b='boolean', f='function', c='callable',
- ['table']='table', ['string']='string', ['number']='number',
- ['boolean']='boolean', ['function']='function', ['callable']='callable',
- ['nil']='nil', ['thread']='thread', ['userdata']='userdata',
+ ['table'] = 'table', t = 'table',
+ ['string'] = 'string', s = 'string',
+ ['number'] = 'number', n = 'number',
+ ['boolean'] = 'boolean', b = 'boolean',
+ ['function'] = 'function', f = 'function',
+ ['callable'] = 'callable', c = 'callable',
+ ['nil'] = 'nil',
+ ['thread'] = 'thread',
+ ['userdata'] = 'userdata',
}
- local function _type_name(t)
- local tname = type_names[t]
- if tname == nil then
- error(string.format('invalid type name: %s', tostring(t)))
- end
- return tname
- end
+
local function _is_type(val, t)
return t == 'callable' and vim.is_callable(val) or type(val) == t
end
- return function(opt)
- assert(type(opt) == 'table', string.format('opt: expected table, got %s', type(opt)))
+ local function is_valid(opt)
+ if type(opt) ~= 'table' then
+ return false, string.format('opt: expected table, got %s', type(opt))
+ end
+
for param_name, spec in pairs(opt) do
- assert(type(spec) == 'table', string.format('%s: expected table, got %s', param_name, type(spec)))
+ if type(spec) ~= 'table' then
+ return false, string.format('opt[%s]: expected table, got %s', param_name, type(spec))
+ end
local val = spec[1] -- Argument value.
local t = spec[2] -- Type name, or callable.
local optional = (true == spec[3])
- if not vim.is_callable(t) then -- Check type name.
- if (not optional or val ~= nil) and not _is_type(val, _type_name(t)) then
- error(string.format("%s: expected %s, got %s", param_name, _type_name(t), type(val)))
+ if type(t) == 'string' then
+ local t_name = type_names[t]
+ if not t_name then
+ return false, string.format('invalid type name: %s', t)
+ end
+
+ if (not optional or val ~= nil) and not _is_type(val, t_name) then
+ return false, string.format("%s: expected %s, got %s", param_name, t_name, type(val))
end
- elseif not t(val) then -- Check user-provided validation function.
- error(string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), val))
+ elseif vim.is_callable(t) then
+ -- Check user-provided validation function.
+ local valid, optional_message = t(val)
+ if not valid then
+ local error_message = string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), val)
+ if optional_message ~= nil then
+ error_message = error_message .. string.format(". Info: %s", optional_message)
+ end
+
+ return false, error_message
+ end
+ else
+ return false, string.format("invalid type name: %s", tostring(t))
end
end
- return true
+
+ return true, nil
end
-end)()
+ function vim.validate(opt)
+ local ok, err_msg = is_valid(opt)
+ if not ok then
+ error(debug.traceback(err_msg, 2), 2)
+ end
+ end
+end
--- Returns true if object `f` can be called as a function.
---
--@param f Any object