aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md7
-rw-r--r--test/busted/outputHandlers/nvim.lua10
-rw-r--r--test/deprecated.lua9
-rw-r--r--test/functional/api/buffer_updates_spec.lua10
-rw-r--r--test/functional/api/command_spec.lua4
-rw-r--r--test/functional/api/extmark_spec.lua5
-rw-r--r--test/functional/api/server_notifications_spec.lua13
-rw-r--r--test/functional/api/server_requests_spec.lua5
-rw-r--r--test/functional/api/vim_spec.lua85
-rw-r--r--test/functional/api/window_spec.lua38
-rw-r--r--test/functional/autocmd/focus_spec.lua (renamed from test/functional/autoread/focus_spec.lua)0
-rw-r--r--test/functional/autocmd/tabnewentered_spec.lua32
-rw-r--r--test/functional/autocmd/termxx_spec.lua13
-rw-r--r--test/functional/cmdline/ctrl_r_spec.lua34
-rw-r--r--test/functional/core/channels_spec.lua5
-rw-r--r--test/functional/core/exit_spec.lua14
-rw-r--r--test/functional/core/job_spec.lua9
-rw-r--r--test/functional/core/startup_spec.lua69
-rw-r--r--test/functional/editor/K_spec.lua (renamed from test/functional/normal/K_spec.lua)6
-rw-r--r--test/functional/editor/completion_spec.lua (renamed from test/functional/viml/completion_spec.lua)3
-rw-r--r--test/functional/editor/count_spec.lua (renamed from test/functional/normal/count_spec.lua)0
-rw-r--r--test/functional/editor/fold_spec.lua (renamed from test/functional/normal/fold_spec.lua)0
-rw-r--r--test/functional/editor/jump_spec.lua (renamed from test/functional/normal/jump_spec.lua)18
-rw-r--r--test/functional/editor/lang_spec.lua (renamed from test/functional/normal/lang_spec.lua)0
-rw-r--r--test/functional/editor/langmap_spec.lua (renamed from test/functional/normal/langmap_spec.lua)0
-rw-r--r--test/functional/editor/macro_spec.lua (renamed from test/functional/normal/macro_spec.lua)0
-rw-r--r--test/functional/editor/meta_key_spec.lua (renamed from test/functional/insert/insert_spec.lua)38
-rw-r--r--test/functional/editor/mode_cmdline_spec.lua (renamed from test/functional/cmdline/history_spec.lua)39
-rw-r--r--test/functional/editor/mode_insert_spec.lua89
-rw-r--r--test/functional/editor/mode_visual_spec.lua27
-rw-r--r--test/functional/editor/put_spec.lua (renamed from test/functional/normal/put_spec.lua)0
-rw-r--r--test/functional/editor/search_spec.lua (renamed from test/functional/normal/search_spec.lua)0
-rw-r--r--test/functional/editor/tabpage_spec.lua (renamed from test/functional/normal/tabpage_spec.lua)0
-rw-r--r--test/functional/editor/undo_spec.lua (renamed from test/functional/normal/undo_spec.lua)0
-rw-r--r--test/functional/eval/backtick_expansion_spec.lua50
-rw-r--r--test/functional/eval/function_spec.lua37
-rw-r--r--test/functional/eval/interrupt_spec.lua61
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua5
-rw-r--r--test/functional/ex_cmds/drop_spec.lua1
-rw-r--r--test/functional/ex_cmds/echo_spec.lua30
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua9
-rw-r--r--test/functional/ex_cmds/quickfix_commands_spec.lua11
-rw-r--r--test/functional/ex_cmds/source_spec.lua61
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua3
-rw-r--r--test/functional/ex_cmds/write_spec.lua18
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua116
-rw-r--r--test/functional/fixtures/middle/filen.lua1
-rw-r--r--test/functional/fixtures/nvim/after/filen.lua1
-rw-r--r--test/functional/fixtures/nvim/filen.lua1
-rw-r--r--test/functional/fixtures/pack/foo/opt/funky/filen.lua12
-rw-r--r--test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua1
-rw-r--r--test/functional/fixtures/pack/foo/opt/superspecial/filen.lua1
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua1
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua1
-rw-r--r--test/functional/fixtures/shell-test.c17
-rw-r--r--test/functional/helpers.lua27
-rw-r--r--test/functional/insert/ctrl_o_spec.lua54
-rw-r--r--test/functional/insert/ctrl_r_spec.lua19
-rw-r--r--test/functional/legacy/007_ball_buffer_list_spec.lua5
-rw-r--r--test/functional/legacy/008_autocommands_spec.lua3
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua4
-rw-r--r--test/functional/legacy/012_directory_spec.lua1
-rw-r--r--test/functional/legacy/063_match_and_matchadd_spec.lua24
-rw-r--r--test/functional/legacy/arglist_spec.lua2
-rw-r--r--test/functional/legacy/assert_spec.lua65
-rw-r--r--test/functional/legacy/autocmd_option_spec.lua6
-rw-r--r--test/functional/legacy/cdo_spec.lua4
-rw-r--r--test/functional/legacy/eval_spec.lua6
-rw-r--r--test/functional/legacy/fixeol_spec.lua4
-rw-r--r--test/functional/legacy/listchars_spec.lua2
-rw-r--r--test/functional/legacy/memory_usage_spec.lua3
-rw-r--r--test/functional/legacy/mksession_spec.lua2
-rw-r--r--test/functional/lua/api_spec.lua7
-rw-r--r--test/functional/lua/buffer_updates_spec.lua16
-rw-r--r--test/functional/lua/commands_spec.lua44
-rw-r--r--test/functional/lua/diagnostic_spec.lua1147
-rw-r--r--test/functional/lua/highlight_spec.lua25
-rw-r--r--test/functional/lua/json_spec.lua133
-rw-r--r--test/functional/lua/luaeval_spec.lua56
-rw-r--r--test/functional/lua/mpack_spec.lua23
-rw-r--r--test/functional/lua/overrides_spec.lua47
-rw-r--r--test/functional/lua/ui_spec.lua46
-rw-r--r--test/functional/lua/uri_spec.lua32
-rw-r--r--test/functional/lua/vim_spec.lua122
-rw-r--r--test/functional/lua/xdiff_spec.lua112
-rw-r--r--test/functional/normal/meta_key_spec.lua22
-rw-r--r--test/functional/options/defaults_spec.lua28
-rw-r--r--test/functional/options/tabstop_spec.lua5
-rw-r--r--test/functional/plugin/lsp/codelens_spec.lua32
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua214
-rw-r--r--test/functional/plugin/lsp/snippet_spec.lua152
-rw-r--r--test/functional/plugin/lsp_spec.lua613
-rw-r--r--test/functional/plugin/shada_spec.lua6
-rw-r--r--test/functional/provider/clipboard_spec.lua2
-rw-r--r--test/functional/provider/python3_spec.lua3
-rw-r--r--test/functional/provider/ruby_spec.lua4
-rw-r--r--test/functional/shada/errors_spec.lua5
-rw-r--r--test/functional/shada/history_spec.lua4
-rw-r--r--test/functional/shada/marks_spec.lua6
-rw-r--r--test/functional/shada/merging_spec.lua12
-rw-r--r--test/functional/shada/variables_spec.lua8
-rw-r--r--test/functional/terminal/buffer_spec.lua23
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua3
-rw-r--r--test/functional/terminal/tui_spec.lua4
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua3
-rw-r--r--test/functional/treesitter/highlight_spec.lua43
-rw-r--r--test/functional/treesitter/node_spec.lua62
-rw-r--r--test/functional/treesitter/parser_spec.lua37
-rw-r--r--test/functional/ui/bufhl_spec.lua22
-rw-r--r--test/functional/ui/cmdline_spec.lua4
-rw-r--r--test/functional/ui/cursor_spec.lua4
-rw-r--r--test/functional/ui/decorations_spec.lua602
-rw-r--r--test/functional/ui/diff_spec.lua73
-rw-r--r--test/functional/ui/float_spec.lua338
-rw-r--r--test/functional/ui/fold_spec.lua2
-rw-r--r--test/functional/ui/highlight_spec.lua162
-rw-r--r--test/functional/ui/inccommand_spec.lua23
-rw-r--r--test/functional/ui/mouse_spec.lua124
-rw-r--r--test/functional/ui/multigrid_spec.lua171
-rw-r--r--test/functional/ui/output_spec.lua6
-rw-r--r--test/functional/ui/popupmenu_spec.lua4
-rw-r--r--test/functional/ui/screen.lua7
-rw-r--r--test/functional/ui/sign_spec.lua28
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua42
-rw-r--r--test/functional/ui/tabline_spec.lua1
-rw-r--r--test/functional/viml/function_spec.lua216
-rw-r--r--test/functional/vimscript/api_functions_spec.lua (renamed from test/functional/eval/api_functions_spec.lua)9
-rw-r--r--test/functional/vimscript/buf_functions_spec.lua (renamed from test/functional/eval/buf_functions_spec.lua)10
-rw-r--r--test/functional/vimscript/changedtick_spec.lua (renamed from test/functional/eval/changedtick_spec.lua)85
-rw-r--r--test/functional/vimscript/container_functions_spec.lua (renamed from test/functional/eval/container_functions_spec.lua)0
-rw-r--r--test/functional/vimscript/ctx_functions_spec.lua (renamed from test/functional/eval/ctx_functions_spec.lua)38
-rw-r--r--test/functional/vimscript/environ_spec.lua (renamed from test/functional/eval/environ_spec.lua)0
-rw-r--r--test/functional/vimscript/errorlist_spec.lua (renamed from test/functional/viml/errorlist_spec.lua)0
-rw-r--r--test/functional/vimscript/eval_spec.lua146
-rw-r--r--test/functional/vimscript/executable_spec.lua (renamed from test/functional/eval/executable_spec.lua)0
-rw-r--r--test/functional/vimscript/execute_spec.lua (renamed from test/functional/eval/execute_spec.lua)18
-rw-r--r--test/functional/vimscript/exepath_spec.lua (renamed from test/functional/eval/exepath_spec.lua)0
-rw-r--r--test/functional/vimscript/fnamemodify_spec.lua (renamed from test/functional/eval/fnamemodify_spec.lua)0
-rw-r--r--test/functional/vimscript/functions_spec.lua20
-rw-r--r--test/functional/vimscript/getline_spec.lua (renamed from test/functional/eval/getline_spec.lua)0
-rw-r--r--test/functional/vimscript/glob_spec.lua (renamed from test/functional/eval/glob_spec.lua)0
-rw-r--r--test/functional/vimscript/has_spec.lua (renamed from test/functional/eval/has_spec.lua)0
-rw-r--r--test/functional/vimscript/hostname_spec.lua (renamed from test/functional/eval/hostname_spec.lua)0
-rw-r--r--test/functional/vimscript/input_spec.lua (renamed from test/functional/eval/input_spec.lua)0
-rw-r--r--test/functional/vimscript/json_functions_spec.lua (renamed from test/functional/eval/json_functions_spec.lua)16
-rw-r--r--test/functional/vimscript/lang_spec.lua (renamed from test/functional/viml/lang_spec.lua)2
-rw-r--r--test/functional/vimscript/let_spec.lua (renamed from test/functional/eval/let_spec.lua)10
-rw-r--r--test/functional/vimscript/map_functions_spec.lua (renamed from test/functional/eval/map_functions_spec.lua)0
-rw-r--r--test/functional/vimscript/match_functions_spec.lua (renamed from test/functional/eval/match_functions_spec.lua)15
-rw-r--r--test/functional/vimscript/minmax_functions_spec.lua (renamed from test/functional/eval/minmax_functions_spec.lua)30
-rw-r--r--test/functional/vimscript/modeline_spec.lua (renamed from test/functional/eval/modeline_spec.lua)4
-rw-r--r--test/functional/vimscript/msgpack_functions_spec.lua (renamed from test/functional/eval/msgpack_functions_spec.lua)135
-rw-r--r--test/functional/vimscript/null_spec.lua (renamed from test/functional/eval/null_spec.lua)22
-rw-r--r--test/functional/vimscript/operators_spec.lua (renamed from test/functional/eval/operators_spec.lua)0
-rw-r--r--test/functional/vimscript/printf_spec.lua (renamed from test/functional/eval/printf_spec.lua)0
-rw-r--r--test/functional/vimscript/reltime_spec.lua (renamed from test/functional/eval/reltime_spec.lua)0
-rw-r--r--test/functional/vimscript/server_spec.lua (renamed from test/functional/eval/server_spec.lua)0
-rw-r--r--test/functional/vimscript/setpos_spec.lua (renamed from test/functional/eval/setpos_spec.lua)0
-rw-r--r--test/functional/vimscript/sort_spec.lua (renamed from test/functional/eval/sort_spec.lua)7
-rw-r--r--test/functional/vimscript/special_vars_spec.lua (renamed from test/functional/eval/special_vars_spec.lua)0
-rw-r--r--test/functional/vimscript/string_spec.lua (renamed from test/functional/eval/string_spec.lua)44
-rw-r--r--test/functional/vimscript/system_spec.lua (renamed from test/functional/eval/system_spec.lua)7
-rw-r--r--test/functional/vimscript/timer_spec.lua (renamed from test/functional/eval/timer_spec.lua)0
-rw-r--r--test/functional/vimscript/uniq_spec.lua (renamed from test/functional/eval/uniq_spec.lua)8
-rw-r--r--test/functional/vimscript/vvar_event_spec.lua (renamed from test/functional/eval/vvar_event_spec.lua)0
-rw-r--r--test/functional/vimscript/wait_spec.lua (renamed from test/functional/eval/wait_spec.lua)0
-rw-r--r--test/functional/vimscript/writefile_spec.lua (renamed from test/functional/eval/writefile_spec.lua)59
-rw-r--r--test/functional/visual/meta_key_spec.lua22
-rw-r--r--test/helpers.lua14
-rw-r--r--test/unit/charset/vim_str2nr_spec.lua240
-rw-r--r--test/unit/eval/typval_spec.lua16
-rw-r--r--test/unit/undo_spec.lua2
-rw-r--r--test/unit/viml/expressions/parser_spec.lua58
173 files changed, 5678 insertions, 1540 deletions
diff --git a/test/README.md b/test/README.md
index a6e9080a40..37aa54c157 100644
--- a/test/README.md
+++ b/test/README.md
@@ -256,8 +256,15 @@ Number; !must be defined to function properly):
- `VALGRIND_LOG` (F) (S): overrides valgrind log file name used for `VALGRIND`.
+- `TEST_COLORS` (F) (U) (D): enable pretty colors in test runner.
+
- `TEST_SKIP_FRAGILE` (F) (D): makes test suite skip some fragile tests.
+- `TEST_TIMEOUT` (FU) (I): specifies maximum time, in seconds, before the test
+ suite run is killed
+
+- `NVIM_LUA_NOTRACK` (F) (D): disable reference counting of Lua objects
+
- `NVIM_PROG`, `NVIM_PRG` (F) (S): override path to Neovim executable (default
to `build/bin/nvim`).
diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua
index 5456e9ca98..0e9801b94b 100644
--- a/test/busted/outputHandlers/nvim.lua
+++ b/test/busted/outputHandlers/nvim.lua
@@ -1,13 +1,9 @@
local pretty = require 'pl.pretty'
local global_helpers = require('test.helpers')
-local colors
-
-local isWindows = package.config:sub(1,1) == '\\'
-
-if isWindows then
- colors = setmetatable({}, {__index = function() return function(s) return s end end})
-else
+-- Colors are disabled by default. #15610
+local colors = setmetatable({}, {__index = function() return function(s) return s == nil and '' or tostring(s) end end})
+if os.getenv "TEST_COLORS" then
colors = require 'term.colors'
end
diff --git a/test/deprecated.lua b/test/deprecated.lua
new file mode 100644
index 0000000000..b162c8fc93
--- /dev/null
+++ b/test/deprecated.lua
@@ -0,0 +1,9 @@
+-- Island of Misfit Toys
+
+local M = {}
+
+function M.redir_exec()
+ error('redir_exec is deprecated, use nvim_exec() or pcall_err()')
+end
+
+return M
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index 05ca0d5f4d..c9c9be5406 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -159,9 +159,8 @@ describe('API: buffer events:', function()
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 29, 29, firstfour, false})
- -- create a new empty buffer and wipe out the old one ... this will
- -- turn off buffer events
- command('enew!')
+ -- delete the current buffer to turn off buffer events
+ command('bdelete!')
expectn('nvim_buf_detach_event', {b})
-- add a line at the start of an empty file
@@ -269,7 +268,7 @@ describe('API: buffer events:', function()
'original foo'}, false})
-- type text into the first line of a blank file, one character at a time
- command('enew!')
+ command('bdelete!')
tick = 2
expectn('nvim_buf_detach_event', {b})
local bnew = nvim('get_current_buf')
@@ -666,7 +665,8 @@ describe('API: buffer events:', function()
tick = tick + 1
expectn('nvim_buf_changedtick_event', {b, tick})
- -- close our buffer by creating a new one
+ -- close our buffer and create a new one
+ command('bdelete')
command('enew')
expectn('nvim_buf_detach_event', {b})
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index e6a9e11fd9..37331d11c7 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -53,7 +53,7 @@ describe('nvim_get_commands', function()
end)
it('gets various command attributes', function()
- local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='0', range='10', register=false, script_id=0, }
+ local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', range='10', register=false, script_id=0, }
local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', range=NIL, register=false, script_id=1, }
local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', range=NIL, register=false, script_id=2, }
local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', range=NIL, register=false, script_id=3, }
@@ -62,7 +62,7 @@ describe('nvim_get_commands', function()
command -complete=custom,ListUsers -nargs=+ Finger !finger <args>
]])
eq({Finger=cmd1}, meths.get_commands({builtin=false}))
- command('command -complete=dir -addr=arguments -count=10 TestCmd pwd <args>')
+ command('command -nargs=1 -complete=dir -addr=arguments -count=10 TestCmd pwd <args>')
eq({Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false}))
source([[
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index d2b555ee5b..50b4b85d2a 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -12,6 +12,7 @@ local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
local meths = helpers.meths
+local assert_alive = helpers.assert_alive
local function expect(contents)
return eq(contents, helpers.curbuf_contents())
@@ -1381,13 +1382,13 @@ describe('API/extmarks', function()
end)
it('does not crash with append/delete/undo seqence', function()
- meths.exec([[
+ meths.exec([[
let ns = nvim_create_namespace('myplugin')
call nvim_buf_set_extmark(0, ns, 0, 0, {})
call append(0, '')
%delete
undo]],false)
- eq(2, meths.eval('1+1')) -- did not crash
+ assert_alive()
end)
it('works with left and right gravity', function()
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index 9ee2570798..6367cc5caa 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -5,6 +5,8 @@ local eq, clear, eval, command, nvim, next_msg =
local meths = helpers.meths
local exec_lua = helpers.exec_lua
local retry = helpers.retry
+local isCI = helpers.isCI
+local assert_alive = helpers.assert_alive
describe('notify', function()
local channel
@@ -72,18 +74,23 @@ describe('notify', function()
nvim('subscribe', 'event1')
nvim('unsubscribe', 'doesnotexist')
nvim('unsubscribe', 'event1')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('cancels stale events on channel close', function()
+ if isCI() then
+ pending('hangs on CI #14083 #15251')
+ return
+ end
if helpers.pending_win32(pending) then return end
local catchan = eval("jobstart(['cat'], {'rpc': v:true})")
- eq({id=catchan, stream='job', mode='rpc', client = {}}, exec_lua ([[
+ local catpath = eval('exepath("cat")')
+ eq({id=catchan, argv={catpath}, stream='job', mode='rpc', client = {}}, exec_lua ([[
vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'})
vim.rpcnotify(..., "nvim_subscribe", "daily_rant")
return vim.api.nvim_get_chan_info(...)
]], catchan))
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
eq({false, 'Invalid channel: '..catchan},
exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan))
retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :(
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 237a4b01e4..e408890906 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -11,6 +11,7 @@ local meths = helpers.meths
local spawn, merge_args = helpers.spawn, helpers.merge_args
local set_session = helpers.set_session
local pcall_err = helpers.pcall_err
+local assert_alive = helpers.assert_alive
describe('server -> client', function()
local cid
@@ -33,7 +34,7 @@ describe('server -> client', function()
call jobstop(ch1)
]])
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
describe('simple call', function()
@@ -158,7 +159,7 @@ describe('server -> client', function()
-- do some busywork, so the first request will return
-- before this one
for _ = 1, 5 do
- eq(2, eval("1+1"))
+ assert_alive()
end
eq(1, eval('rpcnotify('..cid..', "nested_done")'))
return 'done!'
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 91d2745130..ffef6a6066 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,6 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local fmt = string.format
+local assert_alive = helpers.assert_alive
local NIL = helpers.NIL
local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
local command = helpers.command
@@ -57,7 +59,7 @@ describe('API', function()
eq({'notification', 'nvim_error_event',
{error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg())
-- error didn't close channel.
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('failed async request emits nvim_error_event', function()
@@ -67,7 +69,7 @@ describe('API', function()
{error_types.Exception.id, 'Vim:E492: Not an editor command: bogus'}},
next_msg())
-- error didn't close channel.
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('does not set CA_COMMAND_BUSY #7254', function()
@@ -115,6 +117,19 @@ describe('API', function()
nvim('exec','autocmd BufAdd * :let x1 = "Hello"', false)
nvim('command', 'new foo')
eq('Hello', request('nvim_eval', 'g:x1'))
+
+ -- Line continuations
+ nvim('exec', [[
+ let abc = #{
+ \ a: 1,
+ "\ b: 2,
+ \ c: 3
+ \ }]], false)
+ eq({a = 1, c = 3}, request('nvim_eval', 'g:abc'))
+
+ -- try no spaces before continuations to catch off-by-one error
+ nvim('exec', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', false)
+ eq({a = 98}, request('nvim_eval', 'g:ab'))
end)
it('non-ASCII input', function()
@@ -518,7 +533,7 @@ describe('API', function()
nvim("notify", "hello world", 2, {})
end)
- it('can be overriden', function()
+ it('can be overridden', function()
command("lua vim.notify = function(...) return 42 end")
eq(42, meths.exec_lua("return vim.notify('Hello world')", {}))
nvim("notify", "hello world", 4, {})
@@ -1326,10 +1341,10 @@ describe('API', function()
end)
end)
- describe('nvim_list_chans and nvim_get_chan_info', function()
+ describe('nvim_list_chans, nvim_get_chan_info', function()
before_each(function()
- command('autocmd ChanOpen * let g:opened_event = copy(v:event)')
- command('autocmd ChanInfo * let g:info_event = copy(v:event)')
+ command('autocmd ChanOpen * let g:opened_event = deepcopy(v:event)')
+ command('autocmd ChanInfo * let g:info_event = deepcopy(v:event)')
end)
local testinfo = {
stream = 'stdio',
@@ -1350,7 +1365,7 @@ describe('API', function()
eq({}, meths.get_chan_info(10))
end)
- it('works for stdio channel', function()
+ it('stream=stdio channel', function()
eq({[1]=testinfo,[2]=stderr}, meths.list_chans())
eq(testinfo, meths.get_chan_info(1))
eq(stderr, meths.get_chan_info(2))
@@ -1377,11 +1392,13 @@ describe('API', function()
eq(info, meths.get_chan_info(1))
end)
- it('works for job channel', function()
+ it('stream=job channel', function()
eq(3, eval("jobstart(['cat'], {'rpc': v:true})"))
+ local catpath = eval('exepath("cat")')
local info = {
stream='job',
id=3,
+ argv={ catpath },
mode='rpc',
client={},
}
@@ -1394,6 +1411,7 @@ describe('API', function()
info = {
stream='job',
id=3,
+ argv={ catpath },
mode='rpc',
client = {
name='amazing-cat',
@@ -1410,14 +1428,15 @@ describe('API', function()
pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)'))
end)
- it('works for :terminal channel', function()
- command(":terminal")
+ 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.buf_get_option(1, 'channel'))
local info = {
stream='job',
id=3,
+ argv={ eval('exepath(&shell)') },
mode='terminal',
buffer = 1,
pty='?',
@@ -1431,6 +1450,38 @@ describe('API', function()
info.buffer = {id=1}
eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans())
eq(info, meths.get_chan_info(3))
+
+ -- :terminal with args + running process.
+ command(':exe "terminal" shellescape(v:progpath) "-u NONE -i NONE"')
+ eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running?
+ local expected2 = {
+ stream = 'job',
+ id = 4,
+ argv = (
+ iswin() and {
+ eval('&shell'),
+ '/s',
+ '/c',
+ fmt('"%s -u NONE -i NONE"', eval('shellescape(v:progpath)')),
+ } or {
+ eval('&shell'),
+ eval('&shellcmdflag'),
+ fmt('%s -u NONE -i NONE', eval('shellescape(v:progpath)')),
+ }
+ ),
+ mode = 'terminal',
+ buffer = 2,
+ pty = '?',
+ }
+ local actual2 = eval('nvim_get_chan_info(&channel)')
+ expected2.pty = actual2.pty
+ eq(expected2, actual2)
+
+ -- :terminal with args + stopped process.
+ eq(1, eval('jobstop(&channel)'))
+ eval('jobwait([&channel], 1000)') -- Wait.
+ expected2.pty = (iswin() and '?' or '') -- pty stream was closed.
+ eq(expected2, eval('nvim_get_chan_info(&channel)'))
end)
end)
@@ -1540,7 +1591,10 @@ describe('API', function()
eq({'a', '', 'b'}, meths.list_runtime_paths())
meths.set_option('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,')
+ eq({'a', 'b'}, meths.list_runtime_paths())
+ meths.set_option('runtimepath', 'a,b,,')
eq({'a', 'b', ''}, meths.list_runtime_paths())
end)
it('truncates too long paths', function()
@@ -1961,8 +2015,13 @@ describe('API', function()
ok(endswith(val[1], p"autoload/remote/define.vim")
or endswith(val[1], p"autoload/remote/host.vim"))
- eq({}, meths.get_runtime_file("lua", true))
- eq({}, meths.get_runtime_file("lua/vim", true))
+ val = meths.get_runtime_file("lua", true)
+ eq(1, #val)
+ ok(endswith(val[1], p"lua"))
+
+ val = meths.get_runtime_file("lua/vim", true)
+ eq(1, #val)
+ ok(endswith(val[1], p"lua/vim"))
end)
it('can find directories', function()
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index bb72b63b6c..11755a9d97 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1,8 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
- ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf,
+ ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf,
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
- helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval
+ helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval,
+ helpers.tabpage
local poke_eventloop = helpers.poke_eventloop
local curwinmeths = helpers.curwinmeths
local funcs = helpers.funcs
@@ -11,6 +12,7 @@ local NIL = helpers.NIL
local meths = helpers.meths
local command = helpers.command
local pcall_err = helpers.pcall_err
+local assert_alive = helpers.assert_alive
-- check if str is visible at the beginning of some line
local function is_visible(str)
@@ -206,7 +208,7 @@ describe('API/win', function()
end)
end)
- describe('{get,set}_option', function()
+ describe('nvim_win_get_option, nvim_win_set_option', function()
it('works', function()
curwin('set_option', 'colorcolumn', '4,3')
eq('4,3', curwin('get_option', 'colorcolumn'))
@@ -224,6 +226,18 @@ describe('API/win', function()
pcall_err(curwin, 'get_option', 'statusline'))
eq('', eval('&l:statusline')) -- confirm local value was not copied
end)
+
+ it('after switching windows #15390', function()
+ nvim('command', 'tabnew')
+ local tab1 = unpack(nvim('list_tabpages'))
+ local win1 = unpack(tabpage('list_wins', tab1))
+ window('set_option', win1, 'statusline', 'window-status')
+ nvim('command', 'split')
+ nvim('command', 'wincmd J')
+ nvim('command', 'wincmd j')
+ eq('window-status', window('get_option', win1, 'statusline'))
+ assert_alive()
+ end)
end)
describe('get_position', function()
@@ -311,7 +325,8 @@ describe('API/win', function()
eq({newwin}, meths.list_wins())
end)
- it('handles changed buffer', function()
+ it("handles changed buffer when 'hidden' is unset", function()
+ command('set nohidden')
local oldwin = meths.get_current_win()
insert('text')
command('new')
@@ -346,6 +361,21 @@ describe('API/win', function()
eq(2, #meths.list_wins())
eq('', funcs.getcmdwintype())
end)
+
+ it('closing current (float) window of another tabpage #15313', function()
+ command('tabedit')
+ eq(2, eval('tabpagenr()'))
+ local win = meths.open_win(0, true, {
+ relative='editor', row=10, col=10, width=50, height=10
+ })
+ local tab = eval('tabpagenr()')
+ command('tabprevious')
+ eq(1, eval('tabpagenr()'))
+ meths.win_close(win, false)
+
+ eq(1001, meths.tabpage_get_win(tab).id)
+ assert_alive()
+ end)
end)
describe('hide', function()
diff --git a/test/functional/autoread/focus_spec.lua b/test/functional/autocmd/focus_spec.lua
index 3f9a0ad09b..3f9a0ad09b 100644
--- a/test/functional/autoread/focus_spec.lua
+++ b/test/functional/autocmd/focus_spec.lua
diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua
index dc2fd3e97d..b186aa1f50 100644
--- a/test/functional/autocmd/tabnewentered_spec.lua
+++ b/test/functional/autocmd/tabnewentered_spec.lua
@@ -7,7 +7,7 @@ local eval = helpers.eval
local eq = helpers.eq
local feed = helpers.feed
local nvim = helpers.nvim
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
describe('TabNewEntered', function()
describe('au TabNewEntered', function()
@@ -77,7 +77,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -86,7 +85,7 @@ describe('tabpage/previous', function()
> [No Name]
Tab page 4
# [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the fourth.
@@ -117,7 +116,6 @@ describe('tabpage/previous', function()
feed(characters)
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -128,7 +126,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 5
[No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the third.
@@ -161,7 +159,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
# [No Name]
Tab page 2
@@ -170,7 +167,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the first.
@@ -205,7 +202,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
> [No Name]
Tab page 2
@@ -214,7 +210,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
# [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the fourth.
@@ -247,7 +243,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -256,7 +251,7 @@ describe('tabpage/previous', function()
# [No Name]
Tab page 4
> [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the third.
@@ -291,7 +286,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
# [No Name]
Tab page 2
@@ -300,7 +294,7 @@ describe('tabpage/previous', function()
> [No Name]
Tab page 4
[No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the first.
@@ -333,7 +327,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -342,7 +335,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the second.
@@ -377,7 +370,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -386,7 +378,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
# [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the fourth.
@@ -444,14 +436,13 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
[No Name]
Tab page 3
> [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the "zero".
@@ -567,7 +558,6 @@ describe('tabpage/previous', function()
eq(dedent([=[
-
Tab page 1
[No Name]
Tab page 2
@@ -578,7 +568,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- redir_exec('tabs')
+ exec_capture('tabs')
)
end)
end)
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index b12c24b58d..1e8f981437 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -13,7 +13,7 @@ describe('autocmd TermClose', function()
before_each(function()
clear()
nvim('set_option', 'shell', nvim_dir .. '/shell-test')
- nvim('set_option', 'shellcmdflag', 'EXE')
+ command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
end)
it('triggers when fast-exiting terminal job stops', function()
@@ -90,6 +90,17 @@ describe('autocmd TermClose', function()
retry(nil, nil, function() eq('3', eval('g:abuf')) end)
feed('<c-c>:qa!<cr>')
end)
+
+ it('exposes v:event.status', function()
+ command('set shellcmdflag=EXIT')
+ command('autocmd TermClose * let g:status = v:event.status')
+
+ command('terminal 0')
+ retry(nil, nil, function() eq(0, eval('g:status')) end)
+
+ command('terminal 42')
+ retry(nil, nil, function() eq(42, eval('g:status')) end)
+ end)
end)
it('autocmd TermEnter, TermLeave', function()
diff --git a/test/functional/cmdline/ctrl_r_spec.lua b/test/functional/cmdline/ctrl_r_spec.lua
deleted file mode 100644
index a0f3955282..0000000000
--- a/test/functional/cmdline/ctrl_r_spec.lua
+++ /dev/null
@@ -1,34 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear, insert, funcs, eq, feed =
- helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed
-
-describe('cmdline CTRL-R', function()
- before_each(clear)
-
- it('pasting non-special register inserts <CR> *between* lines', function()
- insert([[
- line1abc
- line2somemoretext
- ]])
- -- Yank 2 lines linewise, then paste to cmdline.
- feed([[<C-\><C-N>gg0yj:<C-R>0]])
- -- <CR> inserted between lines, NOT after the final line.
- eq('line1abc\rline2somemoretext', funcs.getcmdline())
-
- -- Yank 2 lines charwise, then paste to cmdline.
- feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
- -- <CR> inserted between lines, NOT after the final line.
- eq('abc\rline2', funcs.getcmdline())
-
- -- Yank 1 line linewise, then paste to cmdline.
- feed([[<C-\><C-N>ggyy:<C-R>0]])
- -- No <CR> inserted.
- eq('line1abc', funcs.getcmdline())
- end)
-
- it('pasting special register inserts <CR>, <NL>', function()
- feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
- eq('foo\nbar\rbaz', funcs.getcmdline())
- end)
-end)
-
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 1ef34c7318..6efa4f9b80 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -89,6 +89,9 @@ describe('channels', function()
command("call chansend(id, 'howdy')")
eq({"notification", "stdout", {id, {"[1, ['howdy'], 'stdin']"}}}, next_msg())
+ command("call chansend(id, 0z686f6c61)")
+ eq({"notification", "stdout", {id, {"[1, ['hola'], 'stdin']"}}}, next_msg())
+
command("call chanclose(id, 'stdin')")
expect_twostreams({{"notification", "stdout", {id, {"[1, [''], 'stdin']"}}},
{'notification', 'stdout', {id, {''}}}},
@@ -131,6 +134,8 @@ describe('channels', function()
command("call chansend(id, 'TEXT\n')")
expect_twoline(id, "stdout", "TEXT\r", "[1, ['TEXT', ''], 'stdin']")
+ command("call chansend(id, 0z426c6f6273210a)")
+ expect_twoline(id, "stdout", "Blobs!\r", "[1, ['Blobs!', ''], 'stdin']")
command("call chansend(id, 'neovan')")
eq({"notification", "stdout", {id, {"neovan"}}}, next_msg())
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index 230b7f8e01..a47e7568a9 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local command = helpers.command
local feed_command = helpers.feed_command
local eval = helpers.eval
@@ -7,7 +8,8 @@ local eq = helpers.eq
local run = helpers.run
local funcs = helpers.funcs
local nvim_prog = helpers.nvim_prog
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
+local exec_capture = helpers.exec_capture
local poke_eventloop = helpers.poke_eventloop
describe('v:exiting', function()
@@ -51,9 +53,9 @@ end)
describe(':cquit', function()
local function test_cq(cmdline, exit_code, redir_msg)
if redir_msg then
- eq('\n' .. redir_msg, redir_exec(cmdline))
+ eq(redir_msg, pcall_err(function() return exec_capture(cmdline) end))
poke_eventloop()
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
else
funcs.system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline})
eq(exit_code, eval('v:shell_error'))
@@ -85,14 +87,14 @@ describe(':cquit', function()
end)
it('exits with redir msg for multiple exit codes after :cquit 1 2', function()
- test_cq('cquit 1 2', nil, 'E488: Trailing characters: cquit 1 2')
+ test_cq('cquit 1 2', nil, 'Vim(cquit):E488: Trailing characters: cquit 1 2')
end)
it('exits with redir msg for non-number exit code after :cquit X', function()
- test_cq('cquit X', nil, 'E488: Trailing characters: cquit X')
+ test_cq('cquit X', nil, 'Vim(cquit):E488: Trailing characters: cquit X')
end)
it('exits with redir msg for negative exit code after :cquit -1', function()
- test_cq('cquit -1', nil, 'E488: Trailing characters: cquit -1')
+ test_cq('cquit -1', nil, 'Vim(cquit):E488: Trailing characters: cquit -1')
end)
end)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 34ab90d760..5e127bce26 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -5,6 +5,7 @@ local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim
helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
helpers.nvim_dir, helpers.ok, helpers.source,
helpers.write_file, helpers.mkdir, helpers.rmdir
+local assert_alive = helpers.assert_alive
local command = helpers.command
local funcs = helpers.funcs
local os_kill = helpers.os_kill
@@ -348,6 +349,12 @@ describe('jobs', function()
eq(false, pcall(function()
nvim('command', 'call jobsend(j, ["some data"])')
end))
+
+ command("let g:job_opts.stdin = 'null'")
+ nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ eq(false, pcall(function()
+ nvim('command', 'call jobsend(j, ["some data"])')
+ end))
end)
it('disallows jobsend on a non-existent job', function()
@@ -864,7 +871,7 @@ describe('jobs', function()
-- loop tick. This is also prevented by try-block, so feed must be used.
feed_command("call DoIt()")
feed('<cr>') -- press RETURN
- eq(2,eval('1+1'))
+ assert_alive()
end)
it('jobstop() kills entire process tree #6530', function()
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index a70b94c0e9..1d83eb799f 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local ok = helpers.ok
@@ -231,7 +232,7 @@ describe('startup', function()
it('does not crash if --embed is given twice', function()
clear{args={'--embed'}}
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('does not crash when expanding cdpath during early_init', function()
@@ -247,9 +248,9 @@ describe('startup', function()
[[" -u NONE -i NONE --cmd "set noruler" --cmd "let g:foo = g:bar"')]])
screen:expect([[
^ |
+ |
Error detected while processing pre-vimrc command line: |
E121: Undefined variable: g:bar |
- E15: Invalid expression: g:bar |
Press ENTER or type command to continue |
|
]])
@@ -309,7 +310,8 @@ describe('startup', function()
end)
local function pack_clear(cmd)
- clear('--cmd', 'set packpath=test/functional/fixtures', '--cmd', cmd)
+ -- add packages after config dir in rtp but before config/after
+ clear{args={'--cmd', 'set packpath=test/functional/fixtures', '--cmd', 'let paths=split(&rtp, ",")', '--cmd', 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")', '--cmd', cmd}, env={XDG_CONFIG_HOME='test/functional/fixtures/'}}
end
@@ -347,6 +349,22 @@ describe('startup', function()
pack_clear [[ packadd! bonus | lua _G.y = require'bonus'.launch() ]]
eq('CPE 1704 TKS', exec_lua [[ return _G.y ]])
end)
+
+ it("handles the correct order with start packages and after/", function()
+ pack_clear [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]
+ eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
+
+ it("handles the correct order with opt packages and after/", function()
+ pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]]
+ eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
+
+ it("handles the correct order with a package that changes packpath", function()
+ pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! funky\nruntime! filen.lua" ]]
+ eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq({'ordinary', 'funky!', 'mittel', 'ordinary after'}, exec_lua [[ return _G.nested_order ]])
+ end)
end)
describe('sysinit', function()
@@ -438,12 +456,15 @@ describe('user config init', function()
local xhome = 'Xhome'
local pathsep = helpers.get_pathsep()
local xconfig = xhome .. pathsep .. 'Xconfig'
+ local xdata = xhome .. pathsep .. 'Xdata'
local init_lua_path = table.concat({xconfig, 'nvim', 'init.lua'}, pathsep)
+ local xenv = { XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata }
before_each(function()
rmdir(xhome)
mkdir_p(xconfig .. pathsep .. 'nvim')
+ mkdir_p(xdata)
write_file(init_lua_path, [[
vim.g.lua_rc = 1
@@ -455,10 +476,10 @@ describe('user config init', function()
end)
it('loads init.lua from XDG config home by default', function()
- clear{ args_rm={'-u' }, env={ XDG_CONFIG_HOME=xconfig }}
+ clear{ args_rm={'-u' }, env=xenv }
eq(1, eval('g:lua_rc'))
- eq(init_lua_path, eval('$MYVIMRC'))
+ eq(funcs.fnamemodify(init_lua_path, ':p'), eval('$MYVIMRC'))
end)
describe 'with explicitly provided config'(function()
@@ -470,7 +491,7 @@ describe('user config init', function()
end)
it('loads custom lua config and does not set $MYVIMRC', function()
- clear{ args={'-u', custom_lua_path }, env={ XDG_CONFIG_HOME=xconfig }}
+ clear{ args={'-u', custom_lua_path }, env=xenv }
eq(1, eval('g:custom_lua_rc'))
eq('', eval('$MYVIMRC'))
end)
@@ -484,10 +505,10 @@ describe('user config init', function()
end)
it('loads default lua config, but shows an error', function()
- clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig }}
+ clear{ args_rm={'-u'}, env=xenv }
feed('<cr>') -- TODO check this, test execution is blocked without it
eq(1, eval('g:lua_rc'))
- matches('Conflicting configs', meths.exec('messages', true))
+ matches('^E5422: Conflicting configs', meths.exec('messages', true))
end)
end)
end)
@@ -496,9 +517,13 @@ describe('runtime:', function()
local xhome = 'Xhome'
local pathsep = helpers.get_pathsep()
local xconfig = xhome .. pathsep .. 'Xconfig'
+ local xdata = xhome .. pathsep .. 'Xdata'
+ local xenv = { XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata }
setup(function()
+ rmdir(xhome)
mkdir_p(xconfig .. pathsep .. 'nvim')
+ mkdir_p(xdata)
end)
teardown(function()
@@ -511,13 +536,13 @@ describe('runtime:', function()
mkdir_p(plugin_folder_path)
write_file(plugin_file_path, [[ vim.g.lua_plugin = 1 ]])
- clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig }}
+ clear{ args_rm={'-u'}, env=xenv }
eq(1, eval('g:lua_plugin'))
rmdir(plugin_folder_path)
end)
- it('loads plugin/*.lua from start plugins', function()
+ it('loads plugin/*.lua from start packages', function()
local plugin_path = table.concat({xconfig, 'nvim', 'pack', 'catagory',
'start', 'test_plugin'}, pathsep)
local plugin_folder_path = table.concat({plugin_path, 'plugin'}, pathsep)
@@ -528,7 +553,7 @@ describe('runtime:', function()
mkdir_p(plugin_folder_path)
write_file(plugin_file_path, [[vim.g.lua_plugin = 2]])
- clear{ args_rm={'-u'}, args={'--startuptime', profiler_file}, env={ XDG_CONFIG_HOME=xconfig }}
+ clear{ args_rm={'-u'}, args={'--startuptime', profiler_file}, env=xenv }
eq(2, eval('g:lua_plugin'))
-- Check if plugin_file_path is listed in :scriptname
@@ -545,6 +570,27 @@ describe('runtime:', function()
rmdir(plugin_path)
end)
+ it('loads plugin/*.lua from site packages', function()
+ local nvimdata = iswin() and "nvim-data" or "nvim"
+ local plugin_path = table.concat({xdata, nvimdata, 'site', 'pack', 'xa', 'start', 'yb'}, pathsep)
+ local plugin_folder_path = table.concat({plugin_path, 'plugin'}, pathsep)
+ local plugin_after_path = table.concat({plugin_path, 'after', 'plugin'}, pathsep)
+ local plugin_file_path = table.concat({plugin_folder_path, 'plugin.lua'}, pathsep)
+ local plugin_after_file_path = table.concat({plugin_after_path, 'helloo.lua'}, pathsep)
+
+ mkdir_p(plugin_folder_path)
+ write_file(plugin_file_path, [[table.insert(_G.lista, "unos")]])
+ mkdir_p(plugin_after_path)
+ write_file(plugin_after_file_path, [[table.insert(_G.lista, "dos")]])
+
+ clear{ args_rm={'-u'}, args={'--cmd', 'lua _G.lista = {}'}, env=xenv }
+
+ eq({'unos', 'dos'}, exec_lua "return _G.lista")
+
+ rmdir(plugin_path)
+ end)
+
+
it('loads ftdetect/*.lua', function()
local ftdetect_folder = table.concat({xconfig, 'nvim', 'ftdetect'}, pathsep)
local ftdetect_file = table.concat({ftdetect_folder , 'new-ft.lua'}, pathsep)
@@ -554,6 +600,7 @@ describe('runtime:', function()
-- TODO(shadmansaleh): Figure out why this test fails without
-- setting VIMRUNTIME
clear{ args_rm={'-u'}, env={XDG_CONFIG_HOME=xconfig,
+ XDG_DATA_HOME=xdata,
VIMRUNTIME='runtime/'}}
eq(1, eval('g:lua_ftdetect'))
diff --git a/test/functional/normal/K_spec.lua b/test/functional/editor/K_spec.lua
index 174313d80e..40f36491e4 100644
--- a/test/functional/normal/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed
+local eq, clear, eval, feed, retry =
+ helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.retry
describe('K', function()
local test_file = 'K_spec_out'
@@ -31,7 +31,7 @@ describe('K', function()
-- K on the text "K_spec_out" resolves to `!echo fnord >> K_spec_out`.
feed('i'..test_file..'<ESC>K')
- feed('<CR>') -- Press ENTER
+ retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end)
eq({'fnord'}, eval("readfile('"..test_file.."')"))
end)
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/editor/completion_spec.lua
index a4241fe5aa..befad29922 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect
@@ -870,7 +871,7 @@ describe('completion', function()
{3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
]])
- eval('1 + 1')
+ assert_alive()
-- popupmenu still visible
screen:expect{grid=[[
foobar fooegg |
diff --git a/test/functional/normal/count_spec.lua b/test/functional/editor/count_spec.lua
index 94f741250a..94f741250a 100644
--- a/test/functional/normal/count_spec.lua
+++ b/test/functional/editor/count_spec.lua
diff --git a/test/functional/normal/fold_spec.lua b/test/functional/editor/fold_spec.lua
index 00e83bedc8..00e83bedc8 100644
--- a/test/functional/normal/fold_spec.lua
+++ b/test/functional/editor/fold_spec.lua
diff --git a/test/functional/normal/jump_spec.lua b/test/functional/editor/jump_spec.lua
index 9e7158e2f7..d09c20f226 100644
--- a/test/functional/normal/jump_spec.lua
+++ b/test/functional/editor/jump_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local eq = helpers.eq
local funcs = helpers.funcs
local feed = helpers.feed
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local write_file = helpers.write_file
describe('jumplist', function()
@@ -78,7 +78,7 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
feed('<C-O>')
feed('<C-O>')
- eq( '\n'
+ eq( ''
.. ' jump line col file/text\n'
.. ' 4 102 0 \n'
.. ' 3 1 0 Line 1\n'
@@ -87,11 +87,11 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. '> 0 30 0 Line 30\n'
.. ' 1 40 0 Line 40\n'
.. ' 2 50 0 Line 50',
- redir_exec('jumps'))
+ exec_capture('jumps'))
feed('90gg')
- eq( '\n'
+ eq( ''
.. ' jump line col file/text\n'
.. ' 5 102 0 \n'
.. ' 4 1 0 Line 1\n'
@@ -99,14 +99,14 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 20 0 Line 20\n'
.. ' 1 30 0 Line 30\n'
.. '>',
- redir_exec('jumps'))
+ exec_capture('jumps'))
end)
it('does not add the same location twice adjacently', function()
feed('60gg')
feed('60gg')
- eq( '\n'
+ eq( ''
.. ' jump line col file/text\n'
.. ' 7 102 0 \n'
.. ' 6 1 0 Line 1\n'
@@ -116,14 +116,14 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 40 0 Line 40\n'
.. ' 1 50 0 Line 50\n'
.. '>',
- redir_exec('jumps'))
+ exec_capture('jumps'))
end)
it('does add the same location twice nonadjacently', function()
feed('10gg')
feed('20gg')
- eq( '\n'
+ eq( ''
.. ' jump line col file/text\n'
.. ' 8 102 0 \n'
.. ' 7 1 0 Line 1\n'
@@ -134,6 +134,6 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 50 0 Line 50\n'
.. ' 1 10 0 Line 10\n'
.. '>',
- redir_exec('jumps'))
+ exec_capture('jumps'))
end)
end)
diff --git a/test/functional/normal/lang_spec.lua b/test/functional/editor/lang_spec.lua
index 24d1262f5f..24d1262f5f 100644
--- a/test/functional/normal/lang_spec.lua
+++ b/test/functional/editor/lang_spec.lua
diff --git a/test/functional/normal/langmap_spec.lua b/test/functional/editor/langmap_spec.lua
index e4349a22e7..e4349a22e7 100644
--- a/test/functional/normal/langmap_spec.lua
+++ b/test/functional/editor/langmap_spec.lua
diff --git a/test/functional/normal/macro_spec.lua b/test/functional/editor/macro_spec.lua
index 102d8fc723..102d8fc723 100644
--- a/test/functional/normal/macro_spec.lua
+++ b/test/functional/editor/macro_spec.lua
diff --git a/test/functional/insert/insert_spec.lua b/test/functional/editor/meta_key_spec.lua
index 330cfbd830..2a9541ba96 100644
--- a/test/functional/insert/insert_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -1,32 +1,40 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command = helpers.command
-local eq = helpers.eq
local expect = helpers.expect
local funcs = helpers.funcs
+local eq = helpers.eq
-describe('insert-mode', function()
+describe('meta-keys #8226 #13042', function()
before_each(function()
clear()
end)
- it('CTRL-@', function()
- -- Inserts last-inserted text, leaves insert-mode.
+ it('ALT/META, normal-mode', function()
+ -- Unmapped ALT-chords behave as ESC+c
insert('hello')
- feed('i<C-@>x')
- expect('hellhello')
-
- -- C-Space is the same as C-@.
- -- CTRL-SPC inserts last-inserted text, leaves insert-mode.
- feed('i<C-Space>x')
- expect('hellhellhello')
+ feed('0<A-x><M-x>')
+ expect('llo')
+ -- Mapped ALT-chord behaves as mapped.
+ command('nnoremap <M-l> Ameta-l<Esc>')
+ command('nnoremap <A-j> Aalt-j<Esc>')
+ feed('<A-j><M-l>')
+ expect('lloalt-jmeta-l')
+ end)
- -- CTRL-A inserts last inserted text
- feed('i<C-A>x')
- expect('hellhellhellhelloxo')
+ it('ALT/META, visual-mode', function()
+ -- Unmapped ALT-chords behave as ESC+c
+ insert('peaches')
+ feed('viw<A-x>viw<M-x>')
+ expect('peach')
+ -- Mapped ALT-chord behaves as mapped.
+ command('vnoremap <M-l> Ameta-l<Esc>')
+ command('vnoremap <A-j> Aalt-j<Esc>')
+ feed('viw<A-j>viw<M-l>')
+ expect('peachalt-jmeta-l')
end)
- it('ALT/META #8213', function()
+ it('ALT/META insert-mode', function()
-- Mapped ALT-chord behaves as mapped.
command('inoremap <M-l> meta-l')
command('inoremap <A-j> alt-j')
diff --git a/test/functional/cmdline/history_spec.lua b/test/functional/editor/mode_cmdline_spec.lua
index ee2d36f642..0f7d821bb5 100644
--- a/test/functional/cmdline/history_spec.lua
+++ b/test/functional/editor/mode_cmdline_spec.lua
@@ -1,8 +1,41 @@
+-- Cmdline-mode tests.
+
local helpers = require('test.functional.helpers')(after_each)
-local clear, meths, funcs, eq =
- helpers.clear, helpers.meths, helpers.funcs, helpers.eq
+local clear, insert, funcs, eq, feed =
+ helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed
+local meths = helpers.meths
+
+describe('cmdline CTRL-R', function()
+ before_each(clear)
+
+ it('pasting non-special register inserts <CR> *between* lines', function()
+ insert([[
+ line1abc
+ line2somemoretext
+ ]])
+ -- Yank 2 lines linewise, then paste to cmdline.
+ feed([[<C-\><C-N>gg0yj:<C-R>0]])
+ -- <CR> inserted between lines, NOT after the final line.
+ eq('line1abc\rline2somemoretext', funcs.getcmdline())
+
+ -- Yank 2 lines charwise, then paste to cmdline.
+ feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
+ -- <CR> inserted between lines, NOT after the final line.
+ eq('abc\rline2', funcs.getcmdline())
+
+ -- Yank 1 line linewise, then paste to cmdline.
+ feed([[<C-\><C-N>ggyy:<C-R>0]])
+ -- No <CR> inserted.
+ eq('line1abc', funcs.getcmdline())
+ end)
+
+ it('pasting special register inserts <CR>, <NL>', function()
+ feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
+ eq('foo\nbar\rbaz', funcs.getcmdline())
+ end)
+end)
-describe('history support code', function()
+describe('cmdline history', function()
before_each(clear)
it('correctly clears start of the history', function()
diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua
new file mode 100644
index 0000000000..46ab483036
--- /dev/null
+++ b/test/functional/editor/mode_insert_spec.lua
@@ -0,0 +1,89 @@
+-- Insert-mode tests.
+
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local expect = helpers.expect
+local command = helpers.command
+local eq = helpers.eq
+local eval = helpers.eval
+local meths = helpers.meths
+
+describe('insert-mode', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('CTRL-@', function()
+ -- Inserts last-inserted text, leaves insert-mode.
+ insert('hello')
+ feed('i<C-@>x')
+ expect('hellhello')
+
+ -- C-Space is the same as C-@.
+ -- CTRL-SPC inserts last-inserted text, leaves insert-mode.
+ feed('i<C-Space>x')
+ expect('hellhellhello')
+
+ -- CTRL-A inserts last inserted text
+ feed('i<C-A>x')
+ expect('hellhellhellhelloxo')
+ end)
+
+ describe('Ctrl-R', function()
+ it('works', function()
+ command("let @@ = 'test'")
+ feed('i<C-r>"')
+ expect('test')
+ end)
+
+ it('works with multi-byte text', function()
+ command("let @@ = 'påskägg'")
+ feed('i<C-r>"')
+ expect('påskägg')
+ end)
+ end)
+
+ describe('Ctrl-O', function()
+ it('enters command mode for one command', function()
+ feed('ihello world<C-o>')
+ feed(':let ctrlo = "test"<CR>')
+ feed('iii')
+ expect('hello worldiii')
+ eq(1, eval('ctrlo ==# "test"'))
+ end)
+
+ it('re-enters insert mode at the end of the line when running startinsert', function()
+ -- #6962
+ feed('ihello world<C-o>')
+ feed(':startinsert<CR>')
+ feed('iii')
+ expect('hello worldiii')
+ end)
+
+ it('re-enters insert mode at the beginning of the line when running startinsert', function()
+ insert('hello world')
+ feed('0<C-o>')
+ feed(':startinsert<CR>')
+ feed('aaa')
+ expect('aaahello world')
+ end)
+
+ it('re-enters insert mode in the middle of the line when running startinsert', function()
+ insert('hello world')
+ feed('bi<C-o>')
+ feed(':startinsert<CR>')
+ feed('ooo')
+ expect('hello oooworld')
+ end)
+
+ it("doesn't cancel Ctrl-O mode when processing event", function()
+ feed('iHello World<c-o>')
+ eq({mode='niI', blocking=false}, meths.get_mode()) -- fast event
+ eq(2, eval('1+1')) -- causes K_EVENT key
+ eq({mode='niI', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
+ feed('dd')
+ eq({mode='i', blocking=false}, meths.get_mode()) -- left ctrl-o mode
+ expect('') -- executed the command
+ end)
+ end)
+end)
diff --git a/test/functional/editor/mode_visual_spec.lua b/test/functional/editor/mode_visual_spec.lua
new file mode 100644
index 0000000000..468ae00e01
--- /dev/null
+++ b/test/functional/editor/mode_visual_spec.lua
@@ -0,0 +1,27 @@
+-- Visual-mode tests.
+
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local expect = helpers.expect
+local feed = helpers.feed
+local meths = helpers.meths
+
+describe('visual-mode', function()
+ before_each(clear)
+
+ it("select-mode Ctrl-O doesn't cancel Ctrl-O mode when processing event #15688", function()
+ feed('iHello World<esc>gh<c-o>')
+ eq({mode='vs', blocking=false}, meths.get_mode()) -- fast event
+ eq({mode='vs', blocking=false}, meths.get_mode()) -- again #15288
+ eq(2, eval('1+1')) -- causes K_EVENT key
+ eq({mode='vs', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
+ feed('^')
+ eq({mode='s', blocking=false}, meths.get_mode()) -- left ctrl-o mode
+ feed('h')
+ eq({mode='i', blocking=false}, meths.get_mode()) -- entered insert mode
+ expect('h') -- selection is the whole line and is replaced
+ end)
+end)
+
diff --git a/test/functional/normal/put_spec.lua b/test/functional/editor/put_spec.lua
index 26967ecbba..26967ecbba 100644
--- a/test/functional/normal/put_spec.lua
+++ b/test/functional/editor/put_spec.lua
diff --git a/test/functional/normal/search_spec.lua b/test/functional/editor/search_spec.lua
index d5df131725..d5df131725 100644
--- a/test/functional/normal/search_spec.lua
+++ b/test/functional/editor/search_spec.lua
diff --git a/test/functional/normal/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua
index d1d6854b07..d1d6854b07 100644
--- a/test/functional/normal/tabpage_spec.lua
+++ b/test/functional/editor/tabpage_spec.lua
diff --git a/test/functional/normal/undo_spec.lua b/test/functional/editor/undo_spec.lua
index a023ca3d90..a023ca3d90 100644
--- a/test/functional/normal/undo_spec.lua
+++ b/test/functional/editor/undo_spec.lua
diff --git a/test/functional/eval/backtick_expansion_spec.lua b/test/functional/eval/backtick_expansion_spec.lua
deleted file mode 100644
index b1b44cfa8b..0000000000
--- a/test/functional/eval/backtick_expansion_spec.lua
+++ /dev/null
@@ -1,50 +0,0 @@
-local lfs = require('lfs')
-local helpers = require('test.functional.helpers')(after_each)
-local clear, command, eval, eq = helpers.clear, helpers.command, helpers.eval, helpers.eq
-local write_file = helpers.write_file
-
-describe("backtick expansion", function()
- setup(function()
- clear()
- lfs.mkdir("test-backticks")
- write_file("test-backticks/file1", "test file 1")
- write_file("test-backticks/file2", "test file 2")
- write_file("test-backticks/file3", "test file 3")
- lfs.mkdir("test-backticks/subdir")
- write_file("test-backticks/subdir/file4", "test file 4")
- -- Long path might cause "Press ENTER" prompt; use :silent to avoid it.
- command('silent cd test-backticks')
- end)
-
- teardown(function()
- helpers.rmdir('test-backticks')
- end)
-
- it("with default 'shell'", function()
- if helpers.iswin() then
- command(":silent args `dir /b *2`")
- else
- command(":silent args `echo ***2`")
- end
- eq({ "file2", }, eval("argv()"))
- if helpers.iswin() then
- command(":silent args `dir /s/b *4`")
- eq({ "subdir\\file4", }, eval("map(argv(), 'fnamemodify(v:val, \":.\")')"))
- else
- command(":silent args `echo */*4`")
- eq({ "subdir/file4", }, eval("argv()"))
- end
- end)
-
- it("with shell=fish", function()
- if eval("executable('fish')") == 0 then
- pending('missing "fish" command')
- return
- end
- command("set shell=fish")
- command(":silent args `echo ***2`")
- eq({ "file2", }, eval("argv()"))
- command(":silent args `echo */*4`")
- eq({ "subdir/file4", }, eval("argv()"))
- end)
-end)
diff --git a/test/functional/eval/function_spec.lua b/test/functional/eval/function_spec.lua
deleted file mode 100644
index ce8850fcc2..0000000000
--- a/test/functional/eval/function_spec.lua
+++ /dev/null
@@ -1,37 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local clear = helpers.clear
-local eq = helpers.eq
-local matches = helpers.matches
-local exc_exec = helpers.exc_exec
-local iswin = helpers.iswin
-local eval = helpers.eval
-
-describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
- local max_func_args = 20 -- from eval.h
- local range = helpers.funcs.range
-
- before_each(clear)
-
- it('printf()', function()
- local printf = helpers.funcs.printf
- local rep = helpers.funcs['repeat']
- local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
- eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args))))
- local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
- eq('Vim(call):E740: Too many arguments for function printf', ret)
- end)
-
- it('rpcnotify()', function()
- local rpcnotify = helpers.funcs.rpcnotify
- local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args)))
- eq(1, ret)
- ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
- eq('Vim(call):E740: Too many arguments for function rpcnotify', ret)
- end)
-end)
-
-it('windowsversion()', function()
- clear()
- matches(iswin() and '^%d+%.%d+$' or '^$', eval('windowsversion()'))
-end)
diff --git a/test/functional/eval/interrupt_spec.lua b/test/functional/eval/interrupt_spec.lua
deleted file mode 100644
index 05b1f4ff57..0000000000
--- a/test/functional/eval/interrupt_spec.lua
+++ /dev/null
@@ -1,61 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local command = helpers.command
-local meths = helpers.meths
-local clear = helpers.clear
-local sleep = helpers.sleep
-local poke_eventloop = helpers.poke_eventloop
-local feed = helpers.feed
-local eq = helpers.eq
-
-local dur
-local min_dur = 8
-local len = 131072
-
-describe('List support code', function()
- if not pending('does not actually allows interrupting with just got_int', function() end) then return end
- -- The following tests are confirmed to work with os_breakcheck() just before
- -- `if (got_int) {break;}` in tv_list_copy and list_join_inner() and not to
- -- work without.
- setup(function()
- clear()
- dur = 0
- while true do
- command(([[
- let rt = reltime()
- let bl = range(%u)
- let dur = reltimestr(reltime(rt))
- ]]):format(len))
- dur = tonumber(meths.get_var('dur'))
- if dur >= min_dur then
- -- print(('Using len %u, dur %g'):format(len, dur))
- break
- else
- len = len * 2
- end
- end
- end)
- it('allows interrupting copy', function()
- feed(':let t_rt = reltime()<CR>:let t_bl = copy(bl)<CR>')
- sleep(min_dur / 16 * 1000)
- feed('<C-c>')
- poke_eventloop()
- command('let t_dur = reltimestr(reltime(t_rt))')
- local t_dur = tonumber(meths.get_var('t_dur'))
- if t_dur >= dur / 8 then
- eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
- end
- end)
- it('allows interrupting join', function()
- feed(':let t_rt = reltime()<CR>:let t_j = join(bl)<CR>')
- sleep(min_dur / 16 * 1000)
- feed('<C-c>')
- poke_eventloop()
- command('let t_dur = reltimestr(reltime(t_rt))')
- local t_dur = tonumber(meths.get_var('t_dur'))
- print(('t_dur: %g'):format(t_dur))
- if t_dur >= dur / 8 then
- eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
- end
- end)
-end)
diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index e5c9a20db3..21adcf37da 100644
--- a/test/functional/ex_cmds/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source
local insert = helpers.insert
local eq, next_msg = helpers.eq, helpers.next_msg
@@ -325,7 +326,7 @@ describe('VimL dictionary notifications', function()
]])
command('call MakeWatch()')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
@@ -354,7 +355,7 @@ describe('VimL dictionary notifications', function()
command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]])
insert('t');
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('does not cause use-after-free when unletting from callback', function()
diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua
index ef53fe75e3..9d84a2d4f6 100644
--- a/test/functional/ex_cmds/drop_spec.lua
+++ b/test/functional/ex_cmds/drop_spec.lua
@@ -55,6 +55,7 @@ describe(":drop", function()
end)
it("splits off a new window when a buffer can't be abandoned", function()
+ command("set nohidden")
feed_command("edit tmp1")
feed_command("vsplit")
feed_command("edit tmp2")
diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua
index 404dc39ad2..d320425de1 100644
--- a/test/functional/ex_cmds/echo_spec.lua
+++ b/test/functional/ex_cmds/echo_spec.lua
@@ -10,7 +10,7 @@ local source = helpers.source
local dedent = helpers.dedent
local command = helpers.command
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local matches = helpers.matches
describe(':echo :echon :echomsg :echoerr', function()
@@ -199,10 +199,8 @@ describe(':echo :echon :echomsg :echoerr', function()
let d.tdr = TestDictRef
]])
eq(dedent([[
-
- function('TestDict', {'tdr': function('TestDict', {...@1})})
function('TestDict', {'tdr': function('TestDict', {...@1})})]]),
- redir_exec('echo String(d.tdr)'))
+ exec_capture('echo String(d.tdr)'))
end)
it('dumps automatically created partials', function()
@@ -229,10 +227,8 @@ describe(':echo :echon :echomsg :echoerr', function()
function()
meths.set_var('d', {v=true})
eq(dedent([[
-
- {'p': function('<SNR>2_Test2', {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}
{'p': function('<SNR>2_Test2', {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]]),
- redir_exec('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
+ exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
end)
it('does not show errors when dumping partials referencing the same dictionary',
@@ -256,10 +252,8 @@ describe(':echo :echon :echomsg :echoerr', function()
-- test/unit/api/private_helpers_spec.lua.
eval('add(l, function("Test1", l))')
eq(dedent([=[
-
- function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])
function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]),
- redir_exec('echo String(function("Test1", l))'))
+ exec_capture('echo String(function("Test1", l))'))
end)
it('does not crash or halt when dumping partials with reference cycles in self and arguments',
@@ -270,10 +264,8 @@ describe(':echo :echon :echomsg :echoerr', function()
eval('add(l, function("Test1", l))')
eval('add(l, function("Test1", d))')
eq(dedent([=[
-
- {'p': function('<SNR>2_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}
{'p': function('<SNR>2_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]=]),
- redir_exec('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
+ exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
end)
end)
@@ -303,8 +295,8 @@ describe(':echo :echon :echomsg :echoerr', function()
it('dumps recursive lists without error', function()
meths.set_var('l', {})
eval('add(l, l)')
- eq('\n[[...@0]]\n[[...@0]]', redir_exec('echo String(l)'))
- eq('\n[[[...@1]]]\n[[[...@1]]]', redir_exec('echo String([l])'))
+ eq('[[...@0]]', exec_capture('echo String(l)'))
+ eq('[[[...@1]]]', exec_capture('echo String([l])'))
end)
end)
@@ -333,10 +325,10 @@ describe(':echo :echon :echomsg :echoerr', function()
it('dumps recursive dictionaries without the error', function()
meths.set_var('d', {d=1})
eval('extend(d, {"d": d})')
- eq('\n{\'d\': {...@0}}\n{\'d\': {...@0}}',
- redir_exec('echo String(d)'))
- eq('\n{\'out\': {\'d\': {...@1}}}\n{\'out\': {\'d\': {...@1}}}',
- redir_exec('echo String({"out": d})'))
+ eq('{\'d\': {...@0}}',
+ exec_capture('echo String(d)'))
+ eq('{\'out\': {\'d\': {...@1}}}',
+ exec_capture('echo String({"out": d})'))
end)
end)
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 949724bb53..09eaa36686 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -43,7 +43,7 @@ describe(':mksession', function()
-- Restore session.
command('source '..session_file)
- eq({3,3,2},
+ eq({2,2,4},
{funcs.winbufnr(1), funcs.winbufnr(2), funcs.winbufnr(3)})
end)
@@ -91,7 +91,12 @@ describe(':mksession', function()
command('tabnext 1')
eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', funcs.expand('%:p'))
command('tabnext 2')
- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
+ -- :mksession stores paths using unix slashes, but Nvim doesn't adjust these
+ -- for absolute paths in all cases yet. Absolute paths are used in the
+ -- session file after :tcd, so we need to expect unix slashes here for now
+ -- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
+ eq(cwd_dir:gsub([[\]], '/') .. '/' .. tmpfile_base .. '2',
+ funcs.expand('%:p'))
end)
it('restores CWD for :terminal buffers #11288', function()
diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua
index 3392a90270..c956a2df2d 100644
--- a/test/functional/ex_cmds/quickfix_commands_spec.lua
+++ b/test/functional/ex_cmds/quickfix_commands_spec.lua
@@ -37,9 +37,9 @@ for _, c in ipairs({'l', 'c'}) do
-- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual
-- results. First line (i.e. `{lnum=…`) was obtained from legacy test.
local list = {
- {lnum=700, col=10, text='Line 700', module='',
+ {lnum=700, end_lnum=0, col=10, end_col=0, text='Line 700', module='',
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=800, col=15, text='Line 800', module='',
+ {lnum=800, end_lnum=0, col=15, end_col=0, text='Line 800', module='',
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
}
eq(list, getlist())
@@ -47,6 +47,7 @@ for _, c in ipairs({'l', 'c'}) do
eq(('%s-2.res'):format(file), funcs.bufname(list[2].bufnr))
-- Run cfile/lfile from a modified buffer
+ command('set nohidden')
command('enew!')
curbufmeths.set_lines(1, 1, true, {'Quickfix'})
eq(('Vim(%s):E37: No write since last change (add ! to override)'):format(
@@ -58,7 +59,7 @@ for _, c in ipairs({'l', 'c'}) do
]]):format(file))
command(('%s %s'):format(addfcmd, file))
list[#list + 1] = {
- lnum=900, col=30, text='Line 900', module='',
+ lnum=900, end_lnum=0, col=30, end_col=0, text='Line 900', module='',
nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='',
}
eq(list, getlist())
@@ -71,9 +72,9 @@ for _, c in ipairs({'l', 'c'}) do
command('enew!')
command(('%s %s'):format(getfcmd, file))
list = {
- {lnum=222, col=77, text='Line 222', module='',
+ {lnum=222, end_lnum=0, col=77, end_col=0, text='Line 222', module='',
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=333, col=88, text='Line 333', module='',
+ {lnum=333, end_lnum=0, col=88, end_col=0, text='Line 333', module='',
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
}
eq(list, getlist())
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index 37c97f519a..bdf6ae76d1 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -8,6 +8,8 @@ local feed = helpers.feed
local feed_command = helpers.feed_command
local write_file = helpers.write_file
local exec = helpers.exec
+local exc_exec = helpers.exc_exec
+local exec_lua = helpers.exec_lua
local eval = helpers.eval
local exec_capture = helpers.exec_capture
local neq = helpers.neq
@@ -18,16 +20,30 @@ describe(':source', function()
end)
it('current buffer', function()
- insert('let a = 2')
+ insert([[
+ let a = 2
+ let b = #{
+ \ k: "v"
+ "\ (o_o)
+ \ }]])
+
command('source')
eq('2', meths.exec('echo a', true))
+ eq("{'k': 'v'}", meths.exec('echo b', true))
+
+ exec('set cpoptions+=C')
+ eq('Vim(let):E15: Invalid expression: #{', exc_exec('source'))
end)
it('selection in current buffer', function()
- insert(
- 'let a = 2\n'..
- 'let a = 3\n'..
- 'let a = 4\n')
+ insert([[
+ let a = 2
+ let a = 3
+ let a = 4
+ let b = #{
+ "\ (>_<)
+ \ K: "V"
+ \ }]])
-- Source the 2nd line only
feed('ggjV')
@@ -38,13 +54,26 @@ describe(':source', function()
feed('ggjVG')
feed_command(':source')
eq('4', meths.exec('echo a', true))
+ eq("{'K': 'V'}", meths.exec('echo b', true))
+
+ exec('set cpoptions+=C')
+ eq('Vim(let):E15: Invalid expression: #{', exc_exec("'<,'>source"))
+ end)
+
+ it('does not break if current buffer is modified while sourced', function()
+ insert [[
+ bwipeout!
+ let a = 123
+ ]]
+ command('source')
+ eq('123', meths.exec('echo a', true))
end)
it('multiline heredoc command', function()
- insert(
- 'lua << EOF\n'..
- 'y = 4\n'..
- 'EOF\n')
+ insert([[
+ lua << EOF
+ y = 4
+ EOF]])
command('source')
eq('4', meths.exec('echo luaeval("y")', true))
@@ -67,13 +96,21 @@ describe(':source', function()
vim.g.b = 5
vim.g.b = 6
vim.g.b = 7
+ a = [=[
+ "\ a
+ \ b]=]
]])
command('edit '..test_file)
+
feed('ggjV')
feed_command(':source')
-
eq(6, eval('g:b'))
+
+ feed('GVkk')
+ feed_command(':source')
+ eq(' "\\ a\n \\ b', exec_lua('return _G.a'))
+
os.remove(test_file)
end)
@@ -84,12 +121,16 @@ describe(':source', function()
vim.g.c = 10
vim.g.c = 11
vim.g.c = 12
+ a = [=[
+ \ 1
+ "\ 2]=]
]])
command('edit '..test_file)
feed_command(':source')
eq(12, eval('g:c'))
+ eq(' \\ 1\n "\\ 2', exec_lua('return _G.a'))
os.remove(test_file)
end)
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index f2a381869e..d91feb4bc1 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
local eq, eval, expect, source =
helpers.eq, helpers.eval, helpers.expect, helpers.source
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local feed = helpers.feed
@@ -26,7 +27,7 @@ describe(':recover', function()
-- Also check filename ending with ".swp". #9504
eq('Vim(recover):E306: Cannot open '..swapname2,
pcall_err(command, 'recover '..swapname2)) -- Should not segfault. #2117
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index 4f526ddfca..32fe397c03 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -3,8 +3,7 @@ local lfs = require('lfs')
local eq, eval, clear, write_file, source, insert =
helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
helpers.source, helpers.insert
-local redir_exec = helpers.redir_exec
-local exc_exec = helpers.exc_exec
+local pcall_err = helpers.pcall_err
local command = helpers.command
local feed_command = helpers.feed_command
local funcs = helpers.funcs
@@ -96,25 +95,24 @@ describe(':write', function()
eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~'))
-- Message from check_overwrite
if not iswin() then
- eq(('\nE17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
- redir_exec('write .'))
+ eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
+ pcall_err(command, 'write .'))
end
meths.set_option('writeany', true)
-- Message from buf_write
- eq(('\nE502: "." is a directory'),
- redir_exec('write .'))
+ eq(('Vim(write):E502: "." is a directory'), pcall_err(command, 'write .'))
funcs.mkdir(fname_bak)
meths.set_option('backupdir', '.')
meths.set_option('backup', true)
write_file(fname, 'content0')
- eq(0, exc_exec('edit ' .. fname))
+ command('edit ' .. fname)
funcs.setline(1, 'TTY')
eq('Vim(write):E510: Can\'t make backup file (add ! to override)',
- exc_exec('write'))
+ pcall_err(command, 'write'))
meths.set_option('backup', false)
funcs.setfperm(fname, 'r--------')
eq('Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)',
- exc_exec('write'))
+ pcall_err(command, 'write'))
if iswin() then
eq(0, os.execute('del /q/f ' .. fname))
eq(0, os.execute('rd /q/s ' .. fname_bak))
@@ -127,6 +125,6 @@ describe(':write', function()
if iswin() then return end
lfs.link(fname_bak .. ('/xxxxx'):rep(20), fname, true)
eq('Vim(write):E166: Can\'t open linked file for writing',
- exc_exec('write!'))
+ pcall_err(command, 'write!'))
end)
end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index b7fddc8f29..8e03d9a46e 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -43,11 +43,11 @@ end
local function read_message()
local line = io.read("*l")
local length = line:lower():match("content%-length:%s*(%d+)")
- return vim.fn.json_decode(io.read(2 + length):sub(2))
+ return vim.json.decode(io.read(2 + length):sub(2))
end
local function send(payload)
- io.stdout:write(format_message_with_content_length(vim.fn.json_encode(payload)))
+ io.stdout:write(format_message_with_content_length(vim.json.encode(payload)))
end
local function respond(id, err, result)
@@ -126,6 +126,89 @@ function tests.check_workspace_configuration()
}
end
+function tests.prepare_rename_nil()
+ skeleton {
+ on_init = function()
+ return { capabilities = {
+ renameProvider = true,
+ } }
+ end;
+ body = function()
+ notify('start')
+ expect_request('textDocument/prepareRename', function()
+ return nil, nil
+ end)
+ notify('shutdown')
+ end;
+ }
+end
+
+function tests.prepare_rename_placeholder()
+ skeleton {
+ on_init = function()
+ return { capabilities = {
+ renameProvider = true,
+ } }
+ end;
+ body = function()
+ notify('start')
+ expect_request('textDocument/prepareRename', function()
+ return nil, {placeholder = 'placeholder'}
+ end)
+ expect_request('textDocument/rename', function(params)
+ assert_eq(params.newName, 'renameto')
+ return nil, nil
+ end)
+ notify('shutdown')
+ end;
+ }
+end
+
+function tests.prepare_rename_range()
+ skeleton {
+ on_init = function()
+ return { capabilities = {
+ renameProvider = true,
+ } }
+ end;
+ body = function()
+ notify('start')
+ expect_request('textDocument/prepareRename', function()
+ return nil, {
+ start = { line = 1, character = 8 },
+ ['end'] = { line = 1, character = 12 },
+ }
+ end)
+ expect_request('textDocument/rename', function(params)
+ assert_eq(params.newName, 'renameto')
+ return nil, nil
+ end)
+ notify('shutdown')
+ end;
+ }
+end
+
+function tests.prepare_rename_error()
+ skeleton {
+ on_init = function()
+ return { capabilities = {
+ renameProvider = true,
+ } }
+ end;
+ body = function()
+ notify('start')
+ expect_request('textDocument/prepareRename', function()
+ return {}, nil
+ end)
+ expect_request('textDocument/rename', function(params)
+ assert_eq(params.newName, 'renameto')
+ return nil, nil
+ end)
+ notify('shutdown')
+ end;
+ }
+end
+
function tests.basic_check_capabilities()
skeleton {
on_init = function(params)
@@ -481,6 +564,35 @@ function tests.decode_nil()
}
end
+
+function tests.code_action_with_resolve()
+ skeleton {
+ on_init = function()
+ return {
+ capabilities = {
+ codeActionProvider = {
+ resolveProvider = true
+ }
+ }
+ }
+ end;
+ body = function()
+ notify('start')
+ local cmd = {
+ title = 'Command 1',
+ command = 'dummy1'
+ }
+ expect_request('textDocument/codeAction', function()
+ return nil, { cmd, }
+ end)
+ expect_request('codeAction/resolve', function()
+ return nil, cmd
+ end)
+ notify('shutdown')
+ end;
+ }
+end
+
-- Tests will be indexed by TEST_NAME
local kill_timer = vim.loop.new_timer()
diff --git a/test/functional/fixtures/middle/filen.lua b/test/functional/fixtures/middle/filen.lua
new file mode 100644
index 0000000000..fce50cc776
--- /dev/null
+++ b/test/functional/fixtures/middle/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "mittel")
diff --git a/test/functional/fixtures/nvim/after/filen.lua b/test/functional/fixtures/nvim/after/filen.lua
new file mode 100644
index 0000000000..0128a0a16a
--- /dev/null
+++ b/test/functional/fixtures/nvim/after/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "ordinary after")
diff --git a/test/functional/fixtures/nvim/filen.lua b/test/functional/fixtures/nvim/filen.lua
new file mode 100644
index 0000000000..e2bd5e8f7f
--- /dev/null
+++ b/test/functional/fixtures/nvim/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "ordinary")
diff --git a/test/functional/fixtures/pack/foo/opt/funky/filen.lua b/test/functional/fixtures/pack/foo/opt/funky/filen.lua
new file mode 100644
index 0000000000..a33b83c2a7
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/opt/funky/filen.lua
@@ -0,0 +1,12 @@
+table.insert(_G.test_loadorder, "funky!")
+
+if not _G.nesty then
+ _G.nesty = true
+ local save_order = _G.test_loadorder
+ _G.test_loadorder = {}
+ _G.vim.o.pp = "" -- funky!
+ vim.cmd [[runtime! filen.lua ]]
+ _G.nested_order = _G.test_loadorder
+ _G.test_loadorder = save_order
+ _G.nesty = nil
+end
diff --git a/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua b/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua
new file mode 100644
index 0000000000..94bf6850b2
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "SuperSpecial after")
diff --git a/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua b/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua
new file mode 100644
index 0000000000..cbaab1a45a
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "SuperSpecial")
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua
new file mode 100644
index 0000000000..9beac762ee
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "FANCY after")
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua
new file mode 100644
index 0000000000..34e4b9c95e
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua
@@ -0,0 +1 @@
+table.insert(_G.test_loadorder, "FANCY")
diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c
index b95e563932..4196716799 100644
--- a/test/functional/fixtures/shell-test.c
+++ b/test/functional/fixtures/shell-test.c
@@ -19,7 +19,7 @@ static void flush_wait(void)
static void help(void)
{
- puts("A simple implementation of a shell for testing termopen().");
+ puts("Fake shell");
puts("");
puts("Usage:");
puts(" shell-test --help");
@@ -42,6 +42,8 @@ static void help(void)
puts(" 96: foo bar");
puts(" shell-test INTERACT");
puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
+ puts(" shell-test EXIT {code}");
+ puts(" Exits immediately with exit code \"{code}\".");
}
int main(int argc, char **argv)
@@ -103,7 +105,6 @@ int main(int argc, char **argv)
char input[256];
char cmd[100];
int arg;
- int input_argc;
while (1) {
fprintf(stderr, "interact $ ");
@@ -112,8 +113,7 @@ int main(int argc, char **argv)
break; // EOF
}
- input_argc = sscanf(input, "%99s %d", cmd, &arg);
- if(1 == input_argc) {
+ if(1 == sscanf(input, "%99s %d", cmd, &arg)) {
arg = 0;
}
if (strcmp(cmd, "exit") == 0) {
@@ -122,6 +122,15 @@ int main(int argc, char **argv)
fprintf(stderr, "command not found: %s\n", cmd);
}
}
+ } else if (strcmp(argv[1], "EXIT") == 0) {
+ int code = 1;
+ if (argc >= 3) {
+ if (sscanf(argv[2], "%d", &code) != 1) {
+ fprintf(stderr, "Invalid exit code: %s\n", argv[2]);
+ return 2;
+ }
+ }
+ return code;
} else {
fprintf(stderr, "Unknown first argument: %s\n", argv[1]);
return 3;
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 03ef441ef3..a26e883370 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -38,10 +38,16 @@ module.nvim_prog = (
module.nvim_set = (
'set shortmess+=IS background=light noswapfile noautoindent startofline'
..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
- ..' belloff= wildoptions-=pum noshowcmd noruler nomore redrawdebug=invalid')
+ ..' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid')
module.nvim_argv = {
module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', module.nvim_set, '--embed'}
+ '--cmd', module.nvim_set,
+ '--cmd', 'unmap Y',
+ '--cmd', 'unmap <C-L>',
+ '--cmd', 'iunmap <C-U>',
+ '--cmd', 'iunmap <C-W>',
+ '--embed'}
+
-- Directory containing nvim.
module.nvim_dir = module.nvim_prog:gsub("[/\\][^/\\]+$", "")
if module.nvim_dir == module.nvim_prog then
@@ -416,7 +422,7 @@ end
-- Builds an argument list for use in clear().
--
---@see clear() for parameters.
+---@see clear() for parameters.
function module.new_argv(...)
local args = {unpack(module.nvim_argv)}
table.insert(args, '--headless')
@@ -567,7 +573,7 @@ function module.buf_lines(bufnr)
return module.exec_lua("return vim.api.nvim_buf_get_lines((...), 0, -1, false)", bufnr)
end
---@see buf_lines()
+---@see buf_lines()
function module.curbuf_contents()
module.poke_eventloop() -- Before inspecting the buffer, do whatever.
return table.concat(module.curbuf('get_lines', 0, -1, true), '\n')
@@ -779,19 +785,6 @@ function module.exec_lua(code, ...)
return module.meths.exec_lua(code, {...})
end
-function module.redir_exec(cmd)
- module.meths.set_var('__redir_exec_cmd', cmd)
- module.command([[
- redir => g:__redir_exec_output
- silent! execute g:__redir_exec_cmd
- redir END
- ]])
- local ret = module.meths.get_var('__redir_exec_output')
- module.meths.del_var('__redir_exec_output')
- module.meths.del_var('__redir_exec_cmd')
- return ret
-end
-
function module.get_pathsep()
return iswin() and '\\' or '/'
end
diff --git a/test/functional/insert/ctrl_o_spec.lua b/test/functional/insert/ctrl_o_spec.lua
deleted file mode 100644
index 543d0a7d68..0000000000
--- a/test/functional/insert/ctrl_o_spec.lua
+++ /dev/null
@@ -1,54 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local eq = helpers.eq
-local eval = helpers.eval
-local expect = helpers.expect
-local feed = helpers.feed
-local insert = helpers.insert
-local meths = helpers.meths
-
-describe('insert-mode Ctrl-O', function()
- before_each(clear)
-
- it('enters command mode for one command', function()
- feed('ihello world<C-o>')
- feed(':let ctrlo = "test"<CR>')
- feed('iii')
- expect('hello worldiii')
- eq(1, eval('ctrlo ==# "test"'))
- end)
-
- it('re-enters insert mode at the end of the line when running startinsert', function()
- -- #6962
- feed('ihello world<C-o>')
- feed(':startinsert<CR>')
- feed('iii')
- expect('hello worldiii')
- end)
-
- it('re-enters insert mode at the beginning of the line when running startinsert', function()
- insert('hello world')
- feed('0<C-o>')
- feed(':startinsert<CR>')
- feed('aaa')
- expect('aaahello world')
- end)
-
- it('re-enters insert mode in the middle of the line when running startinsert', function()
- insert('hello world')
- feed('bi<C-o>')
- feed(':startinsert<CR>')
- feed('ooo')
- expect('hello oooworld')
- end)
-
- it("doesn't cancel Ctrl-O mode when processing event", function()
- feed('iHello World<c-o>')
- eq({mode='niI', blocking=false}, meths.get_mode()) -- fast event
- eq(2, eval('1+1')) -- causes K_EVENT key
- eq({mode='niI', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
- feed('dd')
- eq({mode='i', blocking=false}, meths.get_mode()) -- left ctrl-o mode
- expect('') -- executed the command
- end)
-end)
diff --git a/test/functional/insert/ctrl_r_spec.lua b/test/functional/insert/ctrl_r_spec.lua
deleted file mode 100644
index adc3c4b406..0000000000
--- a/test/functional/insert/ctrl_r_spec.lua
+++ /dev/null
@@ -1,19 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear, feed = helpers.clear, helpers.feed
-local expect, command = helpers.expect, helpers.command
-
-describe('insert-mode Ctrl-R', function()
- before_each(clear)
-
- it('works', function()
- command("let @@ = 'test'")
- feed('i<C-r>"')
- expect('test')
- end)
-
- it('works with multi-byte text', function()
- command("let @@ = 'påskägg'")
- feed('i<C-r>"')
- expect('påskägg')
- end)
-end)
diff --git a/test/functional/legacy/007_ball_buffer_list_spec.lua b/test/functional/legacy/007_ball_buffer_list_spec.lua
index a180e73301..d4e4547c43 100644
--- a/test/functional/legacy/007_ball_buffer_list_spec.lua
+++ b/test/functional/legacy/007_ball_buffer_list_spec.lua
@@ -8,6 +8,9 @@ describe(':ball', function()
setup(clear)
it('is working', function()
+ -- Must disable 'hidden' so that the BufReadPost autocmd is triggered
+ -- when Xxx2 is reloaded
+ feed_command('set nohidden')
insert([[
start of test file Xxx
this is a test
@@ -18,7 +21,7 @@ describe(':ball', function()
feed('gg')
-- Write test file Xxx1
- feed('A1:.,/end of/w! Xxx1<cr>')
+ feed('A1<esc>:.,/end of/w! Xxx1<cr>')
feed_command('sp Xxx1')
feed_command('close')
diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua
index 939404cb5e..002f037d09 100644
--- a/test/functional/legacy/008_autocommands_spec.lua
+++ b/test/functional/legacy/008_autocommands_spec.lua
@@ -71,6 +71,9 @@ describe('autocommands that delete and unload buffers:', function()
au BufUnload * call CloseAll()
au VimLeave * call WriteToOut()
]])
+ -- Must disable 'hidden' so that the BufUnload autocmd is triggered between
+ -- each :edit
+ command('set nohidden')
command('silent! edit Xxx2')
command('silent! edit Xxx1')
command('silent! edit Makefile') -- an existing file
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 7b6f2f63e9..0fa9290f3c 100644
--- a/test/functional/legacy/011_autocommands_spec.lua
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -129,13 +129,11 @@ describe('file reading, writing and bufnew and filter autocommands', function()
-- Will load Xtest.c.
feed_command('e! foo.c')
feed_command("au FileAppendPre *.out '[,']s/new/NEW/")
- feed_command('au FileAppendPost *.out !cat Xtest.c >>test.out')
+ feed_command('au FileAppendPost *.out !cat Xtest.c >test.out')
-- Append it to the output file.
feed_command('w>>test.out')
-- Discard all prompts and messages.
feed('<C-L>')
- -- Expect the decompressed file in the buffer.
- feed_command('e test.out')
expect([[
/*
diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua
index 48dd24db9e..f666e51469 100644
--- a/test/functional/legacy/012_directory_spec.lua
+++ b/test/functional/legacy/012_directory_spec.lua
@@ -80,6 +80,7 @@ describe("'directory' option", function()
eq({ "Xtest1.swp", "Xtest3" }, ls_dir_sorted("Xtest2"))
meths.set_option('directory', 'Xtest.je')
+ command('bdelete')
command('edit Xtest2/Xtest3')
eq(true, curbufmeths.get_option('swapfile'))
poke_eventloop()
diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua
index a4f5d6ac5b..d164d9c02f 100644
--- a/test/functional/legacy/063_match_and_matchadd_spec.lua
+++ b/test/functional/legacy/063_match_and_matchadd_spec.lua
@@ -6,7 +6,7 @@ local Screen = require('test.functional.ui.screen')
local eval, clear, command = helpers.eval, helpers.clear, helpers.command
local eq, neq = helpers.eq, helpers.neq
local insert = helpers.insert
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
describe('063: Test for ":match", "matchadd()" and related functions', function()
setup(clear)
@@ -67,9 +67,7 @@ describe('063: Test for ":match", "matchadd()" and related functions', function(
-- matchdelete throws error and returns -1 on failure
neq(true, pcall(function() eval('matchdelete(42)') end))
- eq('\nE803: ID not found: 42',
- redir_exec("let r2 = matchdelete(42)"))
- eq(-1, eval('r2'))
+ eq('Vim(let):E803: ID not found: 42', pcall_err(command, 'let r2 = matchdelete(42)'))
-- Check that "clearmatches()" clears all matches defined by ":match" and
-- "matchadd()".
@@ -105,9 +103,8 @@ describe('063: Test for ":match", "matchadd()" and related functions', function(
-- Check that "setmatches()" will not add two matches with the same ID. The
-- expected behaviour (for now) is to add the first match but not the
-- second and to return -1.
- eq('\nE801: ID already taken: 1',
- redir_exec("let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])"))
- eq(-1, eval("r1"))
+ eq('Vim(let):E801: ID already taken: 1',
+ pcall_err(command, "let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])"))
eq({{group = 'MyGroup1', pattern = 'TODO', priority = 10, id = 1}}, eval('getmatches()'))
-- Check that "setmatches()" returns 0 if successful and otherwise -1.
@@ -116,14 +113,11 @@ describe('063: Test for ":match", "matchadd()" and related functions', function(
eq(0,eval("setmatches([])"))
eq(0,eval("setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])"))
command("call clearmatches()")
- eq('\nE714: List required', redir_exec("let rf1 = setmatches(0)"))
- eq(-1, eval('rf1'))
- eq('\nE474: List item 0 is either not a dictionary or an empty one',
- redir_exec("let rf2 = setmatches([0])"))
- eq(-1, eval('rf2'))
- eq('\nE474: List item 0 is missing one of the required keys',
- redir_exec("let rf3 = setmatches([{'wrong key': 'wrong value'}])"))
- eq(-1, eval('rf3'))
+ eq('Vim(let):E714: List required', pcall_err(command, 'let rf1 = setmatches(0)'))
+ eq('Vim(let):E474: List item 0 is either not a dictionary or an empty one',
+ pcall_err(command, 'let rf2 = setmatches([0])'))
+ eq('Vim(let):E474: List item 0 is missing one of the required keys',
+ pcall_err(command, "let rf3 = setmatches([{'wrong key': 'wrong value'}])"))
-- Check that "matchaddpos()" positions matches correctly
insert('abcdefghijklmnopq')
diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua
index 67c5750033..6a2e86ccb4 100644
--- a/test/functional/legacy/arglist_spec.lua
+++ b/test/functional/legacy/arglist_spec.lua
@@ -156,10 +156,12 @@ describe('argument list commands', function()
eq({'a', 'b', 'a', 'c'}, eval('argv()'))
command('0argedit x')
eq({'x', 'a', 'b', 'a', 'c'}, eval('argv()'))
+ command('set nohidden')
command('enew! | set modified')
assert_fails('argedit y', 'E37:')
command('argedit! y')
eq({'x', 'y', 'y', 'a', 'b', 'a', 'c'}, eval('argv()'))
+ command('set hidden')
command('%argd')
command('argedit a b')
eq({'a', 'b'}, eval('argv()'))
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 515d6d91b8..c2b22472bf 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -26,6 +26,14 @@ describe('assert function:', function()
call('assert_beeps', 'normal 0')
expected_errors({'command did not beep: normal 0'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, 'normal h'->assert_beeps())
+ call assert_equal(1, 'normal 0'->assert_beeps())
+ ]]
+ expected_errors({tmpname .. ' line 2: command did not beep: normal 0'})
+ end)
end)
-- assert_equal({expected}, {actual}, [, {msg}])
@@ -133,6 +141,14 @@ describe('assert function:', function()
call('assert_false', {})
expected_errors({'Expected False but got []'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, v:false->assert_false())
+ call assert_equal(1, 123->assert_false())
+ ]]
+ expected_errors({tmpname .. ' line 2: Expected False but got 123'})
+ end)
end)
-- assert_true({actual}, [, {msg}])
@@ -148,6 +164,14 @@ describe('assert function:', function()
eq(1, call('assert_true', 1.5))
expected_errors({'Expected True but got 1.5'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, v:true->assert_true())
+ call assert_equal(1, 0->assert_true())
+ ]]
+ expected_errors({tmpname .. ' line 2: Expected True but got 0'})
+ end)
end)
describe('v:errors', function()
@@ -223,6 +247,15 @@ describe('assert function:', function()
call('assert_match', 'bar.*foo', 'foobar', 'wrong')
expected_errors({"wrong: Pattern 'bar.*foo' does not match 'foobar'"})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'foobar'->assert_match('bar.*foo', 'wrong'))
+ ]]
+ expected_errors({
+ tmpname .. " line 1: wrong: Pattern 'bar.*foo' does not match 'foobar'"
+ })
+ end)
end)
-- assert_notmatch({pat}, {text}[, {msg}])
@@ -237,6 +270,13 @@ describe('assert function:', function()
call('assert_notmatch', 'foo', 'foobar')
expected_errors({"Pattern 'foo' does match 'foobar'"})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'foobar'->assert_notmatch('foo'))
+ ]]
+ expected_errors({tmpname .. " line 1: Pattern 'foo' does match 'foobar'"})
+ end)
end)
-- assert_fails({cmd}, [, {error}])
@@ -267,6 +307,15 @@ describe('assert function:', function()
eq(1, eval([[assert_fails('echo', '', 'echo command')]]))
expected_errors({'command did not fail: echo command'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'echo'->assert_fails('', 'echo command'))
+ ]]
+ expected_errors({
+ tmpname .. ' line 1: command did not fail: echo command'
+ })
+ end)
end)
-- assert_inrange({lower}, {upper}, {actual}[, {msg}])
@@ -292,6 +341,15 @@ describe('assert function:', function()
eq('Vim(call):E119: Not enough arguments for function: assert_inrange',
exc_exec("call assert_inrange(1, 1)"))
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, 5->assert_inrange(5, 7))
+ call assert_equal(0, 7->assert_inrange(5, 7))
+ call assert_equal(1, 8->assert_inrange(5, 7))
+ ]]
+ expected_errors({tmpname .. ' line 3: Expected range 5 - 7, but got 8'})
+ end)
end)
-- assert_report({msg})
@@ -302,6 +360,13 @@ describe('assert function:', function()
command('call remove(v:errors, 0)')
expected_empty()
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'also wrong'->assert_report())
+ ]]
+ expected_errors({tmpname .. ' line 1: also wrong'})
+ end)
end)
-- assert_exception({cmd}, [, {error}])
diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua
index 0c7e43bf31..1914818215 100644
--- a/test/functional/legacy/autocmd_option_spec.lua
+++ b/test/functional/legacy/autocmd_option_spec.lua
@@ -3,7 +3,7 @@ local nvim = helpers.meths
local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
local curbuf, buf = helpers.curbuf, helpers.bufmeths
local curwin = helpers.curwin
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local source, command = helpers.source, helpers.command
local function declare_hook_function()
@@ -102,13 +102,13 @@ local function get_new_window_number()
local old_win = curwin()
command('botright new')
local new_win = curwin()
- local new_winnr = redir_exec('echo winnr()')
+ local new_winnr = exec_capture('echo winnr()')
command('wincmd p') -- move previous window
neq(old_win, new_win)
eq(old_win, curwin())
- return new_winnr:gsub('\n', '')
+ return new_winnr
end
describe('au OptionSet', function()
diff --git a/test/functional/legacy/cdo_spec.lua b/test/functional/legacy/cdo_spec.lua
index 5e46431cc1..8b3216cbfd 100644
--- a/test/functional/legacy/cdo_spec.lua
+++ b/test/functional/legacy/cdo_spec.lua
@@ -91,7 +91,8 @@ describe('cdo', function()
exe "silent! 4,5" . XdoCmd
call assert_equal([], l)
- " Run commands from an unsaved buffer
+ " Run commands from an unsaved buffer when 'hidden' is unset
+ set nohidden
let v:errmsg=''
let l = []
enew
@@ -108,6 +109,7 @@ describe('cdo', function()
if subst_count != 1 || getline('.') != 'xLine1'
call add(v:errors, 'Abort command on error test failed')
endif
+ set hidden
let l = []
exe "2,2" . Xdo . "! call add(l, GetRuler())"
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index ee9bd29fc4..b5de5cd232 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -1,6 +1,7 @@
-- Test for various eval features.
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, command, expect = helpers.clear, helpers.command, helpers.expect
local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file
@@ -506,7 +507,7 @@ describe('eval', function()
command("call setreg('0',x)")
-- nvim didn't crash and "0 was emptied
- eq(2, eval("1+1"))
+ assert_alive()
eq({}, eval("getreg('0',1,1)"))
-- x is a mutable list
@@ -599,7 +600,6 @@ describe('eval', function()
command([[call ErrExe('call setreg(1)')]])
command([[call ErrExe('call setreg(1, 2, 3, 4)')]])
command([=[call ErrExe('call setreg([], 2)')]=])
- command([[call ErrExe('call setreg(1, {})')]])
command([=[call ErrExe('call setreg(1, 2, [])')]=])
command([=[call ErrExe('call setreg("/", ["1", "2"])')]=])
command([=[call ErrExe('call setreg("=", ["1", "2"])')]=])
@@ -614,8 +614,6 @@ describe('eval', function()
Vim(call):E118: Too many arguments for function: setreg
Executing call setreg([], 2)
Vim(call):E730: using List as a String
- Executing call setreg(1, {})
- Vim(call):E731: using Dictionary as a String
Executing call setreg(1, 2, [])
Vim(call):E730: using List as a String
Executing call setreg("/", ["1", "2"])
diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua
index 50236e8617..d3ff86d349 100644
--- a/test/functional/legacy/fixeol_spec.lua
+++ b/test/functional/legacy/fixeol_spec.lua
@@ -23,8 +23,6 @@ describe('fixeol', function()
it('is working', function()
-- First write two test files – with and without trailing EOL.
- -- Use Unix fileformat for consistency.
- feed_command('set ff=unix')
feed_command('enew!')
feed('awith eol<esc>:w! XXEol<cr>')
feed_command('enew!')
@@ -40,7 +38,7 @@ describe('fixeol', function()
feed_command('e! XXNoEol')
feed('ostays without<esc>:set nofixeol<cr>')
feed_command('w! XXTestNoEol')
- feed_command('bwipe XXEol XXNoEol XXTestEol XXTestNoEol')
+ feed_command('bwipe! XXEol XXNoEol XXTestEol XXTestNoEol')
feed_command('set fixeol')
-- Append "END" to each file so that we can see what the last written char was.
diff --git a/test/functional/legacy/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua
index cffb9fd376..dc6ccd3628 100644
--- a/test/functional/legacy/listchars_spec.lua
+++ b/test/functional/legacy/listchars_spec.lua
@@ -8,7 +8,7 @@ local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers
describe("'listchars'", function()
before_each(function()
clear()
- feed_command('set listchars&vi')
+ feed_command('set listchars=eol:$')
end)
-- luacheck: ignore 613 (Trailing whitespace in a string)
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index 0f2d77093a..d86caca0e9 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -168,6 +168,9 @@ describe('memory usage', function()
end)
it('releases memory when closing windows when folds exist', function()
+ if helpers.is_os('mac') then
+ pending('macOS memory compression causes flakiness')
+ end
local pid = eval('getpid()')
source([[
new
diff --git a/test/functional/legacy/mksession_spec.lua b/test/functional/legacy/mksession_spec.lua
index a2af891107..bca9cd833c 100644
--- a/test/functional/legacy/mksession_spec.lua
+++ b/test/functional/legacy/mksession_spec.lua
@@ -12,7 +12,7 @@ describe('mksession', function()
end)
it('supports "skiprtp" value', function()
- command('set sessionoptions&vi')
+ command('set sessionoptions+=options')
command('set rtp+=$HOME')
command('set pp+=$HOME')
command('mksession! Xtest_mks.out')
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index 896554f7a3..fdf79d55b2 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -15,7 +15,7 @@ describe('luaeval(vim.api.…)', function()
describe('nvim_buf_get_lines', function()
it('works', function()
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
- eq({{_TYPE={}, _VAL={'a\nb'}}},
+ eq({'a\000b'},
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)'))
end)
end)
@@ -23,7 +23,7 @@ describe('luaeval(vim.api.…)', function()
it('works', function()
funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
eq(NIL, funcs.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})'))
- eq({'abc', {_TYPE={}, _VAL={'b\na'}}, {_TYPE={}, _VAL={'a\nb'}}, 'ttt'},
+ eq({'abc', 'b\000a', 'a\000b', 'ttt'},
funcs.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)'))
end)
end)
@@ -64,15 +64,18 @@ describe('luaeval(vim.api.…)', function()
it('correctly converts from API objects', function()
eq(1, funcs.luaeval('vim.api.nvim_eval("1")'))
eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]]))
+ eq('Blobby', funcs.luaeval('vim.api.nvim_eval("0z426c6f626279")'))
eq({}, funcs.luaeval('vim.api.nvim_eval("[]")'))
eq({}, funcs.luaeval('vim.api.nvim_eval("{}")'))
eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")'))
+ eq('\000', funcs.luaeval('vim.api.nvim_eval("0z00")'))
eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")'))
eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")'))
eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")'))
eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]]))
eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]]))
+ eq(1, eval([[type(luaeval('vim.api.nvim_eval("0zbeef")'))]]))
eq(3, eval([[type(luaeval('vim.api.nvim_eval("[]")'))]]))
eq(4, eval([[type(luaeval('vim.api.nvim_eval("{}")'))]]))
eq(5, eval([[type(luaeval('vim.api.nvim_eval("1.0")'))]]))
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index a5b613f0b2..073927bf22 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -978,6 +978,22 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it("visual paste", function()
+ local check_events= setup_eventcheck(verify, { "aaa {", "b", "}" })
+ -- Setting up
+ feed[[jdd]]
+ check_events {
+ { "test1", "bytes", 1, 3, 1, 0, 6, 1, 0, 2, 0, 0, 0 };
+ }
+
+ -- Actually testing
+ feed[[v%p]]
+ check_events {
+ { "test1", "bytes", 1, 8, 0, 4, 4, 1, 1, 3, 0, 0, 0 };
+ { "test1", "bytes", 1, 8, 0, 4, 4, 0, 0, 0, 2, 0, 3 };
+ }
+ end)
+
it("nvim_buf_set_lines", function()
local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index f2a1b7dede..2e0d0ea899 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -15,14 +15,14 @@ local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local write_file = helpers.write_file
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local curbufmeths = helpers.curbufmeths
before_each(clear)
describe(':lua command', function()
it('works', function()
- eq('', redir_exec(
+ eq('', exec_capture(
'lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})'))
eq({'', 'TEST'}, curbufmeths.get_lines(0, 100, false))
source(dedent([[
@@ -67,18 +67,19 @@ describe(':lua command', function()
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
end)
it('preserves global and not preserves local variables', function()
- eq('', redir_exec('lua gvar = 42'))
- eq('', redir_exec('lua local lvar = 100500'))
+ eq('', exec_capture('lua gvar = 42'))
+ eq('', exec_capture('lua local lvar = 100500'))
eq(NIL, funcs.luaeval('lvar'))
eq(42, funcs.luaeval('gvar'))
end)
it('works with long strings', function()
local s = ('x'):rep(100500)
- eq('\nE5107: Error loading lua [string ":lua"]:1: unfinished string near \'<eof>\'', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s)))
+ eq('Vim(lua):E5107: Error loading lua [string ":lua"]:0: unfinished string near \'<eof>\'',
+ pcall_err(command, ('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s)))
eq({''}, curbufmeths.get_lines(0, -1, false))
- eq('', redir_exec(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s)))
+ eq('', exec_capture(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s)))
eq({'', s}, curbufmeths.get_lines(0, -1, false))
end)
@@ -144,34 +145,34 @@ end)
describe(':luado command', function()
it('works', function()
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('', redir_exec('luado lines = (lines or {}) lines[#lines + 1] = {linenr, line}'))
+ eq('', exec_capture('luado lines = (lines or {}) lines[#lines + 1] = {linenr, line}'))
eq({'ABC', 'def', 'gHi'}, curbufmeths.get_lines(0, -1, false))
eq({{1, 'ABC'}, {2, 'def'}, {3, 'gHi'}}, funcs.luaeval('lines'))
-- Automatic transformation of numbers
- eq('', redir_exec('luado return linenr'))
+ eq('', exec_capture('luado return linenr'))
eq({'1', '2', '3'}, curbufmeths.get_lines(0, -1, false))
- eq('', redir_exec('luado return ("<%02x>"):format(line:byte())'))
+ eq('', exec_capture('luado return ("<%02x>"):format(line:byte())'))
eq({'<31>', '<32>', '<33>'}, curbufmeths.get_lines(0, -1, false))
end)
it('stops processing lines when suddenly out of lines', function()
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('', redir_exec('2,$luado runs = ((runs or 0) + 1) vim.api.nvim_command("%d")'))
+ eq('', exec_capture('2,$luado runs = ((runs or 0) + 1) vim.api.nvim_command("%d")'))
eq({''}, curbufmeths.get_lines(0, -1, false))
eq(1, funcs.luaeval('runs'))
end)
it('works correctly when changing lines out of range', function()
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('\nE322: line number out of range: 1 past the end\nE320: Cannot find line 2',
- redir_exec('2,$luado vim.api.nvim_command("%d") return linenr'))
+ eq('Vim(luado):E322: line number out of range: 1 past the end',
+ pcall_err(command, '2,$luado vim.api.nvim_command("%d") return linenr'))
eq({''}, curbufmeths.get_lines(0, -1, false))
end)
it('fails on errors', function()
- eq([[Vim(luado):E5109: Error loading lua: [string ":luado"]:1: unexpected symbol near ')']],
- exc_exec('luado ()'))
- eq([[Vim(luado):E5111: Error calling lua: [string ":luado"]:1: attempt to perform arithmetic on global 'liness' (a nil value)]],
- exc_exec('luado return liness + 1'))
+ eq([[Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unexpected symbol near ')']],
+ pcall_err(command, 'luado ()'))
+ eq([[Vim(luado):E5111: Error calling lua: [string ":luado"]:0: attempt to perform arithmetic on global 'liness' (a nil value)]],
+ pcall_err(command, 'luado return liness + 1'))
end)
it('works with NULL errors', function()
eq([=[Vim(luado):E5111: Error calling lua: [NULL]]=],
@@ -179,17 +180,18 @@ describe(':luado command', function()
end)
it('fails in sandbox when needed', function()
curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('\nE48: Not allowed in sandbox: sandbox luado runs = (runs or 0) + 1',
- redir_exec('sandbox luado runs = (runs or 0) + 1'))
+ eq('Vim(luado):E48: Not allowed in sandbox',
+ pcall_err(command, 'sandbox luado runs = (runs or 0) + 1'))
eq(NIL, funcs.luaeval('runs'))
end)
it('works with long strings', function()
local s = ('x'):rep(100500)
- eq('\nE5109: Error loading lua: [string ":luado"]:1: unfinished string near \'<eof>\'', redir_exec(('luado return "%s'):format(s)))
+ eq('Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unfinished string near \'<eof>\'',
+ pcall_err(command, ('luado return "%s'):format(s)))
eq({''}, curbufmeths.get_lines(0, -1, false))
- eq('', redir_exec(('luado return "%s"'):format(s)))
+ eq('', exec_capture(('luado return "%s"'):format(s)))
eq({s}, curbufmeths.get_lines(0, -1, false))
end)
end)
@@ -207,7 +209,7 @@ describe(':luafile', function()
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
]])
- eq('', redir_exec('luafile ' .. fname))
+ eq('', exec_capture('luafile ' .. fname))
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
end)
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
new file mode 100644
index 0000000000..9397af9d9f
--- /dev/null
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -0,0 +1,1147 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local NIL = helpers.NIL
+local command = helpers.command
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local nvim = helpers.nvim
+
+describe('vim.diagnostic', function()
+ before_each(function()
+ clear()
+
+ exec_lua [[
+ require('vim.diagnostic')
+
+ function make_diagnostic(msg, x1, y1, x2, y2, severity, source)
+ return {
+ lnum = x1,
+ col = y1,
+ end_lnum = x2,
+ end_col = y2,
+ message = msg,
+ severity = severity,
+ source = source,
+ }
+ end
+
+ function make_error(msg, x1, y1, x2, y2, source)
+ return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.ERROR, source)
+ end
+
+ function make_warning(msg, x1, y1, x2, y2, source)
+ return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.WARN, source)
+ end
+
+ function make_info(msg, x1, y1, x2, y2, source)
+ return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.INFO, source)
+ end
+
+ function make_hint(msg, x1, y1, x2, y2, source)
+ return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.HINT, source)
+ end
+
+ function count_diagnostics(bufnr, severity, namespace)
+ return #vim.diagnostic.get(bufnr, {severity = severity, namespace = namespace})
+ end
+
+ function count_extmarks(bufnr, namespace)
+ return #vim.api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, {})
+ end
+ ]]
+
+ exec_lua([[
+ diagnostic_ns = vim.api.nvim_create_namespace("diagnostic_spec")
+ other_ns = vim.api.nvim_create_namespace("other_namespace")
+ diagnostic_bufnr = vim.api.nvim_create_buf(true, false)
+ local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"}
+ vim.fn.bufload(diagnostic_bufnr)
+ vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, 1, false, lines)
+ return diagnostic_bufnr
+ ]])
+ end)
+
+ after_each(function()
+ clear()
+ end)
+
+ it('creates highlight groups', function()
+ command('runtime plugin/diagnostic.vim')
+ eq({
+ 'DiagnosticError',
+ 'DiagnosticFloatingError',
+ 'DiagnosticFloatingHint',
+ 'DiagnosticFloatingInfo',
+ 'DiagnosticFloatingWarn',
+ 'DiagnosticHint',
+ 'DiagnosticInfo',
+ 'DiagnosticSignError',
+ 'DiagnosticSignHint',
+ 'DiagnosticSignInfo',
+ 'DiagnosticSignWarn',
+ 'DiagnosticUnderlineError',
+ 'DiagnosticUnderlineHint',
+ 'DiagnosticUnderlineInfo',
+ 'DiagnosticUnderlineWarn',
+ 'DiagnosticVirtualTextError',
+ 'DiagnosticVirtualTextHint',
+ 'DiagnosticVirtualTextInfo',
+ 'DiagnosticVirtualTextWarn',
+ 'DiagnosticWarn',
+ }, exec_lua([[return vim.fn.getcompletion('Diagnostic', 'highlight')]]))
+ end)
+
+ it('retrieves diagnostics from all buffers and namespaces', function()
+ local result = exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, 1, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ vim.diagnostic.set(other_ns, 2, {
+ make_error('Diagnostic #3', 3, 1, 3, 1),
+ })
+ return vim.diagnostic.get()
+ ]]
+ eq(3, #result)
+ eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == 1 end, ...)]], result))
+ eq('Diagnostic #1', result[1].message)
+ end)
+
+ it('saves and count a single error', function()
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
+ ]])
+ end)
+
+ it('saves and count multiple errors', function()
+ eq(2, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
+ ]])
+ end)
+
+ it('saves and count from multiple namespaces', function()
+ eq({1, 1, 2}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1', 1, 1, 1, 1),
+ })
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 2', 1, 1, 1, 1),
+ })
+ return {
+ -- First namespace
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ -- Second namespace
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, other_ns),
+ -- All namespaces
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
+ }
+ ]])
+ end)
+
+ it('saves and count from multiple namespaces with respect to severity', function()
+ eq({3, 0, 3}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ make_error('Diagnostic From Server 1:2', 2, 2, 2, 2),
+ make_error('Diagnostic From Server 1:3', 2, 3, 3, 2),
+ })
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_warning('Warning From Server 2', 3, 3, 3, 3),
+ })
+ return {
+ -- Namespace 1
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ -- Namespace 2
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, other_ns),
+ -- All namespaces
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
+ }
+ ]])
+ end)
+
+ it('handles one namespace clearing highlights while the other still has highlights', function()
+ -- 1 Error (1)
+ -- 1 Warning (2)
+ -- 1 Warning (2) + 1 Warning (1)
+ -- 2 highlights and 2 underlines (since error)
+ -- 1 highlight + 1 underline
+ local all_highlights = {1, 1, 2, 4, 2}
+ eq(all_highlights, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Clear diagnostics from namespace 1, and make sure we have the right amount of stuff for namespace 2
+ eq({1, 1, 2, 0, 2}, exec_lua [[
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Show diagnostics from namespace 1 again
+ eq(all_highlights, exec_lua([[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]]))
+ end)
+
+ it('does not display diagnostics when disabled', function()
+ eq({0, 2}, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+
+ return {
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ eq({4, 0}, exec_lua [[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.disable(diagnostic_bufnr, other_ns)
+
+ return {
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+ end)
+
+ describe('reset()', function()
+ it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
+ -- 1 Error (1)
+ -- 1 Warning (2)
+ -- 1 Warning (2) + 1 Warning (1)
+ -- 2 highlights and 2 underlines (since error)
+ -- 1 highlight + 1 underline
+ local all_highlights = {1, 1, 2, 4, 2}
+ eq(all_highlights, exec_lua [[
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ return {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ }
+ ]])
+
+ -- Reset diagnostics from namespace 1
+ exec_lua([[ vim.diagnostic.reset(diagnostic_ns) ]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 1, 1, 0, 2} , exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ } end )
+ return diagnostic_count
+ ]])
+
+ -- Reset diagnostics from namespace 2
+ exec_lua([[ vim.diagnostic.reset(other_ns) ]])
+
+ -- Make sure we have the right diagnostic count
+ eq({0, 0, 0, 0, 0}, exec_lua [[
+ local diagnostic_count = {}
+ vim.wait(100, function () diagnostic_count = {
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
+ count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN),
+ count_extmarks(diagnostic_bufnr, diagnostic_ns),
+ count_extmarks(diagnostic_bufnr, other_ns),
+ } end )
+ return diagnostic_count
+ ]])
+
+ end)
+ end)
+
+ describe('get_next_pos()', function()
+ it('can find the next pos with only one namespace', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ return vim.diagnostic.get_next_pos()
+ ]])
+ end)
+
+ it('can find next pos with two errors', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('can cycle when position is past error', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('will not cycle when wrap is off', function()
+ eq(false, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns, wrap = false }
+ ]])
+ end)
+
+ it('can cycle even from the last line', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+ end)
+
+ describe('get_prev_pos()', function()
+ it('can find the prev pos with only one namespace', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos()
+ ]])
+ end)
+
+ it('can find prev pos with two errors', function()
+ eq({1, 1}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('can cycle when position is past error', function()
+ eq({4, 4}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
+ ]])
+ end)
+
+ it('respects wrap parameter', function()
+ eq(false, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #2', 4, 4, 4, 4),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 1})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns, wrap = false}
+ ]])
+ end)
+ end)
+
+ describe('get()', function()
+ it('returns an empty table when no diagnostics are present', function()
+ eq({}, exec_lua [[return vim.diagnostic.get(diagnostic_bufnr, {namespace=diagnostic_ns})]])
+ end)
+
+ it('returns all diagnostics when no severity is supplied', function()
+ eq(2, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ })
+
+ return #vim.diagnostic.get(diagnostic_bufnr)
+ ]])
+ end)
+
+ it('returns only requested diagnostics when severity is supplied', function()
+ eq({2, 3, 2}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ make_info("Ignored information", 1, 1, 2, 5),
+ make_hint("Here's a hint", 1, 1, 2, 5),
+ })
+
+ return {
+ #vim.diagnostic.get(diagnostic_bufnr, { severity = {min=vim.diagnostic.severity.WARN} }),
+ #vim.diagnostic.get(diagnostic_bufnr, { severity = {max=vim.diagnostic.severity.WARN} }),
+ #vim.diagnostic.get(diagnostic_bufnr, {
+ severity = {
+ min=vim.diagnostic.severity.INFO,
+ max=vim.diagnostic.severity.WARN,
+ }
+ }),
+ }
+ ]])
+ end)
+
+ it('allows filtering by line', function()
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 5),
+ make_info("Ignored information", 1, 1, 2, 5),
+ make_error("Error On Other Line", 2, 1, 1, 5),
+ })
+
+ return #vim.diagnostic.get(diagnostic_bufnr, {lnum = 2})
+ ]])
+ end)
+ end)
+
+ describe('config()', function()
+ it('can use functions for config values', function()
+ exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = function() return true end,
+ }, diagnostic_ns)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ -- Now, don't enable virtual text.
+ -- We should have one less extmark displayed.
+ exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = function() return false end,
+ }, diagnostic_ns)
+ ]]
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('allows filtering by severity', function()
+ local get_extmark_count_with_severity = function(min_severity)
+ return exec_lua([[
+ vim.diagnostic.config({
+ underline = false,
+ virtual_text = {
+ severity = {min=...},
+ },
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]], min_severity)
+ end
+
+ -- No messages with Error or higher
+ eq(0, get_extmark_count_with_severity("ERROR"))
+
+ -- But now we don't filter it
+ eq(1, get_extmark_count_with_severity("WARN"))
+ eq(1, get_extmark_count_with_severity("HINT"))
+ end)
+
+ it('allows sorting by severity', function()
+ exec_lua [[
+ vim.diagnostic.config({
+ underline = false,
+ signs = true,
+ virtual_text = true,
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Warning', 4, 4, 4, 4),
+ make_error('Error', 4, 4, 4, 4),
+ make_info('Info', 4, 4, 4, 4),
+ })
+
+ function get_virt_text_and_signs(severity_sort)
+ vim.diagnostic.config({
+ severity_sort = severity_sort,
+ })
+
+ local virt_text = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})[1][4].virt_text
+
+ local virt_texts = {}
+ for i = 2, #virt_text do
+ table.insert(virt_texts, (string.gsub(virt_text[i][2], "DiagnosticVirtualText", "")))
+ end
+
+ local signs = {}
+ for _, v in ipairs(vim.fn.sign_getplaced(diagnostic_bufnr, {group = "*"})[1].signs) do
+ table.insert(signs, (string.gsub(v.name, "DiagnosticSign", "")))
+ end
+
+ return {virt_texts, signs}
+ end
+ ]]
+
+ local result = exec_lua [[return get_virt_text_and_signs(false)]]
+
+ -- Virt texts are defined lowest priority to highest, signs from
+ -- highest to lowest
+ eq({'Warn', 'Error', 'Info'}, result[1])
+ eq({'Info', 'Error', 'Warn'}, result[2])
+
+ result = exec_lua [[return get_virt_text_and_signs(true)]]
+ eq({'Info', 'Warn', 'Error'}, result[1])
+ eq({'Error', 'Warn', 'Info'}, result[2])
+
+ result = exec_lua [[return get_virt_text_and_signs({ reverse = true })]]
+ eq({'Error', 'Warn', 'Info'}, result[1])
+ eq({'Info', 'Warn', 'Error'}, result[2])
+ end)
+
+ it('can show diagnostic sources in virtual text', function()
+ local result = exec_lua [[
+ local diagnostics = {
+ make_error('Some error', 0, 0, 0, 0, 'source x'),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics, {
+ underline = false,
+ virtual_text = {
+ prefix = '',
+ source = 'always',
+ }
+ })
+
+ local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local virt_text = extmarks[1][4].virt_text[2][1]
+ return virt_text
+ ]]
+ eq(' source x: Some error', result)
+
+ result = exec_lua [[
+ vim.diagnostic.config({
+ underline = false,
+ virtual_text = {
+ prefix = '',
+ source = 'if_many',
+ }
+ }, diagnostic_ns)
+
+ local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local virt_text = extmarks[1][4].virt_text[2][1]
+ return virt_text
+ ]]
+ eq(' Some error', result)
+
+ result = exec_lua [[
+ local diagnostics = {
+ make_error('Some error', 0, 0, 0, 0, 'source x'),
+ make_error('Another error', 1, 1, 1, 1, 'source y'),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics, {
+ underline = false,
+ virtual_text = {
+ prefix = '',
+ source = 'if_many',
+ }
+ })
+
+ local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local virt_text = {extmarks[1][4].virt_text[2][1], extmarks[2][4].virt_text[2][1]}
+ return virt_text
+ ]]
+ eq(' source x: Some error', result[1])
+ eq(' source y: Another error', result[2])
+ end)
+
+ it('supports a format function for diagnostic messages', function()
+ local result = exec_lua [[
+ vim.diagnostic.config({
+ underline = false,
+ virtual_text = {
+ prefix = '',
+ format = function(diagnostic)
+ if diagnostic.severity == vim.diagnostic.severity.ERROR then
+ return string.format("🔥 %s", diagnostic.message)
+ end
+ return string.format("👀 %s", diagnostic.message)
+ end,
+ }
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Warning', 0, 0, 0, 0),
+ make_error('Error', 1, 0, 1, 0),
+ })
+
+ local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
+ ]]
+ eq(" 👀 Warning", result[1][2][1])
+ eq(" 🔥 Error", result[2][2][1])
+ end)
+
+ it('includes source for formatted diagnostics', function()
+ local result = exec_lua [[
+ vim.diagnostic.config({
+ underline = false,
+ virtual_text = {
+ prefix = '',
+ source = 'always',
+ format = function(diagnostic)
+ if diagnostic.severity == vim.diagnostic.severity.ERROR then
+ return string.format("🔥 %s", diagnostic.message)
+ end
+ return string.format("👀 %s", diagnostic.message)
+ end,
+ }
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Warning', 0, 0, 0, 0, 'some_linter'),
+ make_error('Error', 1, 0, 1, 0, 'another_linter'),
+ })
+
+ local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
+ ]]
+ eq(" some_linter: 👀 Warning", result[1][2][1])
+ eq(" another_linter: 🔥 Error", result[2][2][1])
+ end)
+ end)
+
+ describe('set()', function()
+ it('can perform updates after insert_leave', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ })
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('does not perform updates when not needed', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ virtual_text = true,
+ })
+
+ -- Count how many times we call display.
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
+
+ DisplayCount = 0
+ vim.diagnostic._set_virtual_text = function(...)
+ DisplayCount = DisplayCount + 1
+ return SetVirtualTextOriginal(...)
+ end
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(1, exec_lua [[return DisplayCount]])
+
+ -- Go in and out of insert mode one more time.
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ -- Should not have set the virtual text again.
+ eq(1, exec_lua [[return DisplayCount]])
+ end)
+
+ it('never sets virtual text, in combination with insert leave', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = false,
+ virtual_text = false,
+ })
+
+ -- Count how many times we call display.
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
+
+ DisplayCount = 0
+ vim.diagnostic._set_virtual_text = function(...)
+ DisplayCount = DisplayCount + 1
+ return SetVirtualTextOriginal(...)
+ end
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- No diagnostics displayed yet.
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(0, exec_lua [[return DisplayCount]])
+
+ -- Go in and out of insert mode one more time.
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ -- Should not have set the virtual text still.
+ eq(0, exec_lua [[return DisplayCount]])
+ end)
+
+ it('can perform updates while in insert mode, if desired', function()
+ exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
+ nvim("input", "o")
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+
+ -- Save the diagnostics
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = true,
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Delayed Diagnostic', 4, 4, 4, 4),
+ })
+ ]]
+
+ -- Diagnostics are displayed, because the user wanted them that way!
+ eq({mode='i', blocking=false}, nvim("get_mode"))
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+
+ nvim("input", "<esc>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+
+ eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ end)
+
+ it('can set diagnostics without displaying them', function()
+ eq(0, exec_lua [[
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(2, exec_lua [[
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+ end)
+
+ it('can set display options', function()
+ eq(0, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ }, { virtual_text = false, underline = false })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(1, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
+ }, { virtual_text = true, underline = false })
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+ end)
+ end)
+
+ describe('show_line_diagnostics()', function()
+ it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function()
+ -- Two lines:
+ -- Diagnostic:
+ -- 1. <msg>
+ eq(2, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics()
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('only reports diagnostics from the current buffer when bufnr is omitted #15710', function()
+ eq(2, exec_lua [[
+ local other_bufnr = vim.api.nvim_create_buf(true, false)
+ local buf_1_diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ local buf_2_diagnostics = {
+ make_warning("Some warning", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, buf_1_diagnostics)
+ vim.diagnostic.set(other_ns, other_bufnr, buf_2_diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics()
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('allows filtering by namespace', function()
+ eq(2, exec_lua [[
+ local ns_1_diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ local ns_2_diagnostics = {
+ make_warning("Some warning", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diagnostics)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({namespace = diagnostic_ns})
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('creates floating window and returns popup bufnr and winnr without header, if requested', function()
+ -- One line (since no header):
+ -- 1. <msg>
+ eq(1, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {show_header = false}
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('clamps diagnostic line numbers within the valid range', function()
+ eq(1, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 6, 0, 6, 0),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({show_header = false}, diagnostic_bufnr, 5)
+ return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ ]])
+ end)
+
+ it('can show diagnostic source', function()
+ exec_lua [[vim.api.nvim_win_set_buf(0, diagnostic_bufnr)]]
+
+ eq({"1. Syntax error"}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3, "source x"),
+ }
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ show_header = false,
+ source = "if_many",
+ }
+ local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq({"1. source x: Syntax error"}, exec_lua [[
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ show_header = false,
+ source = "always",
+ }
+ local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq({"1. source x: Syntax error", "2. source y: Another error"}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3, "source x"),
+ make_error("Another error", 0, 1, 0, 3, "source y"),
+ }
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ show_header = false,
+ source = "if_many",
+ }
+ local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+ end)
+ end)
+
+ describe('set_signs()', function()
+ -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...??
+ pending('sets signs by default', function()
+ exec_lua [[
+ vim.diagnostic.config({
+ update_in_insert = true,
+ signs = true,
+ })
+
+ local diagnostics = {
+ make_error('Delayed Diagnostic', 1, 1, 1, 2),
+ make_error('Delayed Diagnostic', 3, 3, 3, 3),
+ }
+
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+
+ vim.diagnostic._set_signs(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ -- return vim.fn.sign_getplaced()
+ ]]
+
+ nvim("input", "o")
+ nvim("input", "<esc>")
+
+ -- TODO(tjdevries): Find a way to get the signs to display in the test...
+ eq(nil, exec_lua [[
+ return im.fn.sign_getplaced()[1].signs
+ ]])
+ end)
+ end)
+
+ describe('setloclist()', function()
+ it('sets diagnostics in lnum order', function()
+ local loc_list = exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Farther Diagnostic', 4, 4, 4, 4),
+ make_error('Lower Diagnostic', 1, 1, 1, 1),
+ })
+
+ vim.diagnostic.setloclist()
+
+ return vim.fn.getloclist(0)
+ ]]
+
+ assert(loc_list[1].lnum < loc_list[2].lnum)
+ end)
+
+ it('sets diagnostics in lnum order, regardless of namespace', function()
+ local loc_list = exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Lower Diagnostic', 1, 1, 1, 1),
+ })
+
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, {
+ make_warning('Farther Diagnostic', 4, 4, 4, 4),
+ })
+
+ vim.diagnostic.setloclist()
+
+ return vim.fn.getloclist(0)
+ ]]
+
+ assert(loc_list[1].lnum < loc_list[2].lnum)
+ end)
+ end)
+
+ describe('match()', function()
+ it('matches a string', function()
+ local msg = "ERROR: george.txt:19:84:Two plus two equals five"
+ local diagnostic = {
+ severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
+ lnum = 18,
+ col = 83,
+ end_lnum = 18,
+ end_col = 83,
+ message = "Two plus two equals five",
+ }
+ eq(diagnostic, exec_lua([[
+ return vim.diagnostic.match(..., "^(%w+): [^:]+:(%d+):(%d+):(.+)$", {"severity", "lnum", "col", "message"})
+ ]], msg))
+ end)
+
+ it('returns nil if the pattern fails to match', function()
+ eq(NIL, exec_lua [[
+ local msg = "The answer to life, the universe, and everything is"
+ return vim.diagnostic.match(msg, "This definitely will not match", {})
+ ]])
+ end)
+
+ it('respects default values', function()
+ local msg = "anna.txt:1:Happy families are all alike"
+ local diagnostic = {
+ severity = exec_lua [[return vim.diagnostic.severity.INFO]],
+ lnum = 0,
+ col = 0,
+ end_lnum = 0,
+ end_col = 0,
+ message = "Happy families are all alike",
+ }
+ eq(diagnostic, exec_lua([[
+ return vim.diagnostic.match(..., "^[^:]+:(%d+):(.+)$", {"lnum", "message"}, nil, {severity = vim.diagnostic.severity.INFO})
+ ]], msg))
+ end)
+
+ it('accepts a severity map', function()
+ local msg = "46:FATAL:Et tu, Brute?"
+ local diagnostic = {
+ severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
+ lnum = 45,
+ col = 0,
+ end_lnum = 45,
+ end_col = 0,
+ message = "Et tu, Brute?",
+ }
+ eq(diagnostic, exec_lua([[
+ return vim.diagnostic.match(..., "^(%d+):(%w+):(.+)$", {"lnum", "severity", "message"}, {FATAL = vim.diagnostic.severity.ERROR})
+ ]], msg))
+ end)
+ end)
+
+ describe('toqflist() and fromqflist()', function()
+ it('works', function()
+ local result = exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Error 1', 0, 1, 0, 1),
+ make_error('Error 2', 1, 1, 1, 1),
+ make_warning('Warning', 2, 2, 2, 2),
+ })
+
+ local diagnostics = vim.diagnostic.get(diagnostic_bufnr)
+ vim.fn.setqflist(vim.diagnostic.toqflist(diagnostics))
+ local list = vim.fn.getqflist()
+ local new_diagnostics = vim.diagnostic.fromqflist(list)
+
+ -- Remove namespace since it isn't present in the return value of
+ -- fromlist()
+ for _, v in ipairs(diagnostics) do
+ v.namespace = nil
+ end
+
+ return {diagnostics, new_diagnostics}
+ ]]
+ eq(result[1], result[2])
+ end)
+ end)
+end)
diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua
new file mode 100644
index 0000000000..50eecb5d09
--- /dev/null
+++ b/test/functional/lua/highlight_spec.lua
@@ -0,0 +1,25 @@
+local helpers = require('test.functional.helpers')(after_each)
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local eval = helpers.eval
+local command = helpers.command
+local clear = helpers.clear
+
+describe('vim.highlight.on_yank', function()
+
+ before_each(function()
+ clear()
+ end)
+
+ it('does not show errors even if buffer is wiped before timeout', function()
+ command('new')
+ exec_lua[[
+ vim.highlight.on_yank({timeout = 10, on_macro = true, event = {operator = "y", regtype = "v"}})
+ vim.cmd('bwipeout!')
+ ]]
+ helpers.sleep(10)
+ helpers.feed('<cr>') -- avoid hang if error message exists
+ eq('', eval('v:errmsg'))
+ end)
+
+end)
diff --git a/test/functional/lua/json_spec.lua b/test/functional/lua/json_spec.lua
new file mode 100644
index 0000000000..fbb21bfd57
--- /dev/null
+++ b/test/functional/lua/json_spec.lua
@@ -0,0 +1,133 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local NIL = helpers.NIL
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+
+describe('vim.json.decode function', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('parses null, true, false', function()
+ eq(NIL, exec_lua([[return vim.json.decode('null')]]))
+ eq(true, exec_lua([[return vim.json.decode('true')]]))
+ eq(false, exec_lua([[return vim.json.decode('false')]]))
+ end)
+
+ it('parses integer numbers', function()
+ eq(100000, exec_lua([[return vim.json.decode('100000')]]))
+ eq(-100000, exec_lua([[return vim.json.decode('-100000')]]))
+ eq(100000, exec_lua([[return vim.json.decode(' 100000 ')]]))
+ eq(-100000, exec_lua([[return vim.json.decode(' -100000 ')]]))
+ eq(0, exec_lua([[return vim.json.decode('0')]]))
+ eq(0, exec_lua([[return vim.json.decode('-0')]]))
+ end)
+
+ it('parses floating-point numbers', function()
+ -- This behavior differs from vim.fn.json_decode, which return '100000.0'
+ eq('100000', exec_lua([[return tostring(vim.json.decode('100000.0'))]]))
+ eq(100000.5, exec_lua([[return vim.json.decode('100000.5')]]))
+ eq(-100000.5, exec_lua([[return vim.json.decode('-100000.5')]]))
+ eq(-100000.5e50, exec_lua([[return vim.json.decode('-100000.5e50')]]))
+ eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e50')]]))
+ eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e+50')]]))
+ eq(-100000.5e-50, exec_lua([[return vim.json.decode('-100000.5e-50')]]))
+ eq(100000.5e-50, exec_lua([[return vim.json.decode('100000.5e-50')]]))
+ eq(100000e-50, exec_lua([[return vim.json.decode('100000e-50')]]))
+ eq(0.5, exec_lua([[return vim.json.decode('0.5')]]))
+ eq(0.005, exec_lua([[return vim.json.decode('0.005')]]))
+ eq(0.005, exec_lua([[return vim.json.decode('0.00500')]]))
+ eq(0.5, exec_lua([[return vim.json.decode('0.00500e+002')]]))
+ eq(0.00005, exec_lua([[return vim.json.decode('0.00500e-002')]]))
+
+ eq(-0.0, exec_lua([[return vim.json.decode('-0.0')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0.0e0')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0.0e+0')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0.0e-0')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0e-0')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0e-2')]]))
+ eq(-0.0, exec_lua([[return vim.json.decode('-0e+2')]]))
+
+ eq(0.0, exec_lua([[return vim.json.decode('0.0')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0.0e0')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0.0e+0')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0.0e-0')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0e-0')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0e-2')]]))
+ eq(0.0, exec_lua([[return vim.json.decode('0e+2')]]))
+ end)
+
+ it('parses containers', function()
+ eq({1}, exec_lua([[return vim.json.decode('[1]')]]))
+ eq({NIL, 1}, exec_lua([[return vim.json.decode('[null, 1]')]]))
+ eq({['1']=2}, exec_lua([[return vim.json.decode('{"1": 2}')]]))
+ eq({['1']=2, ['3']={{['4']={['5']={{}, 1}}}}},
+ exec_lua([[return vim.json.decode('{"1": 2, "3": [{"4": {"5": [ [], 1]}}]}')]]))
+ end)
+
+ it('parses strings properly', function()
+ eq('\n', exec_lua([=[return vim.json.decode([["\n"]])]=]))
+ eq('', exec_lua([=[return vim.json.decode([[""]])]=]))
+ eq('\\/"\t\b\n\r\f', exec_lua([=[return vim.json.decode([["\\\/\"\t\b\n\r\f"]])]=]))
+ eq('/a', exec_lua([=[return vim.json.decode([["\/a"]])]=]))
+ -- Unicode characters: 2-byte, 3-byte
+ eq('«',exec_lua([=[return vim.json.decode([["«"]])]=]))
+ eq('ફ',exec_lua([=[return vim.json.decode([["ફ"]])]=]))
+ end)
+
+ it('parses surrogate pairs properly', function()
+ eq('\240\144\128\128', exec_lua([[return vim.json.decode('"\\uD800\\uDC00"')]]))
+ end)
+
+ it('accepts all spaces in every position where space may be put', function()
+ local s = ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
+ local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s)
+ eq({key={'val', 'val2'}, key2=1}, exec_lua([[return vim.json.decode(...)]], str))
+ end)
+
+end)
+
+describe('vim.json.encode function', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('dumps strings', function()
+ eq('"Test"', exec_lua([[return vim.json.encode('Test')]]))
+ eq('""', exec_lua([[return vim.json.encode('')]]))
+ eq('"\\t"', exec_lua([[return vim.json.encode('\t')]]))
+ eq('"\\n"', exec_lua([[return vim.json.encode('\n')]]))
+ -- vim.fn.json_encode return \\u001B
+ eq('"\\u001b"', exec_lua([[return vim.json.encode('\27')]]))
+ eq('"þÿþ"', exec_lua([[return vim.json.encode('þÿþ')]]))
+ end)
+
+ it('dumps numbers', function()
+ eq('0', exec_lua([[return vim.json.encode(0)]]))
+ eq('10', exec_lua([[return vim.json.encode(10)]]))
+ eq('-10', exec_lua([[return vim.json.encode(-10)]]))
+ end)
+
+ it('dumps floats', function()
+ eq('10.5', exec_lua([[return vim.json.encode(10.5)]]))
+ eq('-10.5', exec_lua([[return vim.json.encode(-10.5)]]))
+ eq('-1e-05', exec_lua([[return vim.json.encode(-1e-5)]]))
+ end)
+
+ it('dumps lists', function()
+ eq('[]', exec_lua([[return vim.json.encode({})]]))
+ eq('[[]]', exec_lua([[return vim.json.encode({{}})]]))
+ eq('[[],[]]', exec_lua([[return vim.json.encode({{}, {}})]]))
+ end)
+
+ it('dumps dictionaries', function()
+ eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict())]]))
+ eq('{"d":[]}', exec_lua([[return vim.json.encode({d={}})]]))
+ end)
+
+ it('dumps vim.NIL', function()
+ eq('null', exec_lua([[return vim.json.encode(vim.NIL)]]))
+ end)
+
+end)
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 2ec48777fd..255e99032f 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -63,11 +63,10 @@ describe('luaeval()', function()
eq('\n[[...@0]]', funcs.execute('echo luaeval("l")'))
end)
end)
- describe('strings', function()
- it('are successfully converted to special dictionaries', function()
+ describe('strings with NULs', function()
+ it('are successfully converted to blobs', function()
command([[let s = luaeval('"\0"')]])
- eq({_TYPE={}, _VAL={'\n'}}, meths.get_var('s'))
- eq(1, funcs.eval('s._TYPE is v:msgpack_types.binary'))
+ eq('\000', meths.get_var('s'))
end)
it('are successfully converted to special dictionaries in table keys',
function()
@@ -76,13 +75,10 @@ describe('luaeval()', function()
eq(1, funcs.eval('d._TYPE is v:msgpack_types.map'))
eq(1, funcs.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string'))
end)
- it('are successfully converted to special dictionaries from a list',
+ it('are successfully converted to blobs from a list',
function()
command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]])
- eq({'abc', {_TYPE={}, _VAL={'a\nb'}}, {_TYPE={}, _VAL={'c\nd'}}, 'def'},
- meths.get_var('l'))
- eq(1, funcs.eval('l[1]._TYPE is v:msgpack_types.binary'))
- eq(1, funcs.eval('l[2]._TYPE is v:msgpack_types.binary'))
+ eq({'abc', 'a\000b', 'c\000d', 'def'}, meths.get_var('l'))
end)
end)
@@ -100,9 +96,9 @@ describe('luaeval()', function()
eq(1, eval('type(luaeval("\'test\'"))'))
eq('', funcs.luaeval('""'))
- eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']]))
- eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']]))
- eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]]))
+ eq('\000', funcs.luaeval([['\0']]))
+ eq('\000\n\000', funcs.luaeval([['\0\n\0']]))
+ eq(10, eval([[type(luaeval("'\\0\\n\\0'"))]]))
eq(true, funcs.luaeval('true'))
eq(false, funcs.luaeval('false'))
@@ -122,12 +118,11 @@ describe('luaeval()', function()
local level = 30
eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s))
- eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}},
+ eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}},
funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]]))
- eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]]))
- eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}},
+ eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}}}},
funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
end)
@@ -175,8 +170,8 @@ describe('luaeval()', function()
end
it('correctly passes special dictionaries', function()
- eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
- eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]')))
+ eq({0, '\000\n\000'}, luaevalarg(sp('binary', '["\\n", "\\n"]')))
+ eq({0, '\000\n\000'}, luaevalarg(sp('string', '["\\n", "\\n"]')))
eq({0, true}, luaevalarg(sp('boolean', 1)))
eq({0, false}, luaevalarg(sp('boolean', 0)))
eq({0, NIL}, luaevalarg(sp('nil', 0)))
@@ -458,6 +453,9 @@ describe('v:lua', function()
function mymod.crashy()
nonexistent()
end
+ function mymod.whatis(value)
+ return type(value) .. ": " .. tostring(value)
+ end
function mymod.omni(findstart, base)
if findstart == 1 then
return 5
@@ -476,11 +474,28 @@ describe('v:lua', function()
eq(true, exec_lua([[return _G.val == vim.NIL]]))
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
eq("hey eval", meths.get_current_line())
+ eq("string: abc", eval('v:lua.mymod.whatis(0z616263)'))
+ eq("string: ", eval('v:lua.mymod.whatis(v:_null_blob)'))
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
pcall_err(eval, 'v:lua.mymod.crashy()'))
end)
+ it('works when called as a method', function()
+ eq(123, eval('110->v:lua.foo(13)'))
+ eq(true, exec_lua([[return _G.val == nil]]))
+
+ eq(321, eval('300->v:lua.foo(21, "boop")'))
+ eq("boop", exec_lua([[return _G.val]]))
+
+ eq(NIL, eval('"there"->v:lua.mymod.noisy()'))
+ eq("hey there", meths.get_current_line())
+ eq({5, 10, 15, 20}, eval('[[1], [2, 3], [4]]->v:lua.vim.tbl_flatten()->map({_, v -> v * 5})'))
+
+ eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
+ pcall_err(eval, '"huh?"->v:lua.mymod.crashy()'))
+ end)
+
it('works in :call', function()
command(":call v:lua.mymod.noisy('command')")
eq("hey command", meths.get_current_line())
@@ -518,8 +533,15 @@ describe('v:lua', function()
eq("Vim:E15: Invalid expression: v:['lua'].foo()", pcall_err(eval, "v:['lua'].foo()"))
eq("Vim(call):E461: Illegal variable name: v:['lua']", pcall_err(command, "call v:['lua'].baar()"))
+ eq("Vim:E117: Unknown function: v:lua", pcall_err(eval, "v:lua()"))
eq("Vim(let):E46: Cannot change read-only variable \"v:['lua']\"", pcall_err(command, "let v:['lua'] = 'xx'"))
eq("Vim(let):E46: Cannot change read-only variable \"v:lua\"", pcall_err(command, "let v:lua = 'xx'"))
+
+ eq("Vim:E107: Missing parentheses: v:lua.func", pcall_err(eval, "'bad'->v:lua.func"))
+ eq("Vim:E274: No white space allowed before parenthesis", pcall_err(eval, "'bad'->v:lua.func ()"))
+ eq("Vim:E107: Missing parentheses: v:lua", pcall_err(eval, "'bad'->v:lua"))
+ eq("Vim:E117: Unknown function: v:lua", pcall_err(eval, "'bad'->v:lua()"))
+ eq("Vim:E15: Invalid expression: v:lua.()", pcall_err(eval, "'bad'->v:lua.()"))
end)
end)
diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua
new file mode 100644
index 0000000000..ef693f01f3
--- /dev/null
+++ b/test/functional/lua/mpack_spec.lua
@@ -0,0 +1,23 @@
+-- Test suite for testing interactions with API bindings
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+
+describe('lua vim.mpack', function()
+ before_each(clear)
+ it('can pack vim.NIL', function()
+ eq({true, true, true, true}, exec_lua [[
+ local var = vim.mpack.unpack(vim.mpack.pack({33, vim.NIL, 77}))
+ return {var[1]==33, var[2]==vim.NIL, var[3]==77, var[4]==nil}
+ ]])
+ end)
+
+ it('can pack vim.empty_dict()', function()
+ eq({{{}, "foo", {}}, true, false}, exec_lua [[
+ local var = vim.mpack.unpack(vim.mpack.pack({{}, "foo", vim.empty_dict()}))
+ return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])}
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index 267c759faf..636479b81f 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -11,8 +11,9 @@ local meths = helpers.meths
local iswin = helpers.iswin
local command = helpers.command
local write_file = helpers.write_file
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local exec_lua = helpers.exec_lua
+local pcall_err = helpers.pcall_err
local screen
@@ -36,11 +37,11 @@ describe('print', function()
write_file(fname, 'print("abc")')
eq('\nabc', funcs.execute('luafile ' .. fname))
- eq('\nabc', redir_exec('lua print("abc")'))
- eq('\nabc', redir_exec('luado print("abc")'))
- eq('\nabc', redir_exec('call luaeval("print(\'abc\')")'))
+ eq('abc', exec_capture('lua print("abc")'))
+ eq('abc', exec_capture('luado print("abc")'))
+ eq('abc', exec_capture('call luaeval("print(\'abc\')")'))
write_file(fname, 'print("abc")')
- eq('\nabc', redir_exec('luafile ' .. fname))
+ eq('abc', exec_capture('luafile ' .. fname))
end)
it('handles errors in __tostring', function()
write_file(fname, [[
@@ -51,30 +52,30 @@ describe('print', function()
v_abcerr = setmetatable({}, meta_abcerr)
v_tblout = setmetatable({}, meta_tblout)
]])
- eq('', redir_exec('luafile ' .. fname))
+ eq('', exec_capture('luafile ' .. fname))
-- TODO(bfredl): these look weird, print() should not use "E5114:" style errors..
- eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
- redir_exec('lua print("foo", v_nilerr, "bar")'))
- eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
- redir_exec('lua print("foo", v_abcerr, "bar")'))
- eq('\nE5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
- redir_exec('lua print("foo", v_tblout, "bar")'))
+ eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
+ pcall_err(command, 'lua print("foo", v_nilerr, "bar")'))
+ eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:0: abc',
+ pcall_err(command, 'lua print("foo", v_abcerr, "bar")'))
+ eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
+ pcall_err(command, 'lua print("foo", v_tblout, "bar")'))
end)
it('prints strings with NULs and NLs correctly', function()
meths.set_option('more', true)
- eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
- redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
- eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
- redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
- eq('\nT^@', redir_exec([[lua print("T\0")]]))
- eq('\nT\n', redir_exec([[lua print("T\n")]]))
+ eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
+ exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
+ eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
+ exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
+ eq('T^@', exec_capture([[lua print("T\0")]]))
+ eq('T\n', exec_capture([[lua print("T\n")]]))
end)
it('prints empty strings correctly', function()
-- Regression: first test used to crash
- eq('', redir_exec('lua print("")'))
- eq('\n def', redir_exec('lua print("", "def")'))
- eq('\nabc ', redir_exec('lua print("abc", "")'))
- eq('\nabc def', redir_exec('lua print("abc", "", "def")'))
+ eq('', exec_capture('lua print("")'))
+ eq(' def', exec_capture('lua print("", "def")'))
+ eq('abc ', exec_capture('lua print("abc", "")'))
+ eq('abc def', exec_capture('lua print("abc", "", "def")'))
end)
it('defers printing in luv event handlers', function()
exec_lua([[
@@ -97,7 +98,7 @@ describe('print', function()
vim.api.nvim_command("sleep 1m") -- force deferred event processing
end
]], (iswin() and "timeout 1") or "sleep 0.1")
- eq('\nvery slow\nvery fast',redir_exec('lua test()'))
+ eq('very slow\nvery fast', exec_capture('lua test()'))
end)
end)
diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua
new file mode 100644
index 0000000000..94f1b5840b
--- /dev/null
+++ b/test/functional/lua/ui_spec.lua
@@ -0,0 +1,46 @@
+local helpers = require('test.functional.helpers')(after_each)
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local clear = helpers.clear
+
+describe('vim.ui', function()
+ before_each(function()
+ clear()
+ end)
+
+
+ describe('select', function()
+ it('can select an item', function()
+ local result = exec_lua[[
+ local items = {
+ { name = 'Item 1' },
+ { name = 'Item 2' },
+ }
+ local opts = {
+ format_item = function(entry)
+ return entry.name
+ end
+ }
+ local selected
+ local cb = function(item)
+ selected = item
+ end
+ -- inputlist would require input and block the test;
+ local choices
+ vim.fn.inputlist = function(x)
+ choices = x
+ return 1
+ end
+ vim.ui.select(items, opts, cb)
+ vim.wait(100, function() return selected ~= nil end)
+ return {selected, choices}
+ ]]
+ eq({ name = 'Item 1' }, result[1])
+ eq({
+ 'Select one of:',
+ '1: Item 1',
+ '2: Item 2',
+ }, result[2])
+ end)
+ end)
+end)
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index f782769935..052a8a1ecd 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -53,12 +53,18 @@ describe('URI methods', function()
describe('uri to filepath', function()
describe('decode Unix file path', function()
- it('file path includes only ascii charactors', function()
+ it('file path includes only ascii characters', function()
exec_lua("uri = 'file:///Foo/Bar/Baz.txt'")
eq('/Foo/Bar/Baz.txt', exec_lua("return vim.uri_to_fname(uri)"))
end)
+ it('local file path without hostname', function()
+ exec_lua("uri = 'file:/Foo/Bar/Baz.txt'")
+
+ eq('/Foo/Bar/Baz.txt', exec_lua("return vim.uri_to_fname(uri)"))
+ end)
+
it('file path including white space', function()
exec_lua("uri = 'file:///Foo%20/Bar/Baz.txt'")
@@ -85,6 +91,15 @@ describe('URI methods', function()
eq('C:\\Foo\\Bar\\Baz.txt', exec_lua(test_case))
end)
+ it('local file path without hostname', function()
+ local test_case = [[
+ local uri = 'file:/C:/Foo/Bar/Baz.txt'
+ return vim.uri_to_fname(uri)
+ ]]
+
+ eq('C:\\Foo\\Bar\\Baz.txt', exec_lua(test_case))
+ end)
+
it('file path includes only ascii charactors with encoded colon character', function()
local test_case = [[
local uri = 'file:///C%3A/Foo/Bar/Baz.txt'
@@ -125,6 +140,12 @@ describe('URI methods', function()
return vim.uri_to_fname('JDT://content/%5C/')
]])
end)
+
+ it('uri_to_fname returns non-file scheme URI without authority unchanged', function()
+ eq('zipfile:/path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
+ return vim.uri_to_fname('zipfile:/path/to/archive.zip%3A%3Afilename.txt')
+ ]])
+ end)
end)
describe('decode URI without scheme', function()
@@ -146,5 +167,14 @@ describe('URI methods', function()
]], uri)
eq(uri, exec_lua(test_case))
end)
+
+ it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority', function()
+ local uri = 'zipfile:/path/to/archive.zip%3A%3Afilename.txt'
+ local test_case = string.format([[
+ local uri = '%s'
+ return vim.uri_from_bufnr(vim.uri_to_bufnr(uri))
+ ]], uri)
+ eq(uri, exec_lua(test_case))
+ end)
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index eff838aea3..a066cfbc10 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -6,6 +6,7 @@ local funcs = helpers.funcs
local meths = helpers.meths
local dedent = helpers.dedent
local command = helpers.command
+local insert = helpers.insert
local clear = helpers.clear
local eq = helpers.eq
local ok = helpers.ok
@@ -17,6 +18,7 @@ local matches = helpers.matches
local source = helpers.source
local NIL = helpers.NIL
local retry = helpers.retry
+local next_msg = helpers.next_msg
before_each(clear)
@@ -603,6 +605,31 @@ describe('lua stdlib', function()
return vim.tbl_islist(c) and count == 0
]]))
+ eq(exec_lua([[
+ local a = { a = { b = 1 } }
+ local b = { a = {} }
+ return vim.tbl_deep_extend("force", a, b)
+ ]]), {a = {b = 1}})
+
+ eq(exec_lua([[
+ local a = { a = 123 }
+ local b = { a = { b = 1} }
+ return vim.tbl_deep_extend("force", a, b)
+ ]]), {a = {b = 1}})
+
+ ok(exec_lua([[
+ local a = { a = {[2] = 3} }
+ local b = { a = {[3] = 3} }
+ local c = vim.tbl_deep_extend("force", a, b)
+ return vim.deep_equal(c, {a = {[3] = 3}})
+ ]]))
+
+ eq(exec_lua([[
+ local a = { a = { b = 1} }
+ local b = { a = 123 }
+ return vim.tbl_deep_extend("force", a, b)
+ ]]), {a = 123 })
+
eq('Error executing lua: vim/shared.lua:0: invalid "behavior": nil',
pcall_err(exec_lua, [[
return vim.tbl_deep_extend()
@@ -712,7 +739,7 @@ describe('lua stdlib', function()
eq({NIL, NIL}, exec_lua([[return vim.fn.Nilly()]]))
-- error handling
- eq({false, 'Vim:E714: List required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
+ eq({false, 'Vim:E897: List or Blob required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
end)
it('vim.fn should error when calling API function', function()
@@ -1332,12 +1359,12 @@ describe('lua stdlib', function()
it('should work for key-value pair options', function()
local listchars = exec_lua [[
- vim.opt.listchars = "tab:>~,space:_"
+ vim.opt.listchars = "tab:> ,space:_"
return vim.opt.listchars:get()
]]
eq({
- tab = ">~",
+ tab = "> ",
space = "_",
}, listchars)
end)
@@ -1855,7 +1882,7 @@ describe('lua stdlib', function()
end)
it('vim.region', function()
- helpers.insert(helpers.dedent( [[
+ insert(helpers.dedent( [[
text tααt tααt text
text tαxt txtα tex
text tαxt tαxt
@@ -1863,65 +1890,67 @@ describe('lua stdlib', function()
eq({5,15}, exec_lua[[ return vim.region(0,{1,5},{1,14},'v',true)[1] ]])
end)
- describe('vim.execute_on_keystroke', function()
- it('should keep track of keystrokes', function()
- helpers.insert([[hello world ]])
+ describe('vim.on_key', function()
+ it('tracks keystrokes', function()
+ insert([[hello world ]])
exec_lua [[
- KeysPressed = {}
+ keys = {}
- vim.register_keystroke_callback(function(buf)
+ vim.on_key(function(buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
- table.insert(KeysPressed, buf)
+ table.insert(keys, buf)
end)
]]
- helpers.insert([[next 🤦 lines å ]])
+ insert([[next 🤦 lines å ]])
-- It has escape in the keys pressed
- eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(KeysPressed, '')]])
+ eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(keys, '')]])
end)
- it('should allow removing trackers.', function()
- helpers.insert([[hello world]])
+ it('allows removing on_key listeners', function()
+ insert([[hello world]])
exec_lua [[
- KeysPressed = {}
+ keys = {}
- return vim.register_keystroke_callback(function(buf)
+ return vim.on_key(function(buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
- table.insert(KeysPressed, buf)
+ table.insert(keys, buf)
end, vim.api.nvim_create_namespace("logger"))
]]
- helpers.insert([[next lines]])
+ insert([[next lines]])
- exec_lua("vim.register_keystroke_callback(nil, vim.api.nvim_create_namespace('logger'))")
+ eq(1, exec_lua('return vim.on_key()'))
+ exec_lua("vim.on_key(nil, vim.api.nvim_create_namespace('logger'))")
+ eq(0, exec_lua('return vim.on_key()'))
- helpers.insert([[more lines]])
+ insert([[more lines]])
-- It has escape in the keys pressed
- eq('inext lines<ESC>', exec_lua [[return table.concat(KeysPressed, '')]])
+ eq('inext lines<ESC>', exec_lua [[return table.concat(keys, '')]])
end)
- it('should not call functions that error again.', function()
- helpers.insert([[hello world]])
+ it('skips any function that caused an error', function()
+ insert([[hello world]])
exec_lua [[
- KeysPressed = {}
+ keys = {}
- return vim.register_keystroke_callback(function(buf)
+ return vim.on_key(function(buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
- table.insert(KeysPressed, buf)
+ table.insert(keys, buf)
if buf == 'l' then
error("Dumb Error")
@@ -1929,35 +1958,30 @@ describe('lua stdlib', function()
end)
]]
- helpers.insert([[next lines]])
- helpers.insert([[more lines]])
+ insert([[next lines]])
+ insert([[more lines]])
-- Only the first letter gets added. After that we remove the callback
- eq('inext l', exec_lua [[ return table.concat(KeysPressed, '') ]])
+ eq('inext l', exec_lua [[ return table.concat(keys, '') ]])
end)
- it('should process mapped keys, not unmapped keys', function()
+ it('processes mapped keys, not unmapped keys', function()
exec_lua [[
- KeysPressed = {}
+ keys = {}
vim.cmd("inoremap hello world")
- vim.register_keystroke_callback(function(buf)
+ vim.on_key(function(buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
- table.insert(KeysPressed, buf)
+ table.insert(keys, buf)
end)
]]
+ insert("hello")
- helpers.insert("hello")
-
- local next_status = exec_lua [[
- return table.concat(KeysPressed, '')
- ]]
-
- eq("iworld<ESC>", next_status)
+ eq('iworld<ESC>', exec_lua[[return table.concat(keys, '')]])
end)
end)
@@ -2153,6 +2177,24 @@ describe('lua stdlib', function()
end)
end)
+ describe('vim.schedule_wrap', function()
+ it('preserves argument lists', function()
+ exec_lua [[
+ local fun = vim.schedule_wrap(function(kling, klang, klonk)
+ vim.rpcnotify(1, 'mayday_mayday', {a=kling, b=klang, c=klonk})
+ end)
+ fun("BOB", nil, "MIKE")
+ ]]
+ eq({'notification', 'mayday_mayday', {{a='BOB', c='MIKE'}}}, next_msg())
+
+ -- let's gooooo
+ exec_lua [[
+ vim.schedule_wrap(function(...) vim.rpcnotify(1, 'boogalo', select('#', ...)) end)(nil,nil,nil,nil)
+ ]]
+ eq({'notification', 'boogalo', {4}}, next_msg())
+ end)
+ end)
+
describe('vim.api.nvim_buf_call', function()
it('can access buf options', function()
local buf1 = meths.get_current_buf()
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
new file mode 100644
index 0000000000..4f28f84c01
--- /dev/null
+++ b/test/functional/lua/xdiff_spec.lua
@@ -0,0 +1,112 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local pcall_err = helpers.pcall_err
+
+describe('xdiff bindings', function()
+ before_each(function()
+ clear()
+ end)
+
+ describe('can diff text', function()
+ before_each(function()
+ exec_lua[[
+ a1 = 'Hello\n'
+ b1 = 'Helli\n'
+
+ a2 = 'Hello\nbye\nfoo\n'
+ b2 = 'Helli\nbye\nbar\nbaz\n'
+ ]]
+ end)
+
+ it('with no callback', function()
+
+ eq(
+ table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n'),
+ exec_lua("return vim.diff(a1, b1)")
+ )
+
+ eq(
+ table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ '@@ -3 +3,2 @@',
+ '-foo',
+ '+bar',
+ '+baz',
+ ''
+ }, '\n'),
+ exec_lua("return vim.diff(a2, b2)")
+ )
+
+ end)
+
+ it('with callback', function()
+ exec_lua([[on_hunk = function(sa, ca, sb, cb)
+ exp[#exp+1] = {sa, ca, sb, cb}
+ end]])
+
+ eq({{1, 1, 1, 1}}, exec_lua[[
+ exp = {}
+ assert(vim.diff(a1, b1, {on_hunk = on_hunk}) == nil)
+ return exp
+ ]])
+
+ eq({{1, 1, 1, 1}, {3, 1, 3, 2}}, exec_lua[[
+ exp = {}
+ assert(vim.diff(a2, b2, {on_hunk = on_hunk}) == nil)
+ return exp
+ ]])
+
+ -- gives higher precedence to on_hunk over result_type
+ eq({{1, 1, 1, 1}, {3, 1, 3, 2}}, exec_lua[[
+ exp = {}
+ assert(vim.diff(a2, b2, {on_hunk = on_hunk, result_type='indices'}) == nil)
+ return exp
+ ]])
+ end)
+
+ it('with error callback', function()
+ exec_lua([[on_hunk = function(sa, ca, sb, cb)
+ error('ERROR1')
+ end]])
+
+ eq([[Error executing lua: [string "<nvim>"]:0: error running function on_hunk: [string "<nvim>"]:0: ERROR1]],
+ pcall_err(exec_lua, [[vim.diff(a1, b1, {on_hunk = on_hunk})]]))
+ end)
+
+ it('with hunk_lines', function()
+ eq({{1, 1, 1, 1}},
+ exec_lua([[return vim.diff(a1, b1, {result_type = 'indices'})]]))
+
+ eq({{1, 1, 1, 1}, {3, 1, 3, 2}},
+ exec_lua([[return vim.diff(a2, b2, {result_type = 'indices'})]]))
+ end)
+
+ end)
+
+ it('can handle bad args', function()
+ eq([[Error executing lua: [string "<nvim>"]:0: Expected at least 2 arguments]],
+ pcall_err(exec_lua, [[vim.diff('a')]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: bad argument #1 to 'diff' (expected string)]],
+ pcall_err(exec_lua, [[vim.diff(1, 2)]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: bad argument #3 to 'diff' (expected table)]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', true)]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: unexpected key: bad_key]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = true })]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: on_hunk is not a function]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', { on_hunk = true })]]))
+
+ end)
+end)
diff --git a/test/functional/normal/meta_key_spec.lua b/test/functional/normal/meta_key_spec.lua
deleted file mode 100644
index 9f9fad67d2..0000000000
--- a/test/functional/normal/meta_key_spec.lua
+++ /dev/null
@@ -1,22 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local command = helpers.command
-local expect = helpers.expect
-
-describe('meta-keys-in-normal-mode', function()
- before_each(function()
- clear()
- end)
-
- it('ALT/META', function()
- -- Unmapped ALT-chords behave as Esc+c
- insert('hello')
- feed('0<A-x><M-x>')
- expect('llo')
- -- Mapped ALT-chord behaves as mapped.
- command('nnoremap <M-l> Ameta-l<Esc>')
- command('nnoremap <A-j> Aalt-j<Esc>')
- feed('<A-j><M-l>')
- expect('lloalt-jmeta-l')
- end)
-end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index eb5e284385..6620c9acef 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local meths = helpers.meths
local command = helpers.command
local clear = helpers.clear
@@ -354,13 +355,13 @@ describe('XDG-based defaults', function()
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup',
+ eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup//',
(meths.get_option('backupdir'):gsub('\\', '/')))
eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//',
(meths.get_option('directory')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo//',
(meths.get_option('undodir')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view//',
(meths.get_option('viewdir')):gsub('\\', '/'))
end)
end)
@@ -404,13 +405,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
@@ -424,13 +425,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
end)
end)
@@ -483,13 +484,13 @@ describe('XDG-based defaults', function()
.. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
), meths.get_option('runtimepath'))
- eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup',
+ eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
meths.get_option('backupdir'))
eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
meths.get_option('directory'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo',
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
meths.get_option('undodir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view',
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
meths.get_option('viewdir'))
end)
end)
@@ -510,8 +511,7 @@ describe('stdpath()', function()
eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t'))
eq('table', type(funcs.stdpath('config_dirs')))
eq('table', type(funcs.stdpath('data_dirs')))
- -- Check for crash. #8393
- eq(2, eval('1+1'))
+ assert_alive() -- Check for crash. #8393
end)
context('returns a String', function()
diff --git a/test/functional/options/tabstop_spec.lua b/test/functional/options/tabstop_spec.lua
index dc3ba38438..e34f678650 100644
--- a/test/functional/options/tabstop_spec.lua
+++ b/test/functional/options/tabstop_spec.lua
@@ -1,9 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local feed = helpers.feed
-local eq = helpers.eq
-local eval = helpers.eval
describe("'tabstop' option", function()
before_each(function()
@@ -18,6 +17,6 @@ describe("'tabstop' option", function()
-- Set 'tabstop' to a very high value.
-- Use feed(), not command(), to provoke crash.
feed(':set tabstop=3000000000<CR>')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua
index e09d93f7cc..c8b75e65fc 100644
--- a/test/functional/plugin/lsp/codelens_spec.lua
+++ b/test/functional/plugin/lsp/codelens_spec.lua
@@ -11,7 +11,7 @@ describe('vim.lsp.codelens', function()
after_each(helpers.clear)
it('on_codelens_stores_and_displays_lenses', function()
- local fake_uri = "file://fake/uri"
+ local fake_uri = "file:///fake/uri"
local bufnr = exec_lua([[
fake_uri = ...
local bufnr = vim.uri_to_bufnr(fake_uri)
@@ -32,7 +32,7 @@ describe('vim.lsp.codelens', function()
command = { title = 'Lens1', command = 'Dummy' }
},
}
- vim.lsp.codelens.on_codelens(nil, 'textDocument/codeLens', lenses, 1, bufnr)
+ vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
]], bufnr)
local stored_lenses = exec_lua('return vim.lsp.codelens.get(...)', bufnr)
@@ -58,5 +58,33 @@ describe('vim.lsp.codelens', function()
]], bufnr)
eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks)
+
+ end)
+ it('codelens uses client commands', function()
+ local fake_uri = "file:///fake/uri"
+ local cmd = exec_lua([[
+ fake_uri = ...
+ local bufnr = vim.uri_to_bufnr(fake_uri)
+ vim.fn.bufload(bufnr)
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'})
+ local lenses = {
+ {
+ range = {
+ start = { line = 0, character = 0, },
+ ['end'] = { line = 0, character = 8 }
+ },
+ command = { title = 'Lens1', command = 'Dummy' }
+ },
+ }
+ vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
+ local cmd_called = nil
+ vim.lsp.commands['Dummy'] = function(command)
+ cmd_called = command
+ end
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.lsp.codelens.run()
+ return cmd_called
+ ]], fake_uri)
+ eq({ command = 'Dummy', title = 'Lens1' }, cmd)
end)
end)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 962028e7e1..243ad6bdb8 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -9,7 +9,10 @@ describe('vim.lsp.diagnostic', function()
local fake_uri
before_each(function()
- clear()
+ clear {env={
+ NVIM_LUA_NOTRACK="1";
+ VIMRUNTIME=os.getenv"VIMRUNTIME";
+ }}
exec_lua [[
require('vim.lsp')
@@ -44,12 +47,12 @@ describe('vim.lsp.diagnostic', function()
count_of_extmarks_for_client = function(bufnr, client_id)
return #vim.api.nvim_buf_get_extmarks(
- bufnr, vim.lsp.diagnostic._get_diagnostic_namespace(client_id), 0, -1, {}
+ bufnr, vim.lsp.diagnostic.get_namespace(client_id), 0, -1, {}
)
end
]]
- fake_uri = "file://fake/uri"
+ fake_uri = "file:///fake/uri"
exec_lua([[
fake_uri = ...
@@ -86,39 +89,6 @@ describe('vim.lsp.diagnostic', function()
eq(2, #result[1])
eq('Diagnostic #1', result[1][1].message)
end)
- it('Can convert diagnostic to quickfix items format', function()
- local bufnr = exec_lua([[
- local fake_uri = ...
- return vim.uri_to_bufnr(fake_uri)
- ]], fake_uri)
- local result = exec_lua([[
- local bufnr = ...
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 2, 1, 2, 1),
- }, bufnr, 1
- )
- return vim.lsp.util.diagnostics_to_items(vim.lsp.diagnostic.get_all())
- ]], bufnr)
- local expected = {
- {
- bufnr = bufnr,
- col = 2,
- lnum = 2,
- text = 'Diagnostic #1',
- type = 'E'
- },
- {
- bufnr = bufnr,
- col = 2,
- lnum = 3,
- text = 'Diagnostic #2',
- type = 'E'
- },
- }
- eq(expected, result)
- end)
it('should be able to save and count a single client error', function()
eq(1, exec_lua [[
vim.lsp.diagnostic.save(
@@ -205,8 +175,8 @@ describe('vim.lsp.diagnostic', function()
make_warning("Warning 1", 2, 1, 2, 5),
}
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_1_diags }, 1)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_2_diags }, 2)
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -218,7 +188,7 @@ describe('vim.lsp.diagnostic', function()
-- Clear diagnostics from server 1, and make sure we have the right amount of stuff for client 2
eq({1, 1, 2, 0, 2}, exec_lua [[
- vim.lsp.diagnostic.clear(diagnostic_bufnr, 1)
+ vim.lsp.diagnostic.disable(diagnostic_bufnr, 1)
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -230,7 +200,7 @@ describe('vim.lsp.diagnostic', function()
-- Show diagnostics from server 1 again
eq(all_highlights, exec_lua([[
- vim.lsp.diagnostic.display(nil, diagnostic_bufnr, 1)
+ vim.lsp.diagnostic.enable(diagnostic_bufnr, 1)
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -241,6 +211,38 @@ describe('vim.lsp.diagnostic', function()
]]))
end)
+ it('should not display diagnostics when disabled', function()
+ eq({0, 2}, exec_lua [[
+ local server_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local server_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
+
+ vim.lsp.diagnostic.disable(diagnostic_bufnr, 1)
+
+ return {
+ count_of_extmarks_for_client(diagnostic_bufnr, 1),
+ count_of_extmarks_for_client(diagnostic_bufnr, 2),
+ }
+ ]])
+
+ eq({4, 0}, exec_lua [[
+ vim.lsp.diagnostic.enable(diagnostic_bufnr, 1)
+ vim.lsp.diagnostic.disable(diagnostic_bufnr, 2)
+
+ return {
+ count_of_extmarks_for_client(diagnostic_bufnr, 1),
+ count_of_extmarks_for_client(diagnostic_bufnr, 2),
+ }
+ ]])
+ end)
+
describe('reset', function()
it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
-- 1 Error (1)
@@ -258,8 +260,8 @@ describe('vim.lsp.diagnostic', function()
make_warning("Warning 1", 2, 1, 2, 5),
}
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_1_diags }, 1)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, { uri = fake_uri, diagnostics = server_2_diags }, 2)
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
return {
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
@@ -426,6 +428,32 @@ describe('vim.lsp.diagnostic', function()
end)
end)
end)
+
+ it('maintains LSP information when translating diagnostics', function()
+ local result = exec_lua [[
+ local diagnostics = {
+ make_error("Error 1", 1, 1, 1, 5),
+ }
+
+ diagnostics[1].code = 42
+ diagnostics[1].tags = {"foo", "bar"}
+ diagnostics[1].data = "Hello world"
+
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = diagnostics,
+ }, {client_id=1})
+
+ return {
+ vim.diagnostic.get(diagnostic_bufnr, {lnum=1})[1],
+ vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)[1],
+ }
+ ]]
+ eq({code = 42, tags = {"foo", "bar"}, data = "Hello world"}, result[1].user_data.lsp)
+ eq(42, result[2].code)
+ eq({"foo", "bar"}, result[2].tags)
+ eq("Hello world", result[2].data)
+ end)
end)
describe("vim.lsp.diagnostic.get_line_diagnostics", function()
@@ -435,14 +463,14 @@ describe('vim.lsp.diagnostic', function()
it('should return all diagnostics when no severity is supplied', function()
eq(2, exec_lua [[
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 5),
make_error("Error On Other Line", 2, 1, 1, 5),
}
- }, 1)
+ }, {client_id=1})
return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)
]])
@@ -450,7 +478,7 @@ describe('vim.lsp.diagnostic', function()
it('should return only requested diagnostics when severity_limit is supplied', function()
eq(2, exec_lua [[
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error("Error 1", 1, 1, 1, 5),
@@ -458,7 +486,7 @@ describe('vim.lsp.diagnostic', function()
make_information("Ignored information", 1, 1, 2, 5),
make_error("Error On Other Line", 2, 1, 1, 5),
}
- }, 1)
+ }, {client_id=1})
return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1, { severity_limit = "Warning" })
]])
@@ -470,12 +498,12 @@ describe('vim.lsp.diagnostic', function()
exec_lua [[
vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
virtual_text = function() return true end,
- })(nil, nil, {
+ })(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -487,12 +515,12 @@ describe('vim.lsp.diagnostic', function()
exec_lua [[
vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
virtual_text = function() return false end,
- })(nil, nil, {
+ })(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -509,12 +537,12 @@ describe('vim.lsp.diagnostic', function()
exec_lua [[
vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
update_in_insert = false,
- })(nil, nil, {
+ })(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -543,20 +571,20 @@ describe('vim.lsp.diagnostic', function()
})
-- Count how many times we call display.
- SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text
+ SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
DisplayCount = 0
- vim.lsp.diagnostic.set_virtual_text = function(...)
+ vim.diagnostic._set_virtual_text = function(...)
DisplayCount = DisplayCount + 1
return SetVirtualTextOriginal(...)
end
- PublishDiagnostics(nil, nil, {
+ PublishDiagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -605,12 +633,12 @@ describe('vim.lsp.diagnostic', function()
return SetVirtualTextOriginal(...)
end
- PublishDiagnostics(nil, nil, {
+ PublishDiagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -647,12 +675,12 @@ describe('vim.lsp.diagnostic', function()
exec_lua [[
vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
update_in_insert = true,
- })(nil, nil, {
+ })(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
]]
@@ -677,17 +705,17 @@ describe('vim.lsp.diagnostic', function()
},
})
- PublishDiagnostics(nil, nil, {
+ PublishDiagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
return vim.api.nvim_buf_get_extmarks(
diagnostic_bufnr,
- vim.lsp.diagnostic._get_diagnostic_namespace(1),
+ vim.lsp.diagnostic.get_namespace(1),
0,
-1,
{ details = true }
@@ -714,17 +742,17 @@ describe('vim.lsp.diagnostic', function()
end,
})
- PublishDiagnostics(nil, nil, {
+ PublishDiagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
return vim.api.nvim_buf_get_extmarks(
diagnostic_bufnr,
- vim.lsp.diagnostic._get_diagnostic_namespace(1),
+ vim.lsp.diagnostic.get_namespace(1),
0,
-1,
{ details = true }
@@ -747,12 +775,12 @@ describe('vim.lsp.diagnostic', function()
},
})
- PublishDiagnostics(nil, nil, {
+ PublishDiagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_warning('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, 1
+ }, {client_id=1}
)
return count_of_extmarks_for_client(diagnostic_bufnr, 1)
@@ -766,6 +794,40 @@ describe('vim.lsp.diagnostic', function()
eq(1, get_extmark_count_with_severity("Warning"))
eq(1, get_extmark_count_with_severity("Hint"))
end)
+
+ it('correctly handles UTF-16 offsets', function()
+ local line = "All 💼 and no 🎉 makes Jack a dull 👦"
+ local result = exec_lua([[
+ local line = ...
+ local client_id = vim.lsp.start_client {
+ cmd_env = {
+ NVIM_LUA_NOTRACK = "1";
+ };
+ cmd = {
+ vim.v.progpath, '-es', '-u', 'NONE', '--headless'
+ };
+ offset_encoding = "utf-16";
+ }
+
+ vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line})
+
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
+ uri = fake_uri,
+ diagnostics = {
+ make_error('UTF-16 Diagnostic', 0, 7, 0, 8),
+ }
+ }, {client_id=client_id}
+ )
+
+ local diags = vim.diagnostic.get(diagnostic_bufnr)
+ vim.lsp.stop_client(client_id)
+ vim.lsp._vim_exit_handler()
+ return diags
+ ]], line)
+ eq(1, #result)
+ eq(exec_lua([[return vim.str_byteindex(..., 7, true)]], line), result[1].col)
+ eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col)
+ end)
end)
describe('lsp.util.show_line_diagnostics', function()
@@ -838,10 +900,10 @@ describe('vim.lsp.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = diagnostics
- }, 1
+ }, {client_id=1}
)
vim.lsp.diagnostic.set_signs(diagnostics, diagnostic_bufnr, 1)
@@ -863,13 +925,13 @@ describe('vim.lsp.diagnostic', function()
local loc_list = exec_lua [[
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Farther Diagnostic', 4, 4, 4, 4),
make_error('Lower Diagnostic', 1, 1, 1, 1),
}
- }, 1
+ }, {client_id=1}
)
vim.lsp.diagnostic.set_loclist()
@@ -884,20 +946,20 @@ describe('vim.lsp.diagnostic', function()
local loc_list = exec_lua [[
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_error('Lower Diagnostic', 1, 1, 1, 1),
}
- }, 1
+ }, {client_id=1}
)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, nil, {
+ vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = {
make_warning('Farther Diagnostic', 4, 4, 4, 4),
}
- }, 2
+ }, {client_id=2}
)
vim.lsp.diagnostic.set_loclist()
diff --git a/test/functional/plugin/lsp/snippet_spec.lua b/test/functional/plugin/lsp/snippet_spec.lua
new file mode 100644
index 0000000000..4e127743eb
--- /dev/null
+++ b/test/functional/plugin/lsp/snippet_spec.lua
@@ -0,0 +1,152 @@
+local helpers = require('test.functional.helpers')(after_each)
+local snippet = require('vim.lsp._snippet')
+
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+
+describe('vim.lsp._snippet', function()
+ before_each(helpers.clear)
+ after_each(helpers.clear)
+
+ local parse = function(...)
+ return exec_lua('return require("vim.lsp._snippet").parse(...)', ...)
+ end
+
+ it('should parse only text', function()
+ eq({
+ type = snippet.NodeType.SNIPPET,
+ children = {
+ {
+ type = snippet.NodeType.TEXT,
+ raw = 'TE\\$\\}XT',
+ esc = 'TE$}XT'
+ }
+ }
+ }, parse('TE\\$\\}XT'))
+ end)
+
+ it('should parse tabstop', function()
+ eq({
+ type = snippet.NodeType.SNIPPET,
+ children = {
+ {
+ type = snippet.NodeType.TABSTOP,
+ tabstop = 1,
+ },
+ {
+ type = snippet.NodeType.TABSTOP,
+ tabstop = 2,
+ }
+ }
+ }, parse('$1${2}'))
+ end)
+
+ it('should parse placeholders', function()
+ eq({
+ type = snippet.NodeType.SNIPPET,
+ children = {
+ {
+ type = snippet.NodeType.PLACEHOLDER,
+ tabstop = 1,
+ children = {
+ {
+ type = snippet.NodeType.PLACEHOLDER,
+ tabstop = 2,
+ children = {
+ {
+ type = snippet.NodeType.TEXT,
+ raw = 'TE\\$\\}XT',
+ esc = 'TE$}XT'
+ },
+ {
+ type = snippet.NodeType.TABSTOP,
+ tabstop = 3,
+ },
+ {
+ type = snippet.NodeType.TABSTOP,
+ tabstop = 1,
+ transform = {
+ type = snippet.NodeType.TRANSFORM,
+ pattern = 'regex',
+ option = 'i',
+ format = {
+ {
+ type = snippet.NodeType.FORMAT,
+ capture_index = 1,
+ modifier = 'upcase'
+ }
+ }
+ },
+ },
+ {
+ type = snippet.NodeType.TEXT,
+ raw = 'TE\\$\\}XT',
+ esc = 'TE$}XT'
+ },
+ }
+ }
+ }
+ },
+ }
+ }, parse('${1:${2:TE\\$\\}XT$3${1/regex/${1:/upcase}/i}TE\\$\\}XT}}'))
+ end)
+
+ it('should parse variables', function()
+ eq({
+ type = snippet.NodeType.SNIPPET,
+ children = {
+ {
+ type = snippet.NodeType.VARIABLE,
+ name = 'VAR',
+ },
+ {
+ type = snippet.NodeType.VARIABLE,
+ name = 'VAR',
+ },
+ {
+ type = snippet.NodeType.VARIABLE,
+ name = 'VAR',
+ children = {
+ {
+ type = snippet.NodeType.TABSTOP,
+ tabstop = 1,
+ }
+ }
+ },
+ {
+ type = snippet.NodeType.VARIABLE,
+ name = 'VAR',
+ transform = {
+ type = snippet.NodeType.TRANSFORM,
+ pattern = 'regex',
+ format = {
+ {
+ type = snippet.NodeType.FORMAT,
+ capture_index = 1,
+ modifier = 'upcase',
+ }
+ }
+ }
+ },
+ }
+ }, parse('$VAR${VAR}${VAR:$1}${VAR/regex/${1:/upcase}/}'))
+ end)
+
+ it('should parse choice', function()
+ eq({
+ type = snippet.NodeType.SNIPPET,
+ children = {
+ {
+ type = snippet.NodeType.CHOICE,
+ tabstop = 1,
+ items = {
+ ',',
+ '|'
+ }
+ }
+ }
+ }, parse('${1|\\,,\\||}'))
+ end)
+
+end)
+
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 508a9f2aed..572573a3a6 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -6,6 +6,7 @@ local buf_lines = helpers.buf_lines
local dedent = helpers.dedent
local exec_lua = helpers.exec_lua
local eq = helpers.eq
+local matches = helpers.matches
local pcall_err = helpers.pcall_err
local pesc = helpers.pesc
local insert = helpers.insert
@@ -14,6 +15,7 @@ local retry = helpers.retry
local NIL = helpers.NIL
local read_file = require('test.helpers').read_file
local write_file = require('test.helpers').write_file
+local isCI = helpers.isCI
-- Use these to get access to a coroutine so that I can run async tests and use
-- yield.
@@ -216,7 +218,7 @@ describe('LSP', function()
it('should run correctly', function()
local expected_handlers = {
- {NIL, "test", {}, 1};
+ {NIL, {}, {method="test", client_id=1}};
}
test_rpc_server {
test_name = "basic_init";
@@ -241,7 +243,7 @@ describe('LSP', function()
it('should fail', function()
local expected_handlers = {
- {NIL, "test", {}, 1};
+ {NIL, {}, {method="test", client_id=1}};
}
test_rpc_server {
test_name = "basic_init";
@@ -262,15 +264,15 @@ describe('LSP', function()
end)
it('should succeed with manual shutdown', function()
- if 'openbsd' == helpers.uname() then
- pending('hangs the build on openbsd #14028, re-enable with freeze timeout #14204')
+ if isCI() then
+ pending('hangs the build on CI #14028, re-enable with freeze timeout #14204')
return
elseif helpers.skip_fragile(pending) then
return
end
local expected_handlers = {
- {NIL, "shutdown", {}, 1, NIL};
- {NIL, "test", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="test", client_id=1}};
}
test_rpc_server {
test_name = "basic_init";
@@ -292,12 +294,12 @@ describe('LSP', function()
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "workspace/configuration", { items = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, { items = {
{ section = "testSetting1" };
{ section = "testSetting2" };
- }}, 1};
- {NIL, "start", {}, 1};
+ }}, { method="workspace/configuration", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -309,9 +311,9 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'start' then
exec_lua([=[
local client = vim.lsp.get_client_by_id(TEST_RPC_CLIENT_ID)
client.config.settings = {
@@ -319,13 +321,13 @@ describe('LSP', function()
testSetting2 = false;
}]=])
end
- if method == 'workspace/configuration' then
- local result = exec_lua([=[
+ if ctx.method == 'workspace/configuration' then
+ local server_result = exec_lua([=[
local method, params = ...
- return require'vim.lsp.handlers'['workspace/configuration'](err, method, params, TEST_RPC_CLIENT_ID)]=], method, params)
- client.notify('workspace/configuration', result)
+ return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=], ctx.method, result)
+ client.notify('workspace/configuration', server_result)
end
- if method == 'shutdown' then
+ if ctx.method == 'shutdown' then
client.stop()
end
end;
@@ -335,19 +337,19 @@ describe('LSP', function()
clear_notrace()
fake_lsp_server_setup('workspace/configuration no settings')
eq({ NIL, NIL, }, exec_lua [[
- local params = {
+ local result = {
items = {
{section = 'foo'},
{section = 'bar'},
}
}
- return vim.lsp.handlers['workspace/configuration'](nil, nil, params, TEST_RPC_CLIENT_ID)
+ return vim.lsp.handlers['workspace/configuration'](nil, result, {client_id=TEST_RPC_CLIENT_ID})
]])
end)
it('should verify capabilities sent', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
}
test_rpc_server {
test_name = "basic_check_capabilities";
@@ -371,7 +373,7 @@ describe('LSP', function()
it('client.supports_methods() should validate capabilities', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
}
test_rpc_server {
test_name = "capabilities_for_client_supports_method";
@@ -405,7 +407,7 @@ describe('LSP', function()
it('should call unsupported_method when trying to call an unsupported method', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
}
test_rpc_server {
test_name = "capabilities_for_client_supports_method";
@@ -413,7 +415,8 @@ describe('LSP', function()
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
- vim.lsp.handlers['textDocument/typeDefinition'] = function(err, method)
+ vim.lsp.handlers['textDocument/typeDefinition'] = function(err, result, ctx)
+ local method = ctx.method
vim.lsp._last_lsp_handler = { err = err; method = method }
end
vim.lsp._unsupported_method = function(method)
@@ -446,7 +449,7 @@ describe('LSP', function()
it('shouldn\'t call unsupported_method when no client and trying to call an unsupported method', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
}
test_rpc_server {
test_name = "capabilities_for_client_supports_method";
@@ -479,8 +482,8 @@ describe('LSP', function()
it('should not send didOpen if the buffer closes before init', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
}
local client
test_rpc_server {
@@ -511,9 +514,9 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -522,9 +525,9 @@ describe('LSP', function()
it('should check the body sent attaching before init', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -554,12 +557,12 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -568,9 +571,9 @@ describe('LSP', function()
it('should check the body sent attaching after init', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -597,12 +600,12 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -611,9 +614,9 @@ describe('LSP', function()
it('should check the body and didChange full', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -640,8 +643,8 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
"boop";
@@ -649,8 +652,8 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -659,9 +662,9 @@ describe('LSP', function()
it('should check the body and didChange full with noeol', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -689,8 +692,8 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
"boop";
@@ -698,8 +701,8 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -708,9 +711,9 @@ describe('LSP', function()
it('should check the body and didChange incremental', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -738,8 +741,8 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
"123boop";
@@ -747,8 +750,8 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -758,9 +761,9 @@ describe('LSP', function()
-- TODO(askhan) we don't support full for now, so we can disable these tests.
pending('should check the body and didChange incremental normal mode editing', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -787,13 +790,13 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
helpers.command("normal! 1Go")
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -802,9 +805,9 @@ describe('LSP', function()
it('should check the body and didChange full with 2 changes', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -831,8 +834,8 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
"321";
@@ -843,8 +846,8 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -853,9 +856,9 @@ describe('LSP', function()
it('should check the body and didChange full lifecycle', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -882,8 +885,8 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- if method == 'start' then
+ on_handler = function(err, result,ctx)
+ if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
"321";
@@ -895,8 +898,8 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -907,9 +910,9 @@ describe('LSP', function()
describe("parsing tests", function()
it('should handle invalid content-length correctly', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "start", {}, 1};
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -924,22 +927,22 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
end;
}
end)
it('should not trim vim.NIL from the end of a list', function()
local expected_handlers = {
- {NIL, "shutdown", {}, 1};
- {NIL, "finish", {}, 1};
- {NIL, "workspace/executeCommand", {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL,{
arguments = { "EXTRACT_METHOD", {metadata = {}}, 3, 0, 6123, NIL },
command = "refactor.perform",
title = "EXTRACT_METHOD"
- }, 1};
- {NIL, "start", {}, 1};
+ }, {method="workspace/executeCommand", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
@@ -963,9 +966,9 @@ describe('LSP', function()
eq(0, code, "exit code", fake_lsp_logfile)
eq(0, signal, "exit signal", fake_lsp_logfile)
end;
- on_handler = function(err, method, params, client_id)
- eq(table.remove(expected_handlers), {err, method, params, client_id}, "expected handler")
- if method == 'finish' then
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
client.stop()
end
end;
@@ -1014,31 +1017,6 @@ describe('LSP', function()
}
end
- it('highlight groups', function()
- eq({
- 'LspDiagnosticsDefaultError',
- 'LspDiagnosticsDefaultHint',
- 'LspDiagnosticsDefaultInformation',
- 'LspDiagnosticsDefaultWarning',
- 'LspDiagnosticsFloatingError',
- 'LspDiagnosticsFloatingHint',
- 'LspDiagnosticsFloatingInformation',
- 'LspDiagnosticsFloatingWarning',
- 'LspDiagnosticsSignError',
- 'LspDiagnosticsSignHint',
- 'LspDiagnosticsSignInformation',
- 'LspDiagnosticsSignWarning',
- 'LspDiagnosticsUnderlineError',
- 'LspDiagnosticsUnderlineHint',
- 'LspDiagnosticsUnderlineInformation',
- 'LspDiagnosticsUnderlineWarning',
- 'LspDiagnosticsVirtualTextError',
- 'LspDiagnosticsVirtualTextHint',
- 'LspDiagnosticsVirtualTextInformation',
- 'LspDiagnosticsVirtualTextWarning',
- }, exec_lua([[require'vim.lsp'; return vim.fn.getcompletion('Lsp', 'highlight')]]))
- end)
-
describe('apply_text_edits', function()
before_each(function()
insert(dedent([[
@@ -1088,6 +1066,30 @@ describe('LSP', function()
'å å ɧ 汉语 ↥ 🤦 🦄';
}, buf_lines(1))
end)
+ it('applies complex edits (reversed range)', function()
+ local edits = {
+ make_edit(0, 0, 0, 0, {"", "12"});
+ make_edit(0, 0, 0, 0, {"3", "foo"});
+ make_edit(0, 1, 0, 1, {"bar", "123"});
+ make_edit(0, #"First line of text", 0, #"First ", {"guy"});
+ make_edit(1, #'Second', 1, 0, {"baz"});
+ make_edit(2, #"Third", 2, #'Th', {"e next"});
+ make_edit(3, #"Fourth", 3, #'', {"another line of text", "before this"});
+ make_edit(3, #"Fourth line of text", 3, #'Fourth', {"!"});
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ '';
+ '123';
+ 'fooFbar';
+ '123irst guy';
+ 'baz line of text';
+ 'The next line of text';
+ 'another line of text';
+ 'before this!';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ end)
it('applies non-ASCII characters edits', function()
local edits = {
make_edit(4, 3, 4, 4, {"ä"});
@@ -1116,6 +1118,86 @@ describe('LSP', function()
}, buf_lines(1))
end)
+ describe('cursor position', function()
+ it('don\'t fix the cursor if the range contains the cursor', function()
+ funcs.nvim_win_set_cursor(0, { 2, 6 })
+ local edits = {
+ make_edit(1, 0, 1, 19, 'Second line of text')
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ 'Second line of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ eq({ 2, 6 }, funcs.nvim_win_get_cursor(0))
+ end)
+
+ it('fix the cursor to the valid column if the content was removed', function()
+ funcs.nvim_win_set_cursor(0, { 2, 6 })
+ local edits = {
+ make_edit(1, 0, 1, 19, '')
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ '';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ end)
+
+ it('fix the cursor row', function()
+ funcs.nvim_win_set_cursor(0, { 3, 0 })
+ local edits = {
+ make_edit(1, 0, 2, 0, '')
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ end)
+
+ it('fix the cursor col', function()
+ funcs.nvim_win_set_cursor(0, { 2, 11 })
+ local edits = {
+ make_edit(1, 7, 1, 11, '')
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ 'Second of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ eq({ 2, 7 }, funcs.nvim_win_get_cursor(0))
+ end)
+
+ it('fix the cursor row and col', function()
+ funcs.nvim_win_set_cursor(0, { 2, 12 })
+ local edits = {
+ make_edit(0, 11, 1, 12, '')
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ eq({
+ 'First line of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'å å ɧ 汉语 ↥ 🤦 🦄';
+ }, buf_lines(1))
+ eq({ 1, 11 }, funcs.nvim_win_get_cursor(0))
+ end)
+ end)
+
describe('with LSP end line after what Vim considers to be the end line', function()
it('applies edits when the last linebreak is considered a new line', function()
local edits = {
@@ -1149,14 +1231,14 @@ describe('LSP', function()
make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄")
},
textDocument = {
- uri = "file://fake/uri";
+ uri = "file:///fake/uri";
version = editVersion
}
}
end
before_each(function()
target_bufnr = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
local lines = {"1st line of text", "2nd line of 语text"}
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
return bufnr
@@ -1223,7 +1305,7 @@ describe('LSP', function()
label = nil;
edit = {};
}
- return vim.lsp.handlers['workspace/applyEdit'](nil, nil, apply_edit)
+ return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit)
]])
end)
end)
@@ -1236,7 +1318,7 @@ describe('LSP', function()
make_edit(row, 0, row, 1000, new_line)
},
textDocument = {
- uri = "file://fake/uri";
+ uri = "file:///fake/uri";
version = editVersion
}
}
@@ -1254,7 +1336,7 @@ describe('LSP', function()
before_each(function()
local ret = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
local lines = {
"Original Line #1",
"Original Line #2"
@@ -1441,8 +1523,10 @@ describe('LSP', function()
{ label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', insertTextFormat=2, textEdit={} },
-- nested snippet tokens
{ label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', insertTextFormat=2, textEdit={} },
+ -- braced tabstop
+ { label='foocar', sortText="j", insertText='foodar()${0}', insertTextFormat=2, textEdit={} },
-- plain text
- { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} },
+ { label='foocar', sortText="k", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} },
}
local completion_list_items = {items=completion_list}
local expected = {
@@ -1454,8 +1538,9 @@ describe('LSP', function()
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="f", textEdit={newText='foobar'} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar(place holder, more ...holder{})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="g", insertText='foodar', insertTextFormat=2, textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ1, var2 *typ2) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ2,typ3 tail) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(${1:var1})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(var1 typ2 tail) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar()', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="j", insertText='foodar()${0}', insertTextFormat=2, textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foodar(${1:var1})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="k", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } },
}
eq(expected, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], completion_list, prefix))
@@ -1534,19 +1619,19 @@ describe('LSP', function()
it('Convert Location[] to items', function()
local expected = {
{
- filename = 'fake/uri',
+ filename = '/fake/uri',
lnum = 1,
col = 3,
text = 'testing'
},
}
local actual = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
local lines = {"testing", "123"}
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
local locations = {
{
- uri = 'file://fake/uri',
+ uri = 'file:///fake/uri',
range = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
@@ -1560,14 +1645,14 @@ describe('LSP', function()
it('Convert LocationLink[] to items', function()
local expected = {
{
- filename = 'fake/uri',
+ filename = '/fake/uri',
lnum = 1,
col = 3,
text = 'testing'
},
}
local actual = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
local lines = {"testing", "123"}
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
local locations = {
@@ -1781,14 +1866,14 @@ describe('LSP', function()
local expected = {
{
col = 1,
- filename = 'test_a',
+ filename = '/test_a',
kind = 'File',
lnum = 2,
text = '[File] TestA'
},
{
col = 1,
- filename = 'test_b',
+ filename = '/test_b',
kind = 'Module',
lnum = 4,
text = '[Module] TestB'
@@ -1811,7 +1896,7 @@ describe('LSP', function()
line = 2
}
},
- uri = "file://test_a"
+ uri = "file:///test_a"
},
contanerName = "TestAContainer"
},
@@ -1830,7 +1915,7 @@ describe('LSP', function()
line = 4
}
},
- uri = "file://test_b"
+ uri = "file:///test_b"
},
contanerName = "TestBContainer"
}
@@ -1869,7 +1954,7 @@ describe('LSP', function()
before_each(function()
target_bufnr = exec_lua [[
- local bufnr = vim.uri_to_bufnr("file://fake/uri")
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
local lines = {"1st line of text", "å å ɧ 汉语 ↥ 🤦 🦄"}
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
return bufnr
@@ -1878,7 +1963,7 @@ describe('LSP', function()
local location = function(start_line, start_char, end_line, end_char)
return {
- uri = "file://fake/uri",
+ uri = "file:///fake/uri",
range = {
start = { line = start_line, character = start_char },
["end"] = { line = end_line, character = end_char },
@@ -1903,7 +1988,7 @@ describe('LSP', function()
it('jumps to a LocationLink', function()
local pos = jump({
- targetUri = "file://fake/uri",
+ targetUri = "file:///fake/uri",
targetSelectionRange = {
start = { line = 0, character = 4 },
["end"] = { line = 0, character = 4 },
@@ -1937,6 +2022,83 @@ describe('LSP', function()
end)
end)
+ describe('lsp.util.make_floating_popup_options', function()
+ before_each(function()
+ exec_lua [[
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
+ local winheight = vim.fn.winheight(0)
+ for i = 1, winheight do
+ vim.api.nvim_buf_set_lines(bufnr, 0, 0, false, {''})
+ end
+ vim.api.nvim_win_set_buf(0, bufnr)
+ vim.api.nvim_win_set_cursor(0, {winheight, 0})
+ ]]
+ end)
+
+ local function popup_row(opts)
+ return exec_lua([[
+ return vim.lsp.util.make_floating_popup_options(...).row
+ ]], 2, 2, opts)
+ end
+
+ local err_pattern = "^Error executing lua: %.%.%./util%.lua:0: invalid floating preview border: .*%. :help vim%.api%.nvim_open_win%(%)$"
+
+ it('calculates default border height correctly', function()
+ eq(0, popup_row())
+ end)
+
+ it('calculates string border height correctly', function()
+ eq(0, popup_row({border = 'none'}))
+ eq(-2, popup_row({border = 'single'}))
+ eq(-2, popup_row({border = 'double'}))
+ eq(-2, popup_row({border = 'rounded'}))
+ eq(-2, popup_row({border = 'solid'}))
+ eq(-1, popup_row({border = 'shadow'}))
+ end)
+
+ it('error on invalid string border', function()
+ matches(err_pattern, pcall_err(popup_row, {border = ''}))
+ matches(err_pattern, pcall_err(popup_row, {border = 'invalid'}))
+ end)
+
+ it('error on invalid array border length', function()
+ matches(err_pattern, pcall_err(popup_row, {border = {}}))
+ matches(err_pattern, pcall_err(popup_row, {border = {'', '', ''}}))
+ matches(err_pattern, pcall_err(popup_row, {border = {'', '', '', '', ''}}))
+ end)
+
+ it('error on invalid array border member type', function()
+ matches(err_pattern, pcall_err(popup_row, {border = {0}}))
+ end)
+
+ it('calculates 8-array border height correctly', function()
+ eq(0, popup_row({border = {'', '', '', '', '', '', '', ''}}))
+ eq(-2, popup_row({border = {'', '~', '', '~', '', '~', '', '~'}}))
+ eq(-1, popup_row({border = {'', '', '', '~', '', '~', '', ''}}))
+ eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}, '', ''}}))
+ end)
+
+ it('calculates 4-array border height correctly', function()
+ eq(0, popup_row({border = {'', '', '', ''}}))
+ eq(-2, popup_row({border = {'', '~', '', '~'}}))
+ eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', ''}}))
+ end)
+
+ it('calculates 2-array border height correctly', function()
+ eq(0, popup_row({border = {'', ''}}))
+ eq(-2, popup_row({border = {'', '~'}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}}}))
+ end)
+
+ it('calculates 1-array border height correctly', function()
+ eq(0, popup_row({border = {''}}))
+ eq(-2, popup_row({border = {'~'}}))
+ eq(-2, popup_row({border = {{'~', 'NormalFloat'}}}))
+ end)
+ end)
+
describe('lsp.util._make_floating_popup_size', function()
before_each(function()
exec_lua [[ contents =
@@ -1955,6 +2117,12 @@ describe('LSP', function()
end)
end)
+ describe('lsp.util.trim.trim_empty_lines', function()
+ it('properly trims empty lines', function()
+ eq({{"foo", "bar"}}, exec_lua[[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]])
+ end)
+ end)
+
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, softtabstop)
exec_lua(string.format([[
@@ -1973,7 +2141,7 @@ describe('LSP', function()
describe('vim.lsp.buf.outgoing_calls', function()
it('does nothing for an empty response', function()
local qflist_count = exec_lua([=[
- require'vim.lsp.handlers'['callHierarchy/outgoingCalls']()
+ require'vim.lsp.handlers'['callHierarchy/outgoingCalls'](nil, nil, {}, nil)
return #vim.fn.getqflist()
]=])
eq(0, qflist_count)
@@ -2020,14 +2188,16 @@ describe('LSP', function()
}
} }
local handler = require'vim.lsp.handlers'['callHierarchy/outgoingCalls']
- handler(nil, nil, rust_analyzer_response)
+ handler(nil, rust_analyzer_response, {})
return vim.fn.getqflist()
]=])
local expected = { {
bufnr = 2,
col = 5,
+ end_col = 0,
lnum = 4,
+ end_lnum = 0,
module = "",
nr = 0,
pattern = "",
@@ -2044,7 +2214,7 @@ describe('LSP', function()
describe('vim.lsp.buf.incoming_calls', function()
it('does nothing for an empty response', function()
local qflist_count = exec_lua([=[
- require'vim.lsp.handlers'['callHierarchy/incomingCalls']()
+ require'vim.lsp.handlers'['callHierarchy/incomingCalls'](nil, nil, {})
return #vim.fn.getqflist()
]=])
eq(0, qflist_count)
@@ -2092,14 +2262,16 @@ describe('LSP', function()
} }
local handler = require'vim.lsp.handlers'['callHierarchy/incomingCalls']
- handler(nil, nil, rust_analyzer_response)
+ handler(nil, rust_analyzer_response, {})
return vim.fn.getqflist()
]=])
local expected = { {
bufnr = 2,
col = 5,
+ end_col = 0,
lnum = 4,
+ end_lnum = 0,
module = "",
nr = 0,
pattern = "",
@@ -2112,4 +2284,149 @@ describe('LSP', function()
eq(expected, qflist)
end)
end)
+
+ describe('vim.lsp.buf.rename', function()
+ for _, test in ipairs({
+ {
+ it = "does not attempt to rename on nil response",
+ name = "prepare_rename_nil",
+ expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ },
+ },
+ {
+ it = "handles prepareRename placeholder response",
+ name = "prepare_rename_placeholder",
+ expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, NIL, {method="textDocument/rename", client_id=1, bufnr=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ },
+ expected_text = "placeholder", -- see fake lsp response
+ },
+ {
+ it = "handles range response",
+ name = "prepare_rename_range",
+ expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, NIL, {method="textDocument/rename", client_id=1, bufnr=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ },
+ expected_text = "line", -- see test case and fake lsp response
+ },
+ {
+ it = "handles error",
+ name = "prepare_rename_error",
+ expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, NIL, {method="textDocument/rename", client_id=1, bufnr=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ },
+ expected_text = "two", -- see test case
+ },
+ }) do
+ it(test.it, function()
+ local client
+ test_rpc_server {
+ test_name = test.name;
+ on_init = function(_client)
+ client = _client
+ eq(true, client.resolved_capabilities().rename)
+ end;
+ on_setup = function()
+ exec_lua([=[
+ local bufnr = vim.api.nvim_get_current_buf()
+ lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
+ vim.lsp._stubs = {}
+ vim.fn.input = function(prompt, text)
+ vim.lsp._stubs.input_prompt = prompt
+ vim.lsp._stubs.input_text = text
+ return 'renameto' -- expect this value in fake lsp
+ end
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'', 'this is line two'})
+ vim.fn.cursor(2, 13) -- the space between "line" and "two"
+ ]=])
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ on_handler = function(err, result, ctx)
+ -- Don't compare & assert params, they're not relevant for the testcase
+ -- This allows us to be lazy and avoid declaring them
+ ctx.params = nil
+
+ eq(table.remove(test.expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'start' then
+ exec_lua("vim.lsp.buf.rename()")
+ end
+ if ctx.method == 'shutdown' then
+ if test.expected_text then
+ eq("New Name: ", exec_lua("return vim.lsp._stubs.input_prompt"))
+ eq(test.expected_text, exec_lua("return vim.lsp._stubs.input_text"))
+ end
+ client.stop()
+ end
+ end;
+ }
+ end)
+ end
+ end)
+
+ describe('vim.lsp.buf.code_action', function()
+ it('Calls client side command if available', function()
+ local client
+ local expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ }
+ test_rpc_server {
+ test_name = 'code_action_with_resolve',
+ on_init = function(client_)
+ client = client_
+ end,
+ on_setup = function()
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end,
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx})
+ if ctx.method == 'start' then
+ exec_lua([[
+ vim.lsp.commands['dummy1'] = function(cmd)
+ vim.lsp.commands['dummy2'] = function()
+ end
+ end
+ local bufnr = vim.api.nvim_get_current_buf()
+ vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
+ vim.fn.inputlist = function()
+ return 1
+ end
+ vim.lsp.buf.code_action()
+ ]])
+ elseif ctx.method == 'shutdown' then
+ eq('function', exec_lua[[return type(vim.lsp.commands['dummy2'])]])
+ client.stop()
+ end
+ end
+ }
+ end)
+ end)
+ describe('vim.lsp.commands', function()
+ it('Accepts only string keys', function()
+ matches(
+ '.*The key for commands in `vim.lsp.commands` must be a string',
+ pcall_err(exec_lua, 'vim.lsp.commands[1] = function() end')
+ )
+ end)
+ it('Accepts only function values', function()
+ matches(
+ '.*Command added to `vim.lsp.commands` must be a function',
+ pcall_err(exec_lua, 'vim.lsp.commands.dummy = 10')
+ )
+ end)
+ end)
end)
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index 5663f248bf..a4d78682ad 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -2161,6 +2161,12 @@ describe('plugin/shada.vim', function()
reset()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
+
+ -- Need to set nohidden so that the buffer containing 'fname' is not unloaded
+ -- after loading 'fname_tmp', otherwise the '++opt not supported' test below
+ -- won't work since the BufReadCmd autocmd won't be triggered.
+ nvim_command('set nohidden')
+
nvim_command('edit ' .. fname)
eq({
'History entry with timestamp ' .. epoch .. ':',
diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua
index e5e21f11a6..986db96a18 100644
--- a/test/functional/provider/clipboard_spec.lua
+++ b/test/functional/provider/clipboard_spec.lua
@@ -653,14 +653,12 @@ describe('clipboard (with fake clipboard.vim)', function()
'',
'',
'E121: Undefined variable: doesnotexist',
- 'E15: Invalid expression: doesnotexist',
}, 'v'}, eval("g:test_clip['*']"))
feed_command(':echo "Howdy!"')
eq({{
'',
'',
'E121: Undefined variable: doesnotexist',
- 'E15: Invalid expression: doesnotexist',
'',
'Howdy!',
}, 'v'}, eval("g:test_clip['*']"))
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index d254edc7d5..d100db8de2 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local eval, command, feed = helpers.eval, helpers.command, helpers.feed
local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
local expect, write_file = helpers.expect, helpers.write_file
@@ -116,6 +117,6 @@ describe('python3 provider', function()
feed_command("exe 'split' tempname()")
feed_command("bwipeout!")
feed_command('help help')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index 2729d8dfa2..fba96100fc 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -1,10 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
-local eval = helpers.eval
local exc_exec = helpers.exc_exec
local expect = helpers.expect
local feed = helpers.feed
@@ -107,7 +107,7 @@ describe('ruby provider', function()
helpers.add_builddir_to_rtp()
command([=[autocmd BufDelete * ruby VIM::evaluate('expand("<afile>")')]=])
feed_command('help help')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua
index 77a41caec7..ebfd73cf85 100644
--- a/test/functional/shada/errors_spec.lua
+++ b/test/functional/shada/errors_spec.lua
@@ -342,6 +342,11 @@ describe('ShaDa error handling', function()
eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable name type', exc_exec(sdrcmd()))
end)
+ it('fails on variable item with BIN value and type value != VAR_TYPE_BLOB', function()
+ wshada('\006\000\007\147\196\001\065\196\000\000')
+ eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable type', exc_exec(sdrcmd()))
+ end)
+
it('fails on replacement item with NIL value', function()
wshada('\003\000\001\192')
eq('Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 is not an array', exc_exec(sdrcmd()))
diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua
index 9291f5e100..84cc34c7cc 100644
--- a/test/functional/shada/history_spec.lua
+++ b/test/functional/shada/history_spec.lua
@@ -2,7 +2,7 @@
local helpers = require('test.functional.helpers')(after_each)
local nvim_command, funcs, meths, nvim_feed, eq =
helpers.command, helpers.funcs, helpers.meths, helpers.feed, helpers.eq
-local eval = helpers.eval
+local assert_alive = helpers.assert_alive
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -244,7 +244,7 @@ describe('ShaDa support code', function()
nvim_command('wshada')
nvim_command('set shada=\'10,:0')
nvim_command('wshada')
- eq(2, eval('1+1')) -- check nvim still running
+ assert_alive()
end)
end)
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index e319fd9e6b..153a1c346f 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq =
helpers.meths, helpers.curwinmeths, helpers.curbufmeths, helpers.command,
helpers.funcs, helpers.eq
-local exc_exec, redir_exec = helpers.exc_exec, helpers.redir_exec
+local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -144,10 +144,10 @@ describe('ShaDa support code', function()
nvim_command('normal! gg')
nvim_command('enew')
nvim_command('normal! gg')
- local saved = redir_exec('jumps')
+ local saved = exec_capture('jumps')
nvim_command('qall')
reset()
- eq(saved, redir_exec('jumps'))
+ eq(saved, exec_capture('jumps'))
end)
it('when dumping jump list also dumps current position', function()
diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua
index 22f2b8348d..2d44b0a950 100644
--- a/test/functional/shada/merging_spec.lua
+++ b/test/functional/shada/merging_spec.lua
@@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local nvim_command, funcs, curbufmeths, eq =
helpers.command, helpers.funcs,
helpers.curbufmeths, helpers.eq
-local exc_exec, redir_exec = helpers.exc_exec, helpers.redir_exec
+local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
@@ -910,14 +910,13 @@ describe('ShaDa jumps support code', function()
.. '\008\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161l\002')
eq(0, exc_exec(sdrcmd()))
eq('', curbufmeths.get_name())
- eq('\n'
- .. ' jump line col file/text\n'
+ eq( ' jump line col file/text\n'
.. ' 5 2 0 ' .. mock_file_path .. 'c\n'
.. ' 4 2 0 ' .. mock_file_path .. 'd\n'
.. ' 3 3 0 ' .. mock_file_path .. 'd\n'
.. ' 2 2 0 ' .. mock_file_path .. 'e\n'
.. ' 1 2 0 ' .. mock_file_path .. 'f\n'
- .. '>', redir_exec('jumps'))
+ .. '>', exec_capture('jumps'))
end)
it('merges jumps when writing', function()
@@ -1001,14 +1000,13 @@ describe('ShaDa changes support code', function()
.. '\011\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\005'
.. '\011\008\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\004')
eq(0, exc_exec(sdrcmd()))
- eq('\n'
- .. 'change line col text\n'
+ eq( 'change line col text\n'
.. ' 5 1 0 0\n'
.. ' 4 2 0 1\n'
.. ' 3 5 0 4\n'
.. ' 2 3 0 2\n'
.. ' 1 4 0 3\n'
- .. '>', redir_exec('changes'))
+ .. '>', exec_capture('changes'))
end)
it('merges changes when writing', function()
diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua
index cc0e7fa537..854add1363 100644
--- a/test/functional/shada/variables_spec.lua
+++ b/test/functional/shada/variables_spec.lua
@@ -1,7 +1,7 @@
-- ShaDa variables saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local meths, funcs, nvim_command, eq =
- helpers.meths, helpers.funcs, helpers.command, helpers.eq
+local meths, funcs, nvim_command, eq, eval =
+ helpers.meths, helpers.funcs, helpers.command, helpers.eq, helpers.eval
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -30,10 +30,12 @@ describe('ShaDa support code', function()
else
meths.set_var(varname, varval)
end
+ local vartype = eval('type(g:' .. varname .. ')')
-- Exit during `reset` is not a regular exit: it does not write shada
-- automatically
nvim_command('qall')
reset('set shada+=!')
+ eq(vartype, eval('type(g:' .. varname .. ')'))
eq(varval, meths.get_var(varname))
end)
end
@@ -47,6 +49,8 @@ describe('ShaDa support code', function()
autotest('false', 'FALSEVAR', false)
autotest('null', 'NULLVAR', 'v:null', true)
autotest('ext', 'EXTVAR', '{"_TYPE": v:msgpack_types.ext, "_VAL": [2, ["", ""]]}', true)
+ autotest('blob', 'BLOBVAR', '0z12ab34cd', true)
+ autotest('blob (with NULs)', 'BLOBVARNULS', '0z004e554c7300', true)
it('does not read back variables without `!` in &shada', function()
meths.set_var('STRVAR', 'foo')
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index c61bf108cb..103ae59b8e 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
local poke_eventloop = helpers.poke_eventloop
local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source
@@ -7,6 +8,7 @@ local eq, neq = helpers.eq, helpers.neq
local write_file = helpers.write_file
local command= helpers.command
local exc_exec = helpers.exc_exec
+local matches = helpers.matches
describe(':terminal buffer', function()
local screen
@@ -255,8 +257,23 @@ describe(':terminal buffer', function()
command('bdelete!')
end)
- it('handles wqall', function()
+ it('requires bang (!) to close a running job #15402', function()
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
+ for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do
+ matches('^Vim%('..cmd:gsub('%%', '')..'%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
+ exc_exec(cmd))
+ end
+ command('call jobstop(&channel)')
+ assert(0 >= eval('jobwait([&channel], 1000)[0]'))
+ command('bdelete')
+ end)
+
+ it('stops running jobs with :quit', function()
+ -- Open in a new window to avoid terminating the nvim instance
+ command('split')
+ command('terminal')
+ command('set nohidden')
+ command('quit')
end)
it('does not segfault when pasting empty buffer #13955', function()
@@ -284,7 +301,7 @@ describe('No heap-buffer-overflow when using', function()
feed('$')
-- Let termopen() modify the buffer
feed_command('call termopen("echo")')
- eq(2, eval('1+1')) -- check nvim still running
+ assert_alive()
feed_command('bdelete!')
end)
end)
@@ -294,6 +311,6 @@ describe('No heap-buffer-overflow when', function()
feed_command('set nowrap')
feed_command('autocmd TermOpen * startinsert')
feed_command('call feedkeys("4000ai\\<esc>:terminal!\\<cr>")')
- eq(2, eval('1+1'))
+ assert_alive()
end)
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 4b512605e1..707c355069 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim
local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
local feed = helpers.feed
@@ -215,7 +216,7 @@ describe(':terminal (with fake shell)', function()
-- handler), :terminal cleanup is pending on the main-loop.
-- This write should be ignored (not crash, #5445).
feed('iiYYYYYYY')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('works with findfile()', function()
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 8a5dd7ef18..f7520b14d4 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -8,12 +8,12 @@ local helpers = require('test.functional.helpers')(after_each)
local uname = helpers.uname
local thelpers = require('test.functional.terminal.helpers')
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local eq = helpers.eq
local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
local clear = helpers.clear
local command = helpers.command
-local eval = helpers.eval
local nvim_dir = helpers.nvim_dir
local retry = helpers.retry
local nvim_prog = helpers.nvim_prog
@@ -82,7 +82,7 @@ describe('TUI', function()
command('call jobresize(b:terminal_job_id, 1, 4)')
screen:try_resize(57, 17)
command('call jobresize(b:terminal_job_id, 57, 17)')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('accepts resize while pager is active', function()
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index 03bd336aec..188afa1e84 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local feed, nvim = helpers.feed, helpers.nvim
local feed_command = helpers.feed_command
@@ -33,7 +34,7 @@ describe(':terminal', function()
command('vsplit foo')
eq(3, eval("winnr('$')"))
feed('ZQ') -- Close split, should not crash. #7538
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('does not change size on WinEnter', function()
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 05e0c5fe2c..175525b3f2 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -570,4 +570,47 @@ describe('treesitter highlighting', function()
]]}
screen:expect{ unchanged=true }
end)
+
+ it("supports highlighting with priority", function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ int x = INT_MAX;
+ #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+ #define foo void main() { \
+ return 42; \
+ }
+ ]])
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c")
+ test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query..'\n((translation_unit) @Error (set! "priority" 101))\n'}})
+ ]]
+ -- expect everything to have Error highlight
+ screen:expect{grid=[[
+ {12:int}{8: x = INT_MAX;} |
+ {8:#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))}|
+ {8:#define foo void main() { \} |
+ {8: return 42; \} |
+ {8: }} |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue1};
+ [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
+ -- bold will not be overwritten at the moment
+ [12] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Grey100};
+ }}
+ end)
end)
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
new file mode 100644
index 0000000000..21c287644e
--- /dev/null
+++ b/test/functional/treesitter/node_spec.lua
@@ -0,0 +1,62 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local insert = helpers.insert
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+local function lua_eval(lua_expr)
+ return exec_lua("return " .. lua_expr)
+end
+
+describe('treesitter node API', function()
+ clear()
+
+ if pending_c_parser(pending) then
+ return
+ end
+
+ it('can move between siblings', function()
+ insert([[
+ int main(int x, int y, int z) {
+ return x + y * z
+ }
+ ]])
+
+ exec_lua([[
+ query = require"vim.treesitter.query"
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ root = tree:root()
+ lang = vim.treesitter.inspect_language('c')
+
+ function node_text(node)
+ return query.get_node_text(node, 0)
+ end
+ ]])
+
+ exec_lua 'node = root:descendant_for_range(0, 11, 0, 16)'
+ eq('int x', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_sibling()'
+ eq(',', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_sibling()'
+ eq('int y', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_sibling()'
+ eq(',', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_sibling()'
+ eq('int x', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_named_sibling()'
+ eq('int y', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_named_sibling()'
+ eq('int x', lua_eval('node_text(node)'))
+ end)
+end)
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index d2f9148e8f..ffaa4141c4 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -10,9 +10,11 @@ local pending_c_parser = helpers.pending_c_parser
before_each(clear)
describe('treesitter parser API', function()
+ clear()
+ if pending_c_parser(pending) then return end
it('parses buffer', function()
- if helpers.pending_win32(pending) or pending_c_parser(pending) then return end
+ if helpers.pending_win32(pending) then return end
insert([[
int main() {
@@ -103,8 +105,6 @@ void ui_refresh(void)
}]]
it('allows to iterate over nodes children', function()
- if pending_c_parser(pending) then return end
-
insert(test_text);
local res = exec_lua([[
@@ -127,8 +127,6 @@ void ui_refresh(void)
end)
it('allows to get a child by field', function()
- if pending_c_parser(pending) then return end
-
insert(test_text);
local res = exec_lua([[
@@ -162,8 +160,6 @@ void ui_refresh(void)
]]
it("supports runtime queries", function()
- if pending_c_parser(pending) then return end
-
local ret = exec_lua [[
return require"vim.treesitter.query".get_query("c", "highlights").captures[1]
]]
@@ -172,8 +168,6 @@ void ui_refresh(void)
end)
it('support query and iter by capture', function()
- if pending_c_parser(pending) then return end
-
insert(test_text)
local res = exec_lua([[
@@ -203,8 +197,6 @@ void ui_refresh(void)
end)
it('support query and iter by match', function()
- if pending_c_parser(pending) then return end
-
insert(test_text)
local res = exec_lua([[
@@ -236,8 +228,6 @@ void ui_refresh(void)
end)
it('can match special regex characters like \\ * + ( with `vim-match?`', function()
- if pending_c_parser(pending) then return end
-
insert('char* astring = "\\n"; (1 + 1) * 2 != 2;')
local res = exec_lua([[
@@ -271,8 +261,6 @@ void ui_refresh(void)
end)
it('supports builtin query predicate any-of?', function()
- if pending_c_parser(pending) then return end
-
insert([[
#include <stdio.h>
@@ -330,8 +318,6 @@ void ui_refresh(void)
end)
it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
- if pending_c_parser(pending) then return end
-
insert('char* astring = "Hello World!";')
local res = exec_lua([[
@@ -407,8 +393,6 @@ void ui_refresh(void)
it('allows to set simple ranges', function()
- if pending_c_parser(pending) then return end
-
insert(test_text)
local res = exec_lua [[
@@ -450,8 +434,6 @@ void ui_refresh(void)
eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
end)
it("allows to set complex ranges", function()
- if pending_c_parser() then return end
-
insert(test_text)
local res = exec_lua [[
@@ -646,6 +628,19 @@ int x = INT_MAX;
{2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
}, get_ranges())
end)
+ it("should list all directives", function()
+ local res_list = exec_lua[[
+ local query = require'vim.treesitter.query'
+
+ local list = query.list_directives()
+
+ table.sort(list)
+
+ return list
+ ]]
+
+ eq({ 'offset!', 'set!' }, res_list)
+ end)
end)
end)
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index af709cd521..16ed3b9486 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -858,8 +858,8 @@ describe('Buffer highlighting', function()
it('works with cursorline', function()
command("set cursorline")
- screen:expect([[
- {14:^1 + 2 }{15:=}{16: 3}{14: }|
+ screen:expect{grid=[[
+ {14:^1 + 2 }{3:=}{2: 3}{14: }|
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
@@ -867,32 +867,32 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
feed('j')
- screen:expect([[
+ screen:expect{grid=[[
1 + 2 {3:=}{2: 3} |
- {14:^3 + }{11:ERROR:}{14: invalid syntax }|
+ {14:^3 + }{11:ERROR:} invalid syntax{14: }|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
feed('j')
- screen:expect([[
+ screen:expect{grid=[[
1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
{14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
- {14:, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s}|
+ {14:, 5, 5, 5, 5, 5, 5, }Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
end)
it('works with color column', function()
@@ -910,11 +910,11 @@ describe('Buffer highlighting', function()
command("set colorcolumn=9")
screen:expect{grid=[[
- ^1 + 2 {3:=}{2: }{17:3} |
+ ^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
- x = 4 {12:暗}{19:x}{12:事} |
+ x = 4 {12:暗x事} |
{1:~ }|
{1:~ }|
|
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 0ea8bab957..ad23402ff9 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -14,6 +14,8 @@ local function new_screen(opt)
[3] = {bold = true, reverse = true},
[4] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[5] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [6] = {foreground = Screen.colors.Magenta},
+ [7] = {bold = true, foreground = Screen.colors.Brown},
})
return screen
end
@@ -267,7 +269,7 @@ local function test_cmdline(linegrid)
special = {'"', true},
}, {
firstc = "=",
- content = {{"1"}, {"+"}, {"2"}},
+ content = {{"1", 6}, {"+", 7}, {"2", 6}},
pos = 3,
}}
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index f75f700fb5..9c035c728b 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -212,10 +212,10 @@ describe('ui/cursor', function()
if m.blinkwait then m.blinkwait = 700 end
end
if m.hl_id then
- m.hl_id = 56
+ m.hl_id = 58
m.attr = {background = Screen.colors.DarkGray}
end
- if m.id_lm then m.id_lm = 57 end
+ if m.id_lm then m.id_lm = 59 end
end
-- Assert the new expectation.
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 98aafd8757..8074f91215 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -562,7 +562,7 @@ end]]
{5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count = unpack(item) |
{5:i}{12:c}{11:ombining color} {13:nil} {5:then} |
{11:replacing color}d_cell |
- {5:e}{8:bl}{14:endy}{15:i}{14:text}{15:o}{14:-}{15:o}{14:h}{7:ere} |
+ {5:e}{8:bl}{7:endy}{10: }{7:text}{10: }{7:-}{10: }{7:here} |
{5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
{11:replacing color} line[colpos] |
cell.text = text |
@@ -697,4 +697,604 @@ end]]
|
]]}
end)
+
+ it('can have virtual text which combines foreground and backround groups', function()
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
+ [3] = {background = tonumber('0x123456'), foreground = tonumber('0xcccccc')};
+ [4] = {background = tonumber('0x234567'), foreground = tonumber('0xbbbbbb')};
+ [5] = {background = tonumber('0x234567'), foreground = tonumber('0xcccccc')};
+ [6] = {bold = true, foreground = tonumber('0xcccccc'), background = tonumber('0x234567')};
+ }
+
+ exec [[
+ hi BgOne guibg=#123456
+ hi BgTwo guibg=#234567
+ hi FgEin guifg=#bbbbbb
+ hi FgZwei guifg=#cccccc
+ hi VeryBold gui=bold
+ ]]
+
+ meths.buf_set_extmark(0, ns, 0, 0, { virt_text={
+ {'a', {'BgOne', 'FgEin'}};
+ {'b', {'BgOne', 'FgZwei'}};
+ {'c', {'BgTwo', 'FgEin'}};
+ {'d', {'BgTwo', 'FgZwei'}};
+ {'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
+ }})
+
+ screen:expect{grid=[[
+ ^ {2:a}{3:b}{4:c}{5:d}{6:X} |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('does not crash when deleting a cleared buffer #15212', function()
+ exec_lua [[
+ ns = vim.api.nvim_create_namespace("myplugin")
+ vim.api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{"a"}}, end_col = 0})
+ ]]
+ screen:expect{grid=[[
+ ^ a |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ vim.cmd("bdelete")
+ ]]
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ helpers.assert_alive()
+ end)
+end)
+
+describe('decorations: virtual lines', function()
+ local screen, ns
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 12)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {foreground = Screen.colors.Cyan4};
+ [3] = {background = Screen.colors.Yellow1};
+ [4] = {bold = true};
+ [5] = {background = Screen.colors.Yellow, foreground = Screen.colors.Blue};
+ [6] = {foreground = Screen.colors.Blue};
+ [7] = {foreground = Screen.colors.SlateBlue};
+ [8] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue};
+ [9] = {foreground = Screen.colors.Brown};
+ }
+
+ ns = meths.create_namespace 'test'
+ end)
+
+ local example_text = [[
+if (h->n_buckets < new_n_buckets) { // expand
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t));
+ h->keys = new_keys;
+ if (kh_is_map && val_size) {
+ char *new_vals = krealloc( h->vals_buf, new_n_buckets * val_size);
+ h->vals_buf = new_vals;
+ }
+}]]
+
+ it('works with one line', function()
+ insert(example_text)
+ feed 'gg'
+ meths.buf_set_extmark(0, ns, 1, 33, {
+ virt_lines={ {{">> ", "NonText"}, {"krealloc", "Identifier"}, {": change the size of an allocation"}}};
+ virt_lines_above=true;
+ })
+
+ screen:expect{grid=[[
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ {1:>> }{2:krealloc}: change the size of an allocation |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ |
+ ]]}
+
+ feed '/krealloc<cr>'
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ {1:>> }{2:krealloc}: change the size of an allocation |
+ khkey_t *new_keys = (khkey_t *){3:^krealloc}((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ /krealloc |
+ ]]}
+
+ -- virtual line remains anchored to the extmark
+ feed 'i<cr>'
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *) |
+ {1:>> }{2:krealloc}: change the size of an allocation |
+ {3:^krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
+ hkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ {4:-- INSERT --} |
+ ]]}
+
+ feed '<esc>3+'
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *) |
+ {1:>> }{2:krealloc}: change the size of an allocation |
+ {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
+ hkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ |
+ ]]}
+
+ meths.buf_set_extmark(0, ns, 5, 0, {
+ virt_lines = { {{"^^ REVIEW:", "Todo"}, {" new_vals variable seems unneccesary?", "Comment"}} };
+ })
+ -- TODO: what about the cursor??
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *) |
+ {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
+ hkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buck^ets * val_size); |
+ {5:^^ REVIEW:}{6: new_vals variable seems unneccesary?} |
+ h->vals_buf = new_vals; |
+ } |
+ |
+ ]]}
+
+ meths.buf_clear_namespace(0, ns, 0, -1)
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *) |
+ {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
+ hkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buck^ets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ |
+ ]]}
+ end)
+
+
+ it('works with text at the beginning of the buffer', function()
+ insert(example_text)
+ feed 'gg'
+
+ screen:expect{grid=[[
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ {1:~ }|
+ |
+ ]]}
+
+ meths.buf_set_extmark(0, ns, 0, 0, {
+ virt_lines={
+ {{"refactor(khash): ", "Special"}, {"take size of values as parameter"}};
+ {{"Author: Dev Devsson, "}, {"Tue Aug 31 10:13:37 2021", "Comment"}};
+ };
+ virt_lines_above=true;
+ right_gravity=false;
+ })
+
+ -- placing virt_text on topline does not automatically cause a scroll
+ screen:expect{grid=[[
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ {1:~ }|
+ |
+ ]], unchanged=true}
+
+ feed '<c-b>'
+ screen:expect{grid=[[
+ {7:refactor(khash): }take size of values as parameter |
+ Author: Dev Devsson, {6:Tue Aug 31 10:13:37 2021} |
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ |
+ ]]}
+ end)
+
+ it('works with text et the end of the buffer', function()
+ insert(example_text)
+ feed 'G'
+
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ ^} |
+ {1:~ }|
+ |
+ ]]}
+
+ local id = meths.buf_set_extmark(0, ns, 7, 0, {
+ virt_lines={{{"Grugg"}}};
+ right_gravity=false;
+ })
+
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ ^} |
+ Grugg |
+ |
+ ]]}
+
+ meths.buf_del_extmark(0, ns, id)
+ screen:expect{grid=[[
+ if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ ^} |
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('works with a block scrolling up', function()
+ screen:try_resize(30, 7)
+ insert("aa\nbb\ncc\ndd\nee\nff\ngg\nhh")
+ feed 'gg'
+
+ meths.buf_set_extmark(0, ns, 6, 0, {
+ virt_lines={
+ {{"they see me"}};
+ {{"scrolling", "Special"}};
+ {{"they"}};
+ {{"hatin'", "Special"}};
+ };
+ })
+
+ screen:expect{grid=[[
+ ^aa |
+ bb |
+ cc |
+ dd |
+ ee |
+ ff |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^bb |
+ cc |
+ dd |
+ ee |
+ ff |
+ gg |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^cc |
+ dd |
+ ee |
+ ff |
+ gg |
+ they see me |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^dd |
+ ee |
+ ff |
+ gg |
+ they see me |
+ {7:scrolling} |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^ee |
+ ff |
+ gg |
+ they see me |
+ {7:scrolling} |
+ they |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^ff |
+ gg |
+ they see me |
+ {7:scrolling} |
+ they |
+ {7:hatin'} |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^gg |
+ they see me |
+ {7:scrolling} |
+ they |
+ {7:hatin'} |
+ hh |
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ they see me |
+ {7:scrolling} |
+ they |
+ {7:hatin'} |
+ ^hh |
+ {1:~ }|
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ {7:scrolling} |
+ they |
+ {7:hatin'} |
+ ^hh |
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ they |
+ {7:hatin'} |
+ ^hh |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ {7:hatin'} |
+ ^hh |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed '<c-e>'
+ screen:expect{grid=[[
+ ^hh |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('works with sign and numbercolumns', function()
+ insert(example_text)
+ feed 'gg'
+ command 'set number signcolumn=yes'
+ screen:expect{grid=[[
+ {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
+ {8: }{9: }d |
+ {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
+ {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
+ {8: }{9: }t)); |
+ {8: }{9: 3 } h->keys = new_keys; |
+ {8: }{9: 4 } if (kh_is_map && val_size) { |
+ {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, |
+ {8: }{9: }new_n_buckets * val_size); |
+ {8: }{9: 6 } h->vals_buf = new_vals; |
+ {8: }{9: 7 } } |
+ |
+ ]]}
+
+ meths.buf_set_extmark(0, ns, 2, 0, {
+ virt_lines={
+ {{"Some special", "Special"}};
+ {{"remark about codes", "Comment"}};
+ };
+ })
+
+ screen:expect{grid=[[
+ {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
+ {8: }{9: }d |
+ {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
+ {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
+ {8: }{9: }t)); |
+ {8: }{9: 3 } h->keys = new_keys; |
+ {8: }{9: }{7:Some special} |
+ {8: }{9: }{6:remark about codes} |
+ {8: }{9: 4 } if (kh_is_map && val_size) { |
+ {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, |
+ {8: }{9: }new_n_buckets * val_size); |
+ |
+ ]]}
+
+ meths.buf_set_extmark(0, ns, 2, 0, {
+ virt_lines={
+ {{"Some special", "Special"}};
+ {{"remark about codes", "Comment"}};
+ };
+ virt_lines_leftcol=true;
+ })
+ screen:expect{grid=[[
+ {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
+ {8: }{9: }d |
+ {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
+ {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
+ {8: }{9: }t)); |
+ {8: }{9: 3 } h->keys = new_keys; |
+ {7:Some special} |
+ {6:remark about codes} |
+ {8: }{9: 4 } if (kh_is_map && val_size) { |
+ {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, |
+ {8: }{9: }new_n_buckets * val_size); |
+ |
+ ]]}
+ end)
+
+
+ it('works with hard tabs', function()
+ insert(example_text)
+ feed 'gg'
+ meths.buf_set_extmark(0, ns, 1, 0, {
+ virt_lines={ {{">>", "NonText"}, {"\tvery\ttabby", "Identifier"}, {"text\twith\ttabs"}}};
+ })
+ screen:expect{grid=[[
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ {1:>>}{2: very tabby}text with tabs |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ |
+ ]]}
+
+ command 'set tabstop=4'
+ screen:expect{grid=[[
+ ^if (h->n_buckets < new_n_buckets) { // expand |
+ khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ h->keys, new_n_buckets * sizeof(khkey_t)); |
+ {1:>>}{2: very tabby}text with tabs |
+ h->keys = new_keys; |
+ if (kh_is_map && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ |
+ ]]}
+ end)
+
end)
diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua
index a8d9fb02fc..df750a1a68 100644
--- a/test/functional/ui/diff_spec.lua
+++ b/test/functional/ui/diff_spec.lua
@@ -1057,7 +1057,7 @@ it('diff updates line numbers below filler lines', function()
vnew
call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
windo diffthis
- setlocal number rnu foldcolumn=0
+ setlocal number rnu cursorline cursorlineopt=number foldcolumn=0
]])
screen:expect([[
{1: }a {3:│}{10:1 }^a |
@@ -1109,7 +1109,7 @@ it('diff updates line numbers below filler lines', function()
{3:[No Name] [+] }{7:[No Name] [+] }|
|
]])
- command("set signcolumn number tgc cursorline")
+ command("set signcolumn number tgc cursorline cursorlineopt=number,line")
command("hi CursorLineNr guibg=red")
screen:expect{grid=[[
{1: }a {3:│}{11: 2 }a |
@@ -1128,3 +1128,72 @@ it('diff updates line numbers below filler lines', function()
signcolumn=auto |
]]}
end)
+
+it('Align the filler lines when changing text in diff mode', function()
+ clear()
+ local screen = Screen.new(40, 20)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray};
+ [2] = {background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1, bold = true};
+ [3] = {reverse = true};
+ [4] = {background = Screen.colors.LightBlue};
+ [5] = {background = Screen.colors.LightMagenta};
+ [6] = {background = Screen.colors.Red, bold = true};
+ [7] = {foreground = Screen.colors.Blue1, bold = true};
+ [8] = {reverse = true, bold = true};
+ })
+ source([[
+ call setline(1, range(1, 15))
+ vnew
+ call setline(1, range(9, 15))
+ windo diffthis
+ wincmd h
+ exe "normal Gl5\<C-E>"
+ ]])
+ screen:expect{grid=[[
+ {1: }{2:------------------}{3:│}{1: }{4:6 }|
+ {1: }{2:------------------}{3:│}{1: }{4:7 }|
+ {1: }{2:------------------}{3:│}{1: }{4:8 }|
+ {1: }9 {3:│}{1: }9 |
+ {1: }10 {3:│}{1: }10 |
+ {1: }11 {3:│}{1: }11 |
+ {1: }12 {3:│}{1: }12 |
+ {1: }13 {3:│}{1: }13 |
+ {1: }14 {3:│}{1: }14 |
+ {1:- }1^5 {3:│}{1:- }15 |
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {8:[No Name] [+] }{3:[No Name] [+] }|
+ |
+ ]]}
+ feed('ax<Esc>')
+ screen:expect{grid=[[
+ {1: }{2:------------------}{3:│}{1: }{4:6 }|
+ {1: }{2:------------------}{3:│}{1: }{4:7 }|
+ {1: }{2:------------------}{3:│}{1: }{4:8 }|
+ {1: }9 {3:│}{1: }9 |
+ {1: }10 {3:│}{1: }10 |
+ {1: }11 {3:│}{1: }11 |
+ {1: }12 {3:│}{1: }12 |
+ {1: }13 {3:│}{1: }13 |
+ {1: }14 {3:│}{1: }14 |
+ {1: }{5:15}{6:^x}{5: }{3:│}{1: }{5:15 }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {8:[No Name] [+] }{3:[No Name] [+] }|
+ |
+ ]]}
+end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 61ed0a65b0..ccf5f963d1 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -74,7 +74,8 @@ describe('float window', function()
funcs.win_execute(win, 'bwipe!')
end)
- it('win_execute() call commands that not allowed' , function()
+ it("win_execute() call commands that are not allowed when 'hidden' is not set" , function()
+ command('set nohidden')
local buf = meths.create_buf(false, false)
meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'})
local win = meths.open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10})
@@ -152,6 +153,132 @@ describe('float window', function()
eq(10, width)
end)
+ it('opened with correct position', function()
+ local pos = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+
+ local opts = {
+ width = 10,
+ height = 10,
+ col = 7,
+ row = 9,
+ relative = 'editor',
+ style = 'minimal'
+ }
+
+ local win_id = vim.api.nvim_open_win(bufnr, false, opts)
+
+ return vim.api.nvim_win_get_position(win_id)
+ ]])
+
+ eq(9, pos[1])
+ eq(7, pos[2])
+ end)
+
+ it('opened with correct position relative to the cursor', function()
+ local pos = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+
+ local opts = {
+ width = 10,
+ height = 10,
+ col = 7,
+ row = 9,
+ relative = 'cursor',
+ style = 'minimal'
+ }
+
+ local win_id = vim.api.nvim_open_win(bufnr, false, opts)
+
+ return vim.api.nvim_win_get_position(win_id)
+ ]])
+
+ eq(9, pos[1])
+ eq(7, pos[2])
+ end)
+
+ it('opened with correct position relative to another window', function()
+ local pos = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+
+ local par_opts = {
+ width = 50,
+ height = 50,
+ col = 7,
+ row = 9,
+ relative = 'editor',
+ style = 'minimal'
+ }
+
+ local par_win_id = vim.api.nvim_open_win(bufnr, false, par_opts)
+
+ local opts = {
+ width = 10,
+ height = 10,
+ col = 7,
+ row = 9,
+ relative = 'win',
+ style = 'minimal',
+ win = par_win_id
+ }
+
+ local win_id = vim.api.nvim_open_win(bufnr, false, opts)
+
+ return vim.api.nvim_win_get_position(win_id)
+ ]])
+
+ eq(18, pos[1])
+ eq(14, pos[2])
+ end)
+
+
+ it('opened with correct position relative to another relative window', function()
+ local pos = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+
+ local root_opts = {
+ width = 50,
+ height = 50,
+ col = 7,
+ row = 9,
+ relative = 'editor',
+ style = 'minimal'
+ }
+
+ local root_win_id = vim.api.nvim_open_win(bufnr, false, root_opts)
+
+ local par_opts = {
+ width = 20,
+ height = 20,
+ col = 2,
+ row = 3,
+ relative = 'win',
+ win = root_win_id,
+ style = 'minimal'
+ }
+
+ local par_win_id = vim.api.nvim_open_win(bufnr, false, par_opts)
+
+ local opts = {
+ width = 10,
+ height = 10,
+ col = 3,
+ row = 2,
+ relative = 'win',
+ win = par_win_id,
+ style = 'minimal'
+ }
+
+ local win_id = vim.api.nvim_open_win(bufnr, false, opts)
+
+ return vim.api.nvim_win_get_position(win_id)
+ ]])
+
+ eq(14, pos[1])
+ eq(12, pos[2])
+ end)
+
+
local function with_ext_multigrid(multigrid)
local screen
before_each(function()
@@ -620,6 +747,134 @@ describe('float window', function()
end
end)
+ it("would not break 'minimal' style with signcolumn=auto:[min]-[max]", function()
+ command('set number')
+ command('set signcolumn=auto:1-3')
+ command('set colorcolumn=1')
+ command('set cursorline')
+ command('set foldcolumn=1')
+ command('hi NormalFloat guibg=#333333')
+ feed('ix<cr>y<cr><esc>gg')
+ local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ {19: }{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {15:x }|
+ {15:y }|
+ {15: }|
+ {15: }|
+ ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ else
+ screen:expect{grid=[[
+ {19: }{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } {15:x } |
+ {0:~ }{15:y }{0: }|
+ {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|
+ |
+ ]]}
+ end
+
+ command('sign define piet1 text=𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄ texthl=Search')
+ command('sign place 1 line=1 name=piet1 buffer=1')
+ -- signcolumn=auto:1-3 still works if there actually are signs
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ {19: }{17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{15:x }|
+ {19: }{15:y }|
+ {19: }{15: }|
+ {15: }|
+ ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+
+ else
+ screen:expect([[
+ {19: }{17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } {17:𐌢̀́̂̃̅̄𐌢̀́̂̃̅̄}{15:x } |
+ {0:~ }{19: }{15:y }{0: }|
+ {0:~ }{19: }{15: }{0: }|
+ {0:~ }{15: }{0: }|
+ |
+ ]])
+ end
+ command('sign unplace 1 buffer=1')
+
+ local buf = meths.create_buf(false, true)
+ meths.win_set_buf(win, buf)
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ {19: }{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 4
+ {15: }|
+ {15: }|
+ {15: }|
+ {15: }|
+ ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ else
+ screen:expect([[
+ {19: }{20: 1 }{22:^x}{21: }|
+ {19: }{14: 2 }{22:y} |
+ {19: }{14: 3 }{22: } {15: } |
+ {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|
+ |
+ ]])
+ end
+ end)
+
it('can have border', function()
local buf = meths.create_buf(false, false)
meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
@@ -653,8 +908,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -696,8 +951,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -739,8 +994,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -782,8 +1037,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -826,8 +1081,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -867,8 +1122,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -908,8 +1163,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -958,8 +1213,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
}}
else
screen:expect{grid=[[
@@ -1009,8 +1264,8 @@ describe('float window', function()
]], float_pos={
[4] = { { id = 1001 }, "NW", 1, 0, 0, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
}}
else
screen:expect{grid=[[
@@ -1067,8 +1322,8 @@ describe('float window', function()
]], float_pos={
[5] = { { id = 1002 }, "NW", 1, 0, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 0, linecount = 3};
}}
else
screen:expect{grid=[[
@@ -1126,8 +1381,8 @@ describe('float window', function()
[5] = { { id = 1002 }, "NW", 1, 0, 5, true, 50 },
[6] = { { id = -1 }, "NW", 5, 4, 0, false, 100 }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 3};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 3, linecount=3};
}}
else
screen:expect{grid=[[
@@ -1576,6 +1831,7 @@ describe('float window', function()
botline = 3,
curline = 0,
curcol = 3,
+ linecount = 2,
win = { id = 1000 }
},
[4] = {
@@ -1583,6 +1839,7 @@ describe('float window', function()
botline = 3,
curline = 0,
curcol = 3,
+ linecount = 2,
win = { id = 1001 }
},
[5] = {
@@ -1590,6 +1847,7 @@ describe('float window', function()
botline = 2,
curline = 0,
curcol = 0,
+ linecount = 1,
win = { id = 1002 }
}
}}
@@ -4907,7 +5165,7 @@ describe('float window', function()
]])
end
- eq(2, eval('1+1'))
+ assert_alive()
end)
it("o (:only) non-float", function()
@@ -6210,8 +6468,8 @@ describe('float window', function()
]], float_pos={
[4] = { { id = 1001 }, "NW", 1, 2, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
}}
else
screen:expect{grid=[[
@@ -6267,10 +6525,10 @@ describe('float window', function()
[5] = { { id = 1002 }, "NW", 1, 3, 8, true };
[6] = { { id = 1003 }, "NW", 1, 4, 10, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1};
+ [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1};
}}
else
screen:expect{grid=[[
@@ -6315,8 +6573,8 @@ describe('float window', function()
]], float_pos={
[4] = { { id = 1001 }, "NW", 1, 2, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
}}
else
screen:expect{grid=[[
@@ -6372,10 +6630,10 @@ describe('float window', function()
[5] = { { id = 1002 }, "NW", 1, 4, 10, true };
[6] = { { id = 1003 }, "NW", 1, 3, 8, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
}}
else
screen:expect{grid=[[
@@ -6435,10 +6693,10 @@ describe('float window', function()
[5] = {{id = 1002}, "NW", 1, 2, 6, true, 50};
[6] = {{id = 1003}, "NW", 1, 3, 7, true, 40};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0};
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
}}
else
screen:expect{grid=[[
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index 8883ad8270..249686234c 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -85,7 +85,7 @@ describe("folded lines", function()
end)
it("highlighting with relative line numbers", function()
- command("set relativenumber foldmethod=marker")
+ command("set relativenumber cursorline cursorlineopt=number foldmethod=marker")
feed_command("set foldcolumn=2")
funcs.setline(1, '{{{1')
funcs.setline(2, 'line 1')
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 8992ee27ce..c00d30fe32 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -789,7 +789,7 @@ describe("'listchars' highlight", function()
[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {background=Screen.colors.Grey90},
[2] = {foreground=Screen.colors.Red},
- [3] = {foreground=Screen.colors.Green1},
+ [3] = {foreground=Screen.colors.X11Green, background=Screen.colors.Red1},
})
feed_command('highlight clear ModeMsg')
feed_command('highlight Whitespace guifg=#FF0000')
@@ -912,6 +912,97 @@ describe('CursorLine highlight', function()
]])
end)
+ it("'cursorlineopt' screenline", function()
+ local screen = Screen.new(20,5)
+ screen:set_default_attr_ids({
+ [1] = {foreground = Screen.colors.Black, background = Screen.colors.White};
+ [2] = {foreground = Screen.colors.Yellow};
+ [3] = {foreground = Screen.colors.Red, background = Screen.colors.Green};
+ [4] = {foreground = Screen.colors.Green, background = Screen.colors.Red};
+ })
+ screen:attach()
+
+ feed_command('set wrap cursorline cursorlineopt=screenline')
+ feed_command('set showbreak=>>>')
+ feed_command('highlight clear NonText')
+ feed_command('highlight clear CursorLine')
+ feed_command('highlight NonText guifg=Yellow gui=NONE')
+ feed_command('highlight LineNr guifg=Red guibg=Green gui=NONE')
+ feed_command('highlight CursorLine guifg=Black guibg=White gui=NONE')
+ feed_command('highlight CursorLineNr guifg=Green guibg=Red gui=NONE')
+
+ feed('30iø<esc>o<esc>30ia<esc>')
+
+ -- CursorLine should not apply to 'showbreak' when 'cursorlineopt' contains "screenline"
+ screen:expect([[
+ øøøøøøøøøøøøøøøøøøøø|
+ {2:>>>}øøøøøøøøøø |
+ aaaaaaaaaaaaaaaaaaaa|
+ {2:>>>}{1:aaaaaaaaa^a }|
+ |
+ ]])
+ feed('gk')
+ screen:expect([[
+ øøøøøøøøøøøøøøøøøøøø|
+ {2:>>>}øøøøøøøøøø |
+ {1:aaaaaaaaaaaa^aaaaaaaa}|
+ {2:>>>}aaaaaaaaaa |
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ {1:øøøøøøøøøøøø^øøøøøøøø}|
+ {2:>>>}øøøøøøøøøø |
+ aaaaaaaaaaaaaaaaaaaa|
+ {2:>>>}aaaaaaaaaa |
+ |
+ ]])
+
+ -- CursorLineNr should not apply to line number when 'cursorlineopt' does not contain "number"
+ feed_command('set relativenumber numberwidth=2')
+ screen:expect([[
+ {3:0 }{1:øøøøøøøøøøøø^øøøøøø}|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+
+ -- CursorLineNr should apply to line number when 'cursorlineopt' contains "number"
+ feed_command('set cursorlineopt+=number')
+ screen:expect([[
+ {4:0 }{1:øøøøøøøøøøøø^øøøøøø}|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {4:0 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}{1:øøøøøøøøø^øøø }|
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {3:1 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {4:0 }{1:aaaaaaaaaaaa^aaaaaa}|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {3:1 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {4:0 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}{1:aaaaaaaaa^aaa }|
+ |
+ ]])
+ end)
+
it('always updated. vim-patch:8.1.0849', function()
local screen = Screen.new(50,5)
screen:set_default_attr_ids({
@@ -1201,6 +1292,75 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
end)
end)
+describe("'number' and 'relativenumber' highlight", function()
+ before_each(clear)
+
+ it('LineNr, LineNrAbove and LineNrBelow', function()
+ local screen = Screen.new(20,10)
+ screen:set_default_attr_ids({
+ [1] = {foreground = Screen.colors.Red},
+ [2] = {foreground = Screen.colors.Blue},
+ [3] = {foreground = Screen.colors.Green},
+ })
+ screen:attach()
+ command('set number relativenumber')
+ command('call setline(1, range(50))')
+ command('highlight LineNr guifg=Red')
+ feed('4j')
+ screen:expect([[
+ {1: 4 }0 |
+ {1: 3 }1 |
+ {1: 2 }2 |
+ {1: 1 }3 |
+ {1:5 }^4 |
+ {1: 1 }5 |
+ {1: 2 }6 |
+ {1: 3 }7 |
+ {1: 4 }8 |
+ |
+ ]])
+ command('highlight LineNrAbove guifg=Blue')
+ screen:expect([[
+ {2: 4 }0 |
+ {2: 3 }1 |
+ {2: 2 }2 |
+ {2: 1 }3 |
+ {1:5 }^4 |
+ {1: 1 }5 |
+ {1: 2 }6 |
+ {1: 3 }7 |
+ {1: 4 }8 |
+ |
+ ]])
+ command('highlight LineNrBelow guifg=Green')
+ screen:expect([[
+ {2: 4 }0 |
+ {2: 3 }1 |
+ {2: 2 }2 |
+ {2: 1 }3 |
+ {1:5 }^4 |
+ {3: 1 }5 |
+ {3: 2 }6 |
+ {3: 3 }7 |
+ {3: 4 }8 |
+ |
+ ]])
+ feed('3j')
+ screen:expect([[
+ {2: 7 }0 |
+ {2: 6 }1 |
+ {2: 5 }2 |
+ {2: 4 }3 |
+ {2: 3 }4 |
+ {2: 2 }5 |
+ {2: 1 }6 |
+ {1:8 }^7 |
+ {3: 1 }8 |
+ |
+ ]])
+ end)
+end)
+
describe("'winhighlight' highlight", function()
local screen
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 712c1f377a..b6e2f2311f 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -1487,6 +1487,29 @@ describe("inccommand=nosplit", function()
]])
eq(eval('v:null'), eval('v:exiting'))
end)
+
+ it("does not break bar-separated command #8796", function()
+ source([[
+ function! F()
+ if v:false | return | endif
+ endfun
+ ]])
+ command('call timer_start(10, {-> F()}, {"repeat":-1})')
+ feed(':%s/')
+ sleep(20) -- Allow some timer activity.
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ Inc substitution on |
+ two lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/^ |
+ ]])
+ end)
end)
describe(":substitute, 'inccommand' with a failing expression", function()
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 7bca741ae3..d3fe38ef52 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1384,4 +1384,128 @@ describe('ui/mouse/input', function()
end) -- level 3 - wrapped
end)
+
+ it('getmousepos works correctly', function()
+ local winwidth = meths.get_option('winwidth')
+ -- Set winwidth=1 so that window sizes don't change.
+ meths.set_option('winwidth', 1)
+ command('tabedit')
+ local tabpage = meths.get_current_tabpage()
+ insert('hello')
+ command('vsplit')
+ local opts = {
+ relative='editor',
+ width=12,
+ height=1,
+ col=8,
+ row=1,
+ anchor='NW',
+ style='minimal',
+ border='single',
+ focusable=1
+ }
+ local float = meths.open_win(meths.get_current_buf(), false, opts)
+ command('redraw')
+ local lines = meths.get_option('lines')
+ local columns = meths.get_option('columns')
+
+ -- Test that screenrow and screencol are set properly for all positions.
+ for row = 0, lines - 1 do
+ for col = 0, columns - 1 do
+ -- Skip the X button that would close the tab.
+ if row ~= 0 or col ~= columns - 1 then
+ meths.input_mouse('left', 'press', '', 0, row, col)
+ meths.set_current_tabpage(tabpage)
+ local mousepos = funcs.getmousepos()
+ eq(row + 1, mousepos.screenrow)
+ eq(col + 1, mousepos.screencol)
+ -- All other values should be 0 when clicking on the command line.
+ if row == lines - 1 then
+ eq(0, mousepos.winid)
+ eq(0, mousepos.winrow)
+ eq(0, mousepos.wincol)
+ eq(0, mousepos.line)
+ eq(0, mousepos.column)
+ end
+ end
+ end
+ end
+
+ -- Test that mouse position values are properly set for the floating window
+ -- with a border. 1 is added to the height and width to account for the
+ -- border.
+ for win_row = 0, opts.height + 1 do
+ for win_col = 0, opts.width + 1 do
+ local row = win_row + opts.row
+ local col = win_col + opts.col
+ meths.input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = funcs.getmousepos()
+ eq(float.id, mousepos.winid)
+ eq(win_row + 1, mousepos.winrow)
+ eq(win_col + 1, mousepos.wincol)
+ local line = 0
+ local column = 0
+ if win_row > 0 and win_row < opts.height + 1
+ and win_col > 0 and win_col < opts.width + 1 then
+ -- Because of border, win_row and win_col don't need to be
+ -- incremented by 1.
+ line = math.min(win_row, funcs.line('$'))
+ column = math.min(win_col, #funcs.getline(line) + 1)
+ end
+ eq(line, mousepos.line)
+ eq(column, mousepos.column)
+ end
+ end
+
+ -- Test that mouse position values are properly set for the floating
+ -- window, after removing the border.
+ opts.border = 'none'
+ meths.win_set_config(float, opts)
+ command('redraw')
+ for win_row = 0, opts.height - 1 do
+ for win_col = 0, opts.width - 1 do
+ local row = win_row + opts.row
+ local col = win_col + opts.col
+ meths.input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = funcs.getmousepos()
+ eq(float.id, mousepos.winid)
+ eq(win_row + 1, mousepos.winrow)
+ eq(win_col + 1, mousepos.wincol)
+ local line = math.min(win_row + 1, funcs.line('$'))
+ local column = math.min(win_col + 1, #funcs.getline(line) + 1)
+ eq(line, mousepos.line)
+ eq(column, mousepos.column)
+ end
+ end
+
+ -- Test that mouse position values are properly set for ordinary windows.
+ -- Set the float to be unfocusable instead of closing, to additionally test
+ -- that getmousepos does not consider unfocusable floats. (see discussion
+ -- in PR #14937 for details).
+ opts.focusable = false
+ meths.win_set_config(float, opts)
+ command('redraw')
+ for nr = 1, 2 do
+ for win_row = 0, funcs.winheight(nr) - 1 do
+ for win_col = 0, funcs.winwidth(nr) - 1 do
+ local row = win_row + funcs.win_screenpos(nr)[1] - 1
+ local col = win_col + funcs.win_screenpos(nr)[2] - 1
+ meths.input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = funcs.getmousepos()
+ eq(funcs.win_getid(nr), mousepos.winid)
+ eq(win_row + 1, mousepos.winrow)
+ eq(win_col + 1, mousepos.wincol)
+ local line = math.min(win_row + 1, funcs.line('$'))
+ local column = math.min(win_col + 1, #funcs.getline(line) + 1)
+ eq(line, mousepos.line)
+ eq(column, mousepos.column)
+ end
+ end
+ end
+
+ -- Restore state and release mouse.
+ command('tabclose!')
+ meths.set_option('winwidth', winwidth)
+ meths.input_mouse('left', 'release', '', 0, 0, 0)
+ end)
end)
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index 719e2ee82a..4e5e9c3a71 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -34,6 +34,7 @@ describe('ext_multigrid', function()
[17] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
[18] = {bold = true, foreground = Screen.colors.Magenta},
[19] = {foreground = Screen.colors.Brown},
+ [20] = {background = Screen.colors.LightGrey},
})
end)
@@ -2034,6 +2035,66 @@ describe('ext_multigrid', function()
]]}
end)
+ it('supports mouse drag with mouse=a', function()
+ command('set mouse=a')
+ command('vsplit')
+ command('wincmd l')
+ command('split')
+ command('enew')
+ feed('ifoo\nbar<esc>')
+
+ meths.input_mouse('left', 'press', '', 5, 0, 0)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 5, 1, 2)
+
+ screen:expect{grid=[[
+ ## grid 1
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}[5:--------------------------]|
+ [4:--------------------------]{12:│}{11:[No Name] [+] }|
+ [4:--------------------------]{12:│}[2:--------------------------]|
+ [4:--------------------------]{12:│}[2:--------------------------]|
+ [4:--------------------------]{12:│}[2:--------------------------]|
+ [4:--------------------------]{12:│}[2:--------------------------]|
+ [4:--------------------------]{12:│}[2:--------------------------]|
+ {12:[No Name] [No Name] }|
+ [3:-----------------------------------------------------]|
+ ## grid 2
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ {7:-- VISUAL --} |
+ ## grid 4
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 5
+ {20:foo} |
+ {20:ba}^r |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ]]}
+
+ end)
+
it('has viewport information', function()
screen:try_resize(48, 8)
screen:expect{grid=[[
@@ -2056,7 +2117,7 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0}
+ [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}
}}
insert([[
Lorem ipsum dolor sit amet, consectetur
@@ -2091,7 +2152,7 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7},
+ [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11},
}}
@@ -2116,7 +2177,7 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0},
+ [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0, linecount = 11},
}}
command("split")
@@ -2140,8 +2201,8 @@ describe('ext_multigrid', function()
reprehenderit in voluptate velit esse cillum |
^dolore eu fugiat nulla pariatur. Excepteur sint |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0},
- [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0},
+ [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11},
+ [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0, linecount = 11},
}}
feed("b")
@@ -2165,8 +2226,8 @@ describe('ext_multigrid', function()
reprehenderit in voluptate velit esse ^cillum |
dolore eu fugiat nulla pariatur. Excepteur sint |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0},
- [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38},
+ [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11},
+ [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38, linecount = 11},
}}
feed("2k")
@@ -2190,8 +2251,8 @@ describe('ext_multigrid', function()
ea commodo consequat. Duis aute irure dolor in |
reprehenderit in voluptate velit esse cillum |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0},
- [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38},
+ [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11},
+ [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11},
}}
-- handles non-current window
@@ -2216,8 +2277,96 @@ describe('ext_multigrid', function()
ea commodo consequat. Duis aute irure dolor in |
reprehenderit in voluptate velit esse cillum |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10},
- [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38},
+ [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11},
+ [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11},
+ }}
+ end)
+
+ it('does not crash when dragging mouse across grid boundary', function()
+ screen:try_resize(48, 8)
+ screen:expect{grid=[[
+ ## grid 1
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ {11:[No Name] }|
+ [3:------------------------------------------------]|
+ ## grid 2
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ |
+ ]], win_viewport={
+ [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}
+ }}
+ insert([[
+ Lorem ipsum dolor sit amet, consectetur
+ adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex
+ ea commodo consequat. Duis aute irure dolor in
+ reprehenderit in voluptate velit esse cillum
+ dolore eu fugiat nulla pariatur. Excepteur sint
+ occaecat cupidatat non proident, sunt in culpa
+ qui officia deserunt mollit anim id est
+ laborum.]])
+
+ screen:expect{grid=[[
+ ## grid 1
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ {11:[No Name] [+] }|
+ [3:------------------------------------------------]|
+ ## grid 2
+ ea commodo consequat. Duis aute irure dolor in |
+ reprehenderit in voluptate velit esse cillum |
+ dolore eu fugiat nulla pariatur. Excepteur sint |
+ occaecat cupidatat non proident, sunt in culpa |
+ qui officia deserunt mollit anim id est |
+ laborum^. |
+ ## grid 3
+ |
+ ]], win_viewport={
+ [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11},
+ }}
+
+ meths.input_mouse('left', 'press', '', 1,5, 1)
+ poke_eventloop()
+ meths.input_mouse('left', 'drag', '', 1, 6, 1)
+
+ screen:expect{grid=[[
+ ## grid 1
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ [2:------------------------------------------------]|
+ {11:[No Name] [+] }|
+ [3:------------------------------------------------]|
+ ## grid 2
+ reprehenderit in voluptate velit esse cillum |
+ dolore eu fugiat nulla pariatur. Excepteur sint |
+ occaecat cupidatat non proident, sunt in culpa |
+ qui officia deserunt mollit anim id est |
+ l^aborum. |
+ {1:~ }|
+ ## grid 3
+ {7:-- VISUAL --} |
+ ]], win_viewport={
+ [2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11},
}}
end)
end)
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 3826707743..50e5dfac84 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -1,9 +1,9 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
local child_session = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir
local eq = helpers.eq
-local eval = helpers.eval
local feed = helpers.feed
local feed_command = helpers.feed_command
local iswin = helpers.iswin
@@ -86,12 +86,12 @@ describe("shell command :!", function()
it("cat a binary file #4142", function()
feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it([[display \x08 char #4142]], function()
feed(":silent !echo \08<CR>")
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('handles control codes', function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 0944bfc21a..aeba049557 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local source = helpers.source
local insert = helpers.insert
@@ -9,7 +10,6 @@ local funcs = helpers.funcs
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
local pcall_err = helpers.pcall_err
-local eval = helpers.eval
describe('ui/ext_popupmenu', function()
local screen
@@ -2211,6 +2211,6 @@ describe('builtin popupmenu', function()
feed('$i')
funcs.complete(col - max_len, items)
feed('<c-y>')
- eq(2, eval('1+1'))
+ assert_alive()
end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index f73d051857..61f19c3794 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -773,13 +773,14 @@ function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height)
self.float_pos[grid] = nil
end
-function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol)
+function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol, linecount)
self.win_viewport[grid] = {
win = win,
topline = topline,
botline = botline,
curline = curline,
- curcol = curcol
+ curcol = curcol,
+ linecount = linecount
}
end
@@ -1306,7 +1307,7 @@ local function fmt_ext_state(name, state)
for k,v in pairs(state) do
str = (str.." ["..k.."] = {win = {id = "..v.win.id.."}, topline = "
..v.topline..", botline = "..v.botline..", curline = "..v.curline
- ..", curcol = "..v.curcol.."};\n")
+ ..", curcol = "..v.curcol..", linecount = "..v.linecount.."};\n")
end
return str .. "}"
elseif name == "float_pos" then
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index 06c92a4b10..741b93043d 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -176,8 +176,8 @@ describe('Signs', function()
command('sign place 5 line=3 name=pietWarn buffer=1')
command('sign place 3 line=3 name=pietError buffer=1')
screen:expect([[
- {1:>>}XX{6: 1 }a |
- XX{1:>>}{6: 2 }b |
+ {1:>>}{8:XX}{6: 1 }a |
+ {8:XX}{1:>>}{6: 2 }b |
{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
@@ -194,7 +194,7 @@ describe('Signs', function()
-- With the default setting, we get the sign with the top id.
command('set signcolumn=yes:1')
screen:expect([[
- XX{6: 1 }a |
+ {8:XX}{6: 1 }a |
{1:>>}{6: 2 }b |
WW{6: 3 }c |
{2: }{6: 4 }^ |
@@ -212,9 +212,9 @@ describe('Signs', function()
-- "auto:3" accommodates all the signs we defined so far.
command('set signcolumn=auto:3')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -230,9 +230,9 @@ describe('Signs', function()
-- Check "yes:9".
command('set signcolumn=yes:9')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{2: }{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{2: }{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -249,9 +249,9 @@ describe('Signs', function()
-- a single line (same result as "auto:3").
command('set signcolumn=auto:4')
screen:expect{grid=[[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -267,8 +267,8 @@ describe('Signs', function()
-- line deletion deletes signs.
command('2d')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}WW{6: 2 }^c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}WW{6: 2 }^c |
{2: }{6: 3 } |
{0:~ }|
{0:~ }|
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index d1af0e955c..4e1852162f 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -913,4 +913,46 @@ describe('Screen', function()
]]}
eq(grid_lines, {{2, 0, {{'c', 0, 3}}}})
end)
+
+ -- Copy of Test_cursor_column_in_concealed_line_after_window_scroll in
+ -- test/functional/ui/syntax_conceal_spec.lua.
+ describe('concealed line after window scroll', function()
+ after_each(function()
+ command(':qall!')
+ os.remove('Xcolesearch')
+ end)
+
+ it('has the correct cursor column', function()
+ insert([[
+ 3split
+ let m = matchadd('Conceal', '=')
+ setl conceallevel=2 concealcursor=nc
+ normal gg
+ "==expr==
+ ]])
+
+ command('write Xcolesearch')
+ feed(":so %<CR>")
+
+ -- Jump to something that is beyond the bottom of the window,
+ -- so there's a scroll down.
+ feed("/expr<CR>")
+
+ -- Are the concealed parts of the current line really hidden?
+ -- Is the window's cursor column properly updated for hidden
+ -- parts of the current line?
+ screen:expect{grid=[[
+ setl conceallevel2 concealcursornc |
+ normal gg |
+ "{5:^expr} |
+ {2:Xcolesearch }|
+ normal gg |
+ "=={5:expr}== |
+ |
+ {0:~ }|
+ {3:Xcolesearch }|
+ /expr |
+ ]]}
+ end)
+ end)
end)
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index ab8d63cda1..809486d4db 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -69,6 +69,7 @@ describe('ui/ext_tabline', function()
command("bnext")
local expected_buffers = {
+ {buffer = { id = 1 }, name = '[No Name]'},
{buffer = { id = 2 }, name = 'another-buffer'},
}
screen:expect{grid=[[
diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua
deleted file mode 100644
index b8137038b1..0000000000
--- a/test/functional/viml/function_spec.lua
+++ /dev/null
@@ -1,216 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local eq = helpers.eq
-local clear = helpers.clear
-local dedent = helpers.dedent
-local redir_exec = helpers.redir_exec
-
-before_each(clear)
-
-local function check_func(fname, body, indent)
- if type(body) == 'number' then
- body = ('return %i'):format(body)
- end
- eq(dedent(([[
-
- function %s()%s
- endfunction]]
- ), 3):format(
- fname,
- body and ('\n1' .. (' '):rep(2 + (indent or 8)) .. body) or ''),
- redir_exec('function ' .. fname))
-end
-
-describe(':endfunction', function()
- it('accepts bang', function()
- eq('', redir_exec([[
- function F()
- endfunction!
- ]]))
- check_func('F')
- eq('', redir_exec([[
- function! F()
- return 1
- endfunction!
- ]]))
- check_func('F', 1)
- end)
- it('accepts comments', function()
- eq('', redir_exec([[
- function F1()
- endfunction " Comment
- ]]))
- check_func('F1')
- eq('', redir_exec([[
- function F2()
- endfunction " }}}
- ]]))
- check_func('F2')
- eq('', redir_exec([[
- function F3()
- endfunction " F3
- ]]))
- check_func('F3')
- eq('', redir_exec([[
- function F4()
- endfunction! " F4
- ]]))
- check_func('F4')
- eq('', redir_exec([[
- function! F4()
- return 2
- endfunction! " F4
- ]]))
- check_func('F4', 2)
- end)
- it('accepts function name', function()
- eq('', redir_exec([[
- function F0()
- endfunction F0
- ]]))
- check_func('F0')
- eq('', redir_exec([[
- function F1()
- endfunction! F1
- ]]))
- check_func('F1')
- eq('', redir_exec([[
- function! F2()
- endfunction! F2
- ]]))
- check_func('F2')
- eq('', redir_exec([[
- function! F2()
- return 3
- endfunction! F2
- ]]))
- check_func('F2', 3)
- end)
- it('accepts weird characters', function()
- eq('', redir_exec([[
- function F1()
- endfunction: }}}
- ]]))
- check_func('F1')
- -- From accurev
- eq('', redir_exec([[
- function F2()
- endfunction :}}}
- ]]))
- check_func('F2')
- -- From cream-vimabbrev
- eq('', redir_exec([[
- function F3()
- endfunction 1}}}
- ]]))
- check_func('F3')
- -- From pyunit
- eq('', redir_exec([[
- function F4()
- endfunction # }}}
- ]]))
- check_func('F4')
- -- From vim-lldb
- eq('', redir_exec([[
- function F5()
- endfunction()
- ]]))
- check_func('F5')
- -- From vim-mail
- eq('', redir_exec([[
- function F6()
- endfunction;
- ]]))
- check_func('F6')
- end)
- it('accepts commented bar', function()
- eq('', redir_exec([[
- function F1()
- endfunction " F1 | echo 42
- ]]))
- check_func('F1')
- eq('', redir_exec([[
- function! F1()
- return 42
- endfunction! " F1 | echo 42
- ]]))
- check_func('F1', 42)
- end)
- it('accepts uncommented bar', function()
- eq('\n42', redir_exec([[
- function F1()
- endfunction | echo 42
- ]]))
- check_func('F1')
- end)
- it('allows running multiple commands', function()
- eq('\n2', redir_exec([[
- function F1()
- echo 2
- endfunction
- call F1()
- ]]))
- check_func('F1', 'echo 2')
- eq('\n2\n3\n4', redir_exec([[
- function F2()
- echo 2
- endfunction F2
- function F3()
- echo 3
- endfunction " F3
- function! F4()
- echo 4
- endfunction!
- call F2()
- call F3()
- call F4()
- ]]))
- check_func('F2', 'echo 2')
- check_func('F3', 'echo 3')
- check_func('F4', 'echo 4')
- end)
- it('allows running multiple commands with only one character in between',
- function()
- eq('\n3', redir_exec(dedent([[
- function! F1()
- echo 3
- endfunction!
- call F1()]])))
- check_func('F1', 'echo 3', 2)
- eq('\n4', redir_exec(dedent([[
- function F5()
- echo 4
- endfunction
- call F5()]])))
- check_func('F5', 'echo 4', 2)
- eq('\n5', redir_exec(dedent([[
- function F6()
- echo 5
- endfunction " TEST
- call F6()]])))
- check_func('F6', 'echo 5', 2)
- eq('\n6', redir_exec(dedent([[
- function F7()
- echo 6
- endfunction F7
- call F7()]])))
- check_func('F7', 'echo 6', 2)
- eq('\n2\n3\n4', redir_exec(dedent([[
- function F2()
- echo 2
- endfunction F2
- function F3()
- echo 3
- endfunction " F3
- function! F4()
- echo 4
- endfunction!
- call F2()
- call F3()
- call F4()]])))
- check_func('F2', 'echo 2', 2)
- check_func('F3', 'echo 3', 2)
- check_func('F4', 'echo 4', 2)
- end)
-end)
--- vim: foldmarker=▶,▲
diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua
index 7d09a652ba..d07e74d40e 100644
--- a/test/functional/eval/api_functions_spec.lua
+++ b/test/functional/vimscript/api_functions_spec.lua
@@ -155,4 +155,13 @@ describe('eval-API', function()
pcall_err(command, "sandbox call nvim_input('ievil')"))
eq({''}, meths.buf_get_lines(0, 0, -1, true))
end)
+
+ it('converts blobs to API strings', function()
+ command('let g:v1 = nvim__id(0z68656c6c6f)')
+ command('let g:v2 = nvim__id(v:_null_blob)')
+ eq(1, eval('type(g:v1)'))
+ eq(1, eval('type(g:v2)'))
+ eq('hello', eval('g:v1'))
+ eq('', eval('g:v2'))
+ end)
end)
diff --git a/test/functional/eval/buf_functions_spec.lua b/test/functional/vimscript/buf_functions_spec.lua
index 06841a4521..e957e5f5af 100644
--- a/test/functional/eval/buf_functions_spec.lua
+++ b/test/functional/vimscript/buf_functions_spec.lua
@@ -221,9 +221,9 @@ describe('getbufvar() function', function()
eq(0, funcs.getbufvar(1, '&l:autoindent'))
eq(0, funcs.getbufvar(1, '&g:autoindent'))
-- Also works with global-only options
- eq(0, funcs.getbufvar(1, '&hidden'))
- eq(0, funcs.getbufvar(1, '&l:hidden'))
- eq(0, funcs.getbufvar(1, '&g:hidden'))
+ eq(1, funcs.getbufvar(1, '&hidden'))
+ eq(1, funcs.getbufvar(1, '&l:hidden'))
+ eq(1, funcs.getbufvar(1, '&g:hidden'))
-- Also works with window-local options
eq(0, funcs.getbufvar(1, '&number'))
eq(0, funcs.getbufvar(1, '&l:number'))
@@ -279,9 +279,9 @@ describe('setbufvar() function', function()
eq(false, winmeths.get_option(windows[3], 'number'))
eq(false, winmeths.get_option(meths.get_current_win(), 'number'))
- eq(false, meths.get_option('hidden'))
- funcs.setbufvar(1, '&hidden', true)
eq(true, meths.get_option('hidden'))
+ funcs.setbufvar(1, '&hidden', 0)
+ eq(false, meths.get_option('hidden'))
eq(false, bufmeths.get_option(buf1, 'autoindent'))
funcs.setbufvar(1, '&autoindent', true)
diff --git a/test/functional/eval/changedtick_spec.lua b/test/functional/vimscript/changedtick_spec.lua
index 99406d9d7a..8533fac9ec 100644
--- a/test/functional/eval/changedtick_spec.lua
+++ b/test/functional/vimscript/changedtick_spec.lua
@@ -8,8 +8,8 @@ local funcs = helpers.funcs
local meths = helpers.meths
local command = helpers.command
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
local pcall_err = helpers.pcall_err
+local exec_capture = helpers.exec_capture
local curbufmeths = helpers.curbufmeths
before_each(clear)
@@ -56,35 +56,35 @@ describe('b:changedtick', function()
local ct = changedtick()
local ctn = ct + 100500
eq(0, exc_exec('let d = b:'))
- eq('\nE46: Cannot change read-only variable "b:changedtick"',
- redir_exec('let b:changedtick = ' .. ctn))
- eq('\nE46: Cannot change read-only variable "b:["changedtick"]"',
- redir_exec('let b:["changedtick"] = ' .. ctn))
- eq('\nE46: Cannot change read-only variable "b:.changedtick"',
- redir_exec('let b:.changedtick = ' .. ctn))
- eq('\nE46: Cannot change read-only variable "d.changedtick"',
- redir_exec('let d.changedtick = ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:changedtick"',
+ pcall_err(command, 'let b:changedtick = ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] = ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:.changedtick"',
+ pcall_err(command, 'let b:.changedtick = ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'let d.changedtick = ' .. ctn))
eq('Key is read-only: changedtick',
pcall_err(curbufmeths.set_var, 'changedtick', ctn))
- eq('\nE795: Cannot delete variable b:changedtick',
- redir_exec('unlet b:changedtick'))
- eq('\nE46: Cannot change read-only variable "b:.changedtick"',
- redir_exec('unlet b:.changedtick'))
- eq('\nE46: Cannot change read-only variable "b:["changedtick"]"',
- redir_exec('unlet b:["changedtick"]'))
- eq('\nE46: Cannot change read-only variable "d.changedtick"',
- redir_exec('unlet d.changedtick'))
+ eq('Vim(unlet):E795: Cannot delete variable b:changedtick',
+ pcall_err(command, 'unlet b:changedtick'))
+ eq('Vim(unlet):E46: Cannot change read-only variable "b:.changedtick"',
+ pcall_err(command, 'unlet b:.changedtick'))
+ eq('Vim(unlet):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'unlet b:["changedtick"]'))
+ eq('Vim(unlet):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'unlet d.changedtick'))
eq('Key is read-only: changedtick',
pcall_err(curbufmeths.del_var, 'changedtick'))
eq(ct, changedtick())
- eq('\nE46: Cannot change read-only variable "b:["changedtick"]"',
- redir_exec('let b:["changedtick"] += ' .. ctn))
- eq('\nE46: Cannot change read-only variable "b:["changedtick"]"',
- redir_exec('let b:["changedtick"] -= ' .. ctn))
- eq('\nE46: Cannot change read-only variable "b:["changedtick"]"',
- redir_exec('let b:["changedtick"] .= ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] += ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] -= ' .. ctn))
+ eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] .= ' .. ctn))
eq(ct, changedtick())
@@ -93,23 +93,22 @@ describe('b:changedtick', function()
eq(ct + 1, changedtick())
end)
it('is listed in :let output', function()
- eq('\nb:changedtick #2',
- redir_exec(':let b:'))
+ eq('b:changedtick #2', exec_capture(':let b:'))
end)
it('fails to unlock b:changedtick', function()
eq(0, exc_exec('let d = b:'))
eq(0, funcs.islocked('b:changedtick'))
eq(0, funcs.islocked('d.changedtick'))
- eq('\nE940: Cannot lock or unlock variable b:changedtick',
- redir_exec('unlockvar b:changedtick'))
- eq('\nE46: Cannot change read-only variable "d.changedtick"',
- redir_exec('unlockvar d.changedtick'))
+ eq('Vim(unlockvar):E940: Cannot lock or unlock variable b:changedtick',
+ pcall_err(command, 'unlockvar b:changedtick'))
+ eq('Vim(unlockvar):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'unlockvar d.changedtick'))
eq(0, funcs.islocked('b:changedtick'))
eq(0, funcs.islocked('d.changedtick'))
- eq('\nE940: Cannot lock or unlock variable b:changedtick',
- redir_exec('lockvar b:changedtick'))
- eq('\nE46: Cannot change read-only variable "d.changedtick"',
- redir_exec('lockvar d.changedtick'))
+ eq('Vim(lockvar):E940: Cannot lock or unlock variable b:changedtick',
+ pcall_err(command, 'lockvar b:changedtick'))
+ eq('Vim(lockvar):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'lockvar d.changedtick'))
eq(0, funcs.islocked('b:changedtick'))
eq(0, funcs.islocked('d.changedtick'))
end)
@@ -119,24 +118,24 @@ describe('b:changedtick', function()
end)
it('cannot be changed by filter() or map()', function()
eq(2, changedtick())
- eq('\nE795: Cannot delete variable filter() argument',
- redir_exec('call filter(b:, 0)'))
- eq('\nE742: Cannot change value of map() argument',
- redir_exec('call map(b:, 0)'))
- eq('\nE742: Cannot change value of map() argument',
- redir_exec('call map(b:, "v:val")'))
+ eq('Vim(call):E795: Cannot delete variable filter() argument',
+ pcall_err(command, 'call filter(b:, 0)'))
+ eq('Vim(call):E742: Cannot change value of map() argument',
+ pcall_err(command, 'call map(b:, 0)'))
+ eq('Vim(call):E742: Cannot change value of map() argument',
+ pcall_err(command, 'call map(b:, "v:val")'))
eq(2, changedtick())
end)
it('cannot be remove()d', function()
eq(2, changedtick())
- eq('\nE795: Cannot delete variable remove() argument',
- redir_exec('call remove(b:, "changedtick")'))
+ eq('Vim(call):E795: Cannot delete variable remove() argument',
+ pcall_err(command, 'call remove(b:, "changedtick")'))
eq(2, changedtick())
end)
it('does not inherit VAR_FIXED when copying dictionary over', function()
eq(2, changedtick())
- eq('', redir_exec('let d1 = copy(b:)|let d1.changedtick = 42'))
- eq('', redir_exec('let d2 = copy(b:)|unlet d2.changedtick'))
+ eq('', exec_capture('let d1 = copy(b:)|let d1.changedtick = 42'))
+ eq('', exec_capture('let d2 = copy(b:)|unlet d2.changedtick'))
eq(2, changedtick())
end)
end)
diff --git a/test/functional/eval/container_functions_spec.lua b/test/functional/vimscript/container_functions_spec.lua
index 04a3248c49..04a3248c49 100644
--- a/test/functional/eval/container_functions_spec.lua
+++ b/test/functional/vimscript/container_functions_spec.lua
diff --git a/test/functional/eval/ctx_functions_spec.lua b/test/functional/vimscript/ctx_functions_spec.lua
index f23adbc556..d92a81c55b 100644
--- a/test/functional/eval/ctx_functions_spec.lua
+++ b/test/functional/vimscript/ctx_functions_spec.lua
@@ -9,7 +9,7 @@ local feed = helpers.feed
local map = helpers.tbl_map
local nvim = helpers.nvim
local parse_context = helpers.parse_context
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local source = helpers.source
local trim = helpers.trim
local write_file = helpers.write_file
@@ -163,33 +163,29 @@ describe('context functions', function()
endfunction
]])
- eq('\nHello, World!', redir_exec([[call Greet('World')]]))
- eq('\nHello, World!'..
+ eq('Hello, World!', exec_capture([[call Greet('World')]]))
+ eq('Hello, World!'..
'\nHello, One!'..
'\nHello, Two!'..
'\nHello, Three!',
- redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
call('SaveSFuncs')
call('DeleteSFuncs')
- eq('\nError detected while processing function Greet:'..
- '\nline 1:'..
- '\nE117: Unknown function: s:greet',
- redir_exec([[call Greet('World')]]))
- eq('\nError detected while processing function GreetAll:'..
- '\nline 1:'..
- '\nE117: Unknown function: s:greet_all',
- redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq('Vim(call):E117: Unknown function: s:greet',
+ pcall_err(command, [[call Greet('World')]]))
+ eq('Vim(call):E117: Unknown function: s:greet_all',
+ pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]]))
call('RestoreFuncs')
- eq('\nHello, World!', redir_exec([[call Greet('World')]]))
- eq('\nHello, World!'..
+ eq('Hello, World!', exec_capture([[call Greet('World')]]))
+ eq('Hello, World!'..
'\nHello, One!'..
'\nHello, Two!'..
'\nHello, Three!',
- redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
end)
it('saves and restores functions properly', function()
@@ -206,12 +202,12 @@ describe('context functions', function()
endfunction
]])
- eq('\nHello, World!', redir_exec([[call Greet('World')]]))
- eq('\nHello, World!'..
+ eq('Hello, World!', exec_capture([[call Greet('World')]]))
+ eq('Hello, World!'..
'\nHello, One!'..
'\nHello, Two!'..
'\nHello, Three!',
- redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
call('ctxpush', {'funcs'})
command('delfunction Greet')
@@ -223,12 +219,12 @@ describe('context functions', function()
call('ctxpop')
- eq('\nHello, World!', redir_exec([[call Greet('World')]]))
- eq('\nHello, World!'..
+ eq('Hello, World!', exec_capture([[call Greet('World')]]))
+ eq('Hello, World!'..
'\nHello, One!'..
'\nHello, Two!'..
'\nHello, Three!',
- redir_exec([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
end)
it('errors out when context stack is empty', function()
diff --git a/test/functional/eval/environ_spec.lua b/test/functional/vimscript/environ_spec.lua
index 9e19568249..9e19568249 100644
--- a/test/functional/eval/environ_spec.lua
+++ b/test/functional/vimscript/environ_spec.lua
diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/vimscript/errorlist_spec.lua
index 077d816903..077d816903 100644
--- a/test/functional/viml/errorlist_spec.lua
+++ b/test/functional/vimscript/errorlist_spec.lua
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
new file mode 100644
index 0000000000..e1459ab5b8
--- /dev/null
+++ b/test/functional/vimscript/eval_spec.lua
@@ -0,0 +1,146 @@
+-- Tests for core Vimscript "eval" behavior.
+--
+-- See also:
+-- let_spec.lua
+-- null_spec.lua
+-- operators_spec.lua
+--
+-- Tests for the Vimscript |functions| library should live in:
+-- test/functional/vimscript/<funcname>_spec.lua
+-- test/functional/vimscript/functions_spec.lua
+
+local helpers = require('test.functional.helpers')(after_each)
+
+local lfs = require('lfs')
+local clear = helpers.clear
+local eq = helpers.eq
+local exc_exec = helpers.exc_exec
+local eval = helpers.eval
+local command = helpers.command
+local write_file = helpers.write_file
+local meths = helpers.meths
+local sleep = helpers.sleep
+local poke_eventloop = helpers.poke_eventloop
+local feed = helpers.feed
+
+describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
+ local max_func_args = 20 -- from eval.h
+ local range = helpers.funcs.range
+
+ before_each(clear)
+
+ it('printf()', function()
+ local printf = helpers.funcs.printf
+ local rep = helpers.funcs['repeat']
+ local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
+ eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args))))
+ local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function printf', ret)
+ end)
+
+ it('rpcnotify()', function()
+ local rpcnotify = helpers.funcs.rpcnotify
+ local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args)))
+ eq(1, ret)
+ ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function rpcnotify', ret)
+ end)
+end)
+
+describe("backtick expansion", function()
+ setup(function()
+ clear()
+ lfs.mkdir("test-backticks")
+ write_file("test-backticks/file1", "test file 1")
+ write_file("test-backticks/file2", "test file 2")
+ write_file("test-backticks/file3", "test file 3")
+ lfs.mkdir("test-backticks/subdir")
+ write_file("test-backticks/subdir/file4", "test file 4")
+ -- Long path might cause "Press ENTER" prompt; use :silent to avoid it.
+ command('silent cd test-backticks')
+ end)
+
+ teardown(function()
+ helpers.rmdir('test-backticks')
+ end)
+
+ it("with default 'shell'", function()
+ if helpers.iswin() then
+ command(":silent args `dir /b *2`")
+ else
+ command(":silent args `echo ***2`")
+ end
+ eq({ "file2", }, eval("argv()"))
+ if helpers.iswin() then
+ command(":silent args `dir /s/b *4`")
+ eq({ "subdir\\file4", }, eval("map(argv(), 'fnamemodify(v:val, \":.\")')"))
+ else
+ command(":silent args `echo */*4`")
+ eq({ "subdir/file4", }, eval("argv()"))
+ end
+ end)
+
+ it("with shell=fish", function()
+ if eval("executable('fish')") == 0 then
+ pending('missing "fish" command')
+ return
+ end
+ command("set shell=fish")
+ command(":silent args `echo ***2`")
+ eq({ "file2", }, eval("argv()"))
+ command(":silent args `echo */*4`")
+ eq({ "subdir/file4", }, eval("argv()"))
+ end)
+end)
+
+describe('List support code', function()
+ local dur
+ local min_dur = 8
+ local len = 131072
+
+ if not pending('does not actually allows interrupting with just got_int', function() end) then return end
+ -- The following tests are confirmed to work with os_breakcheck() just before
+ -- `if (got_int) {break;}` in tv_list_copy and list_join_inner() and not to
+ -- work without.
+ setup(function()
+ clear()
+ dur = 0
+ while true do
+ command(([[
+ let rt = reltime()
+ let bl = range(%u)
+ let dur = reltimestr(reltime(rt))
+ ]]):format(len))
+ dur = tonumber(meths.get_var('dur'))
+ if dur >= min_dur then
+ -- print(('Using len %u, dur %g'):format(len, dur))
+ break
+ else
+ len = len * 2
+ end
+ end
+ end)
+ it('allows interrupting copy', function()
+ feed(':let t_rt = reltime()<CR>:let t_bl = copy(bl)<CR>')
+ sleep(min_dur / 16 * 1000)
+ feed('<C-c>')
+ poke_eventloop()
+ command('let t_dur = reltimestr(reltime(t_rt))')
+ local t_dur = tonumber(meths.get_var('t_dur'))
+ if t_dur >= dur / 8 then
+ eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
+ end
+ end)
+ it('allows interrupting join', function()
+ feed(':let t_rt = reltime()<CR>:let t_j = join(bl)<CR>')
+ sleep(min_dur / 16 * 1000)
+ feed('<C-c>')
+ poke_eventloop()
+ command('let t_dur = reltimestr(reltime(t_rt))')
+ local t_dur = tonumber(meths.get_var('t_dur'))
+ print(('t_dur: %g'):format(t_dur))
+ if t_dur >= dur / 8 then
+ eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
+ end
+ end)
+end)
diff --git a/test/functional/eval/executable_spec.lua b/test/functional/vimscript/executable_spec.lua
index 28aefb72e5..28aefb72e5 100644
--- a/test/functional/eval/executable_spec.lua
+++ b/test/functional/vimscript/executable_spec.lua
diff --git a/test/functional/eval/execute_spec.lua b/test/functional/vimscript/execute_spec.lua
index f52ac4e59b..e21c71dc7f 100644
--- a/test/functional/eval/execute_spec.lua
+++ b/test/functional/vimscript/execute_spec.lua
@@ -3,7 +3,6 @@ local eq = helpers.eq
local eval = helpers.eval
local clear = helpers.clear
local source = helpers.source
-local redir_exec = helpers.redir_exec
local exc_exec = helpers.exc_exec
local funcs = helpers.funcs
local Screen = require('test.functional.ui.screen')
@@ -15,7 +14,14 @@ describe('execute()', function()
before_each(clear)
it('captures the same result as :redir', function()
- eq(redir_exec('messages'), funcs.execute('messages'))
+ command([[
+ echomsg 'foo 1'
+ echomsg 'foo 2'
+ redir => g:__redir_output
+ silent! messages
+ redir END
+ ]])
+ eq(eval('g:__redir_output'), funcs.execute('messages'))
end)
it('captures the concatenated outputs of a List of commands', function()
@@ -322,16 +328,16 @@ describe('execute()', function()
eq('Vim(call):E731: using Dictionary as a String', ret)
ret = exc_exec('call execute("echo add(1, 1)", "")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute("echo add(1, 1)", "silent")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
ret = exc_exec('call execute(["echon 42", "echo add(1, 1)"], "silent")')
- eq('Vim(echo):E714: List required', ret)
+ eq('Vim(echo):E897: List or Blob required', ret)
end)
end)
end)
diff --git a/test/functional/eval/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index 08d2c59af8..08d2c59af8 100644
--- a/test/functional/eval/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
diff --git a/test/functional/eval/fnamemodify_spec.lua b/test/functional/vimscript/fnamemodify_spec.lua
index d54a6db417..d54a6db417 100644
--- a/test/functional/eval/fnamemodify_spec.lua
+++ b/test/functional/vimscript/fnamemodify_spec.lua
diff --git a/test/functional/vimscript/functions_spec.lua b/test/functional/vimscript/functions_spec.lua
new file mode 100644
index 0000000000..0ad7fd8010
--- /dev/null
+++ b/test/functional/vimscript/functions_spec.lua
@@ -0,0 +1,20 @@
+-- Tests for misc Vimscript |functions|.
+--
+-- If a function is non-trivial, consider moving its spec to:
+-- test/functional/vimscript/<funcname>_spec.lua
+--
+-- Core "eval" tests live in eval_spec.lua.
+
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eval = helpers.eval
+local iswin = helpers.iswin
+local matches = helpers.matches
+
+before_each(clear)
+
+it('windowsversion()', function()
+ clear()
+ matches(iswin() and '^%d+%.%d+$' or '^$', eval('windowsversion()'))
+end)
diff --git a/test/functional/eval/getline_spec.lua b/test/functional/vimscript/getline_spec.lua
index 3c56bde094..3c56bde094 100644
--- a/test/functional/eval/getline_spec.lua
+++ b/test/functional/vimscript/getline_spec.lua
diff --git a/test/functional/eval/glob_spec.lua b/test/functional/vimscript/glob_spec.lua
index b8807ecfcc..b8807ecfcc 100644
--- a/test/functional/eval/glob_spec.lua
+++ b/test/functional/vimscript/glob_spec.lua
diff --git a/test/functional/eval/has_spec.lua b/test/functional/vimscript/has_spec.lua
index a3af2d1a20..a3af2d1a20 100644
--- a/test/functional/eval/has_spec.lua
+++ b/test/functional/vimscript/has_spec.lua
diff --git a/test/functional/eval/hostname_spec.lua b/test/functional/vimscript/hostname_spec.lua
index 6112cf64e3..6112cf64e3 100644
--- a/test/functional/eval/hostname_spec.lua
+++ b/test/functional/vimscript/hostname_spec.lua
diff --git a/test/functional/eval/input_spec.lua b/test/functional/vimscript/input_spec.lua
index 14c02f9eb2..14c02f9eb2 100644
--- a/test/functional/eval/input_spec.lua
+++ b/test/functional/vimscript/input_spec.lua
diff --git a/test/functional/eval/json_functions_spec.lua b/test/functional/vimscript/json_functions_spec.lua
index 8dcaea806e..c3b607b544 100644
--- a/test/functional/eval/json_functions_spec.lua
+++ b/test/functional/vimscript/json_functions_spec.lua
@@ -6,7 +6,7 @@ local eq = helpers.eq
local eval = helpers.eval
local command = helpers.command
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
local NIL = helpers.NIL
local source = helpers.source
@@ -517,9 +517,8 @@ describe('json_decode() function', function()
it('does not overflow when writing error message about decoding ["", ""]',
function()
- eq('\nE474: Attempt to decode a blank string'
- .. '\nE474: Failed to parse \n',
- redir_exec('call json_decode(["", ""])'))
+ eq('Vim(call):E474: Attempt to decode a blank string',
+ pcall_err(command, 'call json_decode(["", ""])'))
end)
end)
@@ -538,6 +537,11 @@ describe('json_encode() function', function()
eq('"þÿþ"', funcs.json_encode('þÿþ'))
end)
+ it('dumps blobs', function()
+ eq('[]', eval('json_encode(0z)'))
+ eq('[222, 173, 190, 239]', eval('json_encode(0zDEADBEEF)'))
+ end)
+
it('dumps numbers', function()
eq('0', funcs.json_encode(0))
eq('10', funcs.json_encode(10))
@@ -769,6 +773,10 @@ describe('json_encode() function', function()
eq('""', eval('json_encode($XXX_UNEXISTENT_VAR_XXX)'))
end)
+ it('can dump NULL blob', function()
+ eq('[]', eval('json_encode(v:_null_blob)'))
+ end)
+
it('can dump NULL list', function()
eq('[]', eval('json_encode(v:_null_list)'))
end)
diff --git a/test/functional/viml/lang_spec.lua b/test/functional/vimscript/lang_spec.lua
index 6d603b8822..d5254986ab 100644
--- a/test/functional/viml/lang_spec.lua
+++ b/test/functional/vimscript/lang_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq
local exc_exec, source = helpers.exc_exec, helpers.source
-describe('viml', function()
+describe('vimscript', function()
before_each(clear)
it('parses `<SID>` with turkish locale', function()
diff --git a/test/functional/eval/let_spec.lua b/test/functional/vimscript/let_spec.lua
index 5bc703b567..4ff4090a18 100644
--- a/test/functional/eval/let_spec.lua
+++ b/test/functional/vimscript/let_spec.lua
@@ -5,7 +5,7 @@ local clear = helpers.clear
local command = helpers.command
local eval = helpers.eval
local meths = helpers.meths
-local redir_exec = helpers.redir_exec
+local exec_capture = helpers.exec_capture
local source = helpers.source
local nvim_dir = helpers.nvim_dir
@@ -14,14 +14,14 @@ before_each(clear)
describe(':let', function()
it('correctly lists variables with curly-braces', function()
meths.set_var('v', {0})
- eq('\nv [0]', redir_exec('let {"v"}'))
+ eq('v [0]', exec_capture('let {"v"}'))
end)
it('correctly lists variables with subscript', function()
meths.set_var('v', {0})
- eq('\nv[0] #0', redir_exec('let v[0]'))
- eq('\ng:["v"][0] #0', redir_exec('let g:["v"][0]'))
- eq('\n{"g:"}["v"][0] #0', redir_exec('let {"g:"}["v"][0]'))
+ eq('v[0] #0', exec_capture('let v[0]'))
+ eq('g:["v"][0] #0', exec_capture('let g:["v"][0]'))
+ eq('{"g:"}["v"][0] #0', exec_capture('let {"g:"}["v"][0]'))
end)
it(":unlet self-referencing node in a List graph #6070", function()
diff --git a/test/functional/eval/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua
index 275c72d212..275c72d212 100644
--- a/test/functional/eval/map_functions_spec.lua
+++ b/test/functional/vimscript/map_functions_spec.lua
diff --git a/test/functional/eval/match_functions_spec.lua b/test/functional/vimscript/match_functions_spec.lua
index f399ef47d3..9f168c913a 100644
--- a/test/functional/eval/match_functions_spec.lua
+++ b/test/functional/vimscript/match_functions_spec.lua
@@ -6,7 +6,6 @@ local clear = helpers.clear
local funcs = helpers.funcs
local command = helpers.command
local exc_exec = helpers.exc_exec
-local pcall_err = helpers.pcall_err
before_each(clear)
@@ -40,13 +39,13 @@ describe('setmatches()', function()
}}, funcs.getmatches())
end)
- it('fails with -1 if highlight group is not defined', function()
- eq('Vim:E28: No such highlight group name: 1',
- pcall_err(funcs.setmatches, {{group=1, pattern=2, id=3, priority=4}}))
- eq({}, funcs.getmatches())
- eq('Vim:E28: No such highlight group name: 1',
- pcall_err(funcs.setmatches, {{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
- eq({}, funcs.getmatches())
+ it('does not fail if highlight group is not defined', function()
+ eq(0, funcs.setmatches{{group=1, pattern=2, id=3, priority=4}})
+ eq({{group='1', pattern='2', id=3, priority=4}},
+ funcs.getmatches())
+ eq(0, funcs.setmatches{{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}})
+ eq({{group='1', pos1={2}, pos2={6}, id=3, priority=4, conceal='5'}},
+ funcs.getmatches())
end)
end)
diff --git a/test/functional/eval/minmax_functions_spec.lua b/test/functional/vimscript/minmax_functions_spec.lua
index c6eb754f91..91106bef1e 100644
--- a/test/functional/eval/minmax_functions_spec.lua
+++ b/test/functional/vimscript/minmax_functions_spec.lua
@@ -2,29 +2,28 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local eval = helpers.eval
+local command = helpers.command
local clear = helpers.clear
local funcs = helpers.funcs
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
before_each(clear)
for _, func in ipairs({'min', 'max'}) do
describe(func .. '()', function()
it('gives a single error message when multiple values failed conversions',
function()
- eq('\nE745: Using a List as a Number\n0',
- redir_exec('echo ' .. func .. '([-5, [], [], [], 5])'))
- eq('\nE745: Using a List as a Number\n0',
- redir_exec('echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})'))
+ eq('Vim(echo):E745: Using a List as a Number',
+ pcall_err(command, 'echo ' .. func .. '([-5, [], [], [], 5])'))
+ eq('Vim(echo):E745: Using a List as a Number',
+ pcall_err(command, 'echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})'))
for errmsg, errinput in pairs({
- ['E745: Using a List as a Number'] = '[]',
- ['E805: Using a Float as a Number'] = '0.0',
- ['E703: Using a Funcref as a Number'] = 'function("tr")',
- ['E728: Using a Dictionary as a Number'] = '{}',
+ ['Vim(echo):E745: Using a List as a Number'] = '[]',
+ ['Vim(echo):E805: Using a Float as a Number'] = '0.0',
+ ['Vim(echo):E703: Using a Funcref as a Number'] = 'function("tr")',
+ ['Vim(echo):E728: Using a Dictionary as a Number'] = '{}',
}) do
- eq('\n' .. errmsg .. '\n0',
- redir_exec('echo ' .. func .. '([' .. errinput .. '])'))
- eq('\n' .. errmsg .. '\n0',
- redir_exec('echo ' .. func .. '({1:' .. errinput .. '})'))
+ eq(errmsg, pcall_err(command, 'echo ' .. func .. '([' .. errinput .. '])'))
+ eq(errmsg, pcall_err(command, 'echo ' .. func .. '({1:' .. errinput .. '})'))
end
end)
it('works with arrays/dictionaries with zero items', function()
@@ -42,9 +41,8 @@ for _, func in ipairs({'min', 'max'}) do
it('errors out for invalid types', function()
for _, errinput in ipairs({'1', 'v:true', 'v:false', 'v:null',
'function("tr")', '""'}) do
- eq(('\nE712: Argument of %s() must be a List or Dictionary\n0'):format(
- func),
- redir_exec('echo ' .. func .. '(' .. errinput .. ')'))
+ eq(('Vim(echo):E712: Argument of %s() must be a List or Dictionary'):format(func),
+ pcall_err(command, 'echo ' .. func .. '(' .. errinput .. ')'))
end
end)
end)
diff --git a/test/functional/eval/modeline_spec.lua b/test/functional/vimscript/modeline_spec.lua
index c5bb798f4a..b2346079a1 100644
--- a/test/functional/eval/modeline_spec.lua
+++ b/test/functional/vimscript/modeline_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear, command, write_file = helpers.clear, helpers.command, helpers.write_file
-local eq, eval = helpers.eq, helpers.eval
describe("modeline", function()
local tempfile = helpers.tmpname()
@@ -14,6 +14,6 @@ describe("modeline", function()
write_file(tempfile, 'vim100000000000000000000000')
command('e! ' .. tempfile)
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/vimscript/msgpack_functions_spec.lua
index a8a413f68b..837b629858 100644
--- a/test/functional/eval/msgpack_functions_spec.lua
+++ b/test/functional/vimscript/msgpack_functions_spec.lua
@@ -13,6 +13,7 @@ describe('msgpack*() functions', function()
it(msg, function()
nvim('set_var', 'obj', obj)
eq(obj, eval('msgpackparse(msgpackdump(g:obj))'))
+ eq(obj, eval('msgpackparse(msgpackdump(g:obj, "B"))'))
end)
end
@@ -364,8 +365,7 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xC4\\x01\\n"]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq({{_TYPE={}, _VAL={'\n'}}}, eval('parsed'))
- eq(1, eval('parsed[0]._TYPE is v:msgpack_types.binary'))
+ eq({'\000'}, eval('parsed'))
eq(1, eval('dumped ==# dumped2'))
end)
@@ -392,56 +392,61 @@ describe('msgpack*() functions', function()
end)
end)
+local blobstr = function(list)
+ local l = {}
+ for i,v in ipairs(list) do
+ l[i] = v:gsub('\n', '\000')
+ end
+ return table.concat(l, '\n')
+end
+
+-- Test msgpackparse() with a readfile()-style list and a blob argument
+local parse_eq = function(expect, list_arg)
+ local blob_expr = '0z' .. blobstr(list_arg):gsub('(.)', function(c)
+ return ('%.2x'):format(c:byte())
+ end)
+ eq(expect, funcs.msgpackparse(list_arg))
+ command('let g:parsed = msgpackparse(' .. blob_expr .. ')')
+ eq(expect, eval('g:parsed'))
+end
+
describe('msgpackparse() function', function()
before_each(clear)
it('restores nil as v:null', function()
- command('let dumped = ["\\xC0"]')
- command('let parsed = msgpackparse(dumped)')
- eq('[v:null]', eval('string(parsed)'))
+ parse_eq(eval('[v:null]'), {'\192'})
end)
it('restores boolean false as v:false', function()
- command('let dumped = ["\\xC2"]')
- command('let parsed = msgpackparse(dumped)')
- eq({false}, eval('parsed'))
+ parse_eq({false}, {'\194'})
end)
it('restores boolean true as v:true', function()
- command('let dumped = ["\\xC3"]')
- command('let parsed = msgpackparse(dumped)')
- eq({true}, eval('parsed'))
+ parse_eq({true}, {'\195'})
end)
it('restores FIXSTR as special dict', function()
- command('let dumped = ["\\xa2ab"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={'ab'}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={'ab'}}}, {'\162ab'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.string'))
end)
it('restores BIN 8 as string', function()
- command('let dumped = ["\\xC4\\x02ab"]')
- eq({'ab'}, eval('msgpackparse(dumped)'))
+ parse_eq({'ab'}, {'\196\002ab'})
end)
it('restores FIXEXT1 as special dictionary', function()
- command('let dumped = ["\\xD4\\x10", ""]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, {'\212\016', ''})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext'))
end)
it('restores MAP with BIN key as special dictionary', function()
- command('let dumped = ["\\x81\\xC4\\x01a\\xC4\\n"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={{'a', ''}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={{'a', ''}}}}, {'\129\196\001a\196\n'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
it('restores MAP with duplicate STR keys as special dictionary', function()
command('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]')
- -- FIXME Internal error bug
+ -- FIXME Internal error bug, can't use parse_eq() here
command('silent! let parsed = msgpackparse(dumped)')
eq({{_TYPE={}, _VAL={ {{_TYPE={}, _VAL={'a'}}, ''},
{{_TYPE={}, _VAL={'a'}}, ''}}} }, eval('parsed'))
@@ -451,9 +456,7 @@ describe('msgpackparse() function', function()
end)
it('restores MAP with MAP key as special dictionary', function()
- command('let dumped = ["\\x81\\x80\\xC4\\n"]')
- command('let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={{{}, ''}}}}, eval('parsed'))
+ parse_eq({{_TYPE={}, _VAL={{{}, ''}}}}, {'\129\128\196\n'})
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
@@ -478,43 +481,65 @@ describe('msgpackparse() function', function()
end)
it('fails to parse a string', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse("abcdefghijklmnopqrstuvwxyz")'))
end)
it('fails to parse a number', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(127)'))
end)
it('fails to parse a dictionary', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse({})'))
end)
it('fails to parse a funcref', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(function("tr"))'))
end)
it('fails to parse a partial', function()
command('function T() dict\nendfunction')
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(function("T", [1, 2], {}))'))
end)
it('fails to parse a float', function()
- eq('Vim(call):E686: Argument of msgpackparse() must be a List',
+ eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
exc_exec('call msgpackparse(0.0)'))
end)
+
+ it('fails on incomplete msgpack string', function()
+ local expected = 'Vim(call):E475: Invalid argument: Incomplete msgpack string'
+ eq(expected, exc_exec([[call msgpackparse(["\xc4"])]]))
+ eq(expected, exc_exec([[call msgpackparse(["\xca", "\x02\x03"])]]))
+ eq(expected, exc_exec('call msgpackparse(0zc4)'))
+ eq(expected, exc_exec('call msgpackparse(0zca0a0203)'))
+ end)
+
+ it('fails when unable to parse msgpack string', function()
+ local expected = 'Vim(call):E475: Invalid argument: Failed to parse msgpack string'
+ eq(expected, exc_exec([[call msgpackparse(["\xc1"])]]))
+ eq(expected, exc_exec('call msgpackparse(0zc1)'))
+ end)
end)
describe('msgpackdump() function', function()
before_each(clear)
+ local dump_eq = function(exp_list, arg_expr)
+ eq(exp_list, eval('msgpackdump(' .. arg_expr .. ')'))
+ eq(blobstr(exp_list), eval('msgpackdump(' .. arg_expr .. ', "B")'))
+ end
+
it('dumps string as BIN 8', function()
- nvim('set_var', 'obj', {'Test'})
- eq({"\196\004Test"}, eval('msgpackdump(obj)'))
+ dump_eq({'\196\004Test'}, '["Test"]')
+ end)
+
+ it('dumps blob as BIN 8', function()
+ dump_eq({'\196\005Bl\nb!'}, '[0z426c006221]')
end)
it('can dump generic mapping with generic mapping keys and values', function()
@@ -522,56 +547,56 @@ describe('msgpackdump() function', function()
command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, [todumpv1, todumpv2])')
- eq({'\129\128\128'}, eval('msgpackdump([todump])'))
+ dump_eq({'\129\128\128'}, '[todump]')
end)
it('can dump v:true', function()
- eq({'\195'}, funcs.msgpackdump({true}))
+ dump_eq({'\195'}, '[v:true]')
end)
it('can dump v:false', function()
- eq({'\194'}, funcs.msgpackdump({false}))
+ dump_eq({'\194'}, '[v:false]')
end)
- it('can v:null', function()
- command('let todump = v:null')
+ it('can dump v:null', function()
+ dump_eq({'\192'}, '[v:null]')
end)
it('can dump special bool mapping (true)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
- eq({'\195'}, eval('msgpackdump([todump])'))
+ dump_eq({'\195'}, '[todump]')
end)
it('can dump special bool mapping (false)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
- eq({'\194'}, eval('msgpackdump([todump])'))
+ dump_eq({'\194'}, '[todump]')
end)
it('can dump special nil mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
- eq({'\192'}, eval('msgpackdump([todump])'))
+ dump_eq({'\192'}, '[todump]')
end)
it('can dump special ext mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
- eq({'\212\005', ''}, eval('msgpackdump([todump])'))
+ dump_eq({'\212\005', ''}, '[todump]')
end)
it('can dump special array mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
- eq({'\146\005\145\196\n'}, eval('msgpackdump([todump])'))
+ dump_eq({'\146\005\145\196\n'}, '[todump]')
end)
it('can dump special UINT64_MAX mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
- eq({'\207\255\255\255\255\255\255\255\255'}, eval('msgpackdump([todump])'))
+ dump_eq({'\207\255\255\255\255\255\255\255\255'}, '[todump]')
end)
it('can dump special INT64_MIN mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [-1, 2, 0, 0]')
- eq({'\211\128\n\n\n\n\n\n\n'}, eval('msgpackdump([todump])'))
+ dump_eq({'\211\128\n\n\n\n\n\n\n'}, '[todump]')
end)
it('fails to dump a function reference', function()
@@ -610,13 +635,13 @@ describe('msgpackdump() function', function()
it('can dump dict with two same dicts inside', function()
command('let inter = {}')
command('let todump = {"a": inter, "b": inter}')
- eq({"\130\161a\128\161b\128"}, eval('msgpackdump([todump])'))
+ dump_eq({"\130\161a\128\161b\128"}, '[todump]')
end)
it('can dump list with two same lists inside', function()
command('let inter = []')
command('let todump = [inter, inter]')
- eq({"\146\144\144"}, eval('msgpackdump([todump])'))
+ dump_eq({"\146\144\144"}, '[todump]')
end)
it('fails to dump a recursive list in a special dict', function()
@@ -667,9 +692,9 @@ describe('msgpackdump() function', function()
exc_exec('call msgpackdump()'))
end)
- it('fails when called with two arguments', function()
+ it('fails when called with three arguments', function()
eq('Vim(call):E118: Too many arguments for function: msgpackdump',
- exc_exec('call msgpackdump(["", ""], 1)'))
+ exc_exec('call msgpackdump(["", ""], 1, 2)'))
end)
it('fails to dump a string', function()
@@ -711,9 +736,13 @@ describe('msgpackdump() function', function()
end)
it('can dump NULL string', function()
- eq({'\196\n'}, eval('msgpackdump([$XXX_UNEXISTENT_VAR_XXX])'))
- eq({'\196\n'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
- eq({'\160'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
+ dump_eq({'\196\n'}, '[$XXX_UNEXISTENT_VAR_XXX]')
+ dump_eq({'\196\n'}, '[{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ dump_eq({'\160'}, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ end)
+
+ it('can dump NULL blob', function()
+ eq({'\196\n'}, eval('msgpackdump([v:_null_blob])'))
end)
it('can dump NULL list', function()
diff --git a/test/functional/eval/null_spec.lua b/test/functional/vimscript/null_spec.lua
index b1ceff9115..7ecbcd2fd6 100644
--- a/test/functional/eval/null_spec.lua
+++ b/test/functional/vimscript/null_spec.lua
@@ -1,7 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local curbufmeths = helpers.curbufmeths
-local redir_exec = helpers.redir_exec
local exc_exec = helpers.exc_exec
local command = helpers.command
local clear = helpers.clear
@@ -9,6 +8,19 @@ local meths = helpers.meths
local funcs = helpers.funcs
local eq = helpers.eq
+local function redir_exec(cmd)
+ meths.set_var('__redir_exec_cmd', cmd)
+ command([[
+ redir => g:__redir_exec_output
+ silent! execute g:__redir_exec_cmd
+ redir END
+ ]])
+ local ret = meths.get_var('__redir_exec_output')
+ meths.del_var('__redir_exec_output')
+ meths.del_var('__redir_exec_cmd')
+ return ret
+end
+
describe('NULL', function()
before_each(function()
clear()
@@ -44,7 +56,7 @@ describe('NULL', function()
-- Incorrect behaviour
-- FIXME Should error out with different message
null_test('makes :unlet act as if it is not a list', ':unlet L[0]',
- 'Vim(unlet):E689: Can only index a List or Dictionary')
+ 'Vim(unlet):E689: Can only index a List, Dictionary or Blob')
-- Subjectable behaviour
@@ -53,7 +65,7 @@ describe('NULL', function()
-- Correct behaviour
null_expr_test('can be indexed with error message for empty list', 'L[0]',
- 'E684: list index out of range: 0\nE15: Invalid expression: L[0]', nil)
+ 'E684: list index out of range: 0', nil)
null_expr_test('can be splice-indexed', 'L[:]', 0, {})
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
null_test('is accepted by :for', 'for x in L|throw x|endfor', 0)
@@ -68,7 +80,7 @@ describe('NULL', function()
null_expr_test('can be copied', 'copy(L)', 0, {})
null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
null_expr_test('does not crash when indexed', 'L[1]',
- 'E684: list index out of range: 1\nE15: Invalid expression: L[1]', nil)
+ 'E684: list index out of range: 1', nil)
null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
null_expr_test('does not crash col()', 'col(L)', 0, 0)
null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
@@ -135,7 +147,7 @@ describe('NULL', function()
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
- eq('\nE716: Key not present in Dictionary: "test"\nE15: Invalid expression: v:_null_dict.test',
+ eq('\nE716: Key not present in Dictionary: "test"',
redir_exec('echo v:_null_dict.test'))
end)
null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
diff --git a/test/functional/eval/operators_spec.lua b/test/functional/vimscript/operators_spec.lua
index 4d07bc1b05..4d07bc1b05 100644
--- a/test/functional/eval/operators_spec.lua
+++ b/test/functional/vimscript/operators_spec.lua
diff --git a/test/functional/eval/printf_spec.lua b/test/functional/vimscript/printf_spec.lua
index 27e24c4118..27e24c4118 100644
--- a/test/functional/eval/printf_spec.lua
+++ b/test/functional/vimscript/printf_spec.lua
diff --git a/test/functional/eval/reltime_spec.lua b/test/functional/vimscript/reltime_spec.lua
index d87943e485..d87943e485 100644
--- a/test/functional/eval/reltime_spec.lua
+++ b/test/functional/vimscript/reltime_spec.lua
diff --git a/test/functional/eval/server_spec.lua b/test/functional/vimscript/server_spec.lua
index 238d1aeb0f..238d1aeb0f 100644
--- a/test/functional/eval/server_spec.lua
+++ b/test/functional/vimscript/server_spec.lua
diff --git a/test/functional/eval/setpos_spec.lua b/test/functional/vimscript/setpos_spec.lua
index 935f387bcc..935f387bcc 100644
--- a/test/functional/eval/setpos_spec.lua
+++ b/test/functional/vimscript/setpos_spec.lua
diff --git a/test/functional/eval/sort_spec.lua b/test/functional/vimscript/sort_spec.lua
index e1cc2c2924..e09949a0f2 100644
--- a/test/functional/eval/sort_spec.lua
+++ b/test/functional/vimscript/sort_spec.lua
@@ -8,7 +8,7 @@ local meths = helpers.meths
local funcs = helpers.funcs
local command = helpers.command
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
before_each(clear)
@@ -50,8 +50,7 @@ describe('sort()', function()
return (a:a > a:b) - (a:a < a:b)
endfunction
]])
- eq('\nE745: Using a List as a Number\nE702: Sort compare function failed',
- redir_exec('let sl = sort([1, 0, [], 3, 2], "Cmp")'))
- eq({1, 0, {}, 3, 2}, meths.get_var('sl'))
+ eq('Vim(let):E745: Using a List as a Number',
+ pcall_err(command, 'let sl = sort([1, 0, [], 3, 2], "Cmp")'))
end)
end)
diff --git a/test/functional/eval/special_vars_spec.lua b/test/functional/vimscript/special_vars_spec.lua
index 97a12d490d..97a12d490d 100644
--- a/test/functional/eval/special_vars_spec.lua
+++ b/test/functional/vimscript/special_vars_spec.lua
diff --git a/test/functional/eval/string_spec.lua b/test/functional/vimscript/string_spec.lua
index adc1af9b8e..cb7e93f264 100644
--- a/test/functional/eval/string_spec.lua
+++ b/test/functional/vimscript/string_spec.lua
@@ -5,11 +5,10 @@ local command = helpers.command
local meths = helpers.meths
local eval = helpers.eval
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
local funcs = helpers.funcs
local NIL = helpers.NIL
local source = helpers.source
-local dedent = helpers.dedent
describe('string() function', function()
before_each(clear)
@@ -140,8 +139,8 @@ describe('string() function', function()
let TestDictRef = function('TestDict', d)
let d.tdr = TestDictRef
]])
- eq("\nE724: unable to correctly dump variable with self-referencing container\nfunction('TestDict', {'tdr': function('TestDict', {E724@1})})",
- redir_exec('echo string(d.tdr)'))
+ eq("Vim(echo):E724: unable to correctly dump variable with self-referencing container",
+ pcall_err(command, 'echo string(d.tdr)'))
end)
it('dumps automatically created partials', function()
@@ -163,11 +162,8 @@ describe('string() function', function()
it('does not crash or halt when dumping partials with reference cycles in self',
function()
meths.set_var('d', {v=true})
- eq(dedent([[
-
- E724: unable to correctly dump variable with self-referencing container
- {'p': function('<SNR>1_Test2', {E724@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]),
- redir_exec('echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
+ eq([[Vim(echo):E724: unable to correctly dump variable with self-referencing container]],
+ pcall_err(command, 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
end)
it('does not show errors when dumping partials referencing the same dictionary',
@@ -190,11 +186,8 @@ describe('string() function', function()
-- there was error in dumping partials). Tested explicitly in
-- test/unit/api/private_helpers_spec.lua.
eval('add(l, function("Test1", l))')
- eq(dedent([=[
-
- E724: unable to correctly dump variable with self-referencing container
- function('Test1', [[{E724@2}, function('Test1', [{E724@2}])], function('Test1', [[{E724@4}, function('Test1', [{E724@4}])]])])]=]),
- redir_exec('echo string(function("Test1", l))'))
+ eq([=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
+ pcall_err(command, 'echo string(function("Test1", l))'))
end)
it('does not crash or halt when dumping partials with reference cycles in self and arguments',
@@ -204,11 +197,8 @@ describe('string() function', function()
eval('add(l, l)')
eval('add(l, function("Test1", l))')
eval('add(l, function("Test1", d))')
- eq(dedent([=[
-
- E724: unable to correctly dump variable with self-referencing container
- {'p': function('<SNR>1_Test2', [[{E724@3}, function('Test1', [{E724@3}]), function('Test1', {E724@0})], function('Test1', [[{E724@5}, function('Test1', [{E724@5}]), function('Test1', {E724@0})]]), function('Test1', {E724@0})], {E724@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]),
- redir_exec('echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
+ eq([=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
+ pcall_err(command, 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
end)
end)
@@ -235,10 +225,10 @@ describe('string() function', function()
it('dumps recursive lists despite the error', function()
meths.set_var('l', {})
eval('add(l, l)')
- eq('\nE724: unable to correctly dump variable with self-referencing container\n[{E724@0}]',
- redir_exec('echo string(l)'))
- eq('\nE724: unable to correctly dump variable with self-referencing container\n[[{E724@1}]]',
- redir_exec('echo string([l])'))
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string(l)'))
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string([l])'))
end)
end)
@@ -268,10 +258,10 @@ describe('string() function', function()
it('dumps recursive dictionaries despite the error', function()
meths.set_var('d', {d=1})
eval('extend(d, {"d": d})')
- eq('\nE724: unable to correctly dump variable with self-referencing container\n{\'d\': {E724@0}}',
- redir_exec('echo string(d)'))
- eq('\nE724: unable to correctly dump variable with self-referencing container\n{\'out\': {\'d\': {E724@1}}}',
- redir_exec('echo string({"out": d})'))
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string(d)'))
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string({"out": d})'))
end)
end)
end)
diff --git a/test/functional/eval/system_spec.lua b/test/functional/vimscript/system_spec.lua
index c374baf695..24a1f05390 100644
--- a/test/functional/eval/system_spec.lua
+++ b/test/functional/vimscript/system_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local nvim_dir = helpers.nvim_dir
local eq, call, clear, eval, feed_command, feed, nvim =
helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command,
@@ -302,7 +303,7 @@ describe('system()', function()
if v_errnum then
eq("E5677:", v_errnum)
end
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
@@ -317,11 +318,11 @@ describe('system()', function()
if v_errnum then
eq("E5677:", v_errnum)
end
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('works with an empty string', function()
eq("test\n", eval('system("echo test", "")'))
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/eval/timer_spec.lua b/test/functional/vimscript/timer_spec.lua
index 9ee0735e40..9ee0735e40 100644
--- a/test/functional/eval/timer_spec.lua
+++ b/test/functional/vimscript/timer_spec.lua
diff --git a/test/functional/eval/uniq_spec.lua b/test/functional/vimscript/uniq_spec.lua
index 5cdba0a0f6..43ad4a7640 100644
--- a/test/functional/eval/uniq_spec.lua
+++ b/test/functional/vimscript/uniq_spec.lua
@@ -2,10 +2,9 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local clear = helpers.clear
-local meths = helpers.meths
local command = helpers.command
local exc_exec = helpers.exc_exec
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
before_each(clear)
@@ -24,8 +23,7 @@ describe('uniq()', function()
return (a:a > a:b) - (a:a < a:b)
endfunction
]])
- eq('\nE745: Using a List as a Number\nE882: Uniq compare function failed',
- redir_exec('let fl = uniq([0, 0, [], 1, 1], "Cmp")'))
- eq({0, {}, 1, 1}, meths.get_var('fl'))
+ eq('Vim(let):E745: Using a List as a Number',
+ pcall_err(command, 'let fl = uniq([0, 0, [], 1, 1], "Cmp")'))
end)
end)
diff --git a/test/functional/eval/vvar_event_spec.lua b/test/functional/vimscript/vvar_event_spec.lua
index eec8aa917a..eec8aa917a 100644
--- a/test/functional/eval/vvar_event_spec.lua
+++ b/test/functional/vimscript/vvar_event_spec.lua
diff --git a/test/functional/eval/wait_spec.lua b/test/functional/vimscript/wait_spec.lua
index ee95e02a7f..ee95e02a7f 100644
--- a/test/functional/eval/wait_spec.lua
+++ b/test/functional/vimscript/wait_spec.lua
diff --git a/test/functional/eval/writefile_spec.lua b/test/functional/vimscript/writefile_spec.lua
index 356680ba7c..5f693249a9 100644
--- a/test/functional/eval/writefile_spec.lua
+++ b/test/functional/vimscript/writefile_spec.lua
@@ -8,7 +8,8 @@ local meths = helpers.meths
local exc_exec = helpers.exc_exec
local read_file = helpers.read_file
local write_file = helpers.write_file
-local redir_exec = helpers.redir_exec
+local pcall_err = helpers.pcall_err
+local command = helpers.command
local fname = 'Xtest-functional-eval-writefile'
local dname = fname .. '.d'
@@ -106,51 +107,51 @@ describe('writefile()', function()
it('shows correct file name when supplied numbers', function()
meths.set_current_dir(dname)
- eq('\nE482: Can\'t open file 2 for writing: illegal operation on a directory',
- redir_exec(('call writefile([42], %s)'):format(ddname_tail)))
+ eq('Vim(call):E482: Can\'t open file 2 for writing: illegal operation on a directory',
+ pcall_err(command, ('call writefile([42], %s)'):format(ddname_tail)))
end)
it('errors out with invalid arguments', function()
write_file(fname, 'TEST')
- eq('\nE119: Not enough arguments for function: writefile',
- redir_exec('call writefile()'))
- eq('\nE119: Not enough arguments for function: writefile',
- redir_exec('call writefile([])'))
- eq('\nE118: Too many arguments for function: writefile',
- redir_exec(('call writefile([], "%s", "b", 1)'):format(fname)))
+ eq('Vim(call):E119: Not enough arguments for function: writefile',
+ pcall_err(command, 'call writefile()'))
+ eq('Vim(call):E119: Not enough arguments for function: writefile',
+ pcall_err(command, 'call writefile([])'))
+ eq('Vim(call):E118: Too many arguments for function: writefile',
+ pcall_err(command, ('call writefile([], "%s", "b", 1)'):format(fname)))
for _, arg in ipairs({'0', '0.0', 'function("tr")', '{}', '"test"'}) do
- eq('\nE686: Argument of writefile() must be a List',
- redir_exec(('call writefile(%s, "%s", "b")'):format(arg, fname)))
+ eq('Vim(call):E475: Invalid argument: writefile() first argument must be a List or a Blob',
+ pcall_err(command, ('call writefile(%s, "%s", "b")'):format(arg, fname)))
end
for _, args in ipairs({'[], %s, "b"', '[], "' .. fname .. '", %s'}) do
- eq('\nE806: using Float as a String',
- redir_exec(('call writefile(%s)'):format(args:format('0.0'))))
- eq('\nE730: using List as a String',
- redir_exec(('call writefile(%s)'):format(args:format('[]'))))
- eq('\nE731: using Dictionary as a String',
- redir_exec(('call writefile(%s)'):format(args:format('{}'))))
- eq('\nE729: using Funcref as a String',
- redir_exec(('call writefile(%s)'):format(args:format('function("tr")'))))
+ eq('Vim(call):E806: using Float as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('0.0'))))
+ eq('Vim(call):E730: using List as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('[]'))))
+ eq('Vim(call):E731: using Dictionary as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('{}'))))
+ eq('Vim(call):E729: using Funcref as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")'))))
end
- eq('\nE5060: Unknown flag: «»',
- redir_exec(('call writefile([], "%s", "bs«»")'):format(fname)))
+ eq('Vim(call):E5060: Unknown flag: «»',
+ pcall_err(command, ('call writefile([], "%s", "bs«»")'):format(fname)))
eq('TEST', read_file(fname))
end)
it('does not write to file if error in list', function()
local args = '["tset"] + repeat([%s], 3), "' .. fname .. '"'
- eq('\nE805: Expected a Number or a String, Float found',
- redir_exec(('call writefile(%s)'):format(args:format('0.0'))))
+ eq('Vim(call):E805: Expected a Number or a String, Float found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('0.0'))))
eq(nil, read_file(fname))
write_file(fname, 'TEST')
- eq('\nE745: Expected a Number or a String, List found',
- redir_exec(('call writefile(%s)'):format(args:format('[]'))))
+ eq('Vim(call):E745: Expected a Number or a String, List found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('[]'))))
eq('TEST', read_file(fname))
- eq('\nE728: Expected a Number or a String, Dictionary found',
- redir_exec(('call writefile(%s)'):format(args:format('{}'))))
+ eq('Vim(call):E728: Expected a Number or a String, Dictionary found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('{}'))))
eq('TEST', read_file(fname))
- eq('\nE703: Expected a Number or a String, Funcref found',
- redir_exec(('call writefile(%s)'):format(args:format('function("tr")'))))
+ eq('Vim(call):E703: Expected a Number or a String, Funcref found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")'))))
eq('TEST', read_file(fname))
end)
end)
diff --git a/test/functional/visual/meta_key_spec.lua b/test/functional/visual/meta_key_spec.lua
deleted file mode 100644
index 11f7203da0..0000000000
--- a/test/functional/visual/meta_key_spec.lua
+++ /dev/null
@@ -1,22 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local command = helpers.command
-local expect = helpers.expect
-
-describe('meta-keys-in-visual-mode', function()
- before_each(function()
- clear()
- end)
-
- it('ALT/META', function()
- -- Unmapped ALT-chords behave as Esc+c
- insert('peaches')
- feed('viw<A-x>viw<M-x>')
- expect('peach')
- -- Mapped ALT-chord behaves as mapped.
- command('vnoremap <M-l> Ameta-l<Esc>')
- command('vnoremap <A-j> Aalt-j<Esc>')
- feed('viw<A-j>viw<M-l>')
- expect('peachalt-jmeta-l')
- end)
-end)
diff --git a/test/helpers.lua b/test/helpers.lua
index 12d9f19187..9ac3904776 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -58,9 +58,9 @@ local check_logs_useless_lines = {
--- Invokes `fn` and includes the tail of `logfile` in the error message if it
--- fails.
---
---@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
---@param fn Function to invoke
---@param ... Function arguments
+---@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
+---@param fn Function to invoke
+---@param ... Function arguments
local function dumplog(logfile, fn, ...)
-- module.validate({
-- logfile={logfile,'s',true},
@@ -70,7 +70,7 @@ local function dumplog(logfile, fn, ...)
if status == false then
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local logtail = module.read_nvim_log(logfile)
- error(string.format('%s\n%s', rv, logtail))
+ error(string.format('%s\n%s', tostring(rv), logtail))
end
end
function module.eq(expected, actual, context, logfile)
@@ -102,8 +102,8 @@ end
--- Asserts that `pat` matches one or more lines in the tail of $NVIM_LOG_FILE.
---
---@param pat (string) Lua pattern to search for in the log file.
---@param logfile (string, default=$NVIM_LOG_FILE) full path to log file.
+---@param pat (string) Lua pattern to search for in the log file.
+---@param logfile (string, default=$NVIM_LOG_FILE) full path to log file.
function module.assert_log(pat, logfile)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local nrlines = 10
@@ -810,6 +810,6 @@ function module.read_nvim_log(logfile, ci_rename)
return log
end
-module = shared.tbl_extend('error', module, Paths, shared)
+module = shared.tbl_extend('error', module, Paths, shared, require('test.deprecated'))
return module
diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua
index 891e6def09..5fc3b83a13 100644
--- a/test/unit/charset/vim_str2nr_spec.lua
+++ b/test/unit/charset/vim_str2nr_spec.lua
@@ -43,7 +43,8 @@ local function argreset(arg, args)
end
end
-local function test_vim_str2nr(s, what, exp, maxlen)
+local function test_vim_str2nr(s, what, exp, maxlen, strict)
+ if strict == nil then strict = true end
local bits = {}
for k, _ in pairs(exp) do
bits[#bits + 1] = k
@@ -62,11 +63,11 @@ local function test_vim_str2nr(s, what, exp, maxlen)
cv[k] = args[k]
end
end
- lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen)
+ lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict)
for cck, ccv in pairs(cv) do
if exp[cck] ~= tonumber(ccv[0]) then
- error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d): %d'):format(
- cck, exp[cck], s, tonumber(what), maxlen, tonumber(ccv[0])
+ error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
+ cck, exp[cck], s, tonumber(what), maxlen, tostring(strict), tonumber(ccv[0])
))
end
end
@@ -85,10 +86,13 @@ describe('vim_str2nr()', function()
test_vim_str2nr('', lib.STR2NR_ALL, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
+ test_vim_str2nr('', lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_DEC, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
+ test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
+ test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
end)
itp('works with decimal numbers', function()
@@ -97,31 +101,39 @@ describe('vim_str2nr()', function()
lib.STR2NR_BIN,
lib.STR2NR_OCT,
lib.STR2NR_HEX,
+ lib.STR2NR_OOCT,
lib.STR2NR_BIN + lib.STR2NR_OCT,
lib.STR2NR_BIN + lib.STR2NR_HEX,
lib.STR2NR_OCT + lib.STR2NR_HEX,
+ lib.STR2NR_OOCT + lib.STR2NR_HEX,
lib.STR2NR_ALL,
lib.STR2NR_FORCE + lib.STR2NR_DEC,
}) do
-- Check that all digits are recognized
test_vim_str2nr( '12345', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0)
test_vim_str2nr( '67890', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0)
- test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0)
- test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0)
+ test_vim_str2nr( '12345A', flags, {len = 0}, 0)
+ test_vim_str2nr( '67890A', flags, {len = 0}, 0)
+ test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0, false)
+ test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0, false)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0)
test_vim_str2nr( '42', flags, {len = 1, num = 4, unum = 4, pre = 0}, 1)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 2)
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) -- includes NUL byte in maxlen
- test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0)
- test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3)
+ test_vim_str2nr( '42x', flags, {len = 0}, 0)
+ test_vim_str2nr( '42x', flags, {len = 0}, 3)
+ test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0, false)
+ test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3, false)
test_vim_str2nr('-42', flags, {len = 3, num = -42, unum = 42, pre = 0}, 3)
test_vim_str2nr('-42', flags, {len = 1, num = 0, unum = 0, pre = 0}, 1)
- test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0)
- test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4)
+ test_vim_str2nr('-42x', flags, {len = 0}, 0)
+ test_vim_str2nr('-42x', flags, {len = 0}, 4)
+ test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0, false)
+ test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4, false)
end
end)
itp('works with binary numbers', function()
@@ -144,62 +156,77 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0)
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr( '0b101', flags, {len = 0}, 2)
+ test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0b101', flags, {len = 3, num = 1, unum = 1, pre = bin}, 3)
test_vim_str2nr( '0b101', flags, {len = 4, num = 2, unum = 2, pre = bin}, 4)
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 5)
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6)
- test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0)
- test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6)
+ test_vim_str2nr( '0b1012', flags, {len = 0}, 0)
+ test_vim_str2nr( '0b1012', flags, {len = 0}, 6)
+ test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0, false)
+ test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6, false)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0)
test_vim_str2nr('-0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3)
+ test_vim_str2nr('-0b101', flags, {len = 0}, 3)
+ test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0b101', flags, {len = 4, num = -1, unum = 1, pre = bin}, 4)
test_vim_str2nr('-0b101', flags, {len = 5, num = -2, unum = 2, pre = bin}, 5)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 6)
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7)
- test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0)
- test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7)
+ test_vim_str2nr('-0b1012', flags, {len = 0}, 0)
+ test_vim_str2nr('-0b1012', flags, {len = 0}, 7)
+ test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0, false)
+ test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7, false)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0)
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr( '0B101', flags, {len = 0}, 2)
+ test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0B101', flags, {len = 3, num = 1, unum = 1, pre = BIN}, 3)
test_vim_str2nr( '0B101', flags, {len = 4, num = 2, unum = 2, pre = BIN}, 4)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 5)
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6)
- test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0)
- test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6)
+ test_vim_str2nr( '0B1012', flags, {len = 0}, 0)
+ test_vim_str2nr( '0B1012', flags, {len = 0}, 6)
+ test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0, false)
+ test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6, false)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0)
test_vim_str2nr('-0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3)
+ test_vim_str2nr('-0B101', flags, {len = 0}, 3)
+ test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0B101', flags, {len = 4, num = -1, unum = 1, pre = BIN}, 4)
test_vim_str2nr('-0B101', flags, {len = 5, num = -2, unum = 2, pre = BIN}, 5)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 6)
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7)
- test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0)
- test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7)
+ test_vim_str2nr('-0B1012', flags, {len = 0}, 0)
+ test_vim_str2nr('-0B1012', flags, {len = 0}, 7)
+ test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0, false)
+ test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7, false)
if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-101', flags, {len = 4, num = -5, unum = 5, pre = 0}, 0)
end
end
end)
- itp('works with octal numbers', function()
+ itp('works with octal numbers (0 prefix)', function()
for _, flags in ipairs({
lib.STR2NR_OCT,
lib.STR2NR_OCT + lib.STR2NR_BIN,
lib.STR2NR_OCT + lib.STR2NR_HEX,
+ lib.STR2NR_OCT + lib.STR2NR_OOCT,
lib.STR2NR_ALL,
lib.STR2NR_FORCE + lib.STR2NR_OCT,
+ lib.STR2NR_FORCE + lib.STR2NR_OOCT,
+ lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT,
}) do
local oct
if flags > lib.STR2NR_FORCE then
@@ -218,8 +245,10 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0548', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4)
- test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4)
- test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0)
+ test_vim_str2nr( '054x', flags, {len = 0}, 4)
+ test_vim_str2nr( '054x', flags, {len = 0}, 0)
+ test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4, false)
+ test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0, false)
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0)
test_vim_str2nr('-054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
@@ -229,13 +258,110 @@ describe('vim_str2nr()', function()
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5)
- test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5)
- test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0)
+ test_vim_str2nr('-054x', flags, {len = 0}, 5)
+ test_vim_str2nr('-054x', flags, {len = 0}, 0)
+ test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5, false)
+ test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0, false)
if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-54', flags, {len = 3, num = -44, unum = 44, pre = 0}, 0)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0)
+ test_vim_str2nr('-0548', flags, {len = 0}, 5)
+ test_vim_str2nr('-0548', flags, {len = 0}, 0)
+ test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
+ test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
+ else
+ test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
+ test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
+ end
+ end
+ end)
+ itp('works with octal numbers (0o or 0O prefix)', function()
+ for _, flags in ipairs({
+ lib.STR2NR_OOCT,
+ lib.STR2NR_OOCT + lib.STR2NR_BIN,
+ lib.STR2NR_OOCT + lib.STR2NR_HEX,
+ lib.STR2NR_OCT + lib.STR2NR_OOCT,
+ lib.STR2NR_OCT + lib.STR2NR_OOCT + lib.STR2NR_BIN,
+ lib.STR2NR_OCT + lib.STR2NR_OOCT + lib.STR2NR_HEX,
+ lib.STR2NR_ALL,
+ lib.STR2NR_FORCE + lib.STR2NR_OCT,
+ lib.STR2NR_FORCE + lib.STR2NR_OOCT,
+ lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT,
+ }) do
+ local oct
+ local OCT
+ if flags > lib.STR2NR_FORCE then
+ oct = 0
+ OCT = 0
+ else
+ oct = ('o'):byte()
+ OCT = ('O'):byte()
+ end
+
+ test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0)
+ test_vim_str2nr( '0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr( '0o054', flags, {len = 0}, 2)
+ test_vim_str2nr( '0o054', flags, {len = 3, num = 0, unum = 0, pre = oct}, 3)
+ test_vim_str2nr( '0o054', flags, {len = 4, num = 5, unum = 5, pre = oct}, 4)
+ test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
+ test_vim_str2nr( '0o0548', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
+ test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6)
+
+ test_vim_str2nr( '0o054x', flags, {len = 0}, 6)
+ test_vim_str2nr( '0o054x', flags, {len = 0}, 0)
+ test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6, false)
+ test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0, false)
+
+ test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0)
+ test_vim_str2nr('-0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0o054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0o054', flags, {len = 0}, 3)
+ test_vim_str2nr('-0o054', flags, {len = 4, num = 0, unum = 0, pre = oct}, 4)
+ test_vim_str2nr('-0o054', flags, {len = 5, num = -5, unum = 5, pre = oct}, 5)
+ test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
+ test_vim_str2nr('-0o0548', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
+ test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7)
+
+ test_vim_str2nr('-0o054x', flags, {len = 0}, 7)
+ test_vim_str2nr('-0o054x', flags, {len = 0}, 0)
+ test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7, false)
+ test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0, false)
+
+ test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0)
+ test_vim_str2nr( '0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr( '0O054', flags, {len = 0}, 2)
+ test_vim_str2nr( '0O054', flags, {len = 3, num = 0, unum = 0, pre = OCT}, 3)
+ test_vim_str2nr( '0O054', flags, {len = 4, num = 5, unum = 5, pre = OCT}, 4)
+ test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
+ test_vim_str2nr( '0O0548', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
+ test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6)
+
+ test_vim_str2nr( '0O054x', flags, {len = 0}, 6)
+ test_vim_str2nr( '0O054x', flags, {len = 0}, 0)
+ test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6, false)
+ test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0, false)
+
+ test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0)
+ test_vim_str2nr('-0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0O054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0O054', flags, {len = 0}, 3)
+ test_vim_str2nr('-0O054', flags, {len = 4, num = 0, unum = 0, pre = OCT}, 4)
+ test_vim_str2nr('-0O054', flags, {len = 5, num = -5, unum = 5, pre = OCT}, 5)
+ test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
+ test_vim_str2nr('-0O0548', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
+ test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7)
+
+ test_vim_str2nr('-0O054x', flags, {len = 0}, 7)
+ test_vim_str2nr('-0O054x', flags, {len = 0}, 0)
+ test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7, false)
+ test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0, false)
+
+ if flags > lib.STR2NR_FORCE then
+ test_vim_str2nr('-0548', flags, {len = 0}, 5)
+ test_vim_str2nr('-0548', flags, {len = 0}, 0)
+ test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
+ test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
+ test_vim_str2nr('-055', flags, {len = 4, num = -45, unum = 45, pre = 0}, 0)
else
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
@@ -268,53 +394,85 @@ describe('vim_str2nr()', function()
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 0)
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr( '0x101', flags, {len = 0}, 2)
+ test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0x101', flags, {len = 3, num = 1, unum = 1, pre = hex}, 3)
test_vim_str2nr( '0x101', flags, {len = 4, num = 16, unum = 16, pre = hex}, 4)
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 5)
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 6)
- test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0)
- test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6)
+ test_vim_str2nr( '0x101G', flags, {len = 0}, 0)
+ test_vim_str2nr( '0x101G', flags, {len = 0}, 6)
+ test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0, false)
+ test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6, false)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 0)
test_vim_str2nr('-0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3)
+ test_vim_str2nr('-0x101', flags, {len = 0}, 3)
+ test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0x101', flags, {len = 4, num = -1, unum = 1, pre = hex}, 4)
test_vim_str2nr('-0x101', flags, {len = 5, num = -16, unum = 16, pre = hex}, 5)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 6)
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 7)
- test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0)
- test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7)
+ test_vim_str2nr('-0x101G', flags, {len = 0}, 0)
+ test_vim_str2nr('-0x101G', flags, {len = 0}, 7)
+ test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0, false)
+ test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7, false)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0)
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr( '0X101', flags, {len = 0}, 2)
+ test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
test_vim_str2nr( '0X101', flags, {len = 3, num = 1, unum = 1, pre = HEX}, 3)
test_vim_str2nr( '0X101', flags, {len = 4, num = 16, unum = 16, pre = HEX}, 4)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 5)
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6)
- test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0)
- test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6)
+ test_vim_str2nr( '0X101G', flags, {len = 0}, 0)
+ test_vim_str2nr( '0X101G', flags, {len = 0}, 6)
+ test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0, false)
+ test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6, false)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0)
test_vim_str2nr('-0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3)
+ test_vim_str2nr('-0X101', flags, {len = 0}, 3)
+ test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
test_vim_str2nr('-0X101', flags, {len = 4, num = -1, unum = 1, pre = HEX}, 4)
test_vim_str2nr('-0X101', flags, {len = 5, num = -16, unum = 16, pre = HEX}, 5)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 6)
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7)
- test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0)
- test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7)
+ test_vim_str2nr('-0X101G', flags, {len = 0}, 0)
+ test_vim_str2nr('-0X101G', flags, {len = 0}, 7)
+ test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0, false)
+ test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7, false)
if flags > lib.STR2NR_FORCE then
test_vim_str2nr('-101', flags, {len = 4, num = -257, unum = 257, pre = 0}, 0)
end
end
end)
+ -- Test_str2nr() in test_functions.vim already tests normal usage
+ itp('works with weirdly quoted numbers', function()
+ local flags = lib.STR2NR_DEC + lib.STR2NR_QUOTE
+ test_vim_str2nr("'027", flags, {len = 0}, 0)
+ test_vim_str2nr("'027", flags, {len = 0}, 0, false)
+ test_vim_str2nr("1'2'3'4", flags, {len = 7, num = 1234, unum = 1234, pre = 0}, 0)
+
+ -- counter-intuitive, but like Vim, strict=true should partially accept
+ -- these: (' and - are not alpha-numeric)
+ test_vim_str2nr("7''331", flags, {len = 1, num = 7, unum = 7, pre = 0}, 0)
+ test_vim_str2nr("123'x4", flags, {len = 3, num = 123, unum = 123, pre = 0}, 0)
+ test_vim_str2nr("1337'", flags, {len = 4, num = 1337, unum = 1337, pre = 0}, 0)
+ test_vim_str2nr("-'", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0)
+
+ flags = lib.STR2NR_HEX + lib.STR2NR_QUOTE
+ local hex = ('x'):byte()
+ test_vim_str2nr("0x'abcd", flags, {len = 0}, 0)
+ test_vim_str2nr("0x'abcd", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0, false)
+ test_vim_str2nr("0xab''cd", flags, {len = 4, num = 171, unum = 171, pre = hex}, 0)
+ end)
end)
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index d81e272877..e61b568f3a 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -2531,7 +2531,7 @@ describe('typval.c', function()
value='tr',
dict={},
})
- lib.tv_item_lock(p_tv, -1, true)
+ lib.tv_item_lock(p_tv, -1, true, false)
eq(lib.VAR_UNLOCKED, p_tv.vval.v_partial.pt_dict.dv_lock)
end)
itp('does not change VAR_FIXED values', function()
@@ -2542,14 +2542,14 @@ describe('typval.c', function()
d_tv.vval.v_dict.dv_lock = lib.VAR_FIXED
l_tv.v_lock = lib.VAR_FIXED
l_tv.vval.v_list.lv_lock = lib.VAR_FIXED
- lib.tv_item_lock(d_tv, 1, true)
- lib.tv_item_lock(l_tv, 1, true)
+ lib.tv_item_lock(d_tv, 1, true, false)
+ lib.tv_item_lock(l_tv, 1, true, false)
eq(lib.VAR_FIXED, d_tv.v_lock)
eq(lib.VAR_FIXED, l_tv.v_lock)
eq(lib.VAR_FIXED, d_tv.vval.v_dict.dv_lock)
eq(lib.VAR_FIXED, l_tv.vval.v_list.lv_lock)
- lib.tv_item_lock(d_tv, 1, false)
- lib.tv_item_lock(l_tv, 1, false)
+ lib.tv_item_lock(d_tv, 1, false, false)
+ lib.tv_item_lock(l_tv, 1, false, false)
eq(lib.VAR_FIXED, d_tv.v_lock)
eq(lib.VAR_FIXED, l_tv.v_lock)
eq(lib.VAR_FIXED, d_tv.vval.v_dict.dv_lock)
@@ -2561,9 +2561,9 @@ describe('typval.c', function()
local d_tv = lua2typvalt(null_dict)
local s_tv = lua2typvalt(null_string)
alloc_log:clear()
- lib.tv_item_lock(l_tv, 1, true)
- lib.tv_item_lock(d_tv, 1, true)
- lib.tv_item_lock(s_tv, 1, true)
+ lib.tv_item_lock(l_tv, 1, true, false)
+ lib.tv_item_lock(d_tv, 1, true, false)
+ lib.tv_item_lock(s_tv, 1, true, false)
eq(null_list, typvalt2lua(l_tv))
eq(null_dict, typvalt2lua(d_tv))
eq(null_string, typvalt2lua(s_tv))
diff --git a/test/unit/undo_spec.lua b/test/unit/undo_spec.lua
index 616c6fbe3d..f7f8d26d58 100644
--- a/test/unit/undo_spec.lua
+++ b/test/unit/undo_spec.lua
@@ -38,7 +38,7 @@ child_call_once(function()
--
-- compute a hash for this undofile
buffer_hash = ffi.new('char_u[32]')
- undo.u_compute_hash(buffer_hash)
+ undo.u_compute_hash(file_buffer, buffer_hash)
end)
diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua
index 032baf6578..8342044b5e 100644
--- a/test/unit/viml/expressions/parser_spec.lua
+++ b/test/unit/viml/expressions/parser_spec.lua
@@ -52,6 +52,32 @@ local predefined_hl_defs = {
QuickFixLine=true,
Substitute=true,
Whitespace=true,
+ Error=true,
+ Todo=true,
+ String=true,
+ Character=true,
+ Number=true,
+ Boolean=true,
+ Float=true,
+ Function=true,
+ Conditional=true,
+ Repeat=true,
+ Label=true,
+ Operator=true,
+ Keyword=true,
+ Exception=true,
+ Include=true,
+ Define=true,
+ Macro=true,
+ PreCondit=true,
+ StorageClass=true,
+ Structure=true,
+ Typedef=true,
+ Tag=true,
+ SpecialChar=true,
+ Delimiter=true,
+ SpecialComment=true,
+ Debug=true,
-- From highlight_init_(dark|light)
ColorColumn=true,
@@ -83,8 +109,6 @@ local predefined_hl_defs = {
Visual=true,
WarningMsg=true,
Normal=true,
-
- -- From syncolor.vim, if &background
Comment=true,
Constant=true,
Special=true,
@@ -94,36 +118,6 @@ local predefined_hl_defs = {
Type=true,
Underlined=true,
Ignore=true,
-
- -- From syncolor.vim, below if &background
- Error=true,
- Todo=true,
-
- -- From syncolor.vim, links at the bottom
- String=true,
- Character=true,
- Number=true,
- Boolean=true,
- Float=true,
- Function=true,
- Conditional=true,
- Repeat=true,
- Label=true,
- Operator=true,
- Keyword=true,
- Exception=true,
- Include=true,
- Define=true,
- Macro=true,
- PreCondit=true,
- StorageClass=true,
- Structure=true,
- Typedef=true,
- Tag=true,
- SpecialChar=true,
- Delimiter=true,
- SpecialComment=true,
- Debug=true,
}
local nvim_hl_defs = {}