diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/extmark_spec.lua | 68 | ||||
-rw-r--r-- | test/functional/helpers.lua | 10 | ||||
-rw-r--r-- | test/functional/lua/buffer_updates_spec.lua | 195 | ||||
-rw-r--r-- | test/functional/lua/treesitter_spec.lua | 123 | ||||
-rw-r--r-- | test/functional/options/defaults_spec.lua | 220 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 40 | ||||
-rw-r--r-- | test/functional/provider/clipboard_spec.lua | 10 | ||||
-rw-r--r-- | test/functional/provider/perl_spec.lua | 50 | ||||
-rw-r--r-- | test/functional/ui/bufhl_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/ui/options_spec.lua | 8 | ||||
-rw-r--r-- | test/helpers.lua | 26 | ||||
-rw-r--r-- | test/unit/os/env_spec.lua | 13 |
12 files changed, 583 insertions, 192 deletions
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 9ea35e50a2..a2a188d036 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -17,22 +17,14 @@ local function expect(contents) return eq(contents, helpers.curbuf_contents()) end -local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end - local rv = curbufmeths.get_extmark_by_id(ns, mark) - eq({er, ec}, rv) - feed("u") - rv = curbufmeths.get_extmark_by_id(ns, mark) - eq({sr, sc}, rv) - feed("<c-r>") - rv = curbufmeths.get_extmark_by_id(ns, mark) - eq({er, ec}, rv) -end - local function set_extmark(ns_id, id, line, col, opts) if opts == nil then opts = {} end - return curbufmeths.set_extmark(ns_id, id, line, col, opts) + if id ~= nil and id ~= 0 then + opts.id = id + end + return curbufmeths.set_extmark(ns_id, line, col, opts) end local function get_extmarks(ns_id, start, end_, opts) @@ -42,6 +34,24 @@ local function get_extmarks(ns_id, start, end_, opts) return curbufmeths.get_extmarks(ns_id, start, end_, opts) end +local function get_extmark_by_id(ns_id, id, opts) + if opts == nil then + opts = {} + end + return curbufmeths.get_extmark_by_id(ns_id, id, opts) +end + +local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end + local rv = get_extmark_by_id(ns, mark) + eq({er, ec}, rv) + feed("u") + rv = get_extmark_by_id(ns, mark) + eq({sr, sc}, rv) + feed("<c-r>") + rv = get_extmark_by_id(ns, mark) + eq({er, ec}, rv) +end + local function batch_set(ns_id, positions) local ids = {} for _, pos in ipairs(positions) do @@ -93,7 +103,7 @@ describe('API/extmarks', function() it('adds, updates and deletes marks', function() local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2]) eq(marks[1], rv) - rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + rv = get_extmark_by_id(ns, marks[1]) eq({positions[1][1], positions[1][2]}, rv) -- Test adding a second mark on same row works rv = set_extmark(ns, marks[2], positions[2][1], positions[2][2]) @@ -102,14 +112,14 @@ describe('API/extmarks', function() -- Test an update, (same pos) rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2]) eq(marks[1], rv) - rv = curbufmeths.get_extmark_by_id(ns, marks[2]) + rv = get_extmark_by_id(ns, marks[2]) eq({positions[2][1], positions[2][2]}, rv) -- Test an update, (new pos) row = positions[1][1] col = positions[1][2] + 1 rv = set_extmark(ns, marks[1], row, col) eq(marks[1], rv) - rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + rv = get_extmark_by_id(ns, marks[1]) eq({row, col}, rv) -- remove the test marks @@ -432,7 +442,7 @@ describe('API/extmarks', function() ~ | | ]]) - local rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + local rv = get_extmark_by_id(ns, marks[1]) eq({0, 6}, rv) check_undo_redo(ns, marks[1], 0, 3, 0, 6) end) @@ -906,9 +916,9 @@ describe('API/extmarks', function() -- Set the mark before the cursor, should stay there set_extmark(ns, marks[2], 0, 10) feed("i<cr><esc>") - local rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + local rv = get_extmark_by_id(ns, marks[1]) eq({1, 3}, rv) - rv = curbufmeths.get_extmark_by_id(ns, marks[2]) + rv = get_extmark_by_id(ns, marks[2]) eq({0, 10}, rv) check_undo_redo(ns, marks[1], 0, 12, 1, 3) end) @@ -921,12 +931,12 @@ describe('API/extmarks', function() feed("0iint <esc>A {<cr><esc>0i1M1<esc>") set_extmark(ns, marks[1], 1, 1) feed("0i<c-f><esc>") - local rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + local rv = get_extmark_by_id(ns, marks[1]) eq({1, 3}, rv) check_undo_redo(ns, marks[1], 1, 1, 1, 3) -- now check when cursor at eol feed("uA<c-f><esc>") - rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + rv = get_extmark_by_id(ns, marks[1]) eq({1, 3}, rv) end) @@ -937,12 +947,12 @@ describe('API/extmarks', function() feed("0i<tab><esc>") set_extmark(ns, marks[1], 0, 3) feed("bi<c-d><esc>") - local rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + local rv = get_extmark_by_id(ns, marks[1]) eq({0, 1}, rv) check_undo_redo(ns, marks[1], 0, 3, 0, 1) -- check when cursor at eol feed("uA<c-d><esc>") - rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + rv = get_extmark_by_id(ns, marks[1]) eq({0, 1}, rv) end) @@ -1072,7 +1082,7 @@ describe('API/extmarks', function() check_undo_redo(ns, marks[5], 2, 0, 3, 0) feed('u') feed([[:1,2s:3:\rxx<cr>]]) - eq({1, 3}, curbufmeths.get_extmark_by_id(ns, marks[3])) + eq({1, 3}, get_extmark_by_id(ns, marks[3])) end) it('substitions over multiple lines with replace in substition', function() @@ -1311,16 +1321,16 @@ describe('API/extmarks', function() eq("Invalid ns_id", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])) eq("Invalid ns_id", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1])) eq("Invalid ns_id", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2])) - eq("Invalid ns_id", pcall_err(curbufmeths.get_extmark_by_id, ns_invalid, marks[1])) + eq("Invalid ns_id", pcall_err(get_extmark_by_id, ns_invalid, marks[1])) end) it('when col = line-length, set the mark on eol', function() set_extmark(ns, marks[1], 0, -1) - local rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + local rv = get_extmark_by_id(ns, marks[1]) eq({0, init_text:len()}, rv) -- Test another set_extmark(ns, marks[1], 0, -1) - rv = curbufmeths.get_extmark_by_id(ns, marks[1]) + rv = get_extmark_by_id(ns, marks[1]) eq({0, init_text:len()}, rv) end) @@ -1333,7 +1343,7 @@ describe('API/extmarks', function() local invalid_col = init_text:len() + 1 local invalid_lnum = 3 eq('line value outside range', pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col)) - eq({}, curbufmeths.get_extmark_by_id(ns, marks[1])) + eq({}, get_extmark_by_id(ns, marks[1])) end) it('bug from check_col in extmark_set', function() @@ -1357,14 +1367,14 @@ describe('API/extmarks', function() it('can set a mark to other buffer', function() local buf = request('nvim_create_buf', 0, 1) request('nvim_buf_set_lines', buf, 0, -1, 1, {"", ""}) - local id = bufmeths.set_extmark(buf, ns, 0, 1, 0, {}) + local id = bufmeths.set_extmark(buf, ns, 1, 0, {}) eq({{id, 1, 0}}, bufmeths.get_extmarks(buf, ns, 0, -1, {})) end) it('does not crash with append/delete/undo seqence', function() meths.exec([[ let ns = nvim_create_namespace('myplugin') - call nvim_buf_set_extmark(0, ns, 0, 0, 0, {}) + call nvim_buf_set_extmark(0, ns, 0, 0, {}) call append(0, '') %delete undo]],false) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index e8435cd3b7..e4fb95442c 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -769,14 +769,14 @@ end function module.missing_provider(provider) if provider == 'ruby' or provider == 'node' or provider == 'perl' then - local prog = module.funcs['provider#' .. provider .. '#Detect']() - return prog == '' and (provider .. ' not detected') or false + local e = module.funcs['provider#'..provider..'#Detect']()[2] + return e ~= '' and e or false elseif provider == 'python' or provider == 'python3' then local py_major_version = (provider == 'python3' and 3 or 2) - local errors = module.funcs['provider#pythonx#Detect'](py_major_version)[2] - return errors ~= '' and errors or false + local e = module.funcs['provider#pythonx#Detect'](py_major_version)[2] + return e ~= '' and e or false else - assert(false, 'Unknown provider: ' .. provider) + assert(false, 'Unknown provider: '..provider) end end diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index 77f8189bb9..5be47070a7 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -1,12 +1,16 @@ -- Test suite for testing interactions with API bindings local helpers = require('test.functional.helpers')(after_each) +local inspect = require'vim.inspect' + local command = helpers.command local meths = helpers.meths local clear = helpers.clear local eq = helpers.eq +local fail = helpers.fail local exec_lua = helpers.exec_lua local feed = helpers.feed +local deepcopy = helpers.deepcopy local origlines = {"original line 1", "original line 2", @@ -16,32 +20,37 @@ local origlines = {"original line 1", "original line 6", " indented line"} -describe('lua: buffer event callbacks', function() - before_each(function() - clear() - exec_lua([[ - local events = {} +local function attach_buffer(evname) + exec_lua([[ + local evname = ... + local events = {} - function test_register(bufnr, id, changedtick, utf_sizes) - local function callback(...) - table.insert(events, {id, ...}) - if test_unreg == id then - return true - end - end - local opts = {on_lines=callback, on_detach=callback, utf_sizes=utf_sizes} - if changedtick then - opts.on_changedtick = callback + function test_register(bufnr, id, changedtick, utf_sizes) + local function callback(...) + table.insert(events, {id, ...}) + if test_unreg == id then + return true end - vim.api.nvim_buf_attach(bufnr, false, opts) end - - function get_events() - local ret_events = events - events = {} - return ret_events + local opts = {[evname]=callback, on_detach=callback, utf_sizes=utf_sizes} + if changedtick then + opts.on_changedtick = callback end - ]]) + vim.api.nvim_buf_attach(bufnr, false, opts) + end + + function get_events() + local ret_events = events + events = {} + return ret_events + end + ]], evname) +end + +describe('lua buffer event callbacks: on_lines', function() + before_each(function() + clear() + attach_buffer('on_lines') end) @@ -62,7 +71,7 @@ describe('lua: buffer event callbacks', function() local function check_events(expected) local events = exec_lua("return get_events(...)" ) if utf_sizes then - -- this test case uses ASCII only, so sizes sshould be the same. + -- this test case uses ASCII only, so sizes should be the same. -- Unicode is tested below. for _, event in ipairs(expected) do event[9] = event[8] @@ -216,4 +225,144 @@ describe('lua: buffer event callbacks', function() eq(1, meths.get_var('listener_cursor_line')) end) + it('does not SEGFAULT when calling win_findbuf in on_detach', function() + + exec_lua[[ + local buf = vim.api.nvim_create_buf(false, false) + + vim.cmd"split" + vim.api.nvim_win_set_buf(0, buf) + + vim.api.nvim_buf_attach(buf, false, { + on_detach = function(_, buf) + vim.fn.win_findbuf(buf) + end + }) + ]] + + command("q!") + helpers.assert_alive() + end) + +end) + +describe('lua: nvim_buf_attach on_bytes', function() + before_each(function() + clear() + attach_buffer('on_bytes') + end) + + -- verifying the sizes with nvim_buf_get_offset is nice (checks we cannot + -- assert the wrong thing), but masks errors with unflushed lines (as + -- nvim_buf_get_offset forces a flush of the memline). To be safe run the + -- test both ways. + local function setup_eventcheck(verify) + meths.buf_set_lines(0, 0, -1, true, origlines) + local shadow = deepcopy(origlines) + local shadowbytes = table.concat(shadow, '\n') .. '\n' + -- TODO: while we are brewing the real strong coffe, + -- verify should check buf_get_offset after every check_events + if verify then + meths.buf_get_offset(0, meths.buf_line_count(0)) + end + exec_lua("return test_register(...)", 0, "test1",false, nil) + meths.buf_get_changedtick(0) + + local verify_name = "test1" + local function check_events(expected) + local events = exec_lua("return get_events(...)" ) + + if not pcall(eq, expected, events) then + local msg = 'unexpected byte updates received.\n\nBABBLA MER \n\n' + + msg = msg .. 'received events:\n' + for _, e in ipairs(events) do + msg = msg .. ' ' .. inspect(e) .. ';\n' + end + msg = msg .. '\nexpected events:\n' + for _, e in ipairs(expected) do + msg = msg .. ' ' .. inspect(e) .. ';\n' + end + fail(msg) + end + + if verify then + for _, event in ipairs(events) do + if event[1] == verify_name and event[2] == "bytes" then + local _, _, _, _, _, _, start_byte, _, _, old_byte, _, _, new_byte = unpack(event) + local before = string.sub(shadowbytes, 1, start_byte) + -- no text in the tests will contain 0xff bytes (invalid UTF-8) + -- so we can use it as marker for unknown bytes + local unknown = string.rep('\255', new_byte) + local after = string.sub(shadowbytes, start_byte + old_byte + 1) + shadowbytes = before .. unknown .. after + end + end + local text = meths.buf_get_lines(0, 0, -1, true) + local bytes = table.concat(text, '\n') .. '\n' + eq(string.len(bytes), string.len(shadowbytes), shadowbytes) + for i = 1, string.len(shadowbytes) do + local shadowbyte = string.sub(shadowbytes, i, i) + if shadowbyte ~= '\255' then + eq(string.sub(bytes, i, i), shadowbyte, i) + end + end + end + end + + return check_events + end + + -- Yes, we can do both + local function do_both(verify) + it('single and multiple join', function() + local check_events = setup_eventcheck(verify) + feed 'ggJ' + check_events { + {'test1', 'bytes', 1, 3, 0, 15, 15, 1, 0, 1, 0, 1, 1}; + } + + feed '3J' + check_events { + {'test1', 'bytes', 1, 5, 0, 31, 31, 1, 0, 1, 0, 1, 1}; + {'test1', 'bytes', 1, 5, 0, 47, 47, 1, 0, 1, 0, 1, 1}; + } + end) + + it('opening lines', function() + local check_events = setup_eventcheck(verify) + -- meths.buf_set_option(0, 'autoindent', true) + feed 'Go' + check_events { + { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 }; + } + feed '<cr>' + check_events { + { "test1", "bytes", 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 }; + } + end) + + it('opening lines with autoindent', function() + local check_events = setup_eventcheck(verify) + meths.buf_set_option(0, 'autoindent', true) + feed 'Go' + check_events { + { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 5 }; + } + feed '<cr>' + check_events { + { "test1", "bytes", 1, 4, 8, 0, 115, 0, 4, 4, 0, 0, 0 }; + { "test1", "bytes", 1, 5, 7, 4, 118, 0, 0, 0, 1, 4, 5 }; + } + end) + end + + describe('(with verify) handles', function() + do_both(true) + end) + + describe('(without verify) handles', function() + do_both(false) + end) end) + diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index b0ac9e079a..2c9107a65a 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -127,6 +127,58 @@ void ui_refresh(void) } }]] + it('allows to iterate over nodes children', function() + if not check_parser() then return end + + insert(test_text); + + local res = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") + + func_node = parser:parse():root():child(0) + + res = {} + for node, field in func_node:iter_children() do + table.insert(res, {node:type(), field}) + end + return res + ]]) + + eq({ + {"primitive_type", "type"}, + {"function_declarator", "declarator"}, + {"compound_statement", "body"} + }, res) + end) + + it('allows to get a child by field', function() + if not check_parser() then return end + + insert(test_text); + + local res = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") + + func_node = parser:parse():root():child(0) + + local res = {} + for _, node in ipairs(func_node:field("type")) do + table.insert(res, {node:type(), node:range()}) + end + return res + ]]) + + eq({{ "primitive_type", 0, 0, 0, 4 }}, res) + + local res_fail = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") + + return #func_node:field("foo") == 0 + ]]) + + assert(res_fail) + end) + local query = [[ ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN")) "for" @keyword @@ -198,6 +250,35 @@ void ui_refresh(void) }, res) end) + it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function() + if not check_parser() then return end + + insert('char* astring = "Hello World!";') + + local res = exec_lua([[ + cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))') + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse() + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 0, 1) do + -- can't transmit node over RPC. just check the name and range + local mrepr = {} + for cid,node in pairs(match) do + table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) + end + table.insert(res, {pattern, mrepr}) + end + return res + ]]) + + eq({ + { 1, { { "quote", '"', 0, 16, 0, 17 } } }, + { 2, { { "quote", '"', 0, 16, 0, 17 } } }, + { 1, { { "quote", '"', 0, 29, 0, 30 } } }, + { 2, { { "quote", '"', 0, 29, 0, 30 } } }, + }, res) + end) + it('allows to add predicates', function() insert([[ int main(void) { @@ -231,6 +312,18 @@ void ui_refresh(void) ]], custom_query) eq({{0, 4, 0, 8}}, res) + + local res_list = exec_lua[[ + local query = require'vim.treesitter.query' + + local list = query.list_predicates() + + table.sort(list) + + return list + ]] + + eq({ 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) it('supports highlighting', function() @@ -280,7 +373,7 @@ static int nlua_schedule(lua_State *const lstate) ; Use lua regexes ((identifier) @Identifier (#contains? @Identifier "lua_")) -((identifier) @Constant (#match? @Constant "^[A-Z_]+$")) +((identifier) @Constant (#lua-match? @Constant "^[A-Z_]+$")) ((identifier) @Normal (#vim-match? @Constant "^lstate$")) ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (#eq? @WarningMsg.left @WarningMsg.right)) @@ -352,6 +445,32 @@ static int nlua_schedule(lua_State *const lstate) | ]]} + feed("5Goc<esc>dd") + if true == true then + pending('reenable this check in luahl PR') + return + end + screen:expect{grid=[[ + {2:/// Schedule Lua callback on main loop's event queue} | + {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) | + { | + {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} | + || {6:lstate} != {6:lstate}) { | + {11:^lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); | + {4:return} {11:lua_error}(lstate); | + } | + | + {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); | + | + multiqueue_put(main_loop.events, {11:nlua_schedule_event}, | + {5:1}, ({3:void} *)({3:ptrdiff_t})cb); | + {4:return} {5:0}; | + } | + {1:~ }| + {1:~ }| + | + ]]} + feed('7Go*/<esc>') screen:expect{grid=[[ {2:/// Schedule Lua callback on main loop's event queue} | @@ -361,7 +480,7 @@ static int nlua_schedule(lua_State *const lstate) || {6:lstate} != {6:lstate}) { | {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); | {4:return} {11:lua_error}(lstate); | - {8:*^/} | + *^/ | } | | {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); | diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index 11ce26410d..92d077ed14 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -290,9 +290,6 @@ describe('XDG-based defaults', function() end) end) - -- TODO(jkeyes): tests below fail on win32 because of path separator. - if helpers.pending_win32(pending) then return end - local function vimruntime_and_libdir() local vimruntime = eval('$VIMRUNTIME') -- libdir is hard to calculate reliably across various ci platforms @@ -301,71 +298,78 @@ describe('XDG-based defaults', function() return vimruntime, libdir end + local env_sep = iswin() and ';' or ':' + local data_dir = iswin() and 'nvim-data' or 'nvim' + local root_path = iswin() and 'C:' or '' + describe('with too long XDG variables', function() before_each(function() clear({env={ - XDG_CONFIG_HOME=('/x'):rep(4096), - XDG_CONFIG_DIRS=(('/a'):rep(2048) - .. ':' .. ('/b'):rep(2048) - .. (':/c'):rep(512)), - XDG_DATA_HOME=('/X'):rep(4096), - XDG_DATA_DIRS=(('/A'):rep(2048) - .. ':' .. ('/B'):rep(2048) - .. (':/C'):rep(512)), + XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)), + XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048) + .. env_sep.. root_path .. ('/b'):rep(2048) + .. (env_sep .. root_path .. '/c'):rep(512)), + XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)), + XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048) + .. env_sep .. root_path .. ('/B'):rep(2048) + .. (env_sep .. root_path .. '/C'):rep(512)), }}) end) it('are correctly set', function() local vimruntime, libdir = vimruntime_and_libdir() - eq((('/x'):rep(4096) .. '/nvim' - .. ',' .. ('/a'):rep(2048) .. '/nvim' - .. ',' .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. '/c/nvim'):rep(512) - .. ',' .. ('/X'):rep(4096) .. '/nvim/site' - .. ',' .. ('/A'):rep(2048) .. '/nvim/site' - .. ',' .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. '/C/nvim/site'):rep(512) + eq(((root_path .. ('/x'):rep(4096) .. '/nvim' + .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim' + .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim' + .. (',' .. root_path .. '/c/nvim'):rep(512) + .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site' + .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site' + .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site' + .. (',' .. root_path .. '/C/nvim/site'):rep(512) .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. '/C/nvim/site/after'):rep(512) - .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after' - .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after' - .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after' - .. (',' .. '/c/nvim/after'):rep(512) - .. ',' .. ('/b'):rep(2048) .. '/nvim/after' - .. ',' .. ('/a'):rep(2048) .. '/nvim/after' - .. ',' .. ('/x'):rep(4096) .. '/nvim/after' - ), meths.get_option('runtimepath')) + .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after' + .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after' + .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after' + .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after' + .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after' + .. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after' + ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/')) meths.command('set runtimepath&') meths.command('set backupdir&') meths.command('set directory&') meths.command('set undodir&') meths.command('set viewdir&') - eq((('/x'):rep(4096) .. '/nvim' - .. ',' .. ('/a'):rep(2048) .. '/nvim' - .. ',' .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. '/c/nvim'):rep(512) - .. ',' .. ('/X'):rep(4096) .. '/nvim/site' - .. ',' .. ('/A'):rep(2048) .. '/nvim/site' - .. ',' .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. '/C/nvim/site'):rep(512) + eq(((root_path .. ('/x'):rep(4096) .. '/nvim' + .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim' + .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim' + .. (',' .. root_path .. '/c/nvim'):rep(512) + .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site' + .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site' + .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site' + .. (',' .. root_path .. '/C/nvim/site'):rep(512) .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. '/C/nvim/site/after'):rep(512) - .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after' - .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after' - .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after' - .. (',' .. '/c/nvim/after'):rep(512) - .. ',' .. ('/b'):rep(2048) .. '/nvim/after' - .. ',' .. ('/a'):rep(2048) .. '/nvim/after' - .. ',' .. ('/x'):rep(4096) .. '/nvim/after' - ), meths.get_option('runtimepath')) - eq('.,' .. ('/X'):rep(4096) .. '/nvim/backup', - meths.get_option('backupdir')) - eq(('/X'):rep(4096) .. '/nvim/swap//', meths.get_option('directory')) - eq(('/X'):rep(4096) .. '/nvim/undo', meths.get_option('undodir')) - eq(('/X'):rep(4096) .. '/nvim/view', meths.get_option('viewdir')) + .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after' + .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after' + .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after' + .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after' + .. ',' .. 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', + (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', + (meths.get_option('undodir')):gsub('\\', '/')) + eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view', + (meths.get_option('viewdir')):gsub('\\', '/')) end) end) @@ -381,53 +385,61 @@ describe('XDG-based defaults', function() it('are not expanded', function() local vimruntime, libdir = vimruntime_and_libdir() - eq(('$XDG_DATA_HOME/nvim' + eq((('$XDG_DATA_HOME/nvim' .. ',$XDG_DATA_DIRS/nvim' - .. ',$XDG_CONFIG_HOME/nvim/site' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site' .. ',$XDG_CONFIG_DIRS/nvim/site' .. ',' .. vimruntime .. ',' .. libdir .. ',$XDG_CONFIG_DIRS/nvim/site/after' - .. ',$XDG_CONFIG_HOME/nvim/site/after' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after' .. ',$XDG_DATA_DIRS/nvim/after' .. ',$XDG_DATA_HOME/nvim/after' - ), meths.get_option('runtimepath')) + ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/')) meths.command('set runtimepath&') meths.command('set backupdir&') meths.command('set directory&') meths.command('set undodir&') meths.command('set viewdir&') - eq(('$XDG_DATA_HOME/nvim' + eq((('$XDG_DATA_HOME/nvim' .. ',$XDG_DATA_DIRS/nvim' - .. ',$XDG_CONFIG_HOME/nvim/site' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site' .. ',$XDG_CONFIG_DIRS/nvim/site' .. ',' .. vimruntime .. ',' .. libdir .. ',$XDG_CONFIG_DIRS/nvim/site/after' - .. ',$XDG_CONFIG_HOME/nvim/site/after' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after' .. ',$XDG_DATA_DIRS/nvim/after' .. ',$XDG_DATA_HOME/nvim/after' - ), meths.get_option('runtimepath')) - eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir')) - eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory')) - eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir')) - eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir')) + ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/')) + 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'), + meths.get_option('undodir'):gsub('\\', '/')) + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'), + meths.get_option('viewdir'):gsub('\\', '/')) meths.command('set all&') eq(('$XDG_DATA_HOME/nvim' .. ',$XDG_DATA_DIRS/nvim' - .. ',$XDG_CONFIG_HOME/nvim/site' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site' .. ',$XDG_CONFIG_DIRS/nvim/site' .. ',' .. vimruntime .. ',' .. libdir .. ',$XDG_CONFIG_DIRS/nvim/site/after' - .. ',$XDG_CONFIG_HOME/nvim/site/after' + .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after' .. ',$XDG_DATA_DIRS/nvim/after' .. ',$XDG_DATA_HOME/nvim/after' - ), meths.get_option('runtimepath')) - eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir')) - eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory')) - eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir')) - eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir')) + ):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/')) + 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'), + meths.get_option('undodir'):gsub('\\', '/')) + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'), + meths.get_option('viewdir'):gsub('\\', '/')) end) end) @@ -435,53 +447,58 @@ describe('XDG-based defaults', function() before_each(function() clear({env={ XDG_CONFIG_HOME=', , ,', - XDG_CONFIG_DIRS=',-,-,:-,-,-', + XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-', XDG_DATA_HOME=',=,=,', - XDG_DATA_DIRS=',≡,≡,:≡,≡,≡', + XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡', }}) end) it('are escaped properly', function() local vimruntime, libdir = vimruntime_and_libdir() - eq(('\\, \\, \\,/nvim' - .. ',\\,-\\,-\\,/nvim' - .. ',-\\,-\\,-/nvim' - .. ',\\,=\\,=\\,/nvim/site' - .. ',\\,≡\\,≡\\,/nvim/site' - .. ',≡\\,≡\\,≡/nvim/site' + local path_sep = iswin() and '\\' or '/' + eq(('\\, \\, \\,' .. path_sep .. 'nvim' + .. ',\\,-\\,-\\,' .. path_sep .. 'nvim' + .. ',-\\,-\\,-' .. path_sep .. 'nvim' + .. ',\\,=\\,=\\,' .. path_sep .. data_dir .. path_sep .. 'site' + .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site' + .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site' .. ',' .. vimruntime .. ',' .. libdir - .. ',≡\\,≡\\,≡/nvim/site/after' - .. ',\\,≡\\,≡\\,/nvim/site/after' - .. ',\\,=\\,=\\,/nvim/site/after' - .. ',-\\,-\\,-/nvim/after' - .. ',\\,-\\,-\\,/nvim/after' - .. ',\\, \\, \\,/nvim/after' + .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after' + .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after' + .. ',\\,=\\,=\\,' .. path_sep.. data_dir .. path_sep .. 'site' .. path_sep .. 'after' + .. ',-\\,-\\,-' .. path_sep .. 'nvim' .. path_sep .. 'after' + .. ',\\,-\\,-\\,' .. path_sep .. 'nvim' .. path_sep .. 'after' + .. ',\\, \\, \\,' .. path_sep .. 'nvim' .. path_sep .. 'after' ), meths.get_option('runtimepath')) meths.command('set runtimepath&') meths.command('set backupdir&') meths.command('set directory&') meths.command('set undodir&') meths.command('set viewdir&') - eq(('\\, \\, \\,/nvim' - .. ',\\,-\\,-\\,/nvim' - .. ',-\\,-\\,-/nvim' - .. ',\\,=\\,=\\,/nvim/site' - .. ',\\,≡\\,≡\\,/nvim/site' - .. ',≡\\,≡\\,≡/nvim/site' + eq(('\\, \\, \\,' .. path_sep .. 'nvim' + .. ',\\,-\\,-\\,' .. path_sep ..'nvim' + .. ',-\\,-\\,-' .. path_sep ..'nvim' + .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site' + .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site' + .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site' .. ',' .. vimruntime .. ',' .. libdir - .. ',≡\\,≡\\,≡/nvim/site/after' - .. ',\\,≡\\,≡\\,/nvim/site/after' - .. ',\\,=\\,=\\,/nvim/site/after' - .. ',-\\,-\\,-/nvim/after' - .. ',\\,-\\,-\\,/nvim/after' - .. ',\\, \\, \\,/nvim/after' + .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after' + .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after' + .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site' .. path_sep ..'after' + .. ',-\\,-\\,-' .. path_sep ..'nvim' .. path_sep ..'after' + .. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after' + .. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after' ), meths.get_option('runtimepath')) - eq('.,\\,=\\,=\\,/nvim/backup', meths.get_option('backupdir')) - eq('\\,=\\,=\\,/nvim/swap//', meths.get_option('directory')) - eq('\\,=\\,=\\,/nvim/undo', meths.get_option('undodir')) - eq('\\,=\\,=\\,/nvim/view', meths.get_option('viewdir')) + eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup', + 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', + meths.get_option('undodir')) + eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view', + meths.get_option('viewdir')) end) end) end) @@ -491,6 +508,7 @@ describe('stdpath()', function() -- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions -- due to XDG_CONFIG_HOME and XDG_DATA_HOME being the same. local datadir = iswin() and 'nvim-data' or 'nvim' + local env_sep = iswin() and ';' or ':' it('acceptance', function() clear() -- Do not explicitly set any env vars. @@ -634,13 +652,13 @@ describe('stdpath()', function() local function set_paths_via_system(var_name, paths) local env = base_env() - env[var_name] = table.concat(paths, ':') + env[var_name] = table.concat(paths, env_sep) clear({env=env}) end local function set_paths_at_runtime(var_name, paths) clear({env=base_env()}) - meths.set_var('env_val', table.concat(paths, ':')) + meths.set_var('env_val', table.concat(paths, env_sep)) command(('let $%s=g:env_val'):format(var_name)) end diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 1002011999..f514f4ea6f 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -971,34 +971,34 @@ describe('LSP', function() local prefix = 'foo' local completion_list = { -- resolves into label - { label='foobar' }, - { label='foobar', textEdit={} }, + { label='foobar', sortText="a" }, + { label='foobar', sortText="b", textEdit={} }, -- resolves into insertText - { label='foocar', insertText='foobar' }, - { label='foocar', insertText='foobar', textEdit={} }, + { label='foocar', sortText="c", insertText='foobar' }, + { label='foocar', sortText="d", insertText='foobar', textEdit={} }, -- resolves into textEdit.newText - { label='foocar', insertText='foodar', textEdit={newText='foobar'} }, - { label='foocar', textEdit={newText='foobar'} }, + { label='foocar', sortText="e", insertText='foodar', textEdit={newText='foobar'} }, + { label='foocar', sortText="f", textEdit={newText='foobar'} }, -- real-world snippet text - { label='foocar', insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} }, - { label='foocar', insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} }, + { label='foocar', sortText="g", insertText='foodar', textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} }, + { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', textEdit={} }, -- nested snippet tokens - { label='foocar', insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} }, + { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', textEdit={} }, -- plain text - { label='foocar', insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} }, + { label='foocar', sortText="j", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} }, } local completion_list_items = {items=completion_list} local expected = { - { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label = 'foobar' } } } } }, - { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foobar', textEdit={} } } } } }, - { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foobar' } } } } }, - { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foobar', textEdit={} } } } } }, - { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', insertText='foodar', textEdit={newText='foobar'} } } } } }, - { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', 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', insertText='foodar', 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', insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', 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', insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', 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', insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } }, + { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label = 'foobar', sortText="a" } } } } }, + { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foobar', sortText="b", textEdit={} } } } } }, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="c", insertText='foobar' } } } } }, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="d", insertText='foobar', textEdit={} } } } } }, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="e", insertText='foodar', textEdit={newText='foobar'} } } } } }, + { 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', 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\\}', 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\\}', 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={} } } } } }, } eq(expected, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], completion_list, prefix)) diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua index da9dd09129..1431054494 100644 --- a/test/functional/provider/clipboard_spec.lua +++ b/test/functional/provider/clipboard_spec.lua @@ -153,6 +153,16 @@ describe('clipboard', function() eq('', eval('provider#clipboard#Error()')) end) + it('g:clipboard using lists', function() + source([[let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '+': ['any', 'command'], '*': ['some', 'other'] }, + \ 'paste': { '+': ['any', 'command'], '*': ['some', 'other'] }, + \}]]) + eq('custom', eval('provider#clipboard#Executable()')) + eq('', eval('provider#clipboard#Error()')) + end) + it('g:clipboard using VimL functions', function() -- Implements a fake clipboard provider. cache_enabled is meaningless here. source([[let g:clipboard = { diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua index 7b446e4ab3..125674660b 100644 --- a/test/functional/provider/perl_spec.lua +++ b/test/functional/provider/perl_spec.lua @@ -5,6 +5,10 @@ local command = helpers.command local write_file = helpers.write_file local eval = helpers.eval local retry = helpers.retry +local curbufmeths = helpers.curbufmeths +local insert = helpers.insert +local expect = helpers.expect +local feed = helpers.feed do clear() @@ -19,7 +23,51 @@ before_each(function() clear() end) -describe('perl host', function() +describe('legacy perl provider', function() + if helpers.pending_win32(pending) then return end + + it('feature test', function() + eq(1, eval('has("perl")')) + end) + + it(':perl command', function() + command('perl $vim->vars->{set_by_perl} = [100, 0];') + eq({100, 0}, eval('g:set_by_perl')) + end) + + it(':perlfile command', function() + local fname = 'perlfile.pl' + write_file(fname, '$vim->command("let set_by_perlfile = 123")') + command('perlfile perlfile.pl') + eq(123, eval('g:set_by_perlfile')) + os.remove(fname) + end) + + it(':perldo command', function() + -- :perldo 1; doesn't change $_, + -- the buffer should not be changed + command('normal :perldo 1;') + eq(false, curbufmeths.get_option('modified')) + -- insert some text + insert('abc\ndef\nghi') + expect([[ + abc + def + ghi]]) + -- go to top and select and replace the first two lines + feed('ggvj:perldo $_ = reverse ($_)."$linenr"<CR>') + expect([[ + cba1 + fed2 + ghi]]) + end) + + it('perleval()', function() + eq({1, 2, {['key'] = 'val'}}, eval([[perleval('[1, 2, {"key" => "val"}]')]])) + end) +end) + +describe('perl provider', function() if helpers.pending_win32(pending) then return end teardown(function () os.remove('Xtest-perl-hello.pl') diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 3cb592c714..d7269d2c29 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -690,7 +690,7 @@ describe('Buffer highlighting', function() end) it('can be retrieved', function() - local get_virtual_text = curbufmeths.get_virtual_text + local get_extmarks = curbufmeths.get_extmarks local line_count = curbufmeths.line_count local s1 = {{'Köttbullar', 'Comment'}, {'Kräuterbutter'}} @@ -699,12 +699,14 @@ describe('Buffer highlighting', function() -- TODO: only a virtual text from the same ns curretly overrides -- an existing virtual text. We might add a prioritation system. set_virtual_text(id1, 0, s1, {}) - eq(s1, get_virtual_text(0)) + eq({{1, 0, 0, {virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true})) - set_virtual_text(-1, line_count(), s2, {}) - eq(s2, get_virtual_text(line_count())) + -- TODO: is this really valid? shouldn't the max be line_count()-1? + local lastline = line_count() + set_virtual_text(id1, line_count(), s2, {}) + eq({{3, lastline, 0, {virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true})) - eq({}, get_virtual_text(line_count() + 9000)) + eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {})) end) it('is not highlighted by visual selection', function() diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 9646c3fdad..2f113f6ac6 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -14,10 +14,10 @@ describe('UI receives option updates', function() arabicshape=true, emoji=true, guifont='', - guifontset='', guifontwide='', linespace=0, pumblend=0, + mousefocus=false, showtabline=1, termguicolors=false, ttimeout=true, @@ -110,6 +110,12 @@ describe('UI receives option updates', function() eq(expected, screen.options) end) + command("set mousefocus") + expected.mousefocus = true + screen:expect(function() + eq(expected, screen.options) + end) + command("set nottimeout") expected.ttimeout = false screen:expect(function() diff --git a/test/helpers.lua b/test/helpers.lua index 40b93d9935..2e0258afed 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -82,6 +82,17 @@ end function module.ok(res, msg, logfile) return dumplog(logfile, assert.is_true, res, msg) end + +-- TODO(bfredl): this should "failure" not "error" (issue with dumplog() ) +local function epicfail(state, arguments, _) + state.failure_message = arguments[1] + return false +end +assert:register("assertion", "epicfail", epicfail) +function module.fail(msg, logfile) + return dumplog(logfile, assert.epicfail, msg) +end + function module.matches(pat, actual) if nil ~= string.match(actual, pat) then return true @@ -200,14 +211,25 @@ function module.check_logs() end end fd:close() - os.remove(file) if #lines > 0 then + local status, f local out = io.stdout + if os.getenv('SYMBOLIZER') then + status, f = pcall(module.popen_r, os.getenv('SYMBOLIZER'), '-l', file) + end out:write(start_msg .. '\n') - out:write('= ' .. table.concat(lines, '\n= ') .. '\n') + if status then + for line in f:lines() do + out:write('= '..line..'\n') + end + f:close() + else + out:write('= ' .. table.concat(lines, '\n= ') .. '\n') + end out:write(select(1, start_msg:gsub('.', '=')) .. '\n') table.insert(runtime_errors, file) end + os.remove(file) end end end diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua index ad05b134e0..e7cb5e5d5e 100644 --- a/test/unit/os/env_spec.lua +++ b/test/unit/os/env_spec.lua @@ -78,15 +78,22 @@ describe('env.c', function() end) describe('os_setenv_append_path', function() - itp('appends /foo/bar to $PATH', function() + itp('appends :/foo/bar to $PATH', function() local original_path = os.getenv('PATH') - eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz'))) + eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe'))) eq(original_path..':/foo/bar', os.getenv('PATH')) end) + itp('avoids redundant separator when appending to $PATH #7377', function() + os_setenv('PATH', '/a/b/c:', true) + eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe'))) + -- Must not have duplicate separators. #7377 + eq('/a/b/c:/foo/bar', os.getenv('PATH')) + end) + itp('returns false if `fname` is not absolute', function() local original_path = os.getenv('PATH') - eq(false, cimp.os_setenv_append_path(to_cstr('foo/bar/baz'))) + eq(false, cimp.os_setenv_append_path(to_cstr('foo/bar/baz.exe'))) eq(original_path, os.getenv('PATH')) end) end) |