From f8f82901cdd0ccd5308e05c73af6deb7d083720f Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 1 Feb 2023 12:54:22 +0100 Subject: fix(tests): fixes for using vim.mpack and more ASAN --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 8fcdd9620b..fc550f5861 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -59,7 +59,7 @@ describe('API', function() -- XXX: This must be the last one, else next one will fail: -- "Packer instance already working. Use another Packer ..." - matches("can't serialize object$", + matches("can't serialize object of type .$", pcall_err(request, nil)) end) -- cgit From 46a87a5d2bac598fed0870f0d3c926087f95d30f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 05:19:04 -0500 Subject: refactor(api): VALIDATE macros #22187 Problem: - API validation involves too much boilerplate. - API validation errors are not consistently worded. Solution: Introduce some macros. Currently these are clumsy, but they at least help with consistency and avoid some nesting. --- test/functional/api/vim_spec.lua | 56 ++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index fc550f5861..5c56c90952 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1155,7 +1155,7 @@ describe('API', function() describe('nvim_put', function() it('validates args', function() - eq('Invalid lines (expected array of strings)', + eq("Invalid line: expected String, got Integer", pcall_err(request, 'nvim_put', {42}, 'l', false, false)) eq("Invalid type: 'x'", pcall_err(request, 'nvim_put', {'foo'}, 'x', false, false)) @@ -1410,6 +1410,15 @@ describe('API', function() ok(not nvim('get_option_value', 'equalalways', {})) end) + it('validation', function() + eq("Invalid scope (expected 'local' or 'global')", + pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'})) + eq("Invalid scope (expected 'local' or 'global')", + pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) + eq("Invalid scope: expected String, got Integer", + pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) + end) + it('can get local values when global value is set', function() eq(0, nvim('get_option_value', 'scrolloff', {})) eq(-1, nvim('get_option_value', 'scrolloff', {scope = 'local'})) @@ -1780,9 +1789,9 @@ describe('API', function() it('validates args', function() eq("Invalid key: 'blah'", pcall_err(nvim, 'get_context', {blah={}})) - eq('invalid value for key: types', + eq("Invalid types: expected Array, got Integer", pcall_err(nvim, 'get_context', {types=42})) - eq('unexpected type: zub', + eq("Invalid type: 'zub'", pcall_err(nvim, 'get_context', {types={'jumps', 'zub', 'zam',}})) end) it('returns map of current editor state', function() @@ -2223,15 +2232,14 @@ describe('API', function() eq(5, meths.get_var('avar')) end) - it('throws error on malformed arguments', function() + it('validation', function() local req = { {'nvim_set_var', {'avar', 1}}, {'nvim_set_var'}, {'nvim_set_var', {'avar', 2}}, } - local status, err = pcall(meths.call_atomic, req) - eq(false, status) - ok(err:match('Items in calls array must be arrays of size 2') ~= nil) + eq('Items in calls array must be arrays of size 2', + pcall_err(meths.call_atomic, req)) -- call before was done, but not after eq(1, meths.get_var('avar')) @@ -2239,18 +2247,16 @@ describe('API', function() { 'nvim_set_var', { 'bvar', { 2, 3 } } }, 12, } - status, err = pcall(meths.call_atomic, req) - eq(false, status) - ok(err:match('Items in calls array must be arrays') ~= nil) + eq("Invalid calls item: expected Array, got Integer", + pcall_err(meths.call_atomic, req)) eq({2,3}, meths.get_var('bvar')) req = { {'nvim_set_current_line', 'little line'}, {'nvim_set_var', {'avar', 3}}, } - status, err = pcall(meths.call_atomic, req) - eq(false, status) - ok(err:match('Args must be Array') ~= nil) + eq("Invalid args: expected Array, got String", + pcall_err(meths.call_atomic, req)) -- call before was done, but not after eq(1, meths.get_var('avar')) eq({''}, meths.buf_get_lines(0, 0, -1, true)) @@ -2750,7 +2756,7 @@ describe('API', function() describe('nvim_get_option_info', function() it('should error for unknown options', function() - eq("no such option: 'bogus'", pcall_err(meths.get_option_info, 'bogus')) + eq("Invalid option (not found): 'bogus'", pcall_err(meths.get_option_info, 'bogus')) end) it('should return the same options for short and long name', function() @@ -3031,10 +3037,10 @@ describe('API', function() eq(true, meths.del_mark('F')) eq({0, 0}, meths.buf_get_mark(buf, 'F')) end) - it('fails when invalid marks are used', function() - eq(false, pcall(meths.del_mark, 'f')) - eq(false, pcall(meths.del_mark, '!')) - eq(false, pcall(meths.del_mark, 'fail')) + it('validation', function() + eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.del_mark, 'f')) + eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.del_mark, '!')) + eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.del_mark, 'fail')) end) end) describe('nvim_get_mark', function() @@ -3048,10 +3054,10 @@ describe('API', function() assert(string.find(mark[4], "mybuf$")) eq({2, 2, buf.id, mark[4]}, mark) end) - it('fails when invalid marks are used', function() - eq(false, pcall(meths.del_mark, 'f')) - eq(false, pcall(meths.del_mark, '!')) - eq(false, pcall(meths.del_mark, 'fail')) + it('validation', function() + eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.get_mark, 'f', {})) + eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.get_mark, '!', {})) + eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.get_mark, 'fail', {})) end) it('returns the expected when mark is not set', function() eq(true, meths.del_mark('A')) @@ -3113,15 +3119,15 @@ describe('API', function() meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 })) end) it('rejects multiple-character fillchar', function() - eq('fillchar must be a single character', + eq('Invalid fillchar (not a single character)', pcall_err(meths.eval_statusline, '', { fillchar = 'aa' })) end) it('rejects empty string fillchar', function() - eq('fillchar must be a single character', + eq('Invalid fillchar (not a single character)', pcall_err(meths.eval_statusline, '', { fillchar = '' })) end) it('rejects non-string fillchar', function() - eq('fillchar must be a single character', + eq("Invalid fillchar: expected String, got Integer", pcall_err(meths.eval_statusline, '', { fillchar = 1 })) end) it('rejects invalid string', function() -- cgit From ff3d04b75b4a9314815c37d53ebc4d035a043335 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 08:07:38 -0500 Subject: refactor(api): VALIDATE macros #22256 - VALIDATE() takes a format string - deduplicate check_string_array - VALIDATE_RANGE - validate UI args --- test/functional/api/vim_spec.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5c56c90952..469d8e8b6a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1411,9 +1411,9 @@ describe('API', function() end) it('validation', function() - eq("Invalid scope (expected 'local' or 'global')", + eq("Invalid scope: expected 'local' or 'global'", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'})) - eq("Invalid scope (expected 'local' or 'global')", + eq("Invalid scope: expected 'local' or 'global'", pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) eq("Invalid scope: expected String, got Integer", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) @@ -2238,7 +2238,7 @@ describe('API', function() {'nvim_set_var'}, {'nvim_set_var', {'avar', 2}}, } - eq('Items in calls array must be arrays of size 2', + eq('calls item must be a 2-item Array', pcall_err(meths.call_atomic, req)) -- call before was done, but not after eq(1, meths.get_var('avar')) @@ -3119,11 +3119,11 @@ describe('API', function() meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 })) end) it('rejects multiple-character fillchar', function() - eq('Invalid fillchar (not a single character)', + eq('Invalid fillchar: expected single character', pcall_err(meths.eval_statusline, '', { fillchar = 'aa' })) end) it('rejects empty string fillchar', function() - eq('Invalid fillchar (not a single character)', + eq('Invalid fillchar: expected single character', pcall_err(meths.eval_statusline, '', { fillchar = '' })) end) it('rejects non-string fillchar', function() -- cgit From 556f8646c01d1751cf39fe4df9c622899dceab9d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 14:19:28 -0500 Subject: refactor(api): consistent VALIDATE messages #22262 Problem: Validation messages are not consistently formatted. - Parameter names sometimes are NOT quoted. - Descriptive names (non-parameters) sometimes ARE quoted. Solution: Always quote the `name` value passed to a VALIDATE macro _unless_ the value has whitespace. --- test/functional/api/vim_spec.lua | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 469d8e8b6a..981fc19b36 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -490,7 +490,7 @@ describe('API', function() eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) - it('validates args', function() + it('validation', function() local too_many_args = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' } source([[ function! Foo(...) abort @@ -532,7 +532,7 @@ describe('API', function() eq('@it works@', nvim('call_dict_function', { result = 'it works', G = 'G'}, 'G', {})) end) - it('validates args', function() + it('validation', function() command('let g:d={"baz":"zub","meep":[]}') eq('Not found: bogus', pcall_err(request, 'nvim_call_dict_function', 'g:d', 'bogus', {1,2})) @@ -648,10 +648,10 @@ describe('API', function() end) describe('nvim_paste', function() - it('validates args', function() - eq('Invalid phase: -2', + it('validation', function() + eq("Invalid 'phase': -2", pcall_err(request, 'nvim_paste', 'foo', true, -2)) - eq('Invalid phase: 4', + eq("Invalid 'phase': 4", pcall_err(request, 'nvim_paste', 'foo', true, 4)) end) local function run_streamed_paste_tests() @@ -1154,10 +1154,10 @@ describe('API', function() end) describe('nvim_put', function() - it('validates args', function() - eq("Invalid line: expected String, got Integer", + it('validation', function() + eq("Invalid 'line': expected String, got Integer", pcall_err(request, 'nvim_put', {42}, 'l', false, false)) - eq("Invalid type: 'x'", + eq("Invalid 'type': 'x'", pcall_err(request, 'nvim_put', {'foo'}, 'x', false, false)) end) it("fails if 'nomodifiable'", function() @@ -1259,9 +1259,9 @@ describe('API', function() yyybc line 2 line 3 ]]) - eq("Invalid type: 'bx'", + eq("Invalid 'type': 'bx'", pcall_err(meths.put, {'xxx', 'yyy'}, 'bx', false, true)) - eq("Invalid type: 'b3x'", + eq("Invalid 'type': 'b3x'", pcall_err(meths.put, {'xxx', 'yyy'}, 'b3x', false, true)) end) end) @@ -1288,6 +1288,11 @@ describe('API', function() end) describe('set/get/del variables', function() + it('validation', function() + eq('Key not found: bogus', pcall_err(meths.get_var, 'bogus')) + eq('Key not found: bogus', pcall_err(meths.del_var, 'bogus')) + end) + it('nvim_get_var, nvim_set_var, nvim_del_var', function() nvim('set_var', 'lua', {1, 2, {['3'] = 1}}) eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua')) @@ -1411,12 +1416,14 @@ describe('API', function() end) it('validation', function() - eq("Invalid scope: expected 'local' or 'global'", + eq("Invalid 'scope': expected 'local' or 'global'", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'})) - eq("Invalid scope: expected 'local' or 'global'", + eq("Invalid 'scope': expected 'local' or 'global'", pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) - eq("Invalid scope: expected String, got Integer", + eq("Invalid 'scope': expected String, got Integer", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) + eq("Invalid 'scrolloff': expected Integer/Boolean/String, got Array", + pcall_err(nvim, 'set_option_value', 'scrolloff', {}, {})) end) it('can get local values when global value is set', function() @@ -1786,12 +1793,12 @@ describe('API', function() end) describe('nvim_get_context', function() - it('validates args', function() + it('validation', function() eq("Invalid key: 'blah'", pcall_err(nvim, 'get_context', {blah={}})) - eq("Invalid types: expected Array, got Integer", + eq("Invalid 'types': expected Array, got Integer", pcall_err(nvim, 'get_context', {types=42})) - eq("Invalid type: 'zub'", + eq("Invalid 'type': 'zub'", pcall_err(nvim, 'get_context', {types={'jumps', 'zub', 'zam',}})) end) it('returns map of current editor state', function() @@ -2238,7 +2245,7 @@ describe('API', function() {'nvim_set_var'}, {'nvim_set_var', {'avar', 2}}, } - eq('calls item must be a 2-item Array', + eq("Invalid 'calls' item: expected 2-item Array", pcall_err(meths.call_atomic, req)) -- call before was done, but not after eq(1, meths.get_var('avar')) @@ -2247,7 +2254,7 @@ describe('API', function() { 'nvim_set_var', { 'bvar', { 2, 3 } } }, 12, } - eq("Invalid calls item: expected Array, got Integer", + eq("Invalid 'calls' item: expected Array, got Integer", pcall_err(meths.call_atomic, req)) eq({2,3}, meths.get_var('bvar')) @@ -2255,7 +2262,7 @@ describe('API', function() {'nvim_set_current_line', 'little line'}, {'nvim_set_var', {'avar', 3}}, } - eq("Invalid args: expected Array, got String", + eq("Invalid call args: expected Array, got String", pcall_err(meths.call_atomic, req)) -- call before was done, but not after eq(1, meths.get_var('avar')) @@ -3119,15 +3126,15 @@ describe('API', function() meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 })) end) it('rejects multiple-character fillchar', function() - eq('Invalid fillchar: expected single character', + eq("Invalid 'fillchar': expected single character", pcall_err(meths.eval_statusline, '', { fillchar = 'aa' })) end) it('rejects empty string fillchar', function() - eq('Invalid fillchar: expected single character', + eq("Invalid 'fillchar': expected single character", pcall_err(meths.eval_statusline, '', { fillchar = '' })) end) it('rejects non-string fillchar', function() - eq("Invalid fillchar: expected String, got Integer", + eq("Invalid 'fillchar': expected String, got Integer", pcall_err(meths.eval_statusline, '', { fillchar = 1 })) end) it('rejects invalid string', function() -- cgit From 09b3432eaff3abcadb56d61b6f247f992b80b63f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 16 Feb 2023 10:07:18 -0500 Subject: fix(api): allow empty Lua table for nested dicts #22268 Problem: The Lua-API bridge allows Dict params to be empty Lua (list) tables at the function-signature level. But not for _nested_ Dicts, because they are not modeled: https://github.com/neovim/neovim/blob/fae754073289566051433fae74ec65783f9e7a6a/src/nvim/api/keysets.lua#L184 Some API functions like nvim_cmd check for kObjectTypeDictionary and don't handle the case of empty Lua tables (treated as "Array"). Solution: Introduce VALIDATE_T_DICT and use it in places where kObjectTypeDictionary was being checked directly. fixes #21005 --- test/functional/api/vim_spec.lua | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 981fc19b36..3e40967dd5 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3826,14 +3826,71 @@ describe('API', function() meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) eq(true, meths.get_option_value("cursorline", {})) end) + + it('validation', function() + eq("Invalid 'cmd': expected non-empty String", + pcall_err(meths.cmd, { cmd = ""}, {})) + eq("Invalid 'cmd': expected non-empty String", + pcall_err(meths.cmd, { cmd = {}}, {})) + eq("Invalid 'args': expected Array, got Boolean", + pcall_err(meths.cmd, { cmd = "set", args = true }, {})) + eq("Invalid 'magic': expected Dict, got Array", + pcall_err(meths.cmd, { cmd = "set", args = {}, magic = {} }, {})) + eq("Invalid command arg: expected non-whitespace", + pcall_err(meths.cmd, { cmd = "set", args = {' '}, }, {})) + eq("Invalid command arg: expected valid type, got Array", + pcall_err(meths.cmd, { cmd = "set", args = {{}}, }, {})) + eq("Wrong number of arguments", + pcall_err(meths.cmd, { cmd = "aboveleft", args = {}, }, {})) + eq("Command cannot accept bang: print", + pcall_err(meths.cmd, { cmd = "print", args = {}, bang = true }, {})) + + eq("Command cannot accept range: set", + pcall_err(meths.cmd, { cmd = "set", args = {}, range = {1} }, {})) + eq("Invalid 'range': expected Array, got Boolean", + pcall_err(meths.cmd, { cmd = "print", args = {}, range = true }, {})) + eq("Invalid 'range': expected <=2 elements", + pcall_err(meths.cmd, { cmd = "print", args = {}, range = {1,2,3,4} }, {})) + eq("Invalid range element: expected non-negative Integer", + pcall_err(meths.cmd, { cmd = "print", args = {}, range = {-1} }, {})) + + eq("Command cannot accept count: set", + pcall_err(meths.cmd, { cmd = "set", args = {}, count = 1 }, {})) + eq("Invalid 'count': expected non-negative Integer", + pcall_err(meths.cmd, { cmd = "print", args = {}, count = true }, {})) + eq("Invalid 'count': expected non-negative Integer", + pcall_err(meths.cmd, { cmd = "print", args = {}, count = -1 }, {})) + + eq("Command cannot accept register: set", + pcall_err(meths.cmd, { cmd = "set", args = {}, reg = 'x' }, {})) + eq('Cannot use register "=', + pcall_err(meths.cmd, { cmd = "put", args = {}, reg = '=' }, {})) + eq("Invalid 'reg': expected single character, got xx", + pcall_err(meths.cmd, { cmd = "put", args = {}, reg = 'xx' }, {})) + + -- Lua call allows empty {} for dict item. + eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]])) + eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]])) + + -- Lua call does not allow non-empty list-like {} for dict item. + eq("Invalid 'magic': expected Dict, got Array", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]])) + eq("Invalid key: 'bogus'", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]])) + eq("Invalid key: 'bogus'", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, mods = { bogus = true } }]])) + end) + it('captures output', function() eq("foo", meths.cmd({ cmd = "echo", args = { '"foo"' } }, { output = true })) end) + it('sets correct script context', function() meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) local str = meths.exec([[verbose set cursorline?]], true) neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)")) end) + it('works with range', function() insert [[ line1 -- cgit From 7f424e2b65779c59fc0cac3cc7508ba2ec07f200 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 23 Feb 2023 18:29:36 +0100 Subject: feat(api): more fields in nvim_list_uis Problem: nvim_list_uis does not report all ":help ui-option" fields. Solution: Store ":help ui-option" fields on the `UI` object and update ui_array. --- test/functional/api/vim_spec.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 3e40967dd5..08abf82f47 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2549,20 +2549,26 @@ describe('API', function() { chan = 1, ext_cmdline = false, - ext_popupmenu = false, - ext_tabline = false, - ext_wildmenu = false, + ext_hlstate = false, ext_linegrid = screen._options.ext_linegrid or false, + ext_messages = false, ext_multigrid = false, - ext_hlstate = false, + ext_popupmenu = false, + ext_tabline = false, ext_termcolors = false, - ext_messages = false, + ext_wildmenu = false, height = 4, - rgb = true, override = true, + rgb = true, + stdin_tty = false, + stdout_tty = false, + term_background = '', + term_colors = 0, + term_name = '', width = 20, } } + eq(expected, nvim("list_uis")) screen:detach() -- cgit From 6d0c61d90d316473eee0729363e20bf06825b09b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Mar 2023 21:09:11 +0800 Subject: fix(api): set script context when setting usercmd or option (#22624) --- test/functional/api/vim_spec.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 08abf82f47..48ac491ade 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2832,6 +2832,24 @@ describe('API', function() type = "boolean", was_set = true }, meths.get_option_info'showcmd') + + meths.set_option_value('showcmd', true, {}) + + eq({ + allows_duplicates = true, + commalist = false, + default = true, + flaglist = false, + global_local = false, + last_set_chan = 1, + last_set_linenr = 0, + last_set_sid = -9, + name = "showcmd", + scope = "global", + shortname = "sc", + type = "boolean", + was_set = true + }, meths.get_option_info'showcmd') end) end) -- cgit From 673d2b52fa4335aa083c52e6686f0728e25b8ebd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 7 Mar 2023 16:04:57 +0100 Subject: refactor!: rename vim.pretty_print => vim.print Problem: The function name `vim.pretty_print`: 1. is verbose, which partially defeats its purpose as sugar 2. does not draw from existing precedent or any sort of convention (except external projects like penlight or python?), which reduces discoverability, and degrades signaling about best practices. Solution: - Rename to `vim.print`. - Change the behavior so that 1. strings are printed without quotes 2. each arg is printed on its own line 3. tables are indented with 2 instead of 4 spaces - Example: :lua ='a', 'b', 42, {a=3} a b 42 { a = 3 } Comparison of alternatives: - `vim.print`: - pro: consistent with Lua's `print()` - pro: aligns with potential `nvim_print` API function which will replace nvim_echo, nvim_notify, etc. - con: behaves differently than Lua's `print()`, slightly misleading? - `vim.echo`: - pro: `:echo` has similar "pretty print" behavior. - con: inconsistent with Lua idioms. - `vim.p`: - pro: very short, fits with `vim.o`, etc. - con: not as discoverable as "echo" - con: less opportunity for `local p = vim.p` because of potential shadowing. --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 48ac491ade..2af041c706 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -4042,7 +4042,7 @@ describe('API', function() it('splits arguments correctly for Lua callback', function() meths.exec_lua([[ local function FooFunc(opts) - vim.pretty_print(opts.fargs) + vim.print(opts.fargs) end vim.api.nvim_create_user_command("Foo", FooFunc, { nargs = '+' }) -- cgit From e5641df6d3fc3bb6c3c55593b6152082bfc561b6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 11 Mar 2023 17:11:02 +0000 Subject: feat: add `vim.filetype.get_option()` --- test/functional/api/vim_spec.lua | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 2af041c706..ff1bfef591 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1518,6 +1518,31 @@ describe('API', function() nvim('get_option_value', 'filetype', {buf = buf}) eq({1, 9}, nvim('win_get_cursor', win)) end) + + it('can get default option values for filetypes', function() + command('filetype plugin on') + for ft, opts in pairs { + lua = { commentstring = '-- %s' }, + vim = { commentstring = '"%s' }, + man = { tagfunc = 'v:lua.require\'man\'.goto_tag' }, + xml = { formatexpr = 'xmlformat#Format()' } + } do + for option, value in pairs(opts) do + eq(value, nvim('get_option_value', option, { filetype = ft })) + end + end + + command'au FileType lua setlocal commentstring=NEW\\ %s' + + eq('NEW %s', nvim('get_option_value', 'commentstring', { filetype = 'lua' })) + end) + + it('errors for bad FileType autocmds', function() + command'au FileType lua setlocal commentstring=BAD' + eq([[FileType Autocommands for "lua": Vim(setlocal):E537: 'commentstring' must be empty or contain %s: commentstring=BAD]], + pcall_err(nvim, 'get_option_value', 'commentstring', { filetype = 'lua' })) + end) + end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() -- cgit From fe9cbcb3a5c82932ecfb8f49d07e98a1fc2b31e5 Mon Sep 17 00:00:00 2001 From: Evgeni Chasnovski Date: Sat, 25 Mar 2023 18:58:48 +0200 Subject: feat(api): nvim_exec2(), deprecate nvim_exec() #19032 Problem: The signature of nvim_exec() is not extensible per ":help api-contract". Solution: Introduce nvim_exec2() and deprecate nvim_exec(). --- test/functional/api/vim_spec.lua | 149 +++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 68 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index ff1bfef591..162735dbd7 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -89,132 +89,145 @@ describe('API', function() eq({mode='i', blocking=false}, nvim("get_mode")) end) - describe('nvim_exec', function() + describe('nvim_exec2', function() + it('always returns table', function() + -- In built version this results into `vim.empty_dict()` + eq({}, nvim('exec2', 'echo "Hello"', {})) + eq({}, nvim('exec2', 'echo "Hello"', { output = false })) + eq({ output = 'Hello' }, nvim('exec2', 'echo "Hello"', { output = true })) + end) + + it('default options', function() + -- Should be equivalent to { output = false } + nvim('exec2', "let x0 = 'a'", {}) + eq('a', nvim('get_var', 'x0')) + end) + it('one-line input', function() - nvim('exec', "let x1 = 'a'", false) + nvim('exec2', "let x1 = 'a'", { output = false }) eq('a', nvim('get_var', 'x1')) end) it(':verbose set {option}?', function() - nvim('exec', 'set nowrap', false) - eq('nowrap\n\tLast set from anonymous :source', - nvim('exec', 'verbose set wrap?', true)) + nvim('exec2', 'set nowrap', { output = false }) + eq({ output = 'nowrap\n\tLast set from anonymous :source' }, + nvim('exec2', 'verbose set wrap?', { output = true })) -- Using script var to force creation of a script item - nvim('exec', [[ + nvim('exec2', [[ let s:a = 1 set nowrap - ]], false) - eq('nowrap\n\tLast set from anonymous :source (script id 1)', - nvim('exec', 'verbose set wrap?', true)) + ]], { output = false }) + eq({ output = 'nowrap\n\tLast set from anonymous :source (script id 1)' }, + nvim('exec2', 'verbose set wrap?', { output = true })) end) it('multiline input', function() -- Heredoc + empty lines. - nvim('exec', "let x2 = 'a'\n", false) + nvim('exec2', "let x2 = 'a'\n", { output = false }) eq('a', nvim('get_var', 'x2')) - nvim('exec','lua <avast_ye_hades('ahoy!') - ]], true)) + ]], { output = true })) - eq('ahoy! script-scoped varrrrr', nvim('exec', [[ + eq({ output = "{'output': 'ahoy! script-scoped varrrrr'}" }, nvim('exec2', [[ let s:pirate = 'script-scoped varrrrr' function! Avast_ye_hades(s) abort return a:s .. ' ' .. s:pirate endfunction - echo nvim_exec('echo Avast_ye_hades(''ahoy!'')', 1) - ]], true)) + echo nvim_exec2('echo Avast_ye_hades(''ahoy!'')', {'output': v:true}) + ]], { output = true })) matches('Vim%(echo%):E121: Undefined variable: s:pirate$', - pcall_err(request, 'nvim_exec', [[ + pcall_err(request, 'nvim_exec2', [[ let s:pirate = 'script-scoped varrrrr' - call nvim_exec('echo s:pirate', 1) - ]], false)) + call nvim_exec2('echo s:pirate', {'output': v:true}) + ]], { output = false })) -- Script items are created only on script var access - eq('1\n0', nvim('exec', [[ + eq({ output = '1\n0' }, nvim('exec2', [[ echo expand("")->empty() let s:a = 123 echo expand("")->empty() - ]], true)) + ]], { output = true })) - eq('1\n0', nvim('exec', [[ + eq({ output = '1\n0' }, nvim('exec2', [[ echo expand("")->empty() function s:a() abort endfunction echo expand("")->empty() - ]], true)) + ]], { output = true })) end) it('non-ASCII input', function() - nvim('exec', [=[ + nvim('exec2', [=[ new exe "normal! i ax \n Ax " :%s/ax/--a1234--/g | :%s/Ax/--A1234--/g - ]=], false) + ]=], { output = false }) nvim('command', '1') eq(' --a1234-- ', nvim('get_current_line')) nvim('command', '2') eq(' --A1234-- ', nvim('get_current_line')) - nvim('exec', [[ + nvim('exec2', [[ new call setline(1,['xxx']) call feedkeys('r') call feedkeys('ñ', 'xt') - ]], false) + ]], { output = false }) eq('ñxx', nvim('get_current_line')) end) it('execution error', function() - eq('nvim_exec(): Vim:E492: Not an editor command: bogus_command', - pcall_err(request, 'nvim_exec', 'bogus_command', false)) + eq('nvim_exec2(): Vim:E492: Not an editor command: bogus_command', + pcall_err(request, 'nvim_exec2', 'bogus_command', {})) eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) - eq('nvim_exec(): Vim(buffer):E86: Buffer 23487 does not exist', - pcall_err(request, 'nvim_exec', 'buffer 23487', false)) + eq('nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist', + pcall_err(request, 'nvim_exec2', 'buffer 23487', {})) eq('', eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) @@ -222,17 +235,17 @@ describe('API', function() it('recursion', function() local fname = tmpname() write_file(fname, 'let x1 = "set from :source file"\n') - -- nvim_exec + -- nvim_exec2 -- :source - -- nvim_exec - request('nvim_exec', [[ + -- nvim_exec2 + request('nvim_exec2', [[ let x2 = substitute('foo','o','X','g') let x4 = 'should be overwritten' - call nvim_exec("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec','g')\nlet x5='overwritten'\nlet x4=x5\n", v:false) - ]], false) + call nvim_exec2("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false}) + ]], { output = false }) eq('set from :source file', request('nvim_get_var', 'x1')) eq('fXX', request('nvim_get_var', 'x2')) - eq('set by recursive nvim_exec', request('nvim_get_var', 'x3')) + eq('set by recursive nvim_exec2', request('nvim_get_var', 'x3')) eq('overwritten', request('nvim_get_var', 'x4')) eq('overwritten', request('nvim_get_var', 'x5')) os.remove(fname) @@ -242,35 +255,35 @@ describe('API', function() local fname = tmpname() write_file(fname, 'echo "hello"\n') local sourcing_fname = tmpname() - write_file(sourcing_fname, 'call nvim_exec("source '..fname..'", v:false)\n') - meths.exec('set verbose=2', false) + write_file(sourcing_fname, 'call nvim_exec2("source '..fname..'", {"output": v:false})\n') + meths.exec2('set verbose=2', { output = false }) local traceback_output = 'line 0: sourcing "'..sourcing_fname..'"\n'.. 'line 0: sourcing "'..fname..'"\n'.. 'hello\n'.. 'finished sourcing '..fname..'\n'.. - 'continuing in nvim_exec() called at '..sourcing_fname..':1\n'.. + 'continuing in nvim_exec2() called at '..sourcing_fname..':1\n'.. 'finished sourcing '..sourcing_fname..'\n'.. - 'continuing in nvim_exec() called at nvim_exec():0' - eq(traceback_output, - meths.exec('call nvim_exec("source '..sourcing_fname..'", v:false)', true)) + 'continuing in nvim_exec2() called at nvim_exec2():0' + eq({ output = traceback_output }, + meths.exec2('call nvim_exec2("source '..sourcing_fname..'", {"output": v:false})', { output = true })) os.remove(fname) os.remove(sourcing_fname) end) it('returns output', function() - eq('this is spinal tap', - nvim('exec', 'lua <]]) @@ -575,7 +588,7 @@ describe('API', function() it('sets previous directory', function() meths.set_current_dir("Xtestdir") - meths.exec('cd -', false) + meths.exec2('cd -', { output = false }) eq(funcs.getcwd(), start_dir) end) end) @@ -2674,7 +2687,7 @@ describe('API', function() eq(' 1 %a "[No Name]" line 1\n'.. ' 3 h "[Scratch]" line 0\n'.. ' 4 h "[Scratch]" line 0', - meths.exec('ls', true)) + meths.exec2('ls', { output = true }).output) -- current buffer didn't change eq({id=1}, meths.get_current_buf()) @@ -2788,7 +2801,7 @@ describe('API', function() end) it('should not crash when echoed', function() - meths.exec("echo nvim_get_all_options_info()", true) + meths.exec2("echo nvim_get_all_options_info()", { output = true }) end) end) @@ -2941,13 +2954,13 @@ describe('API', function() it('can save message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {}) - eq("msg\nmsgmsg", meths.exec('messages', true)) + eq("msg\nmsgmsg", meths.exec2('messages', { output = true }).output) end) it('can disable saving message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {}) - eq("", meths.exec("messages", true)) + eq("", meths.exec2("messages", { output = true }).output) end) end) @@ -3936,7 +3949,7 @@ describe('API', function() it('sets correct script context', function() meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) - local str = meths.exec([[verbose set cursorline?]], true) + local str = meths.exec2([[verbose set cursorline?]], { output = true }).output neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)")) end) @@ -3986,7 +3999,7 @@ describe('API', function() line6 ]] meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {}) - meths.exec("1put a", false) + meths.exec2("1put a", { output = false }) expect [[ line1 line2 @@ -4051,11 +4064,11 @@ describe('API', function() { output = true })) end) it('splits arguments correctly', function() - meths.exec([[ + meths.exec2([[ function! FooFunc(...) echo a:000 endfunction - ]], false) + ]], { output = false }) meths.create_user_command("Foo", "call FooFunc()", { nargs = '+' }) eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=], meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}}, -- cgit From 4863ca6b8902c5b0aab95f2af640118cd417d379 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Mar 2023 10:49:32 +0800 Subject: test: use exec_capture() in more places (#22787) Problem: Using `meths.exec2("code", { output = true })` is too verbose. Solution: Use exec_capture() in more places. --- test/functional/api/vim_spec.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 162735dbd7..d8fb1bc623 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -9,6 +9,7 @@ local NIL = helpers.NIL local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq local command = helpers.command local exec = helpers.exec +local exec_capture = helpers.exec_capture local eval = helpers.eval local expect = helpers.expect local funcs = helpers.funcs @@ -588,7 +589,7 @@ describe('API', function() it('sets previous directory', function() meths.set_current_dir("Xtestdir") - meths.exec2('cd -', { output = false }) + command('cd -') eq(funcs.getcwd(), start_dir) end) end) @@ -2687,7 +2688,7 @@ describe('API', function() eq(' 1 %a "[No Name]" line 1\n'.. ' 3 h "[Scratch]" line 0\n'.. ' 4 h "[Scratch]" line 0', - meths.exec2('ls', { output = true }).output) + exec_capture('ls')) -- current buffer didn't change eq({id=1}, meths.get_current_buf()) @@ -2954,13 +2955,13 @@ describe('API', function() it('can save message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {}) - eq("msg\nmsgmsg", meths.exec2('messages', { output = true }).output) + eq("msg\nmsgmsg", exec_capture('messages')) end) it('can disable saving message history', function() nvim('command', 'set cmdheight=2') -- suppress Press ENTER nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {}) - eq("", meths.exec2("messages", { output = true }).output) + eq("", exec_capture('messages')) end) end) @@ -3949,7 +3950,7 @@ describe('API', function() it('sets correct script context', function() meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) - local str = meths.exec2([[verbose set cursorline?]], { output = true }).output + local str = exec_capture([[verbose set cursorline?]]) neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)")) end) @@ -3999,7 +4000,7 @@ describe('API', function() line6 ]] meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {}) - meths.exec2("1put a", { output = false }) + command('1put a') expect [[ line1 line2 @@ -4064,11 +4065,11 @@ describe('API', function() { output = true })) end) it('splits arguments correctly', function() - meths.exec2([[ + exec([[ function! FooFunc(...) echo a:000 endfunction - ]], { output = false }) + ]]) meths.create_user_command("Foo", "call FooFunc()", { nargs = '+' }) eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=], meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}}, -- cgit From b7748662ed5b06c12a74560690b728fdf770666f Mon Sep 17 00:00:00 2001 From: Michal Liszcz Date: Wed, 29 Mar 2023 09:59:01 +0200 Subject: fix(api): Use local LastSet structure in nvim_get_option_info (#22741) fix(api): use local LastSet structure in nvim_get_option_info * nvim_get_option_info is deprecated. It is always using the global LastSet information as reported in #15232. * nvim_get_option_info2 is added. The new function additionally accepts an 'opts' table {scope, buf, win} allowing to specify the option scope and query local options from another buffer or window. --- test/functional/api/vim_spec.lua | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index d8fb1bc623..9d5a0c4b4e 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2892,6 +2892,99 @@ describe('API', function() end) end) + describe('nvim_get_option_info2', function() + local fname + local bufs + local wins + + before_each(function() + fname = tmpname() + write_file(fname, [[ + setglobal dictionary=mydict " 1, global-local (buffer) + setlocal formatprg=myprg " 2, global-local (buffer) + setglobal equalprg=prg1 " 3, global-local (buffer) + setlocal equalprg=prg2 " 4, global-local (buffer) + setglobal fillchars=stl:x " 5, global-local (window) + setlocal listchars=eol:c " 6, global-local (window) + setglobal showbreak=aaa " 7, global-local (window) + setlocal showbreak=bbb " 8, global-local (window) + setglobal completeopt=menu " 9, global + ]]) + + exec_lua 'vim.cmd.vsplit()' + meths.create_buf(false, false) + + bufs = meths.list_bufs() + wins = meths.list_wins() + + meths.win_set_buf(wins[1].id, bufs[1].id) + meths.win_set_buf(wins[2].id, bufs[2].id) + + meths.set_current_win(wins[2].id) + meths.exec('source ' .. fname, false) + + meths.set_current_win(wins[1].id) + end) + + after_each(function() + os.remove(fname) + end) + + it('should return option information', function() + eq(meths.get_option_info('dictionary'), meths.get_option_info2('dictionary', {})) -- buffer + eq(meths.get_option_info('fillchars'), meths.get_option_info2('fillchars', {})) -- window + eq(meths.get_option_info('completeopt'), meths.get_option_info2('completeopt', {})) -- global + end) + + describe('last set', function() + local tests = { + {desc="(buf option, global requested, global set) points to global", linenr=1, sid=1, args={'dictionary', {scope='global'}}}, + {desc="(buf option, global requested, local set) is not set", linenr=0, sid=0, args={'formatprg', {scope='global'}}}, + {desc="(buf option, global requested, both set) points to global", linenr=3, sid=1, args={'equalprg', {scope='global'}}}, + {desc="(buf option, local requested, global set) is not set", linenr=0, sid=0, args={'dictionary', {scope='local'}}}, + {desc="(buf option, local requested, local set) points to local", linenr=2, sid=1, args={'formatprg', {scope='local'}}}, + {desc="(buf option, local requested, both set) points to local", linenr=4, sid=1, args={'equalprg', {scope='local'}}}, + {desc="(buf option, fallback requested, global set) points to global", linenr=1, sid=1, args={'dictionary', {}}}, + {desc="(buf option, fallback requested, local set) points to local", linenr=2, sid=1, args={'formatprg', {}}}, + {desc="(buf option, fallback requested, both set) points to local", linenr=4, sid=1, args={'equalprg', {}}}, + {desc="(win option, global requested, global set) points to global", linenr=5, sid=1, args={'fillchars', {scope='global'}}}, + {desc="(win option, global requested, local set) is not set", linenr=0, sid=0, args={'listchars', {scope='global'}}}, + {desc="(win option, global requested, both set) points to global", linenr=7, sid=1, args={'showbreak', {scope='global'}}}, + {desc="(win option, local requested, global set) is not set", linenr=0, sid=0, args={'fillchars', {scope='local'}}}, + {desc="(win option, local requested, local set) points to local", linenr=6, sid=1, args={'listchars', {scope='local'}}}, + {desc="(win option, local requested, both set) points to local", linenr=8, sid=1, args={'showbreak', {scope='local'}}}, + {desc="(win option, fallback requested, global set) points to global", linenr=5, sid=1, args={'fillchars', {}}}, + {desc="(win option, fallback requested, local set) points to local", linenr=6, sid=1, args={'listchars', {}}}, + {desc="(win option, fallback requested, both set) points to local", linenr=8, sid=1, args={'showbreak', {}}}, + {desc="(global option, global requested) points to global", linenr=9, sid=1, args={'completeopt', {scope='global'}}}, + {desc="(global option, local requested) is not set", linenr=0, sid=0, args={'completeopt', {scope='local'}}}, + {desc="(global option, fallback requested) points to global", linenr=9, sid=1, args={'completeopt', {}}}, + } + + for _, t in pairs(tests) do + it(t.desc, function() + -- Switch to the target buffer/window so that curbuf/curwin are used. + meths.set_current_win(wins[2].id) + local info = meths.get_option_info2(unpack(t.args)) + eq(t.linenr, info.last_set_linenr) + eq(t.sid, info.last_set_sid) + end) + end + + it('is provided for cross-buffer requests', function() + local info = meths.get_option_info2('formatprg', {buf=bufs[2].id}) + eq(2, info.last_set_linenr) + eq(1, info.last_set_sid) + end) + + it('is provided for cross-window requests', function() + local info = meths.get_option_info2('listchars', {win=wins[2].id}) + eq(6, info.last_set_linenr) + eq(1, info.last_set_sid) + end) + end) + end) + describe('nvim_echo', function() local screen -- cgit From 7c8c1550737b34fabb3e4cecbc6b6bf3581b2235 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 4 Apr 2023 08:59:11 +0800 Subject: fix(api): avoid double hit-enter prompt with nvim_err_writeln (#22879) --- test/functional/api/vim_spec.lua | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 9d5a0c4b4e..83347a499b 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2080,6 +2080,46 @@ describe('API', function() end) end) + describe('nvim_err_writeln', function() + local screen + + before_each(function() + screen = Screen.new(40, 8) + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {foreground = Screen.colors.White, background = Screen.colors.Red}, + [2] = {bold = true, foreground = Screen.colors.SeaGreen}, + [3] = {bold = true, reverse = true}, + }) + end) + + it('shows only one return prompt after all lines are shown', function() + nvim_async('err_writeln', 'FAILURE\nERROR\nEXCEPTION\nTRACEBACK') + screen:expect([[ + | + {0:~ }| + {3: }| + {1:FAILURE} | + {1:ERROR} | + {1:EXCEPTION} | + {1:TRACEBACK} | + {2:Press ENTER or type command to continue}^ | + ]]) + feed('') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) + end) + describe('nvim_list_chans, nvim_get_chan_info', function() before_each(function() command('autocmd ChanOpen * let g:opened_event = deepcopy(v:event)') -- cgit From a5c572bd446a89be2dccb2f7479ff1b017074640 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 4 Apr 2023 19:07:33 +0200 Subject: docs: fix typos Co-authored-by: Gregory Anders Co-authored-by: Raphael Co-authored-by: C.D. MacEachern Co-authored-by: himanoa --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 83347a499b..de0d82119c 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -4180,7 +4180,7 @@ describe('API', function() meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = true } } }, { output = true })) - -- with emsg_silent = true error is suppresed + -- with emsg_silent = true error is suppressed feed([[:lua vim.api.nvim_cmd({ cmd = 'call', mods = { emsg_silent = true } }, {})]]) eq('', meths.cmd({ cmd = 'messages' }, { output = true })) -- error from the next command typed is not suppressed #21420 -- cgit From 743860de40502227b3f0ed64317eb937d24d4a36 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 4 Apr 2023 21:59:06 +0200 Subject: test: replace lfs with luv and vim.fs test: replace lfs with luv luv already pretty much does everything lfs does, so this duplication of dependencies isn't needed. --- test/functional/api/vim_spec.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index de0d82119c..ab26425425 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,6 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local lfs = require('lfs') local luv = require('luv') local fmt = string.format @@ -4193,7 +4192,7 @@ describe('API', function() vim.api.nvim_echo({{ opts.fargs[1] }}, false, {}) end, { nargs = 1 }) ]]) - eq(lfs.currentdir(), + eq(luv.cwd(), meths.cmd({ cmd = "Foo", args = { '%:p:h' }, magic = { file = true } }, { output = true })) end) -- cgit From f0ac91c58b42ed4f38dea7352d89fd39a88142f4 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 1 Apr 2023 14:58:52 +0200 Subject: feat(api): evaluate 'statuscolumn' with nvim_eval_statusline() --- test/functional/api/vim_spec.lua | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index ab26425425..cddea48a76 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3421,6 +3421,40 @@ describe('API', function() 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', { use_winbar = true, highlights = true })) end) + it('works with statuscolumn', function() + command([[ + let &stc='%C%s%=%l ' + set cul nu nuw=3 scl=yes:2 fdc=2 + call setline(1, repeat(['aaaaa'], 5)) + let g:ns = nvim_create_namespace('') + call sign_define('a', {'text':'aa', 'texthl':'IncSearch', 'numhl':'Normal'}) + call sign_place(2, 1, 'a', bufnr(), {'lnum':4}) + call nvim_buf_set_extmark(0, g:ns, 3, 1, { 'sign_text':'bb', 'sign_hl_group':'ErrorMsg' }) + 1,5fold | 1,5 fold | foldopen! + ]]) + command('norm 4G') + command('let v:lnum=4') + eq({ + str = '││aabb 4 ', + width = 9, + highlights = { + { group = 'CursorLineFold', start = 0 }, + { group = 'Normal', start = 6 }, + { group = 'IncSearch', start = 6 }, + { group = 'ErrorMsg', start = 8 }, + { group = 'Normal', start = 10 } + } + }, meths.eval_statusline('%C%s%=%l ', { use_statuscol = true, highlights = true })) + command('let v:lnum=3') + eq({ + str = '3 ' , + width = 2, + highlights = { + { group = 'LineNr', start = 0 }, + { group = 'ErrorMsg', start = 1 } + } + }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol = true, highlights = true })) + end) it('no memory leak with click functions', function() meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) eq({ -- cgit From 25dfed6e0148771cdb659df8c616df3860583c47 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Thu, 6 Apr 2023 03:33:57 +0200 Subject: feat(api): set statuscolumn line number in nvim_eval_statusline() Having the user set `v:lnum` before calling `nvim_eval_statusline()` is unnecesarily fragile. Redraws inbetween setting `v:lnum` and the `nvim_eval_statusline()` call will overwrite `v:lnum`. --- test/functional/api/vim_spec.lua | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index cddea48a76..af6fbf092a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3422,7 +3422,7 @@ describe('API', function() { use_winbar = true, highlights = true })) end) it('works with statuscolumn', function() - command([[ + exec([[ let &stc='%C%s%=%l ' set cul nu nuw=3 scl=yes:2 fdc=2 call setline(1, repeat(['aaaaa'], 5)) @@ -3431,9 +3431,8 @@ describe('API', function() call sign_place(2, 1, 'a', bufnr(), {'lnum':4}) call nvim_buf_set_extmark(0, g:ns, 3, 1, { 'sign_text':'bb', 'sign_hl_group':'ErrorMsg' }) 1,5fold | 1,5 fold | foldopen! + norm 4G ]]) - command('norm 4G') - command('let v:lnum=4') eq({ str = '││aabb 4 ', width = 9, @@ -3444,8 +3443,7 @@ describe('API', function() { group = 'ErrorMsg', start = 8 }, { group = 'Normal', start = 10 } } - }, meths.eval_statusline('%C%s%=%l ', { use_statuscol = true, highlights = true })) - command('let v:lnum=3') + }, meths.eval_statusline('%C%s%=%l ', { use_statuscol_lnum = 4, highlights = true })) eq({ str = '3 ' , width = 2, @@ -3453,7 +3451,7 @@ describe('API', function() { group = 'LineNr', start = 0 }, { group = 'ErrorMsg', start = 1 } } - }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol = true, highlights = true })) + }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true })) end) it('no memory leak with click functions', function() meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) -- cgit From 3a1e17e3a1767b4ff8a082150f7f9d6bda50cc8f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 19:03:08 +0800 Subject: test: add tests for executing commands with backwards range --- test/functional/api/vim_spec.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index af6fbf092a..c81b6e90cc 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -361,6 +361,12 @@ describe('API', function() eq('', eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) + + it('gives E493 instead of prompting on backwards range', function() + command('split') + eq('Vim(windo):E493: Backwards range given: 2,1windo echo', + pcall_err(command, '2,1windo echo')) + end) end) describe('nvim_command_output', function() -- cgit From 1fe1bb084d0099fc4f9bfdc11189485d0f74b75a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 19 Dec 2022 16:37:45 +0000 Subject: refactor(options): deprecate nvim[_buf|_win]_[gs]et_option Co-authored-by: zeertzjq Co-authored-by: famiu --- test/functional/api/vim_spec.lua | 88 ++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 48 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c81b6e90cc..5b8b52a559 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1051,7 +1051,7 @@ describe('API', function() line 3 ]]) eq({0,4,1,0}, funcs.getpos('.')) -- Cursor follows the paste. - eq(false, nvim('get_option', 'paste')) + eq(false, nvim('get_option_value', 'paste', {})) command('%delete _') -- Without final "\n". nvim('paste', 'line 1\nline 2\nline 3', true, -1) @@ -1091,7 +1091,7 @@ describe('API', function() nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', true, -1) expect('line 1\n\n\nline 2\nline 3\nline 4\n') eq({0,7,1,0}, funcs.getpos('.')) - eq(false, nvim('get_option', 'paste')) + eq(false, nvim('get_option_value', 'paste', {})) end) it('Replace-mode', function() -- Within single line @@ -1382,44 +1382,38 @@ describe('API', function() end) end) - describe('nvim_get_option, nvim_set_option', function() + describe('nvim_get_option_value, nvim_set_option_value', function() it('works', function() - ok(nvim('get_option', 'equalalways')) - nvim('set_option', 'equalalways', false) - ok(not nvim('get_option', 'equalalways')) + ok(nvim('get_option_value', 'equalalways', {})) + nvim('set_option_value', 'equalalways', false, {}) + ok(not nvim('get_option_value', 'equalalways', {})) end) it('works to get global value of local options', function() - eq(false, nvim('get_option', 'lisp')) - eq(8, nvim('get_option', 'shiftwidth')) + eq(false, nvim('get_option_value', 'lisp', {})) + eq(8, nvim('get_option_value', 'shiftwidth', {})) end) it('works to set global value of local options', function() - nvim('set_option', 'lisp', true) - eq(true, nvim('get_option', 'lisp')) - eq(false, helpers.curbuf('get_option', 'lisp')) + nvim('set_option_value', 'lisp', true, {scope='global'}) + eq(true, nvim('get_option_value', 'lisp', {scope='global'})) + eq(false, nvim('get_option_value', 'lisp', {buf=0})) eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp')) eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp')) - nvim('set_option', 'shiftwidth', 20) + nvim('set_option_value', 'shiftwidth', 20, {scope='global'}) eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+')) eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+')) end) - it('most window-local options have no global value', function() - local status, err = pcall(nvim, 'get_option', 'foldcolumn') - eq(false, status) - ok(err:match('Invalid option name') ~= nil) - end) - it('updates where the option was last set from', function() - nvim('set_option', 'equalalways', false) + nvim('set_option_value', 'equalalways', false, {}) local status, rv = pcall(nvim, 'command_output', 'verbose set equalalways?') eq(true, status) ok(nil ~= string.find(rv, 'noequalalways\n'.. '\tLast set from API client %(channel id %d+%)')) - nvim('exec_lua', 'vim.api.nvim_set_option("equalalways", true)', {}) + nvim('exec_lua', 'vim.api.nvim_set_option_value("equalalways", true, {})', {}) status, rv = pcall(nvim, 'command_output', 'verbose set equalalways?') eq(true, status) @@ -1499,7 +1493,6 @@ describe('API', function() end) it('set window options', function() - -- Same as to nvim_win_set_option nvim('set_option_value', 'colorcolumn', '4,3', {win=0}) eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'})) command("set modified hidden") @@ -1508,7 +1501,6 @@ describe('API', function() end) it('set local window options', function() - -- Different to nvim_win_set_option nvim('set_option_value', 'colorcolumn', '4,3', {win=0, scope='local'}) eq('4,3', nvim('get_option_value', 'colorcolumn', {win = 0, scope = 'local'})) command("set modified hidden") @@ -1519,11 +1511,11 @@ describe('API', function() it('get buffer or window-local options', function() nvim('command', 'new') local buf = nvim('get_current_buf').id - nvim('buf_set_option', buf, 'tagfunc', 'foobar') + nvim('set_option_value', 'tagfunc', 'foobar', {buf=buf}) eq('foobar', nvim('get_option_value', 'tagfunc', {buf = buf})) local win = nvim('get_current_win').id - nvim('win_set_option', win, 'number', true) + nvim('set_option_value', 'number', true, {win=win}) eq(true, nvim('get_option_value', 'number', {win = win})) end) @@ -2215,7 +2207,7 @@ describe('API', function() it('stream=job :terminal channel', function() command(':terminal') eq({id=1}, meths.get_current_buf()) - eq(3, meths.buf_get_option(1, 'channel')) + eq(3, meths.get_option_value('channel', {buf=1})) local info = { stream='job', @@ -2368,45 +2360,45 @@ describe('API', function() end) it('returns nothing with empty &runtimepath', function() - meths.set_option('runtimepath', '') + meths.set_option_value('runtimepath', '', {}) eq({}, meths.list_runtime_paths()) end) it('returns single runtimepath', function() - meths.set_option('runtimepath', 'a') + meths.set_option_value('runtimepath', 'a', {}) eq({'a'}, meths.list_runtime_paths()) end) it('returns two runtimepaths', function() - meths.set_option('runtimepath', 'a,b') + meths.set_option_value('runtimepath', 'a,b', {}) eq({'a', 'b'}, meths.list_runtime_paths()) end) it('returns empty strings when appropriate', function() - meths.set_option('runtimepath', 'a,,b') + meths.set_option_value('runtimepath', 'a,,b', {}) eq({'a', '', 'b'}, meths.list_runtime_paths()) - meths.set_option('runtimepath', ',a,b') + meths.set_option_value('runtimepath', ',a,b', {}) eq({'', 'a', 'b'}, meths.list_runtime_paths()) -- Trailing "," is ignored. Use ",," if you really really want CWD. - meths.set_option('runtimepath', 'a,b,') + meths.set_option_value('runtimepath', 'a,b,', {}) eq({'a', 'b'}, meths.list_runtime_paths()) - meths.set_option('runtimepath', 'a,b,,') + meths.set_option_value('runtimepath', 'a,b,,', {}) eq({'a', 'b', ''}, meths.list_runtime_paths()) end) it('truncates too long paths', function() local long_path = ('/a'):rep(8192) - meths.set_option('runtimepath', long_path) + meths.set_option_value('runtimepath', long_path, {}) local paths_list = meths.list_runtime_paths() eq({}, paths_list) end) end) it('can throw exceptions', function() - local status, err = pcall(nvim, 'get_option', 'invalid-option') + local status, err = pcall(nvim, 'get_option_value', 'invalid-option', {}) eq(false, status) - ok(err:match('Invalid option name') ~= nil) + ok(err:match("Invalid 'option': 'invalid%-option'") ~= nil) end) it('does not truncate error message <1 MB #5984', function() local very_long_name = 'A'..('x'):rep(10000)..'Z' - local status, err = pcall(nvim, 'get_option', very_long_name) + local status, err = pcall(nvim, 'get_option_value', very_long_name, {}) eq(false, status) eq(very_long_name, err:match('Ax+Z?')) end) @@ -2419,7 +2411,7 @@ describe('API', function() describe('nvim_parse_expression', function() before_each(function() - meths.set_option('isident', '') + meths.set_option_value('isident', '', {}) end) local function simplify_east_api_node(line, east_api_node) @@ -2704,9 +2696,9 @@ describe('API', function() end) it('can change buftype before visiting', function() - meths.set_option("hidden", false) + meths.set_option_value("hidden", false, {}) eq({id=2}, meths.create_buf(true, false)) - meths.buf_set_option(2, "buftype", "nofile") + meths.set_option_value("buftype", "nofile", {buf=2}) meths.buf_set_lines(2, 0, -1, true, {"test text"}) command("split | buffer 2") eq({id=2}, meths.get_current_buf()) @@ -2749,10 +2741,10 @@ describe('API', function() local edited_buf = 2 meths.buf_set_lines(edited_buf, 0, -1, true, {"some text"}) for _,b in ipairs(scratch_bufs) do - eq('nofile', meths.buf_get_option(b, 'buftype')) - eq('hide', meths.buf_get_option(b, 'bufhidden')) - eq(false, meths.buf_get_option(b, 'swapfile')) - eq(false, meths.buf_get_option(b, 'modeline')) + eq('nofile', meths.get_option_value('buftype', {buf=b})) + eq('hide', meths.get_option_value('bufhidden', {buf=b})) + eq(false, meths.get_option_value('swapfile', {buf=b})) + eq(false, meths.get_option_value('modeline', {buf=b})) end -- @@ -2765,10 +2757,10 @@ describe('API', function() {1:~ }| | ]]) - eq('nofile', meths.buf_get_option(edited_buf, 'buftype')) - eq('hide', meths.buf_get_option(edited_buf, 'bufhidden')) - eq(false, meths.buf_get_option(edited_buf, 'swapfile')) - eq(false, meths.buf_get_option(edited_buf, 'modeline')) + eq('nofile', meths.get_option_value('buftype', {buf=edited_buf})) + eq('hide', meths.get_option_value('bufhidden', {buf=edited_buf})) + eq(false, meths.get_option_value('swapfile', {buf=edited_buf})) + eq(false, meths.get_option_value('modeline', {buf=edited_buf})) -- Scratch buffer can be wiped without error. command('bwipe') @@ -2899,7 +2891,7 @@ describe('API', function() it('should have information about global options', function() -- precondition: the option was changed from its default -- in test setup. - eq(false, meths.get_option'showcmd') + eq(false, meths.get_option_value('showcmd', {})) eq({ allows_duplicates = true, -- cgit From 576dddb46168e81aa0f78c28816082c662dedea1 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 22 May 2023 12:47:10 +0600 Subject: test: don't unnecessarily specify win/buf for `nvim_(get|set)_option_value` `nvim_(get|set)_option_value` pick the current buffer / window by default for buffer-local/window-local (but not global-local) options. So specifying `buf = 0` or `win = 0` in opts is unnecessary for those options. This PR removes those to reduce code clutter. --- test/functional/api/vim_spec.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5b8b52a559..040c26e058 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1397,7 +1397,7 @@ describe('API', function() it('works to set global value of local options', function() nvim('set_option_value', 'lisp', true, {scope='global'}) eq(true, nvim('get_option_value', 'lisp', {scope='global'})) - eq(false, nvim('get_option_value', 'lisp', {buf=0})) + eq(false, nvim('get_option_value', 'lisp', {})) eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp')) eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp')) nvim('set_option_value', 'shiftwidth', 20, {scope='global'}) @@ -1493,7 +1493,7 @@ describe('API', function() end) it('set window options', function() - nvim('set_option_value', 'colorcolumn', '4,3', {win=0}) + nvim('set_option_value', 'colorcolumn', '4,3', {}) eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'})) command("set modified hidden") command("enew") -- edit new buffer, window option is preserved -- cgit From 0e0a166a0cc5a2dc199136e313e58c27bfb91977 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 7 Jun 2023 09:00:55 +0800 Subject: refactor(api): adjust errors for setting options (#23942) --- test/functional/api/vim_spec.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 040c26e058..98e5482218 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1435,8 +1435,12 @@ describe('API', function() pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) eq("Invalid 'scope': expected String, got Integer", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) - eq("Invalid 'scrolloff': expected Integer/Boolean/String, got Array", + eq("Invalid 'value': expected Integer/Boolean/String, got Array", pcall_err(nvim, 'set_option_value', 'scrolloff', {}, {})) + eq("Invalid value for option 'scrolloff': expected Number, got Boolean true", + pcall_err(nvim, 'set_option_value', 'scrolloff', true, {})) + eq("Invalid value for option 'scrolloff': expected Number, got String \"wrong\"", + pcall_err(nvim, 'set_option_value', 'scrolloff', 'wrong', {})) end) it('can get local values when global value is set', function() -- cgit From 2f17ef1fc4b96cf1106fd95ba090d34a2e4b977b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 22 Jun 2023 04:09:14 -0700 Subject: fix(messages): use "Vimscript" instead of "VimL" #24111 followup to #24109 fix #16150 --- test/functional/api/vim_spec.lua | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 98e5482218..d56f780ca6 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -346,15 +346,15 @@ describe('API', function() os.remove(fname) end) - it('VimL validation error: fails with specific error', function() + it('Vimscript validation error: fails with specific error', function() local status, rv = pcall(nvim, "command", "bogus_command") eq(false, status) -- nvim_command() failed. - eq("E492:", string.match(rv, "E%d*:")) -- VimL error was returned. + eq("E492:", string.match(rv, "E%d*:")) -- Vimscript error was returned. eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) - it('VimL execution error: fails with specific error', function() + it('Vimscript execution error: fails with specific error', function() local status, rv = pcall(nvim, "command", "buffer 23487") eq(false, status) -- nvim_command() failed. eq("E86: Buffer 23487 does not exist", string.match(rv, "E%d*:.*")) @@ -422,7 +422,7 @@ describe('API', function() eq(':!echo foo\r\n\nfoo'..win_lf..'\n', nvim('command_output', [[!echo foo]])) end) - it('VimL validation error: fails with specific error', function() + it('Vimscript validation error: fails with specific error', function() local status, rv = pcall(nvim, "command_output", "bogus commannnd") eq(false, status) -- nvim_command_output() failed. eq("E492: Not an editor command: bogus commannnd", @@ -432,7 +432,7 @@ describe('API', function() eq({mode='n', blocking=false}, nvim("get_mode")) end) - it('VimL execution error: fails with specific error', function() + it('Vimscript execution error: fails with specific error', function() local status, rv = pcall(nvim, "command_output", "buffer 42") eq(false, status) -- nvim_command_output() failed. eq("E86: Buffer 42 does not exist", string.match(rv, "E%d*:.*")) @@ -463,7 +463,7 @@ describe('API', function() eq(2, request("vim_eval", "1+1")) end) - it("VimL error: returns error details, does NOT update v:errmsg", function() + it("Vimscript error: returns error details, does NOT update v:errmsg", function() eq('Vim:E121: Undefined variable: bogus', pcall_err(request, 'nvim_eval', 'bogus expression')) eq('', eval('v:errmsg')) -- v:errmsg was not updated. @@ -478,7 +478,7 @@ describe('API', function() eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'})) end) - it("VimL validation error: returns specific error, does NOT update v:errmsg", function() + it("Vimscript validation error: returns specific error, does NOT update v:errmsg", function() eq('Vim:E117: Unknown function: bogus function', pcall_err(request, 'nvim_call_function', 'bogus function', {'arg1'})) eq('Vim:E119: Not enough arguments for function: atan', @@ -487,7 +487,7 @@ describe('API', function() eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) - it("VimL error: returns error details, does NOT update v:errmsg", function() + it("Vimscript error: returns error details, does NOT update v:errmsg", function() eq('Vim:E808: Number or Float required', pcall_err(request, 'nvim_call_function', 'atan', {'foo'})) eq('Vim:Invalid channel stream "xxx"', @@ -498,7 +498,7 @@ describe('API', function() eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) - it("VimL exception: returns exception details, does NOT update v:errmsg", function() + it("Vimscript exception: returns exception details, does NOT update v:errmsg", function() source([[ function! Foo() abort throw 'wtf' @@ -523,7 +523,7 @@ describe('API', function() end) describe('nvim_call_dict_function', function() - it('invokes VimL dict function', function() + it('invokes Vimscript dict function', function() source([[ function! F(name) dict return self.greeting.', '.a:name.'!' @@ -653,7 +653,7 @@ describe('API', function() end) describe('nvim_input', function() - it("VimL error: does NOT fail, updates v:errmsg", function() + it("Vimscript error: does NOT fail, updates v:errmsg", function() local status, _ = pcall(nvim, "input", ":call bogus_fn()") local v_errnum = string.match(nvim("eval", "v:errmsg"), "E%d*:") eq(true, status) -- nvim_input() did not fail. -- cgit From e0453d7f5743ad2f515deea76e363d11a7e1fa96 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 28 Jun 2023 04:51:55 -0700 Subject: fix(api): nvim_cmd{cmd="win_getid"} parsed as :winsize #24181 Problem: `:lua vim.cmd.win_getid(30,10)` is interpreted as `:win[size] 30 10`. User intention was to call `vim.fn.win_getid(30,10)`. Solution: Check that the `cmd` actually matches the resolved command. --- test/functional/api/vim_spec.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index d56f780ca6..1ac732b128 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -335,8 +335,7 @@ describe('API', function() nvim('command', 'edit '..fname) nvim('command', 'normal itesting\napi') nvim('command', 'w') - local f = io.open(fname) - ok(f ~= nil) + local f = assert(io.open(fname)) if is_os('win') then eq('testing\r\napi\r\n', f:read('*a')) else @@ -3950,7 +3949,7 @@ describe('API', function() } }, meths.parse_cmd('MyCommand test it', {})) end) - it('errors for invalid command', function() + it('validates command', function() eq('Error while parsing command line', pcall_err(meths.parse_cmd, '', {})) eq('Error while parsing command line', pcall_err(meths.parse_cmd, '" foo', {})) eq('Error while parsing command line: E492: Not an editor command: Fubar', @@ -4097,6 +4096,11 @@ describe('API', function() eq("Invalid 'reg': expected single character, got xx", pcall_err(meths.cmd, { cmd = "put", args = {}, reg = 'xx' }, {})) + -- #20681 + eq('Invalid command: "win_getid"', pcall_err(meths.cmd, { cmd = 'win_getid'}, {})) + eq('Invalid command: "echo "hi""', pcall_err(meths.cmd, { cmd = 'echo "hi"'}, {})) + eq('Invalid command: "win_getid"', pcall_err(exec_lua, [[return vim.cmd.win_getid{}]])) + -- Lua call allows empty {} for dict item. eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]])) eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]])) -- cgit From a741c7fd0465c949a0016fcbee5f4526b65f8c02 Mon Sep 17 00:00:00 2001 From: Alexandre Teoi Date: Sat, 1 Jul 2023 10:33:51 -0300 Subject: fix(api): nvim_parse_cmd error message in pcall() #23297 Problem: nvim_parse_cmd() in pcall() may show an error message (side-effect): :lua pcall(vim.api.nvim_parse_cmd, vim.fn.getcmdline(), {}) E16: Invalid range Solution: Avoid emsg() in the nvim_parse_cmd() codepath. - refactor(api): add error message output parameter to get_address() - fix: null check emsg() parameter - refactor: remove emsg_off workaround from do_incsearch_highlighting() - refactor: remove emsg_off workaround from cmdpreview_may_show() - refactor: remove remaining calls to emsg() from parse_cmd_address() and get_address() - (refactor): lint set_cmd_dflall_range() - refactor: addr_error() - move output parameter to return value Fix #20339 TODO: These are the functions called by `get_address()`: ``` nvim_parse_cmd() -> parse_cmdline() -> parse_cmd_address() -> get_address() skipwhite() addr_error() qf_get_cur_idx() qf_get_cur_valid_idx() qf_get_size() qf_get_valid_size() mark_get() mark_check() assert() skip_regexp() magic_isset() > do_search() > searchit() ascii_isdigit() getdigits() getdigits_int32() compute_buffer_local_count() hasFolding() ``` From these functions, I found at least two that call emsg directly: - do_search() - seems to be simple to refactor - searchit() - will be more challenging because it may generate multiple error messages, which can't be handled by the current `errormsg` out-parameter. For example, it makes multiple calls to `vim_regexec_multi()` in a loop that possibly generate error messages, and later `searchit()` itself may generate another one: - https://github.com/neovim/neovim/blob/c194acbfc479d8e5839fa629363f93f6550d035c/src/nvim/search.c#L631-L647 - https://github.com/neovim/neovim/blob/c194acbfc479d8e5839fa629363f93f6550d035c/src/nvim/search.c#L939-L954 --------- Co-authored-by: Justin M. Keyes --- test/functional/api/vim_spec.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 1ac732b128..c4f89318e0 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3467,6 +3467,7 @@ describe('API', function() end) end) end) + describe('nvim_parse_cmd', function() it('works', function() eq({ @@ -4048,7 +4049,13 @@ describe('API', function() meths.cmd(meths.parse_cmd("set cursorline", {}), {}) eq(true, meths.get_option_value("cursorline", {})) end) + it('no side-effects (error messages) in pcall() #20339', function() + eq({ false, 'Error while parsing command line: E16: Invalid range' }, + exec_lua([=[return {pcall(vim.api.nvim_parse_cmd, "'<,'>n", {})}]=])) + eq('', eval('v:errmsg')) + end) end) + describe('nvim_cmd', function() it('works', function () meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) -- cgit From 92760a7f42a95bb252966c2a38423e5bc9d57cc7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 4 Jul 2023 07:19:02 +0800 Subject: fix(api, lua): make blank lines in a message work properly (#24244) --- test/functional/api/vim_spec.lua | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c4f89318e0..664cd4cbca 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -577,7 +577,6 @@ describe('API', function() local start_dir before_each(function() - clear() funcs.mkdir("Xtestdir") start_dir = funcs.getcwd() end) @@ -1990,6 +1989,39 @@ describe('API', function() ]]) eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', meths.get_var('out')) end) + + it('blank line in message works', function() + local screen = Screen.new(40, 8) + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {bold = true, foreground = Screen.colors.SeaGreen}, + [2] = {bold = true, reverse = true}, + }) + feed([[:call nvim_out_write("\na\n")]]) + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {2: }| + | + a | + {1:Press ENTER or type command to continue}^ | + ]]} + feed('') + feed([[:call nvim_out_write("b\n\nc\n")]]) + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }| + {2: }| + b | + | + c | + {1:Press ENTER or type command to continue}^ | + ]]} + end) end) describe('nvim_err_write', function() @@ -3029,11 +3061,10 @@ describe('API', function() local screen before_each(function() - clear() screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, + [0] = {bold = true, foreground = Screen.colors.Blue}, [1] = {bold = true, foreground = Screen.colors.SeaGreen}, [2] = {bold = true, reverse = true}, [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement @@ -3103,7 +3134,6 @@ describe('API', function() local screen before_each(function() - clear() screen = Screen.new(100, 35) screen:attach() screen:set_default_attr_ids({ -- cgit From b2e8c0df2062f765a4cf7d96379c5f0f19393dfd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 5 Jul 2023 12:06:14 +0800 Subject: fix(edit): fix K_EVENT interfering with 'digraph' (#24258) --- test/functional/api/vim_spec.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 664cd4cbca..6f75de7f1b 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1828,6 +1828,23 @@ describe('API', function() feed('') expect('a') -- recognized i_0_CTRL-D end) + + it("does not interrupt with 'digraph'", function() + command('set digraph') + feed('i,') + eq(2, eval('1+1')) -- causes K_EVENT key + feed('') + eq(2, eval('1+1')) -- causes K_EVENT key + feed('.') + expect('…') -- digraph ",." worked + feed('') + feed(':,') + eq(2, eval('1+1')) -- causes K_EVENT key + feed('') + eq(2, eval('1+1')) -- causes K_EVENT key + feed('.') + eq('…', funcs.getcmdline()) -- digraph ",." worked + end) end) describe('nvim_get_context', function() -- cgit From 2afb04758c341e17c70b8d2e3869c901c8cdb7d2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 6 Jul 2023 12:56:19 +0800 Subject: fix(vim.system): close check handle (#24270) Fix hang after running vim.system() with sanitizers. --- test/functional/api/vim_spec.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 6f75de7f1b..617d0f12ff 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -440,7 +440,7 @@ describe('API', function() eq({mode='n', blocking=false}, nvim("get_mode")) end) - it('Does not cause heap buffer overflow with large output', function() + it('does not cause heap buffer overflow with large output', function() eq(eval('string(range(1000000))'), nvim('command_output', 'echo range(1000000)')) end) @@ -4411,8 +4411,6 @@ describe('API', function() eq('1', meths.cmd({cmd = 'echo', args = {true}}, {output = true})) end) describe('first argument as count', function() - before_each(clear) - it('works', function() command('vsplit | enew') meths.cmd({cmd = 'bdelete', args = {meths.get_current_buf()}}, {}) -- cgit From 24e3ee9d07e1433cb13b4d96ec20999f5f02b204 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 22 Jul 2023 09:52:13 +0100 Subject: fix(api/options): validate buf and win Fixes #24398 --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 617d0f12ff..6aa9dcc8fa 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2445,7 +2445,7 @@ describe('API', function() it('can throw exceptions', function() local status, err = pcall(nvim, 'get_option_value', 'invalid-option', {}) eq(false, status) - ok(err:match("Invalid 'option': 'invalid%-option'") ~= nil) + ok(err:match("Unknown option 'invalid%-option'") ~= nil) end) it('does not truncate error message <1 MB #5984', function() -- cgit From 0b351c3740d621689b17267171e162abd421e759 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 2 Aug 2023 13:00:13 +0200 Subject: test(api): update tests to new error messages --- test/functional/api/vim_spec.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 6aa9dcc8fa..70fa80f2a2 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -4112,12 +4112,10 @@ describe('API', function() it('validation', function() eq("Invalid 'cmd': expected non-empty String", pcall_err(meths.cmd, { cmd = ""}, {})) - eq("Invalid 'cmd': expected non-empty String", + eq("Invalid 'cmd': expected String, got Array", pcall_err(meths.cmd, { cmd = {}}, {})) eq("Invalid 'args': expected Array, got Boolean", pcall_err(meths.cmd, { cmd = "set", args = true }, {})) - eq("Invalid 'magic': expected Dict, got Array", - pcall_err(meths.cmd, { cmd = "set", args = {}, magic = {} }, {})) eq("Invalid command arg: expected non-whitespace", pcall_err(meths.cmd, { cmd = "set", args = {' '}, }, {})) eq("Invalid command arg: expected valid type, got Array", @@ -4138,7 +4136,7 @@ describe('API', function() eq("Command cannot accept count: set", pcall_err(meths.cmd, { cmd = "set", args = {}, count = 1 }, {})) - eq("Invalid 'count': expected non-negative Integer", + eq("Invalid 'count': expected Integer, got Boolean", pcall_err(meths.cmd, { cmd = "print", args = {}, count = true }, {})) eq("Invalid 'count': expected non-negative Integer", pcall_err(meths.cmd, { cmd = "print", args = {}, count = -1 }, {})) @@ -4158,9 +4156,10 @@ describe('API', function() -- Lua call allows empty {} for dict item. eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]])) eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]])) + eq('', meths.cmd({ cmd = "set", args = {}, magic = {} }, {})) -- Lua call does not allow non-empty list-like {} for dict item. - eq("Invalid 'magic': expected Dict, got Array", + eq("Invalid 'magic': Expected Dict-like Lua table", pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]])) eq("Invalid key: 'bogus'", pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]])) -- cgit From 017ff93b020e1915d03d9a2dd9a895613148f181 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 13 Aug 2023 22:14:48 +0800 Subject: fix(keycodes): recognize as a key (#24700) Problem: The result of keytrans() sometimes can't be translated back. Solution: Recognize as a key. --- test/functional/api/vim_spec.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 70fa80f2a2..7edf1d9cde 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1957,6 +1957,12 @@ describe('API', function() -- value. eq('', meths.replace_termcodes('', true, true, true)) end) + + -- Not exactly the case, as nvim_replace_termcodes() escapes K_SPECIAL in Unicode + it('translates the result of keytrans() on string with 0x80 byte back', function() + local s = 'ff\128\253\097tt' + eq(s, meths.replace_termcodes(funcs.keytrans(s), true, true, true)) + end) end) describe('nvim_feedkeys', function() -- cgit From 008154954791001efcc46c28146e21403f3a698b Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 21 Aug 2023 14:52:17 +0200 Subject: refactor(change): do API changes to buffer without curbuf switch Most of the messy things when changing a non-current buffer is not about the buffer, it is about windows. In particular, it is about `curwin`. When editing a non-current buffer which is displayed in some other window in the current tabpage, one such window will be "borrowed" as the curwin. But this means if two or more non-current windows displayed the buffers, one of them will be treated differenty. this is not desirable. In particular, with nvim_buf_set_text, cursor _column_ position was only corrected for one single window. Two new tests are added: the test with just one non-current window passes, but the one with two didn't. Two corresponding such tests were also added for nvim_buf_set_lines. This already worked correctly on master, but make sure this is well-tested for future refactors. Also, nvim_create_buf no longer invokes autocmds just because you happened to use `scratch=true`. No option value was changed, therefore OptionSet must not be fired. --- test/functional/api/vim_spec.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 7edf1d9cde..2de1990b14 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -28,7 +28,6 @@ local write_file = helpers.write_file local exec_lua = helpers.exec_lua local exc_exec = helpers.exc_exec local insert = helpers.insert -local expect_exit = helpers.expect_exit local skip = helpers.skip local pcall_err = helpers.pcall_err @@ -2832,7 +2831,9 @@ describe('API', function() it('does not cause heap-use-after-free on exit while setting options', function() command('au OptionSet * q') - expect_exit(command, 'silent! call nvim_create_buf(0, 1)') + command('silent! call nvim_create_buf(0, 1)') + -- nowadays this works because we don't execute any spurious autocmds at all #24824 + assert_alive() end) end) -- cgit From c3e176f6e24e2b97603b59bb89b125d540e1274d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 5 Sep 2023 20:03:25 +0800 Subject: fix(options): correct condition for calling did_set_option() (#25026) --- test/functional/api/vim_spec.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 2de1990b14..f734bfb0c0 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1416,6 +1416,20 @@ describe('API', function() eq(true, status) eq(' equalalways\n\tLast set from Lua', rv) end) + + it('updates whether the option has ever been set #25025', function() + eq(false, nvim('get_option_info2', 'autochdir', {}).was_set) + nvim('set_option_value', 'autochdir', true, {}) + eq(true, nvim('get_option_info2', 'autochdir', {}).was_set) + + eq(false, nvim('get_option_info2', 'cmdwinheight', {}).was_set) + nvim('set_option_value', 'cmdwinheight', 10, {}) + eq(true, nvim('get_option_info2', 'cmdwinheight', {}).was_set) + + eq(false, nvim('get_option_info2', 'debug', {}).was_set) + nvim('set_option_value', 'debug', 'beep', {}) + eq(true, nvim('get_option_info2', 'debug', {}).was_set) + end) end) describe('nvim_get_option_value, nvim_set_option_value', function() -- cgit From 5331d5772ffbbdb3635d0a4b41306817097e86de Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 23 Sep 2023 15:59:37 +0800 Subject: fix(lua): show error message when failing to set variable (#25321) --- test/functional/api/vim_spec.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index f734bfb0c0..fcf3eae5ec 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1353,6 +1353,9 @@ describe('API', function() -- Set readonly v: var. eq('Key is read-only: count', pcall_err(request, 'nvim_set_vvar', 'count', 42)) + -- Set non-existent v: var. + eq('Dictionary is locked', + pcall_err(request, 'nvim_set_vvar', 'nosuchvar', 42)) -- Set writable v: var. meths.set_vvar('errmsg', 'set by API') eq('set by API', meths.get_vvar('errmsg')) -- cgit From 4d3a38ac074fff7e2a4bede4cee7699bdd55ffdc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 24 Sep 2023 10:57:09 +0800 Subject: fix(api, lua): handle setting v: variables properly (#25325) --- test/functional/api/vim_spec.lua | 58 +++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index fcf3eae5ec..d82e5f66c9 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1350,15 +1350,59 @@ describe('API', function() end) it('nvim_get_vvar, nvim_set_vvar', function() - -- Set readonly v: var. - eq('Key is read-only: count', - pcall_err(request, 'nvim_set_vvar', 'count', 42)) - -- Set non-existent v: var. - eq('Dictionary is locked', - pcall_err(request, 'nvim_set_vvar', 'nosuchvar', 42)) - -- Set writable v: var. + eq('Key is read-only: count', pcall_err(request, 'nvim_set_vvar', 'count', 42)) + eq('Dictionary is locked', pcall_err(request, 'nvim_set_vvar', 'nosuchvar', 42)) meths.set_vvar('errmsg', 'set by API') eq('set by API', meths.get_vvar('errmsg')) + meths.set_vvar('errmsg', 42) + eq('42', eval('v:errmsg')) + meths.set_vvar('oldfiles', { 'one', 'two' }) + eq({ 'one', 'two' }, eval('v:oldfiles')) + meths.set_vvar('oldfiles', {}) + eq({}, eval('v:oldfiles')) + eq('Setting v:oldfiles to value with wrong type', pcall_err(meths.set_vvar, 'oldfiles', 'a')) + eq({}, eval('v:oldfiles')) + + feed('i foo foo foo0/foo') + eq({1, 1}, meths.win_get_cursor(0)) + eq(1, eval('v:searchforward')) + feed('n') + eq({1, 5}, meths.win_get_cursor(0)) + meths.set_vvar('searchforward', 0) + eq(0, eval('v:searchforward')) + feed('n') + eq({1, 1}, meths.win_get_cursor(0)) + meths.set_vvar('searchforward', 1) + eq(1, eval('v:searchforward')) + feed('n') + eq({1, 5}, meths.win_get_cursor(0)) + + local screen = Screen.new(60, 3) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {background = Screen.colors.Yellow}, + }) + screen:attach() + eq(1, eval('v:hlsearch')) + screen:expect{grid=[[ + {1:foo} {1:^foo} {1:foo} | + {0:~ }| + | + ]]} + meths.set_vvar('hlsearch', 0) + eq(0, eval('v:hlsearch')) + screen:expect{grid=[[ + foo ^foo foo | + {0:~ }| + | + ]]} + meths.set_vvar('hlsearch', 1) + eq(1, eval('v:hlsearch')) + screen:expect{grid=[[ + {1:foo} {1:^foo} {1:foo} | + {0:~ }| + | + ]]} end) it('vim_set_var returns the old value', function() -- cgit From b3be7b741386bbbf076e87859cb1e3d990316f5c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 25 Sep 2023 11:06:15 +0800 Subject: fix(api): handle NUL in nvim_err_write() and nvim_out_write() (#25354) --- test/functional/api/vim_spec.lua | 50 +++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index d82e5f66c9..09495fbaac 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2053,6 +2053,19 @@ describe('API', function() end) describe('nvim_out_write', function() + local screen + + before_each(function() + screen = Screen.new(40, 8) + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {bold = true, foreground = Screen.colors.SeaGreen}, + [2] = {bold = true, reverse = true}, + [3] = {foreground = Screen.colors.Blue}, + }) + end) + it('prints long messages correctly #20534', function() exec([[ set more @@ -2073,14 +2086,7 @@ describe('API', function() eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', meths.get_var('out')) end) - it('blank line in message works', function() - local screen = Screen.new(40, 8) - screen:attach() - screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, - [1] = {bold = true, foreground = Screen.colors.SeaGreen}, - [2] = {bold = true, reverse = true}, - }) + it('blank line in message', function() feed([[:call nvim_out_write("\na\n")]]) screen:expect{grid=[[ | @@ -2105,6 +2111,20 @@ describe('API', function() {1:Press ENTER or type command to continue}^ | ]]} end) + + it('NUL bytes in message', function() + feed([[:lua vim.api.nvim_out_write('aaa\0bbb\0\0ccc\nddd\0\0\0eee\n')]]) + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {2: }| + aaa{3:^@}bbb{3:^@^@}ccc | + ddd{3:^@^@^@}eee | + {1:Press ENTER or type command to continue}^ | + ]]} + end) end) describe('nvim_err_write', function() @@ -2193,6 +2213,20 @@ describe('API', function() ]]) feed('') -- exit the press ENTER screen end) + + it('NUL bytes in message', function() + nvim_async('err_write', 'aaa\0bbb\0\0ccc\nddd\0\0\0eee\n') + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {3: }| + {1:aaa^@bbb^@^@ccc} | + {1:ddd^@^@^@eee} | + {2:Press ENTER or type command to continue}^ | + ]]} + end) end) describe('nvim_err_writeln', function() -- cgit From b2a8a9314798e18c0685faf7463bda32f691d755 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 3 Oct 2023 20:54:42 +0800 Subject: fix(api): avoid immediate TextChanged with nvim_create_buf (#25492) --- test/functional/api/vim_spec.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 09495fbaac..f28d6ea869 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2869,6 +2869,18 @@ describe('API', function() eq(false, eval('g:fired')) end) + it('TextChanged and TextChangedI do not trigger without changes', function() + local buf = meths.create_buf(true, false) + command([[let g:changed = '']]) + meths.create_autocmd({'TextChanged', 'TextChangedI'}, { + buffer = buf, + command = 'let g:changed ..= mode()', + }) + meths.set_current_buf(buf) + feed('i') + eq('', meths.get_var('changed')) + end) + it('scratch-buffer', function() eq({id=2}, meths.create_buf(false, true)) eq({id=3}, meths.create_buf(true, true)) -- cgit From 6c87d3e0fbf88ae693be11a3ede3a1ec6ec0e30e Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Thu, 19 Oct 2023 20:09:02 +0600 Subject: refactor(options): `get_option_value_strict()` and `SREQ_*` `SREQ_*` values are now actual typedef'd enums. `get_option_value_strict()` has also been refactored and split into two functions, `get_option_attrs()` for getting the option attributes, and `get_option_value_strict()` for getting the actual value. Moreover, it now returns an `OptVal`. Other miscellaneous refactors have also been made. --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index f28d6ea869..4e259befa8 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1493,7 +1493,7 @@ describe('API', function() pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) eq("Invalid 'scope': expected String, got Integer", pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) - eq("Invalid 'value': expected Integer/Boolean/String, got Array", + eq("Invalid 'value': expected valid option type, got Array", pcall_err(nvim, 'set_option_value', 'scrolloff', {}, {})) eq("Invalid value for option 'scrolloff': expected Number, got Boolean true", pcall_err(nvim, 'set_option_value', 'scrolloff', true, {})) -- cgit From 43a7945f1b483d121e76ea7495d1dabc773935ea Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 28 Oct 2023 22:51:07 +0600 Subject: test: add test coverage for #25741 --- test/functional/api/vim_spec.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 4e259befa8..2849fcc6af 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1477,14 +1477,6 @@ describe('API', function() nvim('set_option_value', 'debug', 'beep', {}) eq(true, nvim('get_option_info2', 'debug', {}).was_set) end) - end) - - describe('nvim_get_option_value, nvim_set_option_value', function() - it('works', function() - ok(nvim('get_option_value', 'equalalways', {})) - nvim('set_option_value', 'equalalways', false, {}) - ok(not nvim('get_option_value', 'equalalways', {})) - end) it('validation', function() eq("Invalid 'scope': expected 'local' or 'global'", @@ -1616,6 +1608,15 @@ describe('API', function() pcall_err(nvim, 'get_option_value', 'commentstring', { filetype = 'lua' })) end) + it("value of 'modified' is always false for scratch buffers", function() + nvim('set_current_buf', nvim('create_buf', true, true)) + insert([[ + foo + bar + baz + ]]) + eq(false, nvim('get_option_value', 'modified', {})) + end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() -- cgit From e19cc9c9b715d8171f7940632b8855104b5290b6 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sat, 14 Oct 2023 22:19:11 +0600 Subject: refactor(options)!: unify `set_option` and `set_string_option` While the interfaces for setting number and boolean options are now unified by #25394, there is still a separate `set_string_option` function that is used for setting a string option. This PR removes that function and merges it with set_option. BREAKING CHANGE: `v:option_old` is now the old global value for all global-local options, instead of just string global-local options. Local value for a global-local number/boolean option is now unset when the option is set (e.g. using `:set` or `nvim_set_option_value`) without a scope, which means they now behave the same way as string options. Ref: #25672 --- test/functional/api/vim_spec.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 2849fcc6af..c346dfbe6c 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1536,14 +1536,18 @@ describe('API', function() -- Now try with options with a special "local is unset" value (e.g. 'undolevels') nvim('set_option_value', 'undolevels', 1000, {}) - eq(1000, nvim('get_option_value', 'undolevels', {scope = 'local'})) + nvim('set_option_value', 'undolevels', 1200, {scope = 'local'}) + eq(1200, nvim('get_option_value', 'undolevels', {scope = 'local'})) nvim('set_option_value', 'undolevels', NIL, {scope = 'local'}) eq(-123456, nvim('get_option_value', 'undolevels', {scope = 'local'})) + eq(1000, nvim('get_option_value', 'undolevels', {})) nvim('set_option_value', 'autoread', true, {}) - eq(true, nvim('get_option_value', 'autoread', {scope = 'local'})) + nvim('set_option_value', 'autoread', false, {scope = 'local'}) + eq(false, nvim('get_option_value', 'autoread', {scope = 'local'})) nvim('set_option_value', 'autoread', NIL, {scope = 'local'}) eq(NIL, nvim('get_option_value', 'autoread', {scope = 'local'})) + eq(true, nvim('get_option_value', 'autoread', {})) end) it('set window options', function() -- cgit From e9b9a86cd5a555943b87f0ba40c4527561c3c124 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Nov 2023 10:21:14 +0800 Subject: fix(context): don't crash on invalid arg to nvim_get_context (#25977) Note: The crash happens in the second test case when using uninitialized memory, and therefore doesn't happen with ASAN. --- test/functional/api/vim_spec.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c346dfbe6c..bc7e747916 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1979,6 +1979,13 @@ describe('API', function() nvim('load_context', ctx) eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]')) end) + + it('errors when context dictionary is invalid', function() + eq('E474: Failed to convert list to msgpack string buffer', + pcall_err(nvim, 'load_context', { regs = { {} } })) + eq("Empty dictionary keys aren't allowed", + pcall_err(nvim, 'load_context', { regs = { { [''] = '' } } })) + end) end) describe('nvim_replace_termcodes', function() -- cgit From fdaf6bc5573f578d100321dfc084d513884fd73a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Nov 2023 13:10:26 +0800 Subject: fix(context): don't leak memory on multiple invalid objects (#25979) --- test/functional/api/vim_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/api/vim_spec.lua') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index bc7e747916..8bbadda9b0 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1982,7 +1982,7 @@ describe('API', function() it('errors when context dictionary is invalid', function() eq('E474: Failed to convert list to msgpack string buffer', - pcall_err(nvim, 'load_context', { regs = { {} } })) + pcall_err(nvim, 'load_context', { regs = { {} }, jumps = { {} } })) eq("Empty dictionary keys aren't allowed", pcall_err(nvim, 'load_context', { regs = { { [''] = '' } } })) end) -- cgit