aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/_meta.lua28
-rw-r--r--test/functional/lua/vim_spec.lua122
2 files changed, 148 insertions, 2 deletions
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index c3f3bf66d3..92c8fe0e26 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -311,6 +311,28 @@ local get_option_type = function(name, info)
end
+-- Check whether the OptionTypes is allowed for vim.opt
+-- If it does not match, throw an error which indicates which option causes the error.
+local function assert_valid_value(name, value, types)
+ local type_of_value = type(value)
+ for _, valid_type in ipairs(types) do
+ if valid_type == type_of_value then
+ return
+ end
+ end
+
+ error(string.format("Invalid option type '%s' for '%s', should be %s", type_of_value, name, table.concat(types, " or ")))
+end
+
+local valid_types = {
+ [OptionTypes.BOOLEAN] = { "boolean" },
+ [OptionTypes.NUMBER] = { "number" },
+ [OptionTypes.STRING] = { "string" },
+ [OptionTypes.SET] = { "string", "table" },
+ [OptionTypes.ARRAY] = { "string", "table" },
+ [OptionTypes.MAP] = { "string", "table" },
+}
+
--- Convert a lua value to a vimoption_T value
local convert_value_to_vim = (function()
-- Map of functions to take a Lua style value and convert to vimoption_T style value.
@@ -340,7 +362,6 @@ local convert_value_to_vim = (function()
[OptionTypes.MAP] = function(_, value)
if type(value) == "string" then return value end
- if type(value) == "function" then error(debug.traceback("asdf")) end
local result = {}
for opt_key, opt_value in pairs(value) do
@@ -353,7 +374,10 @@ local convert_value_to_vim = (function()
}
return function(name, info, value)
- return to_vim_value[get_option_type(name, info)](info, value)
+ local option_type = get_option_type(name, info)
+ assert_valid_value(name, value, valid_types[option_type])
+
+ return to_vim_value[option_type](info, value)
end
end)()
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 890f6427bb..e3d19008cc 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -1592,6 +1592,128 @@ describe('lua stdlib', function()
eq(wildmode, 'full,list,full')
end)
+
+ describe('option types', function()
+ it('should allow to set option with numeric value', function()
+ eq(4, exec_lua [[
+ vim.opt.tabstop = 4
+ return vim.bo.tabstop
+ ]])
+
+ matches("Invalid option type 'string' for 'tabstop'", pcall_err(exec_lua, [[
+ vim.opt.tabstop = '4'
+ ]]))
+ matches("Invalid option type 'boolean' for 'tabstop'", pcall_err(exec_lua, [[
+ vim.opt.tabstop = true
+ ]]))
+ matches("Invalid option type 'table' for 'tabstop'", pcall_err(exec_lua, [[
+ vim.opt.tabstop = {4, 2}
+ ]]))
+ matches("Invalid option type 'function' for 'tabstop'", pcall_err(exec_lua, [[
+ vim.opt.tabstop = function()
+ return 4
+ end
+ ]]))
+ end)
+
+ it('should allow to set option with boolean value', function()
+ eq(true, exec_lua [[
+ vim.opt.undofile = true
+ return vim.bo.undofile
+ ]])
+
+ matches("Invalid option type 'number' for 'undofile'", pcall_err(exec_lua, [[
+ vim.opt.undofile = 0
+ ]]))
+ matches("Invalid option type 'table' for 'undofile'", pcall_err(exec_lua, [[
+ vim.opt.undofile = {true}
+ ]]))
+ matches("Invalid option type 'string' for 'undofile'", pcall_err(exec_lua, [[
+ vim.opt.undofile = 'true'
+ ]]))
+ matches("Invalid option type 'function' for 'undofile'", pcall_err(exec_lua, [[
+ vim.opt.undofile = function()
+ return true
+ end
+ ]]))
+ end)
+
+ it('should allow to set option with array or string value', function()
+ eq('indent,eol,start', exec_lua [[
+ vim.opt.backspace = {'indent','eol','start'}
+ return vim.go.backspace
+ ]])
+ eq('indent,eol,start', exec_lua [[
+ vim.opt.backspace = 'indent,eol,start'
+ return vim.go.backspace
+ ]])
+
+ matches("Invalid option type 'boolean' for 'backspace'", pcall_err(exec_lua, [[
+ vim.opt.backspace = true
+ ]]))
+ matches("Invalid option type 'number' for 'backspace'", pcall_err(exec_lua, [[
+ vim.opt.backspace = 2
+ ]]))
+ matches("Invalid option type 'function' for 'backspace'", pcall_err(exec_lua, [[
+ vim.opt.backspace = function()
+ return 'indent,eol,start'
+ end
+ ]]))
+ end)
+
+ it('should allow set option with map or string value', function()
+ eq("eol:~,space:.", exec_lua [[
+ vim.opt.listchars = {
+ eol = "~",
+ space = ".",
+ }
+ return vim.o.listchars
+ ]])
+ eq("eol:~,space:.,tab:>~", exec_lua [[
+ vim.opt.listchars = "eol:~,space:.,tab:>~"
+ return vim.o.listchars
+ ]])
+
+ matches("Invalid option type 'boolean' for 'listchars'", pcall_err(exec_lua, [[
+ vim.opt.listchars = true
+ ]]))
+ matches("Invalid option type 'number' for 'listchars'", pcall_err(exec_lua, [[
+ vim.opt.listchars = 2
+ ]]))
+ matches("Invalid option type 'function' for 'listchars'", pcall_err(exec_lua, [[
+ vim.opt.listchars = function()
+ return "eol:~,space:.,tab:>~"
+ end
+ ]]))
+ end)
+
+ it('should allow set option with set or string value', function()
+ local ww = exec_lua [[
+ vim.opt.whichwrap = {
+ b = true,
+ s = 1,
+ }
+ return vim.go.whichwrap
+ ]]
+ eq(true, ww == "bs" or ww == "sb")
+ eq("b,s,<,>,[,]", exec_lua [[
+ vim.opt.whichwrap = "b,s,<,>,[,]"
+ return vim.go.whichwrap
+ ]])
+
+ matches("Invalid option type 'boolean' for 'whichwrap'", pcall_err(exec_lua, [[
+ vim.opt.whichwrap = true
+ ]]))
+ matches("Invalid option type 'number' for 'whichwrap'", pcall_err(exec_lua, [[
+ vim.opt.whichwrap = 2
+ ]]))
+ matches("Invalid option type 'function' for 'whichwrap'", pcall_err(exec_lua, [[
+ vim.opt.whichwrap = function()
+ return "b,s,<,>,[,]"
+ end
+ ]]))
+ end)
+ end)
end) -- vim.opt
it('vim.cmd', function()