diff options
Diffstat (limited to 'test/functional/plugin')
21 files changed, 5515 insertions, 3846 deletions
diff --git a/test/functional/plugin/cfilter_spec.lua b/test/functional/plugin/cfilter_spec.lua index 8b1e75b495..37261d59df 100644 --- a/test/functional/plugin/cfilter_spec.lua +++ b/test/functional/plugin/cfilter_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command local eq = helpers.eq -local funcs = helpers.funcs +local fn = helpers.fn describe('cfilter.lua', function() before_each(function() @@ -13,16 +13,16 @@ describe('cfilter.lua', function() for _, list in ipairs({ { name = 'Cfilter', - get = funcs.getqflist, - set = funcs.setqflist, + get = fn.getqflist, + set = fn.setqflist, }, { name = 'Lfilter', get = function() - return funcs.getloclist(0) + return fn.getloclist(0) end, set = function(items) - return funcs.setloclist(0, items) + return fn.setloclist(0, items) end, }, }) do @@ -39,7 +39,7 @@ describe('cfilter.lua', function() describe((':%s'):format(list.name), function() it('does not error on empty list', function() filter('nothing') - eq({}, funcs.getqflist()) + eq({}, fn.getqflist()) end) it('requires an argument', function() @@ -66,7 +66,7 @@ describe('cfilter.lua', function() end local toname = function(qflist) - return funcs.map(qflist, 'v:val.text') + return fn.map(qflist, 'v:val.text') end test('filters with no matches', 'does not match', {}) @@ -83,7 +83,7 @@ describe('cfilter.lua', function() { filename = 'foo', lnum = 3, text = 'zed' }, }) - funcs.setreg('/', 'ba') + fn.setreg('/', 'ba') filter('/') eq({ 'bar', 'baz' }, toname(list.get())) @@ -96,7 +96,7 @@ describe('cfilter.lua', function() { filename = 'foo', lnum = 3, text = 'zed' }, }) - funcs.setreg('/', 'ba') + fn.setreg('/', 'ba') filter('/', true) eq({ 'zed' }, toname(list.get())) diff --git a/test/functional/plugin/editorconfig_spec.lua b/test/functional/plugin/editorconfig_spec.lua index ac78003a8c..115c28fbf6 100644 --- a/test/functional/plugin/editorconfig_spec.lua +++ b/test/functional/plugin/editorconfig_spec.lua @@ -3,8 +3,8 @@ local clear = helpers.clear local command = helpers.command local eq = helpers.eq local pathsep = helpers.get_pathsep() -local funcs = helpers.funcs -local meths = helpers.meths +local fn = helpers.fn +local api = helpers.api local exec_lua = helpers.exec_lua local testdir = 'Xtest-editorconfig' @@ -13,7 +13,7 @@ local function test_case(name, expected) local filename = testdir .. pathsep .. name command('edit ' .. filename) for opt, val in pairs(expected) do - eq(val, meths.get_option_value(opt, {buf=0}), name) + eq(val, api.nvim_get_option_value(opt, { buf = 0 }), name) end end @@ -195,15 +195,15 @@ But not this one end) it('can be disabled globally', function() - meths.set_var('editorconfig', false) - meths.set_option_value('shiftwidth', 42, {}) + api.nvim_set_var('editorconfig', false) + api.nvim_set_option_value('shiftwidth', 42, {}) test_case('3_space.txt', { shiftwidth = 42 }) end) it('can be disabled per-buffer', function() - meths.set_option_value('shiftwidth', 42, {}) - local bufnr = funcs.bufadd(testdir .. pathsep .. '3_space.txt') - meths.buf_set_var(bufnr, 'editorconfig', false) + api.nvim_set_option_value('shiftwidth', 42, {}) + local bufnr = fn.bufadd(testdir .. pathsep .. '3_space.txt') + api.nvim_buf_set_var(bufnr, 'editorconfig', false) test_case('3_space.txt', { shiftwidth = 42 }) test_case('4_space.py', { shiftwidth = 4 }) end) diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index 50b1d03f36..8564ec7c9b 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -5,12 +5,15 @@ local clear = helpers.clear local curbuf_contents = helpers.curbuf_contents local command = helpers.command local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches -local getcompletion = helpers.funcs.getcompletion +local getcompletion = helpers.fn.getcompletion +local insert = helpers.insert +local source = helpers.source +local exec_lua = helpers.exec_lua describe(':checkhealth', function() - it("detects invalid $VIMRUNTIME", function() + it('detects invalid $VIMRUNTIME', function() clear({ - env={ VIMRUNTIME='bogus', }, + env = { VIMRUNTIME = 'bogus' }, }) local status, err = pcall(command, 'checkhealth') eq(false, status) @@ -23,32 +26,32 @@ describe(':checkhealth', function() eq(false, status) eq("Invalid 'runtimepath'", string.match(err, 'Invalid.*')) end) - it("detects invalid $VIM", function() + it('detects invalid $VIM', function() clear() -- Do this after startup, otherwise it just breaks $VIMRUNTIME. command("let $VIM='zub'") - command("checkhealth nvim") + command('checkhealth nvim') matches('ERROR $VIM .* zub', curbuf_contents()) end) it('completions can be listed via getcompletion()', function() clear() eq('nvim', getcompletion('nvim', 'checkhealth')[1]) - eq('provider', getcompletion('prov', 'checkhealth')[1]) + eq('provider.clipboard', getcompletion('prov', 'checkhealth')[1]) eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1]) - neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health + neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health end) end) describe('health.vim', function() before_each(function() - clear{args={'-u', 'NORC'}} + clear { args = { '-u', 'NORC' } } -- Provides healthcheck functions - command("set runtimepath+=test/functional/fixtures") + command('set runtimepath+=test/functional/fixtures') end) - describe(":checkhealth", function() - it("functions report_*() render correctly", function() - command("checkhealth full_render") + describe(':checkhealth', function() + it('functions report_*() render correctly', function() + command('checkhealth full_render') helpers.expect([[ ============================================================================== @@ -70,8 +73,8 @@ describe('health.vim', function() ]]) end) - it("concatenates multiple reports", function() - command("checkhealth success1 success2 test_plug") + it('concatenates multiple reports', function() + command('checkhealth success1 success2 test_plug') helpers.expect([[ ============================================================================== @@ -100,8 +103,8 @@ describe('health.vim', function() ]]) end) - it("lua plugins submodules", function() - command("checkhealth test_plug.submodule") + it('lua plugins submodules', function() + command('checkhealth test_plug.submodule') helpers.expect([[ ============================================================================== @@ -115,8 +118,8 @@ describe('health.vim', function() ]]) end) - it("... including empty reports", function() - command("checkhealth test_plug.submodule_empty") + it('... including empty reports', function() + command('checkhealth test_plug.submodule_empty') helpers.expect([[ ============================================================================== @@ -126,7 +129,7 @@ describe('health.vim', function() ]]) end) - it("highlights OK, ERROR", function() + it('highlights OK, ERROR', function() local screen = Screen.new(50, 12) screen:attach() screen:set_default_attr_ids({ @@ -135,9 +138,10 @@ describe('health.vim', function() Heading = { foreground = tonumber('0x6a0dad') }, Bar = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGrey }, }) - command("checkhealth foo success1") - command("set nofoldenable nowrap laststatus=0") - screen:expect{grid=[[ + command('checkhealth foo success1') + command('set nofoldenable nowrap laststatus=0') + screen:expect { + grid = [[ ^ | {Bar:──────────────────────────────────────────────────}| {Heading:foo: } | @@ -150,15 +154,17 @@ describe('health.vim', function() {Heading:report 1} | - {Ok:OK} everything is fine | | - ]]} + ]], + } end) - it("fold healthchecks", function() + it('fold healthchecks', function() local screen = Screen.new(50, 7) screen:attach() - command("checkhealth foo success1") - command("set nowrap laststatus=0") - screen:expect{grid=[[ + command('checkhealth foo success1') + command('set nowrap laststatus=0') + screen:expect { + grid = [[ ^ | ──────────────────────────────────────────────────| +WE 4 lines: foo: ·······························| @@ -166,11 +172,12 @@ describe('health.vim', function() +-- 8 lines: test_plug.success1: require("test_pl| ~ | | - ]]} + ]], + } end) - it("gracefully handles invalid healthcheck", function() - command("checkhealth non_existent_healthcheck") + it('gracefully handles invalid healthcheck', function() + command('checkhealth non_existent_healthcheck') -- luacheck: ignore 613 helpers.expect([[ @@ -181,9 +188,9 @@ describe('health.vim', function() ]]) end) - it("does not use vim.health as a healtcheck", function() + it('does not use vim.health as a healtcheck', function() -- vim.health is not a healthcheck - command("checkhealth vim") + command('checkhealth vim') helpers.expect([[ ERROR: No healthchecks found.]]) end) @@ -200,3 +207,187 @@ describe(':checkhealth provider', function() eq(nil, string.match(curbuf_contents(), 'WRONG!!!')) end) end) + +describe(':checkhealth window', function() + before_each(function() + clear { args = { '-u', 'NORC' } } + -- Provides healthcheck functions + command('set runtimepath+=test/functional/fixtures') + command('set nofoldenable nowrap laststatus=0') + end) + + it('opens directly if no buffer created', function() + local screen = Screen.new(50, 12) + screen:attach({ ext_multigrid = true }) + command('checkhealth success1') + screen:expect { + grid = [[ + ## grid 1 + [2:--------------------------------------------------]|*11 + [3:--------------------------------------------------]| + ## grid 2 + ^ | + ──────────────────────────────────────────────────| + ──────────────────────────── | + test_plug.success1: require("test_plug.success1. | + health").check() | + | + report 1 | + - OK everything is fine | + | + report 2 | + - OK nothing to see here | + ## grid 3 + | + ]], + } + end) + + local function test_health_vsplit(left, emptybuf, mods) + local screen = Screen.new(50, 20) + screen:attach({ ext_multigrid = true }) + if not emptybuf then + insert('hello') + end + command(mods .. ' checkhealth success1') + screen:expect( + ([[ + ## grid 1 + %s + [3:--------------------------------------------------]| + ## grid 2 + %s | + ~ |*18 + ## grid 3 + | + ## grid 4 + ^ | + ─────────────────────────|*3 + ─── | + test_plug.success1: | + require("test_plug. | + success1.health").check()| + | + report 1 | + - OK everything is fine | + | + report 2 | + - OK nothing to see here | + | + ~ |*4 + ]]):format( + left and '[4:-------------------------]│[2:------------------------]|*19' + or '[2:------------------------]│[4:-------------------------]|*19', + emptybuf and ' ' or 'hello' + ) + ) + end + + for _, mods in ipairs({ 'vertical', 'leftabove vertical', 'topleft vertical' }) do + it(('opens in left vsplit window with :%s and no buffer created'):format(mods), function() + test_health_vsplit(true, true, mods) + end) + it(('opens in left vsplit window with :%s and non-empty buffer'):format(mods), function() + test_health_vsplit(true, false, mods) + end) + end + + for _, mods in ipairs({ 'rightbelow vertical', 'botright vertical' }) do + it(('opens in right vsplit window with :%s and no buffer created'):format(mods), function() + test_health_vsplit(false, true, mods) + end) + it(('opens in right vsplit window with :%s and non-empty buffer'):format(mods), function() + test_health_vsplit(false, false, mods) + end) + end + + local function test_health_split(top, emptybuf, mods) + local screen = Screen.new(50, 25) + screen:attach({ ext_multigrid = true }) + if not emptybuf then + insert('hello') + end + command(mods .. ' checkhealth success1') + screen:expect( + ([[ + ## grid 1 +%s + [3:--------------------------------------------------]| + ## grid 2 + %s | + ~ |*10 + ## grid 3 + | + ## grid 4 + ^ | + ──────────────────────────────────────────────────| + ──────────────────────────── | + test_plug.success1: require("test_plug.success1. | + health").check() | + | + report 1 | + - OK everything is fine | + | + report 2 | + - OK nothing to see here | + | + ]]):format( + top + and [[ + [4:--------------------------------------------------]|*12 + health:// | + [2:--------------------------------------------------]|*11]] + or ([[ + [2:--------------------------------------------------]|*11 + [No Name] %s | + [4:--------------------------------------------------]|*12]]):format( + emptybuf and ' ' or '[+]' + ), + emptybuf and ' ' or 'hello' + ) + ) + end + + for _, mods in ipairs({ 'horizontal', 'leftabove', 'topleft' }) do + it(('opens in top split window with :%s and no buffer created'):format(mods), function() + test_health_split(true, true, mods) + end) + it(('opens in top split window with :%s and non-empty buffer'):format(mods), function() + test_health_split(true, false, mods) + end) + end + + for _, mods in ipairs({ 'rightbelow', 'botright' }) do + it(('opens in bottom split window with :%s and no buffer created'):format(mods), function() + test_health_split(false, true, mods) + end) + it(('opens in bottom split window with :%s and non-empty buffer'):format(mods), function() + test_health_split(false, false, mods) + end) + end + + it('opens in tab', function() + -- create an empty buffer called "my_buff" + exec_lua 'vim.api.nvim_create_buf(false, true)' + command('file my_buff') + command('checkhealth success1') + -- define a function that collects all buffers in each tab + -- returns a dictionary like {tab1 = ["buf1", "buf2"], tab2 = ["buf3"]} + source([[ + function CollectBuffersPerTab() + let buffs = {} + for i in range(tabpagenr('$')) + let key = 'tab' . (i + 1) + let value = [] + for j in tabpagebuflist(i + 1) + call add(value, bufname(j)) + endfor + let buffs[key] = value + endfor + return buffs + endfunction + ]]) + local buffers_per_tab = exec_lua('return vim.fn.CollectBuffersPerTab()') + eq(buffers_per_tab, { tab1 = { 'my_buff' }, tab2 = { 'health://' } }) + end) +end) diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua index 3d7a15a191..29daf7a066 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -11,17 +11,21 @@ describe('vim.lsp.codelens', function() after_each(helpers.clear) it('on_codelens_stores_and_displays_lenses', function() - local fake_uri = "file:///fake/uri" - local bufnr = exec_lua([[ + local fake_uri = 'file:///fake/uri' + local bufnr = exec_lua( + [[ fake_uri = ... local bufnr = vim.uri_to_bufnr(fake_uri) local lines = {'So', 'many', 'lines'} vim.fn.bufload(bufnr) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) return bufnr - ]], fake_uri) + ]], + fake_uri + ) - exec_lua([[ + exec_lua( + [[ local bufnr = ... local lenses = { { @@ -33,14 +37,16 @@ describe('vim.lsp.codelens', function() }, } vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) - ]], bufnr) + ]], + bufnr + ) local stored_lenses = exec_lua('return vim.lsp.codelens.get(...)', bufnr) local expected = { { range = { start = { line = 0, character = 0 }, - ['end'] = { line = 0, character = 0 } + ['end'] = { line = 0, character = 0 }, }, command = { title = 'Lens1', @@ -50,28 +56,35 @@ describe('vim.lsp.codelens', function() } eq(expected, stored_lenses) - local virtual_text_chunks = exec_lua([[ + local virtual_text_chunks = exec_lua( + [[ local bufnr = ... local ns = vim.lsp.codelens.__namespaces[1] local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {}) return vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, extmarks[1][1], { details = true })[3].virt_text - ]], bufnr) + ]], + bufnr + ) - eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks) + eq({ [1] = { 'Lens1', 'LspCodeLens' } }, virtual_text_chunks) end) it('can clear all lens', function() - local fake_uri = "file:///fake/uri" - local bufnr = exec_lua([[ + local fake_uri = 'file:///fake/uri' + local bufnr = exec_lua( + [[ fake_uri = ... local bufnr = vim.uri_to_bufnr(fake_uri) local lines = {'So', 'many', 'lines'} vim.fn.bufload(bufnr) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) return bufnr - ]], fake_uri) + ]], + fake_uri + ) - exec_lua([[ + exec_lua( + [[ local bufnr = ... local lenses = { { @@ -83,7 +96,9 @@ describe('vim.lsp.codelens', function() }, } vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr}) - ]], bufnr) + ]], + bufnr + ) local stored_lenses = exec_lua('return vim.lsp.codelens.get(...)', bufnr) eq(1, #stored_lenses) diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 9354654afe..655eb76be6 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local exec_lua = helpers.exec_lua - --- Convert completion results. --- ---@param line string line contents. Mark cursor position with `|` @@ -13,9 +12,10 @@ local exec_lua = helpers.exec_lua local function complete(line, candidates, lnum) lnum = lnum or 0 -- nvim_win_get_cursor returns 0 based column, line:find returns 1 based - local cursor_col = line:find("|") - 1 - line = line:gsub("|", "") - return exec_lua([[ + local cursor_col = line:find('|') - 1 + line = line:gsub('|', '') + return exec_lua( + [[ local line, cursor_col, lnum, result = ... local line_to_cursor = line:sub(1, cursor_col) local client_start_boundary = vim.fn.match(line_to_cursor, '\\k*$') @@ -32,18 +32,22 @@ local function complete(line, candidates, lnum) items = items, server_start_boundary = server_start_boundary } - ]], line, cursor_col, lnum, candidates) + ]], + line, + cursor_col, + lnum, + candidates + ) end - -describe("vim.lsp._completion", function() +describe('vim.lsp._completion', function() before_each(helpers.clear) -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion it('prefers textEdit over label as word', function() local range0 = { start = { line = 0, character = 0 }, - ["end"] = { line = 0, character = 0 }, + ['end'] = { line = 0, character = 0 }, } local completion_list = { -- resolves into label @@ -57,7 +61,12 @@ describe("vim.lsp._completion", function() { label = 'foocar', sortText = 'c', insertText = 'foobar' }, { label = 'foocar', sortText = 'd', insertText = 'foobar' }, -- resolves into textEdit.newText - { label = 'foocar', sortText = 'e', insertText = 'foodar', textEdit = { newText = 'foobar', range = range0 } }, + { + label = 'foocar', + sortText = 'e', + insertText = 'foodar', + textEdit = { newText = 'foobar', range = range0 }, + }, { label = 'foocar', sortText = 'f', textEdit = { newText = 'foobar', range = range0 } }, -- real-world snippet text { @@ -65,7 +74,10 @@ describe("vim.lsp._completion", function() sortText = 'g', insertText = 'foodar', insertTextFormat = 2, - textEdit = { newText = 'foobar(${1:place holder}, ${2:more ...holder{\\}})', range = range0 }, + textEdit = { + newText = 'foobar(${1:place holder}, ${2:more ...holder{\\}})', + range = range0, + }, }, { label = 'foocar', @@ -81,7 +93,7 @@ describe("vim.lsp._completion", function() insertTextFormat = 2, }, -- braced tabstop - { label = 'foocar', sortText = 'j', insertText = 'foodar()${0}', insertTextFormat = 2}, + { label = 'foocar', sortText = 'j', insertText = 'foodar()${0}', insertTextFormat = 2 }, -- plain text { label = 'foocar', @@ -140,32 +152,32 @@ describe("vim.lsp._completion", function() result = vim.tbl_map(function(x) return { abbr = x.abbr, - word = x.word + word = x.word, } end, result.items) eq(expected, result) end) - it("uses correct start boundary", function() + it('uses correct start boundary', function() local completion_list = { isIncomplete = false, items = { { - filterText = "this_thread", - insertText = "this_thread", + filterText = 'this_thread', + insertText = 'this_thread', insertTextFormat = 1, kind = 9, - label = " this_thread", + label = ' this_thread', score = 1.3205767869949, - sortText = "4056f757this_thread", + sortText = '4056f757this_thread', textEdit = { - newText = "this_thread", + newText = 'this_thread', range = { start = { line = 0, character = 7 }, - ["end"] = { line = 0, character = 11 }, + ['end'] = { line = 0, character = 11 }, }, - } + }, }, - } + }, } local expected = { abbr = ' this_thread', @@ -176,50 +188,50 @@ describe("vim.lsp._completion", function() menu = '', word = 'this_thread', } - local result = complete(" std::this|", completion_list) + local result = complete(' std::this|', completion_list) eq(7, result.server_start_boundary) local item = result.items[1] item.user_data = nil eq(expected, item) end) - it("should search from start boundary to cursor position", function() + it('should search from start boundary to cursor position', function() local completion_list = { isIncomplete = false, items = { { - filterText = "this_thread", - insertText = "this_thread", + filterText = 'this_thread', + insertText = 'this_thread', insertTextFormat = 1, kind = 9, - label = " this_thread", + label = ' this_thread', score = 1.3205767869949, - sortText = "4056f757this_thread", + sortText = '4056f757this_thread', textEdit = { - newText = "this_thread", + newText = 'this_thread', range = { start = { line = 0, character = 7 }, - ["end"] = { line = 0, character = 11 }, + ['end'] = { line = 0, character = 11 }, }, - } + }, }, { - filterText = "notthis_thread", - insertText = "notthis_thread", + filterText = 'notthis_thread', + insertText = 'notthis_thread', insertTextFormat = 1, kind = 9, - label = " notthis_thread", + label = ' notthis_thread', score = 1.3205767869949, - sortText = "4056f757this_thread", + sortText = '4056f757this_thread', textEdit = { - newText = "notthis_thread", + newText = 'notthis_thread', range = { start = { line = 0, character = 7 }, - ["end"] = { line = 0, character = 11 }, + ['end'] = { line = 0, character = 11 }, }, - } + }, }, - } + }, } local expected = { abbr = ' this_thread', @@ -230,10 +242,38 @@ describe("vim.lsp._completion", function() menu = '', word = 'this_thread', } - local result = complete(" std::this|is", completion_list) + local result = complete(' std::this|is', completion_list) eq(1, #result.items) local item = result.items[1] item.user_data = nil eq(expected, item) end) + + it('uses defaults from itemDefaults', function() + --- @type lsp.CompletionList + local completion_list = { + isIncomplete = false, + itemDefaults = { + editRange = { + start = { line = 1, character = 1 }, + ['end'] = { line = 1, character = 4 }, + }, + insertTextFormat = 2, + data = 'foobar', + }, + items = { + { + label = 'hello', + data = 'item-property-has-priority', + textEditText = 'hello', + }, + }, + } + local result = complete('|', completion_list) + eq(1, #result.items) + local item = result.items[1].user_data.nvim.lsp.completion_item --- @type lsp.CompletionItem + eq(2, item.insertTextFormat) + eq('item-property-has-priority', item.data) + eq({ line = 1, character = 1 }, item.textEdit.range.start) + end) end) diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index 1da0222114..705c182df7 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -12,10 +12,10 @@ describe('vim.lsp.diagnostic', function() local fake_uri before_each(function() - clear {env={ - NVIM_LUA_NOTRACK="1"; - VIMRUNTIME=os.getenv"VIMRUNTIME"; - }} + clear { env = { + NVIM_LUA_NOTRACK = '1', + VIMRUNTIME = os.getenv 'VIMRUNTIME', + } } exec_lua [[ require('vim.lsp') @@ -76,9 +76,10 @@ describe('vim.lsp.diagnostic', function() } ]] - fake_uri = "file:///fake/uri" + fake_uri = 'file:///fake/uri' - exec_lua([[ + exec_lua( + [[ fake_uri = ... diagnostic_bufnr = vim.uri_to_bufnr(fake_uri) local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"} @@ -86,7 +87,9 @@ describe('vim.lsp.diagnostic', function() vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, 1, false, lines) vim.api.nvim_win_set_buf(0, diagnostic_bufnr) return diagnostic_bufnr - ]], fake_uri) + ]], + fake_uri + ) end) after_each(function() @@ -113,17 +116,18 @@ describe('vim.lsp.diagnostic', function() vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)[1], } ]] - eq({code = 42, data = "Hello world"}, result[1].user_data.lsp) + eq({ code = 42, data = 'Hello world' }, result[1].user_data.lsp) eq(42, result[1].code) eq(42, result[2].code) - eq("Hello world", result[2].data) + eq('Hello world', result[2].data) end) end) - describe("vim.lsp.diagnostic.on_publish_diagnostics", function() + describe('vim.lsp.diagnostic.on_publish_diagnostics', function() it('allows configuring the virtual text via vim.lsp.with', function() local expected_spacing = 10 - local extmarks = exec_lua([[ + local extmarks = exec_lua( + [[ PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { virtual_text = { spacing = ..., @@ -139,7 +143,9 @@ describe('vim.lsp.diagnostic', function() ) return get_extmarks(diagnostic_bufnr, client_id) - ]], expected_spacing) + ]], + expected_spacing + ) local virt_text = extmarks[1][4].virt_text local spacing = virt_text[1][1] @@ -149,7 +155,8 @@ describe('vim.lsp.diagnostic', function() it('allows configuring the virtual text via vim.lsp.with using a function', function() local expected_spacing = 10 - local extmarks = exec_lua([[ + local extmarks = exec_lua( + [[ spacing = ... PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { @@ -169,7 +176,9 @@ describe('vim.lsp.diagnostic', function() ) return get_extmarks(diagnostic_bufnr, client_id) - ]], expected_spacing) + ]], + expected_spacing + ) local virt_text = extmarks[1][4].virt_text local spacing = virt_text[1][1] @@ -179,11 +188,12 @@ describe('vim.lsp.diagnostic', function() it('allows filtering via severity limit', function() local get_extmark_count_with_severity = function(severity_limit) - return exec_lua([[ + return exec_lua( + [[ PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { underline = false, virtual_text = { - severity_limit = ... + severity = { min = ... } }, }) @@ -196,20 +206,23 @@ describe('vim.lsp.diagnostic', function() ) return #get_extmarks(diagnostic_bufnr, client_id) - ]], severity_limit) + ]], + severity_limit + ) end -- No messages with Error or higher - eq(0, get_extmark_count_with_severity("Error")) + eq(0, get_extmark_count_with_severity('ERROR')) -- But now we don't filter it - eq(1, get_extmark_count_with_severity("Warning")) - eq(1, get_extmark_count_with_severity("Hint")) + eq(1, get_extmark_count_with_severity('WARN')) + 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 = 'All 💼 and no 🎉 makes Jack a dull 👦' + local result = exec_lua( + [[ local line = ... vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line}) @@ -225,7 +238,9 @@ describe('vim.lsp.diagnostic', function() vim.lsp.stop_client(client_id) vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) return diags - ]], line) + ]], + 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) diff --git a/test/functional/plugin/lsp/handler_spec.lua b/test/functional/plugin/lsp/handler_spec.lua index 3086c23fe8..56e29e7337 100644 --- a/test/functional/plugin/lsp/handler_spec.lua +++ b/test/functional/plugin/lsp/handler_spec.lua @@ -8,21 +8,30 @@ local matches = helpers.matches describe('lsp-handlers', function() describe('vim.lsp._with_extend', function() it('should return a table with the default keys', function() - eq({hello = 'world' }, exec_lua [[ + eq( + { hello = 'world' }, + exec_lua [[ return vim.lsp._with_extend('test', { hello = 'world' }) - ]]) + ]] + ) end) it('should override with config keys', function() - eq({hello = 'universe', other = true}, exec_lua [[ + eq( + { hello = 'universe', other = true }, + exec_lua [[ return vim.lsp._with_extend('test', { other = true, hello = 'world' }, { hello = 'universe' }) - ]]) + ]] + ) end) it('should not allow invalid keys', function() matches( '.*Invalid option for `test`.*', - pcall_err(exec_lua, "return vim.lsp._with_extend('test', { hello = 'world' }, { invalid = true })") + pcall_err( + exec_lua, + "return vim.lsp._with_extend('test', { hello = 'world' }, { invalid = true })" + ) ) end) end) diff --git a/test/functional/plugin/lsp/helpers.lua b/test/functional/plugin/lsp/helpers.lua index 15e6a62781..97fa108500 100644 --- a/test/functional/plugin/lsp/helpers.lua +++ b/test/functional/plugin/lsp/helpers.lua @@ -4,18 +4,20 @@ local clear = helpers.clear local exec_lua = helpers.exec_lua local run = helpers.run local stop = helpers.stop -local NIL = helpers.NIL +local NIL = vim.NIL local M = {} function M.clear_notrace() -- problem: here be dragons -- solution: don't look too closely for dragons - clear {env={ - NVIM_LUA_NOTRACK="1"; - NVIM_APPNAME="nvim_lsp_test"; - VIMRUNTIME=os.getenv"VIMRUNTIME"; - }} + clear { + env = { + NVIM_LUA_NOTRACK = '1', + NVIM_APPNAME = 'nvim_lsp_test', + VIMRUNTIME = os.getenv 'VIMRUNTIME', + }, + } end M.create_server_definition = [[ @@ -79,7 +81,8 @@ M.fake_lsp_code = 'test/functional/fixtures/fake-lsp-server.lua' M.fake_lsp_logfile = 'Xtest-fake-lsp.log' local function fake_lsp_server_setup(test_name, timeout_ms, options, settings) - exec_lua([=[ + exec_lua( + [=[ lsp = require('vim.lsp') local test_name, fake_lsp_code, fake_lsp_logfile, timeout, options, settings = ... TEST_RPC_CLIENT_ID = lsp.start_client { @@ -115,33 +118,49 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings) vim.rpcnotify(1, "exit", ...) end; } - ]=], test_name, M.fake_lsp_code, M.fake_lsp_logfile, timeout_ms or 1e3, options or {}, settings or {}) + ]=], + test_name, + M.fake_lsp_code, + M.fake_lsp_logfile, + timeout_ms or 1e3, + options or {}, + settings or {} + ) end function M.test_rpc_server(config) if config.test_name then M.clear_notrace() - fake_lsp_server_setup(config.test_name, config.timeout_ms or 1e3, config.options, config.settings) + fake_lsp_server_setup( + config.test_name, + config.timeout_ms or 1e3, + config.options, + config.settings + ) end local client = setmetatable({}, { __index = function(_, name) -- Workaround for not being able to yield() inside __index for Lua 5.1 :( -- Otherwise I would just return the value here. return function(...) - return exec_lua([=[ + return exec_lua( + [=[ local name = ... if type(TEST_RPC_CLIENT[name]) == 'function' then return TEST_RPC_CLIENT[name](select(2, ...)) else return TEST_RPC_CLIENT[name] end - ]=], name, ...) + ]=], + name, + ... + ) end - end; + end, }) local code, signal local function on_request(method, args) - if method == "init" then + if method == 'init' then if config.on_init then config.on_init(client, unpack(args)) end diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua index 724b3efb97..bd1842ceb5 100644 --- a/test/functional/plugin/lsp/incremental_sync_spec.lua +++ b/test/functional/plugin/lsp/incremental_sync_spec.lua @@ -1,13 +1,13 @@ -- Test suite for testing interactions with the incremental sync algorithms powering the LSP client local helpers = require('test.functional.helpers')(after_each) -local meths = helpers.meths +local api = helpers.api local clear = helpers.clear local eq = helpers.eq local exec_lua = helpers.exec_lua local feed = helpers.feed -before_each(function () +before_each(function() clear() exec_lua [[ local evname = ... @@ -52,19 +52,24 @@ before_each(function () ]] end) -local function test_edit(prev_buffer, edit_operations, expected_text_changes, offset_encoding, line_ending) +local function test_edit( + prev_buffer, + edit_operations, + expected_text_changes, + offset_encoding, + line_ending +) offset_encoding = offset_encoding or 'utf-16' line_ending = line_ending or '\n' - meths.buf_set_lines(0, 0, -1, true, prev_buffer) - exec_lua("return test_register(...)", 0, "test1", offset_encoding, line_ending) + api.nvim_buf_set_lines(0, 0, -1, true, prev_buffer) + exec_lua('return test_register(...)', 0, 'test1', offset_encoding, line_ending) for _, edit in ipairs(edit_operations) do feed(edit) end - eq(expected_text_changes, exec_lua("return get_events(...)" )) + eq(expected_text_changes, exec_lua('return get_events(...)')) exec_lua("test_unreg = 'test1'") - end describe('incremental synchronization', function() @@ -75,18 +80,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 0, - line = 0 - } + line = 0, + }, }, rangeLength = 0, - text = 'a' - } + text = 'a', + }, } - test_edit({""}, {"ia"}, expected_text_changes, 'utf-16', '\n') + test_edit({ '' }, { 'ia' }, expected_text_changes, 'utf-16', '\n') end) it('inserting a character in the middle of a the first line', function() local expected_text_changes = { @@ -94,18 +99,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 1, - line = 0 + line = 0, }, ['end'] = { character = 1, - line = 0 - } + line = 0, + }, }, rangeLength = 0, - text = 'a' - } + text = 'a', + }, } - test_edit({"ab"}, {"lia"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'ab' }, { 'lia' }, expected_text_changes, 'utf-16', '\n') end) it('deleting the only character in a buffer', function() local expected_text_changes = { @@ -113,18 +118,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 1, - line = 0 - } + line = 0, + }, }, rangeLength = 1, - text = '' - } + text = '', + }, } - test_edit({"a"}, {"x"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'a' }, { 'x' }, expected_text_changes, 'utf-16', '\n') end) it('deleting a character in the middle of the line', function() local expected_text_changes = { @@ -132,18 +137,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 1, - line = 0 + line = 0, }, ['end'] = { character = 2, - line = 0 - } + line = 0, + }, }, rangeLength = 1, - text = '' - } + text = '', + }, } - test_edit({"abc"}, {"lx"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'abc' }, { 'lx' }, expected_text_changes, 'utf-16', '\n') end) it('replacing a character', function() local expected_text_changes = { @@ -151,18 +156,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 1, - line = 0 - } + line = 0, + }, }, rangeLength = 1, - text = 'b' - } + text = 'b', + }, } - test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'a' }, { 'rb' }, expected_text_changes, 'utf-16', '\n') end) it('deleting a line', function() local expected_text_changes = { @@ -170,18 +175,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 0, - line = 1 - } + line = 1, + }, }, rangeLength = 12, - text = '' - } + text = '', + }, } - test_edit({"hello world"}, {"dd"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'hello world' }, { 'dd' }, expected_text_changes, 'utf-16', '\n') end) it('deleting an empty line', function() local expected_text_changes = { @@ -189,18 +194,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 0, - line = 2 - } + line = 2, + }, }, rangeLength = 1, - text = '' - } + text = '', + }, } - test_edit({"hello world", ""}, {"jdd"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'hello world', '' }, { 'jdd' }, expected_text_changes, 'utf-16', '\n') end) it('adding a line', function() local expected_text_changes = { @@ -212,14 +217,14 @@ describe('incremental synchronization', function() }, ['end'] = { character = 0, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = '\nhello world\n' - } + text = '\nhello world\n', + }, } - test_edit({"hello world"}, {"yyp"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'hello world' }, { 'yyp' }, expected_text_changes, 'utf-16', '\n') end) it('adding an empty line', function() local expected_text_changes = { @@ -227,18 +232,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 11, - line = 0 + line = 0, }, ['end'] = { character = 0, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = '\n\n' - } + text = '\n\n', + }, } - test_edit({"hello world"}, {"o"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'hello world' }, { 'o' }, expected_text_changes, 'utf-16', '\n') end) it('adding a line to an empty buffer', function() local expected_text_changes = { @@ -246,18 +251,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 0, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = '\n\n' - } + text = '\n\n', + }, } - test_edit({""}, {"o"}, expected_text_changes, 'utf-16', '\n') + test_edit({ '' }, { 'o' }, expected_text_changes, 'utf-16', '\n') end) it('insert a line above the current line', function() local expected_text_changes = { @@ -265,18 +270,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 0, - line = 0 - } + line = 0, + }, }, rangeLength = 0, - text = '\n' - } + text = '\n', + }, } - test_edit({""}, {"O"}, expected_text_changes, 'utf-16', '\n') + test_edit({ '' }, { 'O' }, expected_text_changes, 'utf-16', '\n') end) end) describe('multi line edit', function() @@ -287,115 +292,115 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 4, - line = 1 + line = 1, }, ['end'] = { character = 9, - line = 1 - } + line = 1, + }, }, rangeLength = 5, - text = '' + text = '', }, -- delete "hello world\n" from line 2 { range = { ['start'] = { character = 0, - line = 2 + line = 2, }, ['end'] = { character = 0, - line = 3 - } + line = 3, + }, }, rangeLength = 12, - text = '' + text = '', }, -- delete "1234" from beginning of line 2 { range = { ['start'] = { character = 0, - line = 2 + line = 2, }, ['end'] = { character = 4, - line = 2 - } + line = 2, + }, }, rangeLength = 4, - text = '' + text = '', }, -- add " asdf" to end of line 1 { range = { ['start'] = { character = 4, - line = 1 + line = 1, }, ['end'] = { character = 4, - line = 1 - } + line = 1, + }, }, rangeLength = 0, - text = ' asdf' + text = ' asdf', }, -- delete " asdf\n" from line 2 { range = { ['start'] = { character = 0, - line = 2 + line = 2, }, ['end'] = { character = 0, - line = 3 - } + line = 3, + }, }, rangeLength = 6, - text = '' + text = '', }, -- undo entire deletion { range = { ['start'] = { character = 4, - line = 1 + line = 1, }, ['end'] = { character = 9, - line = 1 - } + line = 1, + }, }, rangeLength = 5, - text = "_fdsa\nhello world\n1234 asdf" + text = '_fdsa\nhello world\n1234 asdf', }, -- redo entire deletion { range = { ['start'] = { character = 4, - line = 1 + line = 1, }, ['end'] = { character = 9, - line = 3 - } + line = 3, + }, }, rangeLength = 27, - text = ' asdf' + text = ' asdf', }, } local original_lines = { - "\\begin{document}", - "test_fdsa", - "hello world", - "1234 asdf", - "\\end{document}" + '\\begin{document}', + 'test_fdsa', + 'hello world', + '1234 asdf', + '\\end{document}', } - test_edit(original_lines, {"jf_vejjbhhdu<C-R>"}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { 'jf_vejjbhhdu<C-R>' }, expected_text_changes, 'utf-16', '\n') end) end) @@ -404,64 +409,83 @@ describe('incremental synchronization', function() local expected_text_changes = { { range = { - ["end"] = { - character = 11, - line = 2 }, - ["start"] = { - character = 10, - line = 2 } }, + ['end'] = { + character = 11, + line = 2, + }, + ['start'] = { + character = 10, + line = 2, + }, + }, rangeLength = 1, text = '', - },{ + }, + { range = { - ["end"] = { + ['end'] = { character = 10, - line = 2 }, + line = 2, + }, start = { character = 10, - line = 2 } }, + line = 2, + }, + }, rangeLength = 0, text = '2', - },{ + }, + { range = { - ["end"] = { + ['end'] = { character = 11, - line = 3 }, - ["start"] = { + line = 3, + }, + ['start'] = { character = 10, - line = 3 } }, + line = 3, + }, + }, rangeLength = 1, - text = '' - },{ + text = '', + }, + { range = { ['end'] = { character = 10, - line = 3 }, + line = 3, + }, ['start'] = { character = 10, - line = 3 } }, + line = 3, + }, + }, rangeLength = 0, - text = '3' }, + text = '3', + }, { range = { ['end'] = { character = 0, - line = 3 }, + line = 3, + }, ['start'] = { character = 12, - line = 2 } }, + line = 2, + }, + }, rangeLength = 1, - text = '\n' - } + text = '\n', + }, } local original_lines = { - "\\begin{document}", - "\\section*{1}", - "\\section*{1}", - "\\section*{1}", - "\\end{document}" + '\\begin{document}', + '\\section*{1}', + '\\section*{1}', + '\\section*{1}', + '\\end{document}', } - test_edit(original_lines, {"3gg$h<C-V>jg<C-A>"}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { '3gg$h<C-V>jg<C-A>' }, expected_text_changes, 'utf-16', '\n') end) it('join and undo', function() local expected_text_changes = { @@ -469,44 +493,46 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 11, - line = 0 + line = 0, }, ['end'] = { character = 11, - line = 0 - } + line = 0, + }, }, rangeLength = 0, - text = ' test3' - },{ + text = ' test3', + }, + { range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 0, - line = 2 - } + line = 2, + }, }, rangeLength = 6, - text = '' - },{ + text = '', + }, + { range = { ['start'] = { character = 11, - line = 0 + line = 0, }, ['end'] = { character = 17, - line = 0 - } + line = 0, + }, }, rangeLength = 6, - text = '\ntest3' + text = '\ntest3', }, } - test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n') + test_edit({ 'test1 test2', 'test3' }, { 'J', 'u' }, expected_text_changes, 'utf-16', '\n') end) end) @@ -517,18 +543,18 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 0 + line = 0, }, ['end'] = { character = 2, - line = 0 - } + line = 0, + }, }, rangeLength = 2, - text = '' - } + text = '', + }, } - test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n') + test_edit({ '🔥' }, { 'x' }, expected_text_changes, 'utf-16', '\n') end) it('replacing a multibyte character with matching prefix', function() local expected_text_changes = { @@ -536,24 +562,24 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 1, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = '⟩' - } + text = '⟩', + }, } -- ⟨ is e29fa8, ⟩ is e29fa9 local original_lines = { - "\\begin{document}", - "⟨", - "\\end{document}", + '\\begin{document}', + '⟨', + '\\end{document}', } - test_edit(original_lines, {"jr⟩"}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { 'jr⟩' }, expected_text_changes, 'utf-16', '\n') end) it('replacing a multibyte character with matching suffix', function() local expected_text_changes = { @@ -561,24 +587,24 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 1, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = 'ḟ' - } + text = 'ḟ', + }, } -- ฟ is e0b89f, ḟ is e1b89f local original_lines = { - "\\begin{document}", - "ฟ", - "\\end{document}", + '\\begin{document}', + 'ฟ', + '\\end{document}', } - test_edit(original_lines, {"jrḟ"}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { 'jrḟ' }, expected_text_changes, 'utf-16', '\n') end) it('inserting before a multibyte character', function() local expected_text_changes = { @@ -586,23 +612,23 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 0, - line = 1 - } + line = 1, + }, }, rangeLength = 0, - text = ' ' - } + text = ' ', + }, } local original_lines = { - "\\begin{document}", - "→", - "\\end{document}", + '\\begin{document}', + '→', + '\\end{document}', } - test_edit(original_lines, {"ji "}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { 'ji ' }, expected_text_changes, 'utf-16', '\n') end) it('deleting a multibyte character from a long line', function() local expected_text_changes = { @@ -610,23 +636,23 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 85, - line = 1 + line = 1, }, ['end'] = { character = 86, - line = 1 - } + line = 1, + }, }, rangeLength = 1, - text = '' - } + text = '', + }, } local original_lines = { - "\\begin{document}", - "→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→", - "\\end{document}", + '\\begin{document}', + '→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→', + '\\end{document}', } - test_edit(original_lines, {"jx"}, expected_text_changes, 'utf-16', '\n') + test_edit(original_lines, { 'jx' }, expected_text_changes, 'utf-16', '\n') end) it('deleting multiple lines containing multibyte characters', function() local expected_text_changes = { @@ -634,19 +660,25 @@ describe('incremental synchronization', function() range = { ['start'] = { character = 0, - line = 1 + line = 1, }, ['end'] = { character = 0, - line = 3 - } + line = 3, + }, }, --utf 16 len of 🔥 is 2 rangeLength = 8, - text = '' - } + text = '', + }, } - test_edit({"a🔥", "b🔥", "c🔥", "d🔥"}, {"j2dd"}, expected_text_changes, 'utf-16', '\n') + test_edit( + { 'a🔥', 'b🔥', 'c🔥', 'd🔥' }, + { 'j2dd' }, + expected_text_changes, + 'utf-16', + '\n' + ) end) end) end) diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua index d0d55df72b..192797b312 100644 --- a/test/functional/plugin/lsp/inlay_hint_spec.lua +++ b/test/functional/plugin/lsp/inlay_hint_spec.lua @@ -40,7 +40,7 @@ local grid_without_inlay_hints = [[ | ]] -local grid_with_inlay_hints = [[ +local grid_with_inlay_hints = [[ auto add(int a, int b)-> int { return a + b; } | | int main() { | @@ -60,7 +60,8 @@ before_each(function() screen:attach() exec_lua(create_server_definition) - exec_lua([[ + exec_lua( + [[ local response = ... server = _create_server({ capabilities = { @@ -77,7 +78,9 @@ before_each(function() vim.api.nvim_win_set_buf(0, bufnr) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) - ]], response) + ]], + response + ) insert(text) exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]]) @@ -145,7 +148,8 @@ describe('vim.lsp.inlay_hint', function() paddingRight = false, } - exec_lua([[ + exec_lua( + [[ local expected2 = ... server2 = _create_server({ capabilities = { @@ -159,7 +163,9 @@ describe('vim.lsp.inlay_hint', function() }) client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd }) vim.lsp.inlay_hint.enable(bufnr) - ]], expected2) + ]], + expected2 + ) --- @type vim.lsp.inlay_hint.get.ret local res = exec_lua([[return vim.lsp.inlay_hint.get()]]) diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua index b7ac53f270..77e39c81c8 100644 --- a/test/functional/plugin/lsp/semantic_tokens_spec.lua +++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua @@ -23,21 +23,20 @@ after_each(function() end) describe('semantic token highlighting', function() - local screen before_each(function() screen = Screen.new(40, 16) screen:attach() screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }; - [2] = { foreground = Screen.colors.DarkCyan }; - [3] = { foreground = Screen.colors.SlateBlue }; - [4] = { bold = true, foreground = Screen.colors.SeaGreen }; - [5] = { foreground = tonumber('0x6a0dad') }; - [6] = { foreground = Screen.colors.Blue1 }; - [7] = { bold = true, foreground = Screen.colors.DarkCyan }; - [8] = { bold = true, foreground = Screen.colors.SlateBlue }; - [9] = { bold = true, foreground = tonumber('0x6a0dad') }; + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + [2] = { foreground = Screen.colors.DarkCyan }, + [3] = { foreground = Screen.colors.SlateBlue }, + [4] = { bold = true, foreground = Screen.colors.SeaGreen }, + [5] = { foreground = tonumber('0x6a0dad') }, + [6] = { foreground = Screen.colors.Blue1 }, + [7] = { bold = true, foreground = Screen.colors.DarkCyan }, + [8] = { bold = true, foreground = Screen.colors.SlateBlue }, + [9] = { bold = true, foreground = tonumber('0x6a0dad') }, } command([[ hi link @lsp.type.namespace Type ]]) command([[ hi link @lsp.type.function Special ]]) @@ -81,7 +80,8 @@ describe('semantic token highlighting', function() before_each(function() exec_lua(create_server_definition) - exec_lua([[ + exec_lua( + [[ local legend, response, edit_response = ... server = _create_server({ capabilities = { @@ -99,7 +99,11 @@ describe('semantic token highlighting', function() end, } }) - ]], legend, response, edit_response) + ]], + legend, + response, + edit_response + ) end) it('buffer is highlighted when attached', function() @@ -112,7 +116,8 @@ describe('semantic token highlighting', function() insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -125,11 +130,10 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } end) it('use LspTokenUpdate and highlight_token', function() @@ -151,7 +155,8 @@ describe('semantic token highlighting', function() insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {9:main}() | @@ -164,12 +169,10 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } - + ]], + } end) it('buffer is unhighlighted when client is detached', function() @@ -186,7 +189,8 @@ describe('semantic token highlighting', function() vim.lsp.buf_detach_client(bufnr, client_id) ]]) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int main() | @@ -199,29 +203,30 @@ describe('semantic token highlighting', function() #endif | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } end) - it('buffer is highlighted and unhighlighted when semantic token highlighting is started and stopped' - , function() - exec_lua([[ + it( + 'buffer is highlighted and unhighlighted when semantic token highlighting is started and stopped', + function() + exec_lua([[ bufnr = vim.api.nvim_get_current_buf() vim.api.nvim_win_set_buf(0, bufnr) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) ]]) - insert(text) + insert(text) - exec_lua([[ + exec_lua([[ vim.notify = function() end vim.lsp.semantic_tokens.stop(bufnr, client_id) ]]) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int main() | @@ -234,17 +239,17 @@ describe('semantic token highlighting', function() #endif | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } - exec_lua([[ + exec_lua([[ vim.lsp.semantic_tokens.start(bufnr, client_id) ]]) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -257,12 +262,12 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } - end) + ]], + } + end + ) it('buffer is re-highlighted when force refreshed', function() exec_lua([[ @@ -273,7 +278,8 @@ describe('semantic token highlighting', function() insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -286,17 +292,17 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } exec_lua([[ vim.lsp.semantic_tokens.force_refresh(bufnr) ]]) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -309,11 +315,11 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]], unchanged = true } + ]], + unchanged = true, + } local messages = exec_lua('return server.messages') local token_request_count = 0 @@ -352,7 +358,8 @@ describe('semantic token highlighting', function() ]]) insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -365,14 +372,14 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } feed_command('%s/int x/int x()/') feed_command('noh') - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -383,13 +390,11 @@ describe('semantic token highlighting', function() {6:#else} | {6: printf("%d\n", x);} | {6:#endif} | - } | - } | - {1:~ }| - {1:~ }| - {1:~ }| + } |*2 + {1:~ }|*3 :noh | - ]] } + ]], + } end) it('prevents starting semantic token highlighting with invalid conditions', function() @@ -400,7 +405,7 @@ describe('semantic token highlighting', function() notifications = {} vim.notify = function(...) table.insert(notifications, 1, {...}) end ]]) - eq(false, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)")) + eq(false, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)')) insert(text) @@ -417,7 +422,8 @@ describe('semantic token highlighting', function() matches('%[LSP%] No client with id %d', notifications[1][1]) end) - it('opt-out: does not activate semantic token highlighting if disabled in client attach', + it( + 'opt-out: does not activate semantic token highlighting if disabled in client attach', function() exec_lua([[ bufnr = vim.api.nvim_get_current_buf() @@ -430,11 +436,12 @@ describe('semantic token highlighting', function() end), }) ]]) - eq(true, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)")) + eq(true, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)')) insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int main() | @@ -447,11 +454,10 @@ describe('semantic token highlighting', function() #endif | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } local notifications = exec_lua([[ local notifications = {} @@ -461,7 +467,8 @@ describe('semantic token highlighting', function() ]]) eq('[LSP] Server does not support semantic tokens', notifications[1][1]) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int main() | @@ -474,14 +481,15 @@ describe('semantic token highlighting', function() #endif | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]], unchanged = true } - end) + ]], + unchanged = true, + } + end + ) - it('ignores null responses from the server', function() + it('ignores null responses from the server', function() exec_lua([[ local legend, response, edit_response = ... server2 = _create_server({ @@ -503,11 +511,12 @@ describe('semantic token highlighting', function() vim.api.nvim_win_set_buf(0, bufnr) client_id = vim.lsp.start({ name = 'dummy', cmd = server2.cmd }) ]]) - eq(true, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)")) + eq(true, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)')) insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int main() | @@ -520,15 +529,15 @@ describe('semantic token highlighting', function() #endif | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } end) it('does not send delta requests if not supported by server', function() - exec_lua([[ + exec_lua( + [[ local legend, response, edit_response = ... server2 = _create_server({ capabilities = { @@ -549,10 +558,15 @@ describe('semantic token highlighting', function() bufnr = vim.api.nvim_get_current_buf() vim.api.nvim_win_set_buf(0, bufnr) client_id = vim.lsp.start({ name = 'dummy', cmd = server2.cmd }) - ]], legend, response, edit_response) + ]], + legend, + response, + edit_response + ) insert(text) - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -565,18 +579,18 @@ describe('semantic token highlighting', function() {6:#endif} | } | ^} | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]] } + ]], + } feed_command('%s/int x/int x()/') feed_command('noh') -- the highlights don't change because our fake server sent the exact -- same result for the same method (the full request). "x" would have -- changed to highlight index 3 had we sent a delta request - screen:expect { grid = [[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -587,13 +601,11 @@ describe('semantic token highlighting', function() {6:#else} | {6: printf("%d\n", x);} | {6:#endif} | - } | - } | - {1:~ }| - {1:~ }| - {1:~ }| + } |*2 + {1:~ }|*3 :noh | - ]] } + ]], + } local messages = exec_lua('return server2.messages') local token_request_count = 0 for _, message in ipairs(messages) do @@ -631,24 +643,13 @@ describe('semantic token highlighting', function() }, }, expected_screen = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ char* {7:foo} = "\n"^; | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*14 | - ]]} + ]], + } end, }, { @@ -763,7 +764,8 @@ int main() }, }, expected_screen = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ #include <iostream> | int {8:main}() | { | @@ -774,13 +776,10 @@ int main() {6: comment} | {6: #endif} | ^} | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*5 | - ]]} + ]], + } end, }, { @@ -824,24 +823,15 @@ b = "as"]], }, }, expected_screen = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ {6:-- comment} | local {7:a} = 1 | {2:b} = "as^" | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*12 | - ]]} + ]], + } end, }, { @@ -954,30 +944,24 @@ b = "as"]], }, }, expected_screen = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ pub fn {8:main}() { | break rust; | //{6:/ what?} | } | ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*10 | - ]]} + ]], + } end, }, }) do it(test.it, function() exec_lua(create_server_definition) - exec_lua([[ + exec_lua( + [[ local legend, resp = ... server = _create_server({ capabilities = { @@ -995,7 +979,10 @@ b = "as"]], bufnr = vim.api.nvim_get_current_buf() vim.api.nvim_win_set_buf(0, bufnr) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) - ]], test.legend, test.response) + ]], + test.legend, + test.response + ) insert(test.text) @@ -1037,7 +1024,7 @@ b = "as"]], end_col = 9, type = 'variable', marked = true, - } + }, }, expected2 = { { @@ -1050,47 +1037,26 @@ b = "as"]], end_col = 9, type = 'variable', marked = true, - } + }, }, expected_screen1 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ char* {7:foo} = "\n"^; | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*14 | - ]]} + ]], + } end, expected_screen2 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | char* {7:foo} = "\n"; | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*13 | - ]]} + ]], + } end, }, { @@ -1207,7 +1173,7 @@ int main() modifiers = {}, type = 'comment', marked = true, - } + }, }, expected2 = { { @@ -1289,10 +1255,11 @@ int main() modifiers = {}, type = 'comment', marked = true, - } + }, }, expected_screen1 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -1304,15 +1271,14 @@ int main() {6: printf("%d\n", x);} | {6:#endif} | ^} | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 | - ]]} + ]], + } end, expected_screen2 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ #include <iostream> | | int {8:main}() | @@ -1325,11 +1291,10 @@ int main() {6: printf("%d\n", x);} | {6:^#endif} | } | - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*3 | - ]]} + ]], + } end, }, { @@ -1356,55 +1321,33 @@ int main() end_col = 6, type = 'variable', marked = true, - } - }, - expected2 = { + }, }, + expected2 = {}, expected_screen1 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ {7:string} = "test^" | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*14 | - ]]} + ]], + } end, expected_screen2 = function() - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*14 | - ]]} + ]], + } end, }, }) do it(test.it, function() exec_lua(create_server_definition) - exec_lua([[ + exec_lua( + [[ local legend, resp1, resp2 = ... server = _create_server({ capabilities = { @@ -1432,7 +1375,11 @@ int main() semantic_tokens.stop(bufnr, client_id) semantic_tokens.start(bufnr, client_id, { debounce = 10 }) end) - ]], test.legend, test.response1, test.response2) + ]], + test.legend, + test.response1, + test.response2 + ) insert(test.text1) @@ -1447,11 +1394,14 @@ int main() if test.edit then feed(test.edit) else - exec_lua([[ + exec_lua( + [[ local text = ... vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.fn.split(text, "\n")) vim.wait(15) -- wait for debounce - ]], test.text2) + ]], + test.text2 + ) end test.expected_screen2() diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index 804dc32f0d..bb9cdb8390 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -10,7 +10,8 @@ describe('vim.lsp.util', function() describe('stylize_markdown', function() local stylize_markdown = function(content, opts) - return exec_lua([[ + return exec_lua( + [[ local bufnr = vim.uri_to_bufnr("file:///fake/uri") vim.fn.bufload(bufnr) @@ -20,14 +21,17 @@ describe('vim.lsp.util', function() local stripped_content = vim.lsp.util.stylize_markdown(bufnr, content, opts) return stripped_content - ]], content, opts) + ]], + content, + opts + ) end it('code fences', function() local lines = { - "```lua", + '```lua', "local hello = 'world'", - "```", + '```', } local expected = { "local hello = 'world'", @@ -38,9 +42,9 @@ describe('vim.lsp.util', function() it('code fences with whitespace surrounded info string', function() local lines = { - "``` lua ", + '``` lua ', "local hello = 'world'", - "```", + '```', } local expected = { "local hello = 'world'", @@ -51,16 +55,16 @@ describe('vim.lsp.util', function() it('adds separator after code block', function() local lines = { - "```lua", + '```lua', "local hello = 'world'", - "```", - "", - "something", + '```', + '', + 'something', } local expected = { "local hello = 'world'", - "─────────────────────", - "something", + '─────────────────────', + 'something', } local opts = { separator = true } eq(expected, stylize_markdown(lines, opts)) @@ -68,28 +72,28 @@ describe('vim.lsp.util', function() it('replaces supported HTML entities', function() local lines = { - "1 < 2", - "3 > 2", - ""quoted"", - "'apos'", - "   ", - "&", + '1 < 2', + '3 > 2', + '"quoted"', + ''apos'', + '   ', + '&', } local expected = { - "1 < 2", - "3 > 2", + '1 < 2', + '3 > 2', '"quoted"', "'apos'", - " ", - "&", + ' ', + '&', } local opts = {} eq(expected, stylize_markdown(lines, opts)) end) end) - describe('normalize_markdown', function () - it('collapses consecutive blank lines', function () + describe('normalize_markdown', function() + it('collapses consecutive blank lines', function() local result = exec_lua [[ local lines = { 'foo', @@ -102,11 +106,11 @@ describe('vim.lsp.util', function() } return vim.lsp.util._normalize_markdown(lines) ]] - local expected = {'foo', '', 'bar', '', 'baz'} + local expected = { 'foo', '', 'bar', '', 'baz' } eq(expected, result) end) - it('removes preceding and trailing empty lines', function () + it('removes preceding and trailing empty lines', function() local result = exec_lua [[ local lines = { '', @@ -117,103 +121,105 @@ describe('vim.lsp.util', function() } return vim.lsp.util._normalize_markdown(lines) ]] - local expected = {'foo', 'bar'} + local expected = { 'foo', 'bar' } eq(expected, result) end) end) - describe("make_floating_popup_options", function () - + describe('make_floating_popup_options', function() local function assert_anchor(anchor_bias, expected_anchor) - local opts = exec_lua([[ + local opts = exec_lua( + [[ local args = { ... } local anchor_bias = args[1] return vim.lsp.util.make_floating_popup_options(30, 10, { anchor_bias = anchor_bias }) - ]], anchor_bias) + ]], + anchor_bias + ) - eq(expected_anchor, string.sub(opts.anchor, 1, 1)) + eq(expected_anchor, string.sub(opts.anchor, 1, 1)) end local screen - before_each(function () + before_each(function() helpers.clear() screen = Screen.new(80, 80) screen:attach() - feed("79i<CR><Esc>") -- fill screen with empty lines + feed('79i<CR><Esc>') -- fill screen with empty lines end) - describe('when on the first line it places window below', function () - before_each(function () + describe('when on the first line it places window below', function() + before_each(function() feed('gg') end) - it('for anchor_bias = "auto"', function () + it('for anchor_bias = "auto"', function() assert_anchor('auto', 'N') end) - it('for anchor_bias = "above"', function () + it('for anchor_bias = "above"', function() assert_anchor('above', 'N') end) - it('for anchor_bias = "below"', function () + it('for anchor_bias = "below"', function() assert_anchor('below', 'N') end) end) - describe('when on the last line it places window above', function () - before_each(function () + describe('when on the last line it places window above', function() + before_each(function() feed('G') end) - it('for anchor_bias = "auto"', function () + it('for anchor_bias = "auto"', function() assert_anchor('auto', 'S') end) - it('for anchor_bias = "above"', function () + it('for anchor_bias = "above"', function() assert_anchor('above', 'S') end) - it('for anchor_bias = "below"', function () + it('for anchor_bias = "below"', function() assert_anchor('below', 'S') end) end) - describe('with 20 lines above, 59 lines below', function () - before_each(function () + describe('with 20 lines above, 59 lines below', function() + before_each(function() feed('gg20j') end) - it('places window below for anchor_bias = "auto"', function () + it('places window below for anchor_bias = "auto"', function() assert_anchor('auto', 'N') end) - it('places window above for anchor_bias = "above"', function () + it('places window above for anchor_bias = "above"', function() assert_anchor('above', 'S') end) - it('places window below for anchor_bias = "below"', function () + it('places window below for anchor_bias = "below"', function() assert_anchor('below', 'N') end) end) - describe('with 59 lines above, 20 lines below', function () - before_each(function () + describe('with 59 lines above, 20 lines below', function() + before_each(function() feed('G20k') end) - it('places window above for anchor_bias = "auto"', function () + it('places window above for anchor_bias = "auto"', function() assert_anchor('auto', 'S') end) - it('places window above for anchor_bias = "above"', function () + it('places window above for anchor_bias = "above"', function() assert_anchor('above', 'S') end) - it('places window below for anchor_bias = "below"', function () + it('places window below for anchor_bias = "below"', function() assert_anchor('below', 'N') end) - it('bordered window truncates dimensions correctly', function () + it('bordered window truncates dimensions correctly', function() local opts = exec_lua([[ return vim.lsp.util.make_floating_popup_options(100, 100, { border = 'single' }) ]]) @@ -222,5 +228,4 @@ describe('vim.lsp.util', function() end) end) end) - end) diff --git a/test/functional/plugin/lsp/watchfiles_spec.lua b/test/functional/plugin/lsp/watchfiles_spec.lua deleted file mode 100644 index a8260e0c98..0000000000 --- a/test/functional/plugin/lsp/watchfiles_spec.lua +++ /dev/null @@ -1,222 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local exec_lua = helpers.exec_lua - -describe('vim.lsp._watchfiles', function() - before_each(helpers.clear) - after_each(helpers.clear) - - local match = function(...) - return exec_lua('return require("vim.lsp._watchfiles")._match(...)', ...) - end - - describe('glob matching', function() - it('should match literal strings', function() - eq(true, match('', '')) - eq(false, match('', 'a')) - eq(true, match('a', 'a')) - eq(true, match('/', '/')) - eq(true, match('abc', 'abc')) - eq(false, match('abc', 'abcdef')) - eq(false, match('abc', 'a')) - eq(false, match('abc', 'bc')) - eq(false, match('a', 'b')) - eq(false, match('.', 'a')) - eq(true, match('$', '$')) - eq(true, match('/dir', '/dir')) - eq(true, match('dir/', 'dir/')) - eq(true, match('dir/subdir', 'dir/subdir')) - eq(false, match('dir/subdir', 'subdir')) - eq(false, match('dir/subdir', 'dir/subdir/file')) - eq(true, match('🤠', '🤠')) - end) - - it('should match * wildcards', function() - eq(false, match('*', '')) - eq(true, match('*', 'a')) - eq(false, match('*', '/')) - eq(false, match('*', '/a')) - eq(false, match('*', 'a/')) - eq(true, match('*', 'aaa')) - eq(true, match('*a', 'aa')) - eq(true, match('*a', 'abca')) - eq(true, match('*.txt', 'file.txt')) - eq(false, match('*.txt', 'file.txtxt')) - eq(false, match('*.txt', 'dir/file.txt')) - eq(false, match('*.txt', '/dir/file.txt')) - eq(false, match('*.txt', 'C:/dir/file.txt')) - eq(false, match('*.dir', 'test.dir/file')) - eq(true, match('file.*', 'file.txt')) - eq(false, match('file.*', 'not-file.txt')) - eq(true, match('*/file.txt', 'dir/file.txt')) - eq(false, match('*/file.txt', 'dir/subdir/file.txt')) - eq(false, match('*/file.txt', '/dir/file.txt')) - eq(true, match('dir/*', 'dir/file.txt')) - eq(false, match('dir/*', 'dir')) - eq(false, match('dir/*.txt', 'file.txt')) - eq(true, match('dir/*.txt', 'dir/file.txt')) - eq(false, match('dir/*.txt', 'dir/subdir/file.txt')) - eq(false, match('dir/*/file.txt', 'dir/file.txt')) - eq(true, match('dir/*/file.txt', 'dir/subdir/file.txt')) - eq(false, match('dir/*/file.txt', 'dir/subdir/subdir/file.txt')) - - -- TODO: The spec does not describe this, but VSCode only interprets ** when it's by - -- itself in a path segment, and otherwise interprets ** as consecutive * directives. - -- The following tests show how this behavior should work, but is not yet fully implemented. - -- Currently, "a**" parses incorrectly as "a" "**" and "**a" parses correctly as "*" "*" "a". - -- see: https://github.com/microsoft/vscode/blob/eef30e7165e19b33daa1e15e92fa34ff4a5df0d3/src/vs/base/common/glob.ts#L112 - eq(true, match('a**', 'abc')) -- '**' should parse as two '*'s when not by itself in a path segment - eq(true, match('**c', 'abc')) - -- eq(false, match('a**', 'ab')) -- each '*' should still represent at least one character - eq(false, match('**c', 'bc')) - eq(true, match('a**', 'abcd')) - eq(true, match('**d', 'abcd')) - -- eq(false, match('a**', 'abc/d')) - eq(false, match('**d', 'abc/d')) - end) - - it('should match ? wildcards', function() - eq(false, match('?', '')) - eq(true, match('?', 'a')) - eq(false, match('??', 'a')) - eq(false, match('?', 'ab')) - eq(true, match('??', 'ab')) - eq(true, match('a?c', 'abc')) - eq(false, match('a?c', 'a/c')) - end) - - it('should match ** wildcards', function() - eq(true, match('**', '')) - eq(true, match('**', 'a')) - eq(true, match('**', '/')) - eq(true, match('**', 'a/')) - eq(true, match('**', '/a')) - eq(true, match('**', 'C:/a')) - eq(true, match('**', 'a/a')) - eq(true, match('**', 'a/a/a')) - eq(false, match('/**', '')) -- /** matches leading / literally - eq(true, match('/**', '/')) - eq(true, match('/**', '/a/b/c')) - eq(true, match('**/', '')) -- **/ absorbs trailing / - eq(true, match('**/', '/a/b/c')) - eq(true, match('**/**', '')) - eq(true, match('**/**', 'a')) - eq(false, match('a/**', '')) - eq(false, match('a/**', 'a')) - eq(true, match('a/**', 'a/b')) - eq(true, match('a/**', 'a/b/c')) - eq(false, match('a/**', 'b/a')) - eq(false, match('a/**', '/a')) - eq(false, match('**/a', '')) - eq(true, match('**/a', 'a')) - eq(false, match('**/a', 'a/b')) - eq(true, match('**/a', '/a')) - eq(true, match('**/a', '/b/a')) - eq(true, match('**/a', '/c/b/a')) - eq(true, match('**/a', '/a/a')) - eq(true, match('**/a', '/abc/a')) - eq(false, match('a/**/c', 'a')) - eq(false, match('a/**/c', 'c')) - eq(true, match('a/**/c', 'a/c')) - eq(true, match('a/**/c', 'a/b/c')) - eq(true, match('a/**/c', 'a/b/b/c')) - eq(false, match('**/a/**', 'a')) - eq(true, match('**/a/**', 'a/')) - eq(false, match('**/a/**', '/dir/a')) - eq(false, match('**/a/**', 'dir/a')) - eq(true, match('**/a/**', 'dir/a/')) - eq(true, match('**/a/**', 'a/dir')) - eq(true, match('**/a/**', 'dir/a/dir')) - eq(true, match('**/a/**', '/a/dir')) - eq(true, match('**/a/**', 'C:/a/dir')) - eq(false, match('**/a/**', 'a.txt')) - end) - - it('should match {} groups', function() - eq(true, match('{}', '')) - eq(false, match('{}', 'a')) - eq(true, match('a{}', 'a')) - eq(true, match('{}a', 'a')) - eq(true, match('{,}', '')) - eq(true, match('{a,}', '')) - eq(true, match('{a,}', 'a')) - eq(true, match('{a}', 'a')) - eq(false, match('{a}', 'aa')) - eq(false, match('{a}', 'ab')) - eq(true, match('{a?c}', 'abc')) - eq(false, match('{ab}', 'a')) - eq(false, match('{ab}', 'b')) - eq(true, match('{ab}', 'ab')) - eq(true, match('{a,b}', 'a')) - eq(true, match('{a,b}', 'b')) - eq(false, match('{a,b}', 'ab')) - eq(true, match('{ab,cd}', 'ab')) - eq(false, match('{ab,cd}', 'a')) - eq(true, match('{ab,cd}', 'cd')) - eq(true, match('{a,b,c}', 'c')) - eq(true, match('{a,{b,c}}', 'c')) - end) - - it('should match [] groups', function() - eq(true, match('[]', '[]')) -- empty [] is a literal - eq(false, match('[a-z]', '')) - eq(true, match('[a-z]', 'a')) - eq(false, match('[a-z]', 'ab')) - eq(true, match('[a-z]', 'z')) - eq(true, match('[a-z]', 'j')) - eq(false, match('[a-f]', 'j')) - eq(false, match('[a-z]', '`')) -- 'a' - 1 - eq(false, match('[a-z]', '{')) -- 'z' + 1 - eq(false, match('[a-z]', 'A')) - eq(false, match('[a-z]', '5')) - eq(true, match('[A-Z]', 'A')) - eq(true, match('[A-Z]', 'Z')) - eq(true, match('[A-Z]', 'J')) - eq(false, match('[A-Z]', '@')) -- 'A' - 1 - eq(false, match('[A-Z]', '[')) -- 'Z' + 1 - eq(false, match('[A-Z]', 'a')) - eq(false, match('[A-Z]', '5')) - eq(true, match('[a-zA-Z0-9]', 'z')) - eq(true, match('[a-zA-Z0-9]', 'Z')) - eq(true, match('[a-zA-Z0-9]', '9')) - eq(false, match('[a-zA-Z0-9]', '&')) - end) - - it('should match [!...] groups', function() - eq(true, match('[!]', '[!]')) -- [!] is a literal - eq(false, match('[!a-z]', '')) - eq(false, match('[!a-z]', 'a')) - eq(false, match('[!a-z]', 'z')) - eq(false, match('[!a-z]', 'j')) - eq(true, match('[!a-f]', 'j')) - eq(false, match('[!a-f]', 'jj')) - eq(true, match('[!a-z]', '`')) -- 'a' - 1 - eq(true, match('[!a-z]', '{')) -- 'z' + 1 - eq(false, match('[!a-zA-Z0-9]', 'a')) - eq(false, match('[!a-zA-Z0-9]', 'A')) - eq(false, match('[!a-zA-Z0-9]', '0')) - eq(true, match('[!a-zA-Z0-9]', '!')) - end) - - it('should match complex patterns', function() - eq(false, match('**/*.{c,h}', '')) - eq(false, match('**/*.{c,h}', 'c')) - eq(false, match('**/*.{c,h}', 'file.m')) - eq(true, match('**/*.{c,h}', 'file.c')) - eq(true, match('**/*.{c,h}', 'file.h')) - eq(true, match('**/*.{c,h}', '/file.c')) - eq(true, match('**/*.{c,h}', 'dir/subdir/file.c')) - eq(true, match('**/*.{c,h}', 'dir/subdir/file.h')) - eq(true, match('**/*.{c,h}', '/dir/subdir/file.c')) - eq(true, match('**/*.{c,h}', 'C:/dir/subdir/file.c')) - eq(true, match('/dir/**/*.{c,h}', '/dir/file.c')) - eq(false, match('/dir/**/*.{c,h}', 'dir/file.c')) - eq(true, match('/dir/**/*.{c,h}', '/dir/subdir/subdir/file.c')) - - eq(true, match('{[0-9],[a-z]}', '0')) - eq(true, match('{[0-9],[a-z]}', 'a')) - eq(false, match('{[0-9],[a-z]}', 'A')) - end) - end) -end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 56d31a0e44..4826153edb 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -11,19 +11,20 @@ local eq = helpers.eq local eval = helpers.eval local matches = helpers.matches local pcall_err = helpers.pcall_err -local pesc = helpers.pesc +local pesc = vim.pesc local insert = helpers.insert -local funcs = helpers.funcs +local fn = helpers.fn local retry = helpers.retry local stop = helpers.stop -local NIL = helpers.NIL +local NIL = vim.NIL local read_file = require('test.helpers').read_file local write_file = require('test.helpers').write_file local is_ci = helpers.is_ci -local meths = helpers.meths +local api = helpers.api local is_os = helpers.is_os local skip = helpers.skip local mkdir = helpers.mkdir +local tmpname = helpers.tmpname local clear_notrace = lsp_helpers.clear_notrace local create_server_definition = lsp_helpers.create_server_definition @@ -32,14 +33,16 @@ local fake_lsp_logfile = lsp_helpers.fake_lsp_logfile local test_rpc_server = lsp_helpers.test_rpc_server local function get_buf_option(name, bufnr) - bufnr = bufnr or "BUFFER" - return exec_lua( - string.format("return vim.api.nvim_get_option_value('%s', { buf = %s })", name, bufnr) - ) + bufnr = bufnr or 'BUFFER' + return exec_lua( + string.format("return vim.api.nvim_get_option_value('%s', { buf = %s })", name, bufnr) + ) end -- TODO(justinmk): hangs on Windows https://github.com/neovim/neovim/pull/11837 -if skip(is_os('win')) then return end +if skip(is_os('win')) then + return +end teardown(function() os.remove(fake_lsp_logfile) @@ -51,8 +54,9 @@ describe('LSP', function() -- Run an instance of nvim on the file which contains our "scripts". -- Pass TEST_NAME to pick the script. - local test_name = "basic_init" - exec_lua([=[ + local test_name = 'basic_init' + exec_lua( + [=[ lsp = require('vim.lsp') local test_name, fake_lsp_code, fake_lsp_logfile = ... function test__start_client() @@ -71,12 +75,16 @@ describe('LSP', function() } end TEST_CLIENT1 = test__start_client() - ]=], test_name, fake_lsp_code, fake_lsp_logfile) + ]=], + test_name, + fake_lsp_code, + fake_lsp_logfile + ) end) after_each(function() exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") - -- exec_lua("lsp.stop_all_clients(true)") + -- exec_lua("lsp.stop_all_clients(true)") end) describe('server_name specified', function() @@ -84,14 +92,20 @@ describe('LSP', function() retry(nil, 4000, function() eq(1, exec_lua('return #lsp.get_clients()')) end) - eq(2, exec_lua([[ + eq( + 2, + exec_lua([[ TEST_CLIENT2 = test__start_client() return TEST_CLIENT2 - ]])) - eq(3, exec_lua([[ + ]]) + ) + eq( + 3, + exec_lua([[ TEST_CLIENT3 = test__start_client() return TEST_CLIENT3 - ]])) + ]]) + ) retry(nil, 4000, function() eq(3, exec_lua('return #lsp.get_clients()')) end) @@ -125,80 +139,62 @@ describe('LSP', function() end) end) end) - - describe('lsp._cmd_parts test', function() - local function _cmd_parts(input) - return exec_lua([[ - lsp = require('vim.lsp') - return lsp._cmd_parts(...) - ]], input) - end - it('should valid cmd argument', function() - eq(true, pcall(_cmd_parts, {"nvim"})) - eq(true, pcall(_cmd_parts, {"nvim", "--head"})) - end) - - it('should invalid cmd argument', function() - eq('.../lsp.lua:0: cmd: expected list, got nvim', - pcall_err(_cmd_parts, 'nvim')) - eq('.../lsp.lua:0: cmd argument: expected string, got number', - pcall_err(_cmd_parts, {'nvim', 1})) - end) - end) end) describe('LSP', function() describe('basic_init test', function() after_each(function() stop() - exec_lua("lsp.stop_client(lsp.get_clients(), true)") + exec_lua('lsp.stop_client(lsp.get_clients(), true)') exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") end) it('should run correctly', function() local expected_handlers = { - {NIL, {}, {method="test", client_id=1}}; + { NIL, {}, { method = 'test', client_id = 1 } }, } test_rpc_server { - test_name = "basic_init"; + test_name = 'basic_init', on_init = function(client, _) -- client is a dummy object which will queue up commands to be run -- once the server initializes. It can't accept lua callbacks or -- other types that may be unserializable for now. client.stop() - end; + end, -- If the program timed out, then code will be nil. on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, -- Note that NIL must be used here. -- on_handler(err, method, result, client_id) on_handler = function(...) - eq(table.remove(expected_handlers), {...}) - end; + eq(table.remove(expected_handlers), { ... }) + end, } end) it('should fail', function() local expected_handlers = { - {NIL, {}, {method="test", client_id=1}}; + { NIL, {}, { method = 'test', client_id = 1 } }, } test_rpc_server { - test_name = "basic_init"; + test_name = 'basic_init', on_init = function(client) client.notify('test') client.stop() - end; + end, on_exit = function(code, signal) - eq(101, code, "exit code") -- See fake-lsp-server.lua - eq(0, signal, "exit signal") - assert_log(pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]), - fake_lsp_logfile) - end; + eq(101, code, 'exit code') -- See fake-lsp-server.lua + eq(0, signal, 'exit signal') + assert_log( + pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]), + fake_lsp_logfile + ) + end, on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, } end) @@ -209,8 +205,8 @@ describe('LSP', function() client.stop() end, on_exit = function(code, signal) - eq(0, code, 'exit code', fake_lsp_logfile) - eq(0, signal, 'exit signal', fake_lsp_logfile) + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') end, settings = { dummy = 1, @@ -218,10 +214,12 @@ describe('LSP', function() }) end) - it("should set the client's offset_encoding when positionEncoding capability is supported", function() - clear() - exec_lua(create_server_definition) - local result = exec_lua([[ + it( + "should set the client's offset_encoding when positionEncoding capability is supported", + function() + clear() + exec_lua(create_server_definition) + local result = exec_lua([[ local server = _create_server({ capabilities = { positionEncoding = "utf-8" @@ -243,8 +241,9 @@ describe('LSP', function() end return client.offset_encoding ]]) - eq('utf-8', result) - end) + eq('utf-8', result) + end + ) it('should succeed with manual shutdown', function() if is_ci() then @@ -254,68 +253,68 @@ describe('LSP', function() return end local expected_handlers = { - {NIL, {}, {method="shutdown", bufnr=1, client_id=1}}; - {NIL, {}, {method="test", client_id=1}}; + { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } }, + { NIL, {}, { method = 'test', client_id = 1 } }, } test_rpc_server { - test_name = "basic_init"; + test_name = 'basic_init', on_init = function(client) eq(0, client.server_capabilities().textDocumentSync.change) client.request('shutdown') client.notify('exit') client.stop() - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, } end) it('should detach buffer in response to nvim_buf_detach', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_finish"; + test_name = 'basic_finish', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) ]] - eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")) - eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)")) + eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)')) + eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)')) exec_lua [[ vim.api.nvim_command(BUFFER.."bwipeout") ]] - end; + end, on_init = function(_client) client = _client client.notify('finish') - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then - exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)") - eq(false, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)")) + exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)') + eq(false, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)')) client.stop() end - end; + end, } end) it('should fire autocommands on attach and detach', function() local client test_rpc_server { - test_name = "basic_init"; + test_name = 'basic_init', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -332,69 +331,75 @@ describe('LSP', function() end, }) ]] - end; + end, on_init = function(_client) client = _client - eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")) + eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)')) client.notify('finish') - end; + end, on_handler = function(_, _, ctx) if ctx.method == 'finish' then - eq('basic_init', meths.get_var('lsp_attached')) - exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)") - eq('basic_init', meths.get_var('lsp_detached')) + eq('basic_init', api.nvim_get_var('lsp_attached')) + exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)') + eq('basic_init', api.nvim_get_var('lsp_detached')) client.stop() end - end; + end, } end) it('should set default options on attach', function() local client test_rpc_server { - test_name = "set_defaults_all_capabilities"; + test_name = 'set_defaults_all_capabilities', on_init = function(_client) client = _client exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) ]] - end; + end, on_handler = function(_, _, ctx) if ctx.method == 'test' then - eq('v:lua.vim.lsp.tagfunc', get_buf_option("tagfunc")) - eq('v:lua.vim.lsp.omnifunc', get_buf_option("omnifunc")) - eq('v:lua.vim.lsp.formatexpr()', get_buf_option("formatexpr")) - eq('', get_buf_option("keywordprg")) - eq(true, exec_lua[[ + eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc')) + eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc')) + eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr')) + eq('', get_buf_option('keywordprg')) + eq( + true, + exec_lua [[ local keymap vim.api.nvim_buf_call(BUFFER, function() keymap = vim.fn.maparg("K", "n", false, true) end) return keymap.callback == vim.lsp.buf.hover - ]]) + ]] + ) client.stop() end - end; + end, on_exit = function(_, _) - eq('', get_buf_option("tagfunc")) - eq('', get_buf_option("omnifunc")) - eq('', get_buf_option("formatexpr")) - eq('', exec_lua[[ + eq('', get_buf_option('tagfunc')) + eq('', get_buf_option('omnifunc')) + eq('', get_buf_option('formatexpr')) + eq( + '', + exec_lua [[ local keymap vim.api.nvim_buf_call(BUFFER, function() keymap = vim.fn.maparg("K", "n", false, false) end) return keymap - ]]) - end; + ]] + ) + end, } end) it('should overwrite options set by ftplugins', function() local client test_rpc_server { - test_name = "set_defaults_all_capabilities"; + test_name = 'set_defaults_all_capabilities', on_init = function(_client) client = _client exec_lua [[ @@ -406,35 +411,35 @@ describe('LSP', function() ]] -- Sanity check to ensure that some values are set after setting filetype. - eq('v:lua.require\'man\'.goto_tag', get_buf_option("tagfunc", "BUFFER_1")) - eq('xmlcomplete#CompleteTags', get_buf_option("omnifunc", "BUFFER_2")) - eq('xmlformat#Format()', get_buf_option("formatexpr", "BUFFER_2")) + eq("v:lua.require'man'.goto_tag", get_buf_option('tagfunc', 'BUFFER_1')) + eq('xmlcomplete#CompleteTags', get_buf_option('omnifunc', 'BUFFER_2')) + eq('xmlformat#Format()', get_buf_option('formatexpr', 'BUFFER_2')) exec_lua [[ lsp.buf_attach_client(BUFFER_1, TEST_RPC_CLIENT_ID) lsp.buf_attach_client(BUFFER_2, TEST_RPC_CLIENT_ID) ]] - end; + end, on_handler = function(_, _, ctx) if ctx.method == 'test' then - eq('v:lua.vim.lsp.tagfunc', get_buf_option("tagfunc", "BUFFER_1")) - eq('v:lua.vim.lsp.omnifunc', get_buf_option("omnifunc", "BUFFER_2")) - eq('v:lua.vim.lsp.formatexpr()', get_buf_option("formatexpr", "BUFFER_2")) + eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc', 'BUFFER_1')) + eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc', 'BUFFER_2')) + eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr', 'BUFFER_2')) client.stop() end - end; + end, on_exit = function(_, _) - eq('', get_buf_option("tagfunc", "BUFFER_1")) - eq('', get_buf_option("omnifunc", "BUFFER_2")) - eq('', get_buf_option("formatexpr", "BUFFER_2")) - end; + eq('', get_buf_option('tagfunc', 'BUFFER_1')) + eq('', get_buf_option('omnifunc', 'BUFFER_2')) + eq('', get_buf_option('formatexpr', 'BUFFER_2')) + end, } end) it('should not overwrite user-defined options', function() local client test_rpc_server { - test_name = "set_defaults_all_capabilities"; + test_name = 'set_defaults_all_capabilities', on_init = function(_client) client = _client exec_lua [[ @@ -444,20 +449,20 @@ describe('LSP', function() vim.api.nvim_set_option_value('formatexpr', 'fex', { buf = BUFFER }) lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) ]] - end; + end, on_handler = function(_, _, ctx) if ctx.method == 'test' then - eq('tfu', get_buf_option("tagfunc")) - eq('ofu', get_buf_option("omnifunc")) - eq('fex', get_buf_option("formatexpr")) + eq('tfu', get_buf_option('tagfunc')) + eq('ofu', get_buf_option('omnifunc')) + eq('fex', get_buf_option('formatexpr')) client.stop() end - end; + end, on_exit = function(_, _) - eq('tfu', get_buf_option("tagfunc")) - eq('ofu', get_buf_option("omnifunc")) - eq('fex', get_buf_option("formatexpr")) - end; + eq('tfu', get_buf_option('tagfunc')) + eq('ofu', get_buf_option('omnifunc')) + eq('fex', get_buf_option('formatexpr')) + end, } end) @@ -481,62 +486,76 @@ describe('LSP', function() num_attached_after = num_attached_after, } ]]) - eq(true, result ~= nil, "exec_lua must return result") + eq(true, result ~= nil, 'exec_lua must return result') eq(1, result.num_attached_before) eq(0, result.num_attached_after) end) it('client should return settings via workspace/configuration handler', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, { items = { - { section = "testSetting1" }; - { section = "testSetting2" }; - { section = "test.Setting3" }; - { section = "test.Setting4" }; - }}, { method="workspace/configuration", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { + NIL, + { + items = { + { section = 'testSetting1' }, + { section = 'testSetting2' }, + { section = 'test.Setting3' }, + { section = 'test.Setting4' }, + }, + }, + { method = 'workspace/configuration', client_id = 1 }, + }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "check_workspace_configuration"; + test_name = 'check_workspace_configuration', on_init = function(_client) client = _client - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + 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 = { + client.settings = { testSetting1 = true; testSetting2 = false; test = {Setting3 = 'nested' }; }]=]) end if ctx.method == 'workspace/configuration' then - local server_result = exec_lua([=[ + local server_result = exec_lua( + [=[ local method, params = ... - return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=], ctx.method, 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 ctx.method == 'shutdown' then client.stop() end - end; + end, } end) - it('workspace/configuration returns NIL per section if client was started without config.settings', function() - local result = nil - test_rpc_server { - test_name = 'basic_init'; - on_init = function(c) c.stop() end, - on_setup = function() - result = exec_lua [[ + it( + 'workspace/configuration returns NIL per section if client was started without config.settings', + function() + local result = nil + test_rpc_server { + test_name = 'basic_init', + on_init = function(c) + c.stop() + end, + on_setup = function() + result = exec_lua [[ local result = { items = { {section = 'foo'}, @@ -545,52 +564,53 @@ describe('LSP', function() } return vim.lsp.handlers['workspace/configuration'](nil, result, {client_id=TEST_RPC_CLIENT_ID}) ]] - end - } - eq({ NIL, NIL }, result) - end) + end, + } + eq({ NIL, NIL }, result) + end + ) it('should verify capabilities sent', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, } test_rpc_server { - test_name = "basic_check_capabilities"; + test_name = 'basic_check_capabilities', on_init = function(client) client.stop() local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") eq(full_kind, client.server_capabilities().textDocumentSync.change) - eq({includeText = false}, client.server_capabilities().textDocumentSync.save) + eq({ includeText = false }, client.server_capabilities().textDocumentSync.save) eq(false, client.server_capabilities().codeLensProvider) - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, } end) it('BufWritePost sends didSave with bool textDocumentSync.save', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "text_document_sync_save_bool"; + test_name = 'text_document_sync_save_bool', on_init = function(c) client = c - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") - if ctx.method == "start" then + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') + if ctx.method == 'start' then exec_lua([=[ BUFFER = vim.api.nvim_get_current_buf() lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) @@ -599,7 +619,7 @@ describe('LSP', function() else client.stop() end - end; + end, } end) @@ -664,7 +684,7 @@ describe('LSP', function() local messages = result.messages eq('textDocument/willSave', messages[3].method) eq('textDocument/willSaveWaitUntil', messages[4].method) - eq({'Hello'}, result.lines) + eq({ 'Hello' }, result.lines) end) it('saveas sends didOpen if filename changed', function() @@ -685,8 +705,8 @@ describe('LSP', function() on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'start' then - local tmpfile_old = helpers.tmpname() - local tmpfile_new = helpers.tmpname() + local tmpfile_old = tmpname() + local tmpfile_new = tmpname() os.remove(tmpfile_new) exec_lua( [=[ @@ -709,22 +729,22 @@ describe('LSP', function() it('BufWritePost sends didSave including text if server capability is set', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "text_document_sync_save_includeText"; + test_name = 'text_document_sync_save_includeText', on_init = function(c) client = c - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") - if ctx.method == "start" then + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') + if ctx.method == 'start' then exec_lua([=[ BUFFER = vim.api.nvim_get_current_buf() vim.api.nvim_buf_set_lines(BUFFER, 0, -1, true, {"help me"}) @@ -734,16 +754,16 @@ describe('LSP', function() else client.stop() end - end; + end, } end) it('client.supports_methods() should validate capabilities', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, } test_rpc_server { - test_name = "capabilities_for_client_supports_method"; + test_name = 'capabilities_for_client_supports_method', on_init = function(client) client.stop() local expected_sync_capabilities = { @@ -761,268 +781,285 @@ describe('LSP', function() eq(true, client.server_capabilities().codeLensProvider.resolveProvider) -- known methods for resolved capabilities - eq(true, client.supports_method("textDocument/hover")) - eq(false, client.supports_method("textDocument/definition")) + eq(true, client.supports_method('textDocument/hover')) + eq(false, client.supports_method('textDocument/definition')) -- unknown methods are assumed to be supported. - eq(true, client.supports_method("unknown-method")) - end; + eq(true, client.supports_method('unknown-method')) + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, } end) it('should not call unsupported_method when trying to call an unsupported method', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, } test_rpc_server { - test_name = "capabilities_for_client_supports_method"; + test_name = 'capabilities_for_client_supports_method', on_setup = function() - exec_lua([=[ + exec_lua([=[ BUFFER = vim.api.nvim_get_current_buf() lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) vim.lsp.handlers['textDocument/typeDefinition'] = function() end ]=]) - end; + end, on_init = function(client) client.stop() - exec_lua("vim.lsp.buf.type_definition()") + exec_lua('vim.lsp.buf.type_definition()') exec_lua [[ vim.api.nvim_command(BUFFER.."bwipeout") ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, } end) - it('should not call unsupported_method when no client and trying to call an unsupported method', function() - local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - } - test_rpc_server { - test_name = "capabilities_for_client_supports_method"; - on_setup = function() + it( + 'should not call unsupported_method when no client and trying to call an unsupported method', + function() + local expected_handlers = { + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + } + test_rpc_server { + test_name = 'capabilities_for_client_supports_method', + on_setup = function() exec_lua([=[ vim.lsp.handlers['textDocument/typeDefinition'] = function() end ]=]) - end; - on_init = function(client) - client.stop() - exec_lua("vim.lsp.buf.type_definition()") - end; - on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; - on_handler = function(...) - eq(table.remove(expected_handlers), {...}, "expected handler") - end; - } - end) + end, + on_init = function(client) + client.stop() + exec_lua('vim.lsp.buf.type_definition()') + end, + on_exit = function(code, signal) + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, + on_handler = function(...) + eq(table.remove(expected_handlers), { ... }, 'expected handler') + end, + } + end + ) it('should not forward RequestCancelled to callback', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, } local client test_rpc_server { - test_name = "check_forward_request_cancelled"; + test_name = 'check_forward_request_cancelled', on_init = function(_client) - _client.request("error_code_test") + _client.request('error_code_test') client = _client - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") - if ctx.method == 'finish' then client.stop() end - end; + eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler') + if ctx.method == 'finish' then + client.stop() + end + end, } end) it('should forward ContentModified to callback', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; - {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, + { { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } }, } local client test_rpc_server { - test_name = "check_forward_content_modified"; + test_name = 'check_forward_content_modified', on_init = function(_client) - _client.request("error_code_test") + _client.request('error_code_test') client = _client - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, _, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, _, ctx }, 'expected handler') -- if ctx.method == 'error_code_test' then client.notify("finish") end - if ctx.method ~= 'finish' then client.notify('finish') end - if ctx.method == 'finish' then client.stop() end - end; + if ctx.method ~= 'finish' then + client.notify('finish') + end + if ctx.method == 'finish' then + client.stop() + end + end, } end) it('should track pending requests to the language server', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } local client test_rpc_server { - test_name = "check_pending_request_tracked"; + test_name = 'check_pending_request_tracked', on_init = function(_client) client = _client - client.request("slow_request") + client.request('slow_request') local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) - eq("slow_request", request.method) - eq("pending", request.type) - client.notify("release") - end; + eq('slow_request', request.method) + eq('pending', request.type) + client.notify('release') + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler') if ctx.method == 'slow_request' then local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) eq(NIL, request) - client.notify("finish") + client.notify('finish') + end + if ctx.method == 'finish' then + client.stop() end - if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should track cancel requests to the language server', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, } local client test_rpc_server { - test_name = "check_cancel_request_tracked"; + test_name = 'check_cancel_request_tracked', on_init = function(_client) client = _client - client.request("slow_request") + client.request('slow_request') client.cancel_request(2) local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) - eq("slow_request", request.method) - eq("cancel", request.type) - client.notify("release") - end; + eq('slow_request', request.method) + eq('cancel', request.type) + client.notify('release') + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler') local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) eq(NIL, request) - if ctx.method == 'finish' then client.stop() end - end; + if ctx.method == 'finish' then + client.stop() + end + end, } end) it('should clear pending and cancel requests on reply', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } local client test_rpc_server { - test_name = "check_tracked_requests_cleared"; + test_name = 'check_tracked_requests_cleared', on_init = function(_client) client = _client - client.request("slow_request") + client.request('slow_request') local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) - eq("slow_request", request.method) - eq("pending", request.type) + eq('slow_request', request.method) + eq('pending', request.type) client.cancel_request(2) request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) - eq("slow_request", request.method) - eq("cancel", request.type) - client.notify("release") - end; + eq('slow_request', request.method) + eq('cancel', request.type) + client.notify('release') + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler') if ctx.method == 'slow_request' then local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=]) eq(NIL, request) - client.notify("finish") + client.notify('finish') end - if ctx.method == 'finish' then client.stop() end - end; + if ctx.method == 'finish' then + client.stop() + end + end, } end) it('should trigger LspRequest autocmd when requests table changes', function() local expected_handlers = { - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="slow_request", bufnr=1, client_id=1}}; + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } local client test_rpc_server { - test_name = "check_tracked_requests_cleared"; + test_name = 'check_tracked_requests_cleared', on_init = function(_client) command('let g:requests = 0') command('autocmd LspRequest * let g:requests+=1') client = _client - client.request("slow_request") + client.request('slow_request') eq(1, eval('g:requests')) client.cancel_request(2) eq(2, eval('g:requests')) - client.notify("release") - end; + client.notify('release') + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - eq(0, #expected_handlers, "did not call expected handler") + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + eq(0, #expected_handlers, 'did not call expected handler') eq(3, eval('g:requests')) - end; + end, on_handler = function(err, _, ctx) - eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler') if ctx.method == 'slow_request' then - client.notify("finish") + client.notify('finish') + end + if ctx.method == 'finish' then + client.stop() end - if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should not send didOpen if the buffer closes before init', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_finish"; + test_name = 'basic_finish', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1031,42 +1068,42 @@ describe('LSP', function() "123"; }) ]] - eq(1, exec_lua("return TEST_RPC_CLIENT_ID")) - eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)")) - eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)")) + eq(1, exec_lua('return TEST_RPC_CLIENT_ID')) + eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)')) + eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)')) exec_lua [[ vim.api.nvim_command(BUFFER.."bwipeout") ]] - end; + end, on_init = function(_client) client = _client local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") eq(full_kind, client.server_capabilities().textDocumentSync.change) eq(true, client.server_capabilities().textDocumentSync.openClose) client.notify('finish') - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body sent attaching before init', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open"; + test_name = 'basic_check_buffer_open', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1078,7 +1115,7 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_init = function(_client) client = _client local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1087,32 +1124,32 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID), "Already attached, returns true") ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body sent attaching after init', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open"; + test_name = 'basic_check_buffer_open', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1121,7 +1158,7 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1130,32 +1167,32 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange full', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change"; + test_name = 'basic_check_buffer_open_and_change', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1164,7 +1201,7 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1173,11 +1210,11 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1187,23 +1224,23 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange full with noeol', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_noeol"; + test_name = 'basic_check_buffer_open_and_change_noeol', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1213,7 +1250,7 @@ describe('LSP', function() }) vim.bo[BUFFER].eol = false ]] - end; + end, on_init = function(_client) client = _client local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1222,11 +1259,11 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1236,37 +1273,41 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should send correct range for inlay hints with noeol', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, { - method="textDocument/inlayHint", - params = { - textDocument = { - uri = 'file://', + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { + NIL, + {}, + { + method = 'textDocument/inlayHint', + params = { + textDocument = { + uri = 'file://', + }, + range = { + start = { line = 0, character = 0 }, + ['end'] = { line = 1, character = 3 }, + }, }, - range = { - start = { line = 0, character = 0 }, - ['end'] = { line = 1, character = 3 }, - } + bufnr = 2, + client_id = 1, }, - bufnr=2, - client_id=1, - }}; - {NIL, {}, {method="start", client_id=1}}; + }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "inlay_hint"; + test_name = 'inlay_hint', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1276,18 +1317,18 @@ describe('LSP', function() }) vim.bo[BUFFER].eol = false ]] - end; + end, on_init = function(_client) client = _client eq(true, client.supports_method('textDocument/inlayHint')) exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1297,26 +1338,26 @@ describe('LSP', function() if ctx.method == 'textDocument/inlayHint' then client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange incremental', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_incremental"; + test_name = 'basic_check_buffer_open_and_change_incremental', options = { allow_incremental_sync = true, - }; + }, on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1325,20 +1366,21 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client - local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") + local sync_kind = + exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") eq(sync_kind, client.server_capabilities().textDocumentSync.change) eq(true, client.server_capabilities().textDocumentSync.openClose) exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1348,26 +1390,26 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange incremental with debounce', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_incremental"; + test_name = 'basic_check_buffer_open_and_change_incremental', options = { allow_incremental_sync = true, - debounce_text_changes = 5 - }; + debounce_text_changes = 5, + }, on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1376,20 +1418,21 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client - local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") + local sync_kind = + exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") eq(sync_kind, client.server_capabilities().textDocumentSync.change) eq(true, client.server_capabilities().textDocumentSync.openClose) exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1399,24 +1442,24 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) -- 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, {}, {method="shutdown", bufnr=1, client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_incremental_editing"; + test_name = 'basic_check_buffer_open_and_change_incremental_editing', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1425,42 +1468,43 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client - local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") + local sync_kind = + exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental") eq(sync_kind, client.server_capabilities().textDocumentSync.change) eq(true, client.server_capabilities().textDocumentSync.openClose) exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then - helpers.command("normal! 1Go") + helpers.command('normal! 1Go') client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange full with 2 changes', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_multi"; + test_name = 'basic_check_buffer_open_and_change_multi', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1469,7 +1513,7 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1478,11 +1522,11 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ @@ -1495,23 +1539,23 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) it('should check the body and didChange full lifecycle', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_multi_and_close"; + test_name = 'basic_check_buffer_open_and_change_multi_and_close', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1520,7 +1564,7 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full") @@ -1529,12 +1573,12 @@ describe('LSP', function() exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; - on_handler = function(err, result,ctx) + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, + on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, { @@ -1547,55 +1591,58 @@ describe('LSP', function() ]] client.notify('finish') end - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) end) - describe("parsing tests", function() + describe('parsing tests', function() it('should handle invalid content-length correctly', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="finish", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'finish', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "invalid_header"; - on_setup = function() - end; + test_name = 'invalid_header', + on_setup = function() end, on_init = function(_client) client = _client client.stop(true) - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") - end; + 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, {}, {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" - }, {method="workspace/executeCommand", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { 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', + }, + { method = 'workspace/executeCommand', client_id = 1 }, + }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "decode_nil"; + test_name = 'decode_nil', on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -1604,23 +1651,23 @@ describe('LSP', function() "123"; }) ]] - end; + end, on_init = function(_client) client = _client exec_lua [[ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) ]] - end; + end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') if ctx.method == 'finish' then client.stop() end - end; + end, } end) end) @@ -1634,10 +1681,10 @@ describe('LSP', function() local function make_edit(y_0, x_0, y_1, x_1, text) return { range = { - start = { line = y_0, character = x_0 }; - ["end"] = { line = y_1, character = x_1 }; - }; - newText = type(text) == 'table' and table.concat(text, '\n') or (text or ""); + start = { line = y_0, character = x_0 }, + ['end'] = { line = y_1, character = x_1 }, + }, + newText = type(text) == 'table' and table.concat(text, '\n') or (text or ''), } end @@ -1652,121 +1699,121 @@ describe('LSP', function() end) it('applies simple edits', function() local edits = { - make_edit(0, 0, 0, 0, {"123"}); - make_edit(1, 0, 1, 1, {"2"}); - make_edit(2, 0, 2, 2, {"3"}); - make_edit(3, 2, 3, 4, {""}); + make_edit(0, 0, 0, 0, { '123' }), + make_edit(1, 0, 1, 1, { '2' }), + make_edit(2, 0, 2, 2, { '3' }), + make_edit(3, 2, 3, 4, { '' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - '123First line of text'; - '2econd line of text'; - '3ird line of text'; - 'Foth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + '123First line of text', + '2econd line of text', + '3ird line of text', + 'Foth line of text', + 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) end) it('applies complex edits', 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 ", 0, #"First line of text", {"guy"}); - make_edit(1, 0, 1, #'Second', {"baz"}); - make_edit(2, #'Th', 2, #"Third", {"e next"}); - make_edit(3, #'', 3, #"Fourth", {"another line of text", "before this"}); - make_edit(3, #'Fourth', 3, #"Fourth line of text", {"!"}); + 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 ', 0, #'First line of text', { 'guy' }), + make_edit(1, 0, 1, #'Second', { 'baz' }), + make_edit(2, #'Th', 2, #'Third', { 'e next' }), + make_edit(3, #'', 3, #'Fourth', { 'another line of text', 'before this' }), + make_edit(3, #'Fourth', 3, #'Fourth line of text', { '!' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - ''; - '123'; - 'fooFbar'; - '123irst guy'; - 'baz line of text'; - 'The next line of text'; - 'another line of text'; - 'before this!'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + '', + '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 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', {"!"}); + 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, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - ''; - '123'; - 'fooFbar'; - '123irst guy'; - 'baz line of text'; - 'The next line of text'; - 'another line of text'; - 'before this!'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + '', + '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, {"ä"}); + make_edit(4, 3, 4, 4, { 'ä' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Second line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å ä ɧ 汉语 ↥ 🤦 🦄'; + 'First line of text', + 'Second line of text', + 'Third line of text', + 'Fourth line of text', + 'å ä ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) end) it('applies text edits at the end of the document', function() local edits = { - make_edit(5, 0, 5, 0, "foobar"); + make_edit(5, 0, 5, 0, 'foobar'), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Second line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; - 'foobar'; + 'First line of text', + 'Second line of text', + 'Third line of text', + 'Fourth line of text', + 'å å ɧ 汉语 ↥ 🤦 🦄', + 'foobar', }, buf_lines(1)) end) it('applies multiple text edits at the end of the document', function() local edits = { - make_edit(4, 0, 5, 0, ""); - make_edit(5, 0, 5, 0, "foobar"); + make_edit(4, 0, 5, 0, ''), + make_edit(5, 0, 5, 0, 'foobar'), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Second line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'foobar'; + 'First line of text', + 'Second line of text', + 'Third line of text', + 'Fourth line of text', + 'foobar', }, buf_lines(1)) end) it('it restores marks', function() local edits = { - make_edit(1, 0, 2, 5, "foobar"); - make_edit(4, 0, 5, 0, "barfoo"); + make_edit(1, 0, 2, 5, 'foobar'), + make_edit(4, 0, 5, 0, 'barfoo'), } eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 1, {})')) - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'foobar line of text'; - 'Fourth line of text'; - 'barfoo'; + 'First line of text', + 'foobar line of text', + 'Fourth line of text', + 'barfoo', }, buf_lines(1)) local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') eq({ 2, 1 }, mark) @@ -1774,16 +1821,16 @@ describe('LSP', function() it('it restores marks to last valid col', function() local edits = { - make_edit(1, 0, 2, 15, "foobar"); - make_edit(4, 0, 5, 0, "barfoo"); + make_edit(1, 0, 2, 15, 'foobar'), + make_edit(4, 0, 5, 0, 'barfoo'), } eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 10, {})')) - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'foobarext'; - 'Fourth line of text'; - 'barfoo'; + 'First line of text', + 'foobarext', + 'Fourth line of text', + 'barfoo', }, buf_lines(1)) local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') eq({ 2, 9 }, mark) @@ -1791,138 +1838,138 @@ describe('LSP', function() it('it restores marks to last valid line', function() local edits = { - make_edit(1, 0, 4, 5, "foobar"); - make_edit(4, 0, 5, 0, "barfoo"); + make_edit(1, 0, 4, 5, 'foobar'), + make_edit(4, 0, 5, 0, 'barfoo'), } eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 4, 1, {})')) - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'foobaro'; + 'First line of text', + 'foobaro', }, buf_lines(1)) local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') eq({ 2, 1 }, mark) 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 }) + it("don't fix the cursor if the range contains the cursor", function() + fn.nvim_win_set_cursor(0, { 2, 6 }) local edits = { - make_edit(1, 0, 1, 19, 'Second line of text') + make_edit(1, 0, 1, 19, 'Second line of text'), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Second line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + '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)) + eq({ 2, 6 }, fn.nvim_win_get_cursor(0)) end) it('fix the cursor to the valid col if the content was removed', function() - funcs.nvim_win_set_cursor(0, { 2, 6 }) + fn.nvim_win_set_cursor(0, { 2, 6 }) local edits = { make_edit(1, 0, 1, 6, ''), - make_edit(1, 6, 1, 19, '') + make_edit(1, 6, 1, 19, ''), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - ''; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + 'First line of text', + '', + 'Third line of text', + 'Fourth line of text', + 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 2, 0 }, funcs.nvim_win_get_cursor(0)) + eq({ 2, 0 }, fn.nvim_win_get_cursor(0)) end) it('fix the cursor to the valid row if the content was removed', function() - funcs.nvim_win_set_cursor(0, { 2, 6 }) + fn.nvim_win_set_cursor(0, { 2, 6 }) local edits = { make_edit(1, 0, 1, 6, ''), - make_edit(0, 18, 5, 0, '') + make_edit(0, 18, 5, 0, ''), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; + 'First line of text', }, buf_lines(1)) - eq({ 1, 17 }, funcs.nvim_win_get_cursor(0)) + eq({ 1, 17 }, fn.nvim_win_get_cursor(0)) end) it('fix the cursor row', function() - funcs.nvim_win_set_cursor(0, { 3, 0 }) + fn.nvim_win_set_cursor(0, { 3, 0 }) local edits = { - make_edit(1, 0, 2, 0, '') + make_edit(1, 0, 2, 0, ''), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + 'First line of text', + 'Third line of text', + 'Fourth line of text', + 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 2, 0 }, funcs.nvim_win_get_cursor(0)) + eq({ 2, 0 }, fn.nvim_win_get_cursor(0)) end) it('fix the cursor col', function() -- append empty last line. See #22636 - exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, {''}) + exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, { '' }) - funcs.nvim_win_set_cursor(0, { 2, 11 }) + fn.nvim_win_set_cursor(0, { 2, 11 }) local edits = { - make_edit(1, 7, 1, 11, '') + make_edit(1, 7, 1, 11, ''), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Second of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; - ''; + '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)) + eq({ 2, 7 }, fn.nvim_win_get_cursor(0)) end) it('fix the cursor row and col', function() - funcs.nvim_win_set_cursor(0, { 2, 12 }) + fn.nvim_win_set_cursor(0, { 2, 12 }) local edits = { - make_edit(0, 11, 1, 12, '') + make_edit(0, 11, 1, 12, ''), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ - 'First line of text'; - 'Third line of text'; - 'Fourth line of text'; - 'å å ɧ 汉语 ↥ 🤦 🦄'; + 'First line of text', + 'Third line of text', + 'Fourth line of text', + 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 1, 11 }, funcs.nvim_win_get_cursor(0)) + eq({ 1, 11 }, fn.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 = { - make_edit(0, 0, 5, 0, {"All replaced"}); + make_edit(0, 0, 5, 0, { 'All replaced' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") - eq({'All replaced'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') + eq({ 'All replaced' }, buf_lines(1)) end) - it('applies edits when the end line is 2 larger than vim\'s', function() + it("applies edits when the end line is 2 larger than vim's", function() local edits = { - make_edit(0, 0, 6, 0, {"All replaced"}); + make_edit(0, 0, 6, 0, { 'All replaced' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") - eq({'All replaced'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') + eq({ 'All replaced' }, buf_lines(1)) end) it('applies edits with a column offset', function() local edits = { - make_edit(0, 0, 5, 2, {"All replaced"}); + make_edit(0, 0, 5, 2, { 'All replaced' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16") - eq({'All replaced'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') + eq({ 'All replaced' }, buf_lines(1)) end) end) end) @@ -1936,33 +1983,39 @@ describe('LSP', function() describe('with LSP end column out of bounds and start column at 0', function() it('applies edits at the end of the buffer', function() local edits = { - make_edit(0, 0, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + make_edit(0, 0, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") - eq({'#include "whatever.h"', '#include <algorithm>'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8') + eq({ '#include "whatever.h"', '#include <algorithm>' }, buf_lines(1)) end) it('applies edits in the middle of the buffer', function() local edits = { - make_edit(0, 0, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + make_edit(0, 0, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") - eq({'#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8') + eq( + { '#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' }, + buf_lines(1) + ) end) end) describe('with LSP end column out of bounds and start column NOT at 0', function() it('applies edits at the end of the buffer', function() local edits = { - make_edit(0, 2, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + make_edit(0, 2, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") - eq({'Te#include "whatever.h"', '#include <algorithm>'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8') + eq({ 'Te#include "whatever.h"', '#include <algorithm>' }, buf_lines(1)) end) it('applies edits in the middle of the buffer', function() local edits = { - make_edit(0, 2, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'}); + make_edit(0, 2, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }), } - exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8") - eq({'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1)) + exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8') + eq( + { 'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' }, + buf_lines(1) + ) end) end) end) @@ -1972,12 +2025,12 @@ describe('LSP', function() local text_document_edit = function(editVersion) return { edits = { - make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄") + make_edit(0, 0, 0, 3, 'First ↥ 🤦 🦄'), }, textDocument = { - uri = "file:///fake/uri"; - version = editVersion - } + uri = 'file:///fake/uri', + version = editVersion, + }, } end before_each(function() @@ -1991,49 +2044,63 @@ describe('LSP', function() it('correctly goes ahead with the edit if all is normal', function() exec_lua("vim.lsp.util.apply_text_document_edit(..., nil, 'utf-16')", text_document_edit(5)) eq({ - 'First ↥ 🤦 🦄 line of text'; - '2nd line of 语text'; + 'First ↥ 🤦 🦄 line of text', + '2nd line of 语text', }, buf_lines(target_bufnr)) end) it('always accepts edit with version = 0', function() - exec_lua([[ + exec_lua( + [[ local args = {...} local bufnr = select(1, ...) local text_edit = select(2, ...) vim.lsp.util.buf_versions[bufnr] = 10 vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16') - ]], target_bufnr, text_document_edit(0)) + ]], + target_bufnr, + text_document_edit(0) + ) eq({ - 'First ↥ 🤦 🦄 line of text'; - '2nd line of 语text'; + 'First ↥ 🤦 🦄 line of text', + '2nd line of 语text', }, buf_lines(target_bufnr)) end) it('skips the edit if the version of the edit is behind the local buffer ', function() local apply_edit_mocking_current_version = function(edit, versionedBuf) - exec_lua([[ + exec_lua( + [[ local args = {...} local versionedBuf = args[2] vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16') - ]], edit, versionedBuf) + ]], + edit, + versionedBuf + ) end local baseText = { - '1st line of text'; - '2nd line of 语text'; + '1st line of text', + '2nd line of 语text', } eq(baseText, buf_lines(target_bufnr)) -- Apply an edit for an old version, should skip - apply_edit_mocking_current_version(text_document_edit(2), {currentVersion=7; bufnr=target_bufnr}) + apply_edit_mocking_current_version( + text_document_edit(2), + { currentVersion = 7, bufnr = target_bufnr } + ) eq(baseText, buf_lines(target_bufnr)) -- no change -- Sanity check that next version to current does apply change - apply_edit_mocking_current_version(text_document_edit(8), {currentVersion=7; bufnr=target_bufnr}) + apply_edit_mocking_current_version( + text_document_edit(8), + { currentVersion = 7, bufnr = target_bufnr } + ) eq({ - 'First ↥ 🤦 🦄 line of text'; - '2nd line of 语text'; + 'First ↥ 🤦 🦄 line of text', + '2nd line of 语text', }, buf_lines(target_bufnr)) end) end) @@ -2041,34 +2108,37 @@ describe('LSP', function() describe('workspace_apply_edit', function() it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function() local expected_handlers = { - {NIL, {}, {method="test", client_id=1}}; + { NIL, {}, { method = 'test', client_id = 1 } }, } test_rpc_server { - test_name = "basic_init"; + test_name = 'basic_init', on_init = function(client, _) client.stop() - end; + end, -- If the program timed out, then code will be nil. on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") - end; + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, -- Note that NIL must be used here. -- on_handler(err, method, result, client_id) on_handler = function(...) local expected = { - applied = true; - failureReason = nil; + applied = true, + failureReason = nil, } - eq(expected, exec_lua [[ + eq( + expected, + exec_lua [[ local apply_edit = { label = nil; edit = {}; } return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit, {client_id = TEST_RPC_CLIENT_ID}) - ]]) - eq(table.remove(expected_handlers), {...}) - end; + ]] + ) + eq(table.remove(expected_handlers), { ... }) + end, } end) end) @@ -2078,12 +2148,12 @@ describe('LSP', function() return { edits = { -- NOTE: This is a hack if you have a line longer than 1000 it won't replace it - make_edit(row, 0, row, 1000, new_line) + make_edit(row, 0, row, 1000, new_line), }, textDocument = { - uri = "file:///fake/uri"; - version = editVersion - } + uri = 'file:///fake/uri', + version = editVersion, + }, } end @@ -2091,7 +2161,7 @@ describe('LSP', function() -- We should not stop applying the edits local make_workspace_edit = function(changes) return { - documentChanges = changes + documentChanges = changes, } end @@ -2127,7 +2197,7 @@ describe('LSP', function() it('apply_workspace_edit applies a single edit', function() local new_lines = { - "First Line", + 'First Line', } local edits = {} @@ -2135,10 +2205,13 @@ describe('LSP', function() table.insert(edits, replace_line_edit(row - 1, line, changedtick)) end - eq({ - "First Line", - "Original Line #2", - }, exec_lua([[ + eq( + { + 'First Line', + 'Original Line #2', + }, + exec_lua( + [[ local args = {...} local workspace_edits = args[1] local target_bufnr = args[2] @@ -2146,13 +2219,17 @@ describe('LSP', function() vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16') return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false) - ]], make_workspace_edit(edits), target_bufnr)) + ]], + make_workspace_edit(edits), + target_bufnr + ) + ) end) it('apply_workspace_edit applies multiple edits', function() local new_lines = { - "First Line", - "Second Line", + 'First Line', + 'Second Line', } local edits = {} @@ -2160,7 +2237,10 @@ describe('LSP', function() table.insert(edits, replace_line_edit(row - 1, line, changedtick)) end - eq(new_lines, exec_lua([[ + eq( + new_lines, + exec_lua( + [[ local args = {...} local workspace_edits = args[1] local target_bufnr = args[2] @@ -2168,10 +2248,14 @@ describe('LSP', function() vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16') return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false) - ]], make_workspace_edit(edits), target_bufnr)) + ]], + make_workspace_edit(edits), + target_bufnr + ) + ) end) it('Supports file creation with CreateFile payload', function() - local tmpfile = helpers.tmpname() + local tmpfile = tmpname() os.remove(tmpfile) -- Should not exist, only interested in a tmpname local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) local edit = { @@ -2180,29 +2264,32 @@ describe('LSP', function() kind = 'create', uri = uri, }, - } + }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) end) - it('Supports file creation in folder that needs to be created with CreateFile payload', function() - local tmpfile = helpers.tmpname() - os.remove(tmpfile) -- Should not exist, only interested in a tmpname - tmpfile = tmpfile .. '/dummy/x/' - local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) - local edit = { - documentChanges = { - { - kind = 'create', - uri = uri, + it( + 'Supports file creation in folder that needs to be created with CreateFile payload', + function() + local tmpfile = tmpname() + os.remove(tmpfile) -- Should not exist, only interested in a tmpname + tmpfile = tmpfile .. '/dummy/x/' + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'create', + uri = uri, + }, }, } - } - exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) - end) + exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') + eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + end + ) it('createFile does not touch file if it exists and ignoreIfExists is set', function() - local tmpfile = helpers.tmpname() + local tmpfile = tmpname() write_file(tmpfile, 'Dummy content') local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) local edit = { @@ -2214,14 +2301,14 @@ describe('LSP', function() ignoreIfExists = true, }, }, - } + }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) eq('Dummy content', read_file(tmpfile)) end) it('createFile overrides file if overwrite is set', function() - local tmpfile = helpers.tmpname() + local tmpfile = tmpname() write_file(tmpfile, 'Dummy content') local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) local edit = { @@ -2234,35 +2321,38 @@ describe('LSP', function() ignoreIfExists = true, -- overwrite must win over ignoreIfExists }, }, - } + }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) eq('', read_file(tmpfile)) end) it('DeleteFile delete file and buffer', function() - local tmpfile = helpers.tmpname() + local tmpfile = tmpname() write_file(tmpfile, 'Be gone') - local uri = exec_lua([[ + local uri = exec_lua( + [[ local fname = select(1, ...) local bufnr = vim.fn.bufadd(fname) vim.fn.bufload(bufnr) return vim.uri_from_fname(fname) - ]], tmpfile) + ]], + tmpfile + ) local edit = { documentChanges = { { kind = 'delete', uri = uri, - } - } + }, + }, } eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')) eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile)) end) it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function() - local tmpfile = helpers.tmpname() + local tmpfile = tmpname() os.remove(tmpfile) local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) local edit = { @@ -2272,9 +2362,9 @@ describe('LSP', function() uri = uri, options = { ignoreIfNotExists = false, - } - } - } + }, + }, + }, } eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit)) eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) @@ -2285,46 +2375,36 @@ describe('LSP', function() local pathsep = helpers.get_pathsep() it('Can rename an existing file', function() - local old = helpers.tmpname() + local old = tmpname() write_file(old, 'Test content') - local new = helpers.tmpname() - os.remove(new) -- only reserve the name, file must not exist for the test scenario - local lines = exec_lua([[ + local new = tmpname() + os.remove(new) -- only reserve the name, file must not exist for the test scenario + local lines = exec_lua( + [[ local old = select(1, ...) local new = select(2, ...) + local old_bufnr = vim.fn.bufadd(old) + vim.fn.bufload(old_bufnr) vim.lsp.util.rename(old, new) - - -- after rename the target file must have the contents of the source file - local bufnr = vim.fn.bufadd(new) - vim.fn.bufload(new) - return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true) - ]], old, new) - eq({'Test content'}, lines) + -- the existing buffer is renamed in-place and its contents is kept + local new_bufnr = vim.fn.bufadd(new) + vim.fn.bufload(new_bufnr) + return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true) + ]], + old, + new + ) + eq({ 'Test content' }, lines) local exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', old) eq(false, exists) exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', new) eq(true, exists) os.remove(new) end) - it("Kills old buffer after renaming an existing file", function() - local old = helpers.tmpname() - write_file(old, 'Test content') - local new = helpers.tmpname() - os.remove(new) -- only reserve the name, file must not exist for the test scenario - local lines = exec_lua([[ - local old = select(1, ...) - local oldbufnr = vim.fn.bufadd(old) - local new = select(2, ...) - vim.lsp.util.rename(old, new) - return vim.fn.bufloaded(oldbufnr) - ]], old, new) - eq(0, lines) - os.remove(new) - end) it('Can rename a directory', function() -- only reserve the name, file must not exist for the test scenario - local old_dir = helpers.tmpname() - local new_dir = helpers.tmpname() + local old_dir = tmpname() + local new_dir = tmpname() os.remove(old_dir) os.remove(new_dir) @@ -2333,64 +2413,211 @@ describe('LSP', function() local file = 'file.txt' write_file(old_dir .. pathsep .. file, 'Test content') - local lines = exec_lua([[ + local lines = exec_lua( + [[ local old_dir = select(1, ...) local new_dir = select(2, ...) - local pathsep = select(3, ...) - local oldbufnr = vim.fn.bufadd(old_dir .. pathsep .. 'file') - + local pathsep = select(3, ...) + local file = select(4, ...) + local old_bufnr = vim.fn.bufadd(old_dir .. pathsep .. file) + vim.fn.bufload(old_bufnr) vim.lsp.util.rename(old_dir, new_dir) - return vim.fn.bufloaded(oldbufnr) - ]], old_dir, new_dir, pathsep) - eq(0, lines) + -- the existing buffer is renamed in-place and its contents is kept + local new_bufnr = vim.fn.bufadd(new_dir .. pathsep .. file) + vim.fn.bufload(new_bufnr) + return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true) + ]], + old_dir, + new_dir, + pathsep, + file + ) + eq({ 'Test content' }, lines) eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old_dir)) eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir)) eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir .. pathsep .. file)) - eq('Test content', read_file(new_dir .. pathsep .. file)) os.remove(new_dir) end) - it('Does not rename file if target exists and ignoreIfExists is set or overwrite is false', function() - local old = helpers.tmpname() - write_file(old, 'Old File') - local new = helpers.tmpname() - write_file(new, 'New file') + it('Does not touch buffers that do not match path prefix', function() + local old = tmpname() + local new = tmpname() + os.remove(old) + os.remove(new) + helpers.mkdir_p(old) - exec_lua([[ + local result = exec_lua( + [[ + local old = select(1, ...) + local new = select(2, ...) + + local old_prefixed = 'explorer://' .. old + local old_suffixed = old .. '.bak' + local new_prefixed = 'explorer://' .. new + local new_suffixed = new .. '.bak' + + local old_prefixed_buf = vim.fn.bufadd(old_prefixed) + local old_suffixed_buf = vim.fn.bufadd(old_suffixed) + local new_prefixed_buf = vim.fn.bufadd(new_prefixed) + local new_suffixed_buf = vim.fn.bufadd(new_suffixed) + + vim.lsp.util.rename(old, new) + + return + vim.api.nvim_buf_is_valid(old_prefixed_buf) and + vim.api.nvim_buf_is_valid(old_suffixed_buf) and + vim.api.nvim_buf_is_valid(new_prefixed_buf) and + vim.api.nvim_buf_is_valid(new_suffixed_buf) and + vim.api.nvim_buf_get_name(old_prefixed_buf) == old_prefixed and + vim.api.nvim_buf_get_name(old_suffixed_buf) == old_suffixed and + vim.api.nvim_buf_get_name(new_prefixed_buf) == new_prefixed and + vim.api.nvim_buf_get_name(new_suffixed_buf) == new_suffixed + ]], + old, + new + ) + eq(true, result) + + os.remove(new) + end) + it( + 'Does not rename file if target exists and ignoreIfExists is set or overwrite is false', + function() + local old = tmpname() + write_file(old, 'Old File') + local new = tmpname() + write_file(new, 'New file') + + exec_lua( + [[ local old = select(1, ...) local new = select(2, ...) vim.lsp.util.rename(old, new, { ignoreIfExists = true }) - ]], old, new) + ]], + old, + new + ) - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) - eq('New file', read_file(new)) + eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq('New file', read_file(new)) - exec_lua([[ + exec_lua( + [[ local old = select(1, ...) local new = select(2, ...) vim.lsp.util.rename(old, new, { overwrite = false }) - ]], old, new) + ]], + old, + new + ) - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) - eq('New file', read_file(new)) + eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq('New file', read_file(new)) + end + ) + it('Maintains undo information for loaded buffer', function() + local old = tmpname() + write_file(old, 'line') + local new = tmpname() + os.remove(new) + + local undo_kept = exec_lua( + [[ + local old = select(1, ...) + local new = select(2, ...) + vim.opt.undofile = true + vim.cmd.edit(old) + vim.cmd.normal('dd') + vim.cmd.write() + local undotree = vim.fn.undotree() + vim.lsp.util.rename(old, new) + -- Renaming uses :saveas, which updates the "last write" information. + -- Other than that, the undotree should remain the same. + undotree.save_cur = undotree.save_cur + 1 + undotree.save_last = undotree.save_last + 1 + undotree.entries[1].save = undotree.entries[1].save + 1 + return vim.deep_equal(undotree, vim.fn.undotree()) + ]], + old, + new + ) + eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new)) + eq(true, undo_kept) + end) + it('Maintains undo information for unloaded buffer', function() + local old = tmpname() + write_file(old, 'line') + local new = tmpname() + os.remove(new) + + local undo_kept = exec_lua( + [[ + local old = select(1, ...) + local new = select(2, ...) + vim.opt.undofile = true + vim.cmd.split(old) + vim.cmd.normal('dd') + vim.cmd.write() + local undotree = vim.fn.undotree() + vim.cmd.bdelete() + vim.lsp.util.rename(old, new) + vim.cmd.edit(new) + return vim.deep_equal(undotree, vim.fn.undotree()) + ]], + old, + new + ) + eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new)) + eq(true, undo_kept) + end) + it('Does not rename file when it conflicts with a buffer without file', function() + local old = tmpname() + write_file(old, 'Old File') + local new = tmpname() + os.remove(new) + + local lines = exec_lua( + [[ + local old = select(1, ...) + local new = select(2, ...) + local old_buf = vim.fn.bufadd(old) + vim.fn.bufload(old_buf) + local conflict_buf = vim.api.nvim_create_buf(true, false) + vim.api.nvim_buf_set_name(conflict_buf, new) + vim.api.nvim_buf_set_lines(conflict_buf, 0, -1, true, {'conflict'}) + vim.api.nvim_win_set_buf(0, conflict_buf) + vim.lsp.util.rename(old, new) + return vim.api.nvim_buf_get_lines(conflict_buf, 0, -1, true) + ]], + old, + new + ) + eq({ 'conflict' }, lines) + eq('Old File', read_file(old)) end) it('Does override target if overwrite is true', function() - local old = helpers.tmpname() + local old = tmpname() write_file(old, 'Old file') - local new = helpers.tmpname() + local new = tmpname() write_file(new, 'New file') - exec_lua([[ + exec_lua( + [[ local old = select(1, ...) local new = select(2, ...) vim.lsp.util.rename(old, new, { overwrite = true }) - ]], old, new) + ]], + old, + new + ) eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new)) - eq('Old file\n', read_file(new)) + eq('Old file', read_file(new)) end) end) @@ -2407,8 +2634,8 @@ describe('LSP', function() range = { start = { line = 0, character = 2 }, ['end'] = { line = 0, character = 3 }, - } - } + }, + }, }, } local actual = exec_lua [[ @@ -2436,7 +2663,7 @@ describe('LSP', function() col = 3, text = 'testing', user_data = { - targetUri = "file:///fake/uri", + targetUri = 'file:///fake/uri', targetRange = { start = { line = 0, character = 2 }, ['end'] = { line = 0, character = 3 }, @@ -2444,8 +2671,8 @@ describe('LSP', function() targetSelectionRange = { start = { line = 0, character = 2 }, ['end'] = { line = 0, character = 3 }, - } - } + }, + }, }, } local actual = exec_lua [[ @@ -2479,24 +2706,26 @@ describe('LSP', function() filename = '', kind = 'File', lnum = 2, - text = '[File] TestA' + text = '[File] TestA', }, { col = 1, filename = '', kind = 'Module', lnum = 4, - text = '[Module] TestB' + text = '[Module] TestB', }, { col = 1, filename = '', kind = 'Namespace', lnum = 6, - text = '[Namespace] TestC' - } + text = '[Namespace] TestC', + }, } - eq(expected, exec_lua [[ + eq( + expected, + exec_lua [[ local doc_syms = { { deprecated = false, @@ -2581,7 +2810,8 @@ describe('LSP', function() } } return vim.lsp.util.symbols_to_items(doc_syms, nil) - ]]) + ]] + ) end) it('DocumentSymbol has no children', function() local expected = { @@ -2590,17 +2820,19 @@ describe('LSP', function() filename = '', kind = 'File', lnum = 2, - text = '[File] TestA' + text = '[File] TestA', }, { col = 1, filename = '', kind = 'Namespace', lnum = 6, - text = '[Namespace] TestC' - } + text = '[Namespace] TestC', + }, } - eq(expected, exec_lua [[ + eq( + expected, + exec_lua [[ local doc_syms = { { deprecated = false, @@ -2656,27 +2888,30 @@ describe('LSP', function() } } return vim.lsp.util.symbols_to_items(doc_syms, nil) - ]]) + ]] + ) end) end) it('convert SymbolInformation[] to items', function() - local expected = { - { - col = 1, - filename = '/test_a', - kind = 'File', - lnum = 2, - text = '[File] TestA' - }, - { - col = 1, - filename = '/test_b', - kind = 'Module', - lnum = 4, - text = '[Module] TestB' - } - } - eq(expected, exec_lua [[ + local expected = { + { + col = 1, + filename = '/test_a', + kind = 'File', + lnum = 2, + text = '[File] TestA', + }, + { + col = 1, + filename = '/test_b', + kind = 'Module', + lnum = 4, + text = '[Module] TestB', + }, + } + eq( + expected, + exec_lua [[ local sym_info = { { deprecated = false, @@ -2718,19 +2953,20 @@ describe('LSP', function() } } return vim.lsp.util.symbols_to_items(sym_info, nil) - ]]) + ]] + ) end) end) describe('lsp.util._get_symbol_kind_name', function() it('returns the name specified by protocol', function() - eq("File", exec_lua("return vim.lsp.util._get_symbol_kind_name(1)")) - eq("TypeParameter", exec_lua("return vim.lsp.util._get_symbol_kind_name(26)")) + eq('File', exec_lua('return vim.lsp.util._get_symbol_kind_name(1)')) + eq('TypeParameter', exec_lua('return vim.lsp.util._get_symbol_kind_name(26)')) end) it('returns the name not specified by protocol', function() - eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(nil)")) - eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(vim.NIL)")) - eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(1000)")) + eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(nil)')) + eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(vim.NIL)')) + eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(1000)')) end) end) @@ -2748,20 +2984,20 @@ 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 }, + ['end'] = { line = end_line, character = end_char }, }, } end local jump = function(msg) - eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, "utf-16")) - eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]]) + eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, 'utf-16')) + eq(target_bufnr, exec_lua [[return vim.fn.bufnr('%')]]) return { - line = exec_lua[[return vim.fn.line('.')]], - col = exec_lua[[return vim.fn.col('.')]], + line = exec_lua [[return vim.fn.line('.')]], + col = exec_lua [[return vim.fn.col('.')]], } end @@ -2773,16 +3009,16 @@ describe('LSP', function() it('jumps to a LocationLink', function() local pos = jump({ - targetUri = "file:///fake/uri", - targetSelectionRange = { - start = { line = 0, character = 4 }, - ["end"] = { line = 0, character = 4 }, - }, - targetRange = { - start = { line = 1, character = 5 }, - ["end"] = { line = 1, character = 5 }, - }, - }) + targetUri = 'file:///fake/uri', + targetSelectionRange = { + start = { line = 0, character = 4 }, + ['end'] = { line = 0, character = 4 }, + }, + targetRange = { + start = { line = 1, character = 5 }, + ['end'] = { line = 1, character = 5 }, + }, + }) eq(1, pos.line) eq(5, pos.col) end) @@ -2791,18 +3027,18 @@ describe('LSP', function() local pos = jump(location(1, 2, 1, 2)) eq(2, pos.line) eq(4, pos.col) - eq('å', exec_lua[[return vim.fn.expand('<cword>')]]) + eq('å', exec_lua [[return vim.fn.expand('<cword>')]]) end) it('adds current position to jumplist before jumping', function() - funcs.nvim_win_set_buf(0, target_bufnr) - local mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + fn.nvim_win_set_buf(0, target_bufnr) + local mark = fn.nvim_buf_get_mark(target_bufnr, "'") eq({ 1, 0 }, mark) - funcs.nvim_win_set_cursor(0, { 2, 3 }) + fn.nvim_win_set_cursor(0, { 2, 3 }) jump(location(0, 9, 0, 9)) - mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + mark = fn.nvim_buf_get_mark(target_bufnr, "'") eq({ 2, 3 }, mark) end) end) @@ -2896,101 +3132,101 @@ describe('LSP', function() end) it('does not add current position to jumplist if not focus', function() - funcs.nvim_win_set_buf(0, target_bufnr) - local mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + fn.nvim_win_set_buf(0, target_bufnr) + local mark = fn.nvim_buf_get_mark(target_bufnr, "'") eq({ 1, 0 }, mark) - funcs.nvim_win_set_cursor(0, { 2, 3 }) + fn.nvim_win_set_cursor(0, { 2, 3 }) show_document(location(0, 9, 0, 9), false, true) show_document(location(0, 9, 0, 9, true), false, true) - mark = funcs.nvim_buf_get_mark(target_bufnr, "'") + mark = fn.nvim_buf_get_mark(target_bufnr, "'") eq({ 1, 0 }, mark) end) it('does not change cursor position if not focus and not reuse_win', function() - funcs.nvim_win_set_buf(0, target_bufnr) - local cursor = funcs.nvim_win_get_cursor(0) + fn.nvim_win_set_buf(0, target_bufnr) + local cursor = fn.nvim_win_get_cursor(0) show_document(location(0, 9, 0, 9), false, false) - eq(cursor, funcs.nvim_win_get_cursor(0)) + eq(cursor, fn.nvim_win_get_cursor(0)) end) it('does not change window if not focus', function() - funcs.nvim_win_set_buf(0, target_bufnr) - local win = funcs.nvim_get_current_win() + fn.nvim_win_set_buf(0, target_bufnr) + local win = fn.nvim_get_current_win() -- same document/bufnr show_document(location(0, 9, 0, 9), false, true) - eq(win, funcs.nvim_get_current_win()) + eq(win, fn.nvim_get_current_win()) -- different document/bufnr, new window/split show_document(location(0, 9, 0, 9, true), false, true) - eq(2, #funcs.nvim_list_wins()) - eq(win, funcs.nvim_get_current_win()) + eq(2, #fn.nvim_list_wins()) + eq(win, fn.nvim_get_current_win()) end) it("respects 'reuse_win' parameter", function() - funcs.nvim_win_set_buf(0, target_bufnr) + fn.nvim_win_set_buf(0, target_bufnr) -- does not create a new window if the buffer is already open show_document(location(0, 9, 0, 9), false, true) - eq(1, #funcs.nvim_list_wins()) + eq(1, #fn.nvim_list_wins()) -- creates a new window even if the buffer is already open show_document(location(0, 9, 0, 9), false, false) - eq(2, #funcs.nvim_list_wins()) + eq(2, #fn.nvim_list_wins()) end) it('correctly sets the cursor of the split if range is given without focus', function() - funcs.nvim_win_set_buf(0, target_bufnr) + fn.nvim_win_set_buf(0, target_bufnr) show_document(location(0, 9, 0, 9, true), false, true) - local wins = funcs.nvim_list_wins() + local wins = fn.nvim_list_wins() eq(2, #wins) table.sort(wins) - eq({ 1, 0 }, funcs.nvim_win_get_cursor(wins[1])) - eq({ 1, 9 }, funcs.nvim_win_get_cursor(wins[2])) + eq({ 1, 0 }, fn.nvim_win_get_cursor(wins[1])) + eq({ 1, 9 }, fn.nvim_win_get_cursor(wins[2])) end) it('does not change cursor of the split if not range and not focus', function() - funcs.nvim_win_set_buf(0, target_bufnr) - funcs.nvim_win_set_cursor(0, { 2, 3 }) + fn.nvim_win_set_buf(0, target_bufnr) + fn.nvim_win_set_cursor(0, { 2, 3 }) exec_lua([[vim.cmd.new()]]) - funcs.nvim_win_set_buf(0, target_bufnr2) - funcs.nvim_win_set_cursor(0, { 2, 3 }) + fn.nvim_win_set_buf(0, target_bufnr2) + fn.nvim_win_set_cursor(0, { 2, 3 }) show_document({ uri = 'file:///fake/uri2' }, false, true) - local wins = funcs.nvim_list_wins() + local wins = fn.nvim_list_wins() eq(2, #wins) - eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[1])) - eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[2])) + eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[1])) + eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[2])) end) it('respects existing buffers', function() - funcs.nvim_win_set_buf(0, target_bufnr) - local win = funcs.nvim_get_current_win() + fn.nvim_win_set_buf(0, target_bufnr) + local win = fn.nvim_get_current_win() exec_lua([[vim.cmd.new()]]) - funcs.nvim_win_set_buf(0, target_bufnr2) - funcs.nvim_win_set_cursor(0, { 2, 3 }) - local split = funcs.nvim_get_current_win() + fn.nvim_win_set_buf(0, target_bufnr2) + fn.nvim_win_set_cursor(0, { 2, 3 }) + local split = fn.nvim_get_current_win() -- reuse win for open document/bufnr if called from split show_document(location(0, 9, 0, 9, true), false, true) - eq({ 1, 9 }, funcs.nvim_win_get_cursor(split)) - eq(2, #funcs.nvim_list_wins()) + eq({ 1, 9 }, fn.nvim_win_get_cursor(split)) + eq(2, #fn.nvim_list_wins()) - funcs.nvim_set_current_win(win) + fn.nvim_set_current_win(win) -- reuse win for open document/bufnr if called outside the split show_document(location(0, 9, 0, 9, true), false, true) - eq({ 1, 9 }, funcs.nvim_win_get_cursor(split)) - eq(2, #funcs.nvim_list_wins()) + eq({ 1, 9 }, fn.nvim_win_get_cursor(split)) + eq(2, #fn.nvim_list_wins()) end) end) @@ -3004,11 +3240,14 @@ describe('LSP', function() end) it('calculates size correctly', function() - eq({19,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) + eq({ 19, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) end) it('calculates size correctly with wrapping', function() - eq({15,5}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]]) + eq( + { 15, 5 }, + exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]] + ) end) it('handles NUL bytes in text', function() @@ -3018,21 +3257,24 @@ describe('LSP', function() '\020\021\022\023\024\025\026\027\028\029', } ]]) command('set list listchars=') - eq({20,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) + eq({ 20, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) command('set display+=uhex') - eq({40,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) + eq({ 40, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]]) 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}) ]]) + eq( + { { 'foo', 'bar' } }, + exec_lua [[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]] + ) end) end) describe('lsp.util.convert_signature_help_to_markdown_lines', function() it('can handle negative activeSignature', function() - local result = exec_lua[[ + local result = exec_lua [[ local signature_help = { activeParameter = 0, activeSignature = -1, @@ -3046,22 +3288,29 @@ describe('LSP', function() } return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'cs', {','}) ]] - local expected = {'```cs', 'TestEntity.TestEntity()', '```', 'some doc'} + local expected = { '```cs', 'TestEntity.TestEntity()', '```', 'some doc' } eq(expected, result) end) end) describe('lsp.util.get_effective_tabstop', function() local function test_tabstop(tabsize, shiftwidth) - exec_lua(string.format([[ + exec_lua(string.format( + [[ vim.bo.shiftwidth = %d vim.bo.tabstop = 2 - ]], shiftwidth)) + ]], + shiftwidth + )) eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()')) end - it('with shiftwidth = 1', function() test_tabstop(1, 1) end) - it('with shiftwidth = 0', function() test_tabstop(2, 0) end) + it('with shiftwidth = 1', function() + test_tabstop(1, 1) + end) + it('with shiftwidth = 0', function() + test_tabstop(2, 0) + end) end) describe('vim.lsp.buf.outgoing_calls', function() @@ -3118,20 +3367,22 @@ describe('LSP', function() return vim.fn.getqflist() ]=]) - local expected = { { - bufnr = 2, - col = 5, - end_col = 0, - lnum = 4, - end_lnum = 0, - module = "", - nr = 0, - pattern = "", - text = "foo", - type = "", - valid = 1, - vcol = 0 - } } + local expected = { + { + bufnr = 2, + col = 5, + end_col = 0, + lnum = 4, + end_lnum = 0, + module = '', + nr = 0, + pattern = '', + text = 'foo', + type = '', + valid = 1, + vcol = 0, + }, + } eq(expected, qflist) end) @@ -3192,20 +3443,22 @@ describe('LSP', function() return vim.fn.getqflist() ]=]) - local expected = { { - bufnr = 2, - col = 5, - end_col = 0, - lnum = 4, - end_lnum = 0, - module = "", - nr = 0, - pattern = "", - text = "main", - type = "", - valid = 1, - vcol = 0 - } } + local expected = { + { + bufnr = 2, + col = 5, + end_col = 0, + lnum = 4, + end_lnum = 0, + module = '', + nr = 0, + pattern = '', + text = 'main', + type = '', + valid = 1, + vcol = 0, + }, + } eq(expected, qflist) end) @@ -3214,52 +3467,52 @@ describe('LSP', function() describe('vim.lsp.buf.rename', function() for _, test in ipairs({ { - it = "does not attempt to rename on nil response", - name = "prepare_rename_nil", + 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}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, }, }, { - it = "handles prepareRename placeholder response", - name = "prepare_rename_placeholder", + 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}}; + { 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 + expected_text = 'placeholder', -- see fake lsp response }, { - it = "handles range response", - name = "prepare_rename_range", + 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}}; + { 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 + expected_text = 'line', -- see test case and fake lsp response }, { - it = "handles error", - name = "prepare_rename_error", + it = 'handles error', + name = 'prepare_rename_error', expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, }, }, }) do - it(test.it, function() - local client - test_rpc_server { - test_name = test.name; - on_init = function(_client) - client = _client - eq(true, client.server_capabilities().renameProvider.prepareProvider) - end; - on_setup = function() - exec_lua([=[ + it(test.it, function() + local client + test_rpc_server { + test_name = test.name, + on_init = function(_client) + client = _client + eq(true, client.server_capabilities().renameProvider.prepareProvider) + 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 = {} @@ -3271,31 +3524,31 @@ describe('LSP', function() 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") - eq(0, signal, "exit signal") - end; - on_handler = function(err, result, ctx) - -- Don't compare & assert params and version, they're not relevant for the testcase - -- This allows us to be lazy and avoid declaring them - ctx.params = nil - ctx.version = 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, + on_exit = function(code, signal) + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, + on_handler = function(err, result, ctx) + -- Don't compare & assert params and version, they're not relevant for the testcase + -- This allows us to be lazy and avoid declaring them + ctx.params = nil + ctx.version = nil + + eq(table.remove(test.expected_handlers), { err, result, ctx }, 'expected handler') + if ctx.method == 'start' then + exec_lua('vim.lsp.buf.rename()') end - client.stop() - end - end; - } - 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) @@ -3303,22 +3556,21 @@ describe('LSP', 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}}; + { 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_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}) + eq(table.remove(expected_handlers), { err, result, ctx }) if ctx.method == 'start' then exec_lua([[ vim.lsp.commands['dummy1'] = function(cmd) @@ -3333,10 +3585,10 @@ describe('LSP', function() vim.lsp.buf.code_action() ]]) elseif ctx.method == 'shutdown' then - eq('function', exec_lua[[return type(vim.lsp.commands['dummy2'])]]) + eq('function', exec_lua [[return type(vim.lsp.commands['dummy2'])]]) client.stop() end - end + end, } end) it('Calls workspace/executeCommand if no client side command', function() @@ -3382,22 +3634,21 @@ describe('LSP', function() it('Filters and automatically applies action if requested', function() local client local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } test_rpc_server { test_name = 'code_action_filter', on_init = function(client_) client = client_ end, - on_setup = function() - end, + on_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}) + eq(table.remove(expected_handlers), { err, result, ctx }) if ctx.method == 'start' then exec_lua([[ vim.lsp.commands['preferred_command'] = function(cmd) @@ -3428,15 +3679,15 @@ describe('LSP', function() }) ]]) elseif ctx.method == 'shutdown' then - eq('function', exec_lua[[return type(vim.lsp.commands['executed_preferred'])]]) - eq('function', exec_lua[[return type(vim.lsp.commands['filtered_type_annotate_foo'])]]) - eq('function', exec_lua[[return type(vim.lsp.commands['executed_type_annotate'])]]) + eq('function', exec_lua [[return type(vim.lsp.commands['executed_preferred'])]]) + eq('function', exec_lua [[return type(vim.lsp.commands['filtered_type_annotate_foo'])]]) + eq('function', exec_lua [[return type(vim.lsp.commands['executed_type_annotate'])]]) client.stop() end - end + end, } end) - it("Fallback to command execution on resolve error", function() + it('Fallback to command execution on resolve error', function() clear() exec_lua(create_server_definition) local result = exec_lua([[ @@ -3476,9 +3727,9 @@ describe('LSP', function() vim.lsp.stop_client(client_id) return server.messages ]]) - eq("codeAction/resolve", result[4].method) - eq("workspace/executeCommand", result[5].method) - eq("command:1", result[5].params.command) + eq('codeAction/resolve', result[4].method) + eq('workspace/executeCommand', result[5].method) + eq('command:1', result[5].params.command) end) end) describe('vim.lsp.commands', function() @@ -3499,25 +3750,25 @@ describe('LSP', function() it('uses client commands', function() local client local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } test_rpc_server { test_name = 'clientside_commands', on_init = function(client_) client = client_ end, - on_setup = function() - end, + on_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}) + eq(table.remove(expected_handlers), { err, result, ctx }) if ctx.method == 'start' then - local fake_uri = "file:///fake/uri" - local cmd = exec_lua([[ + local fake_uri = 'file:///fake/uri' + local cmd = exec_lua( + [[ fake_uri = ... local bufnr = vim.uri_to_bufnr(fake_uri) vim.fn.bufload(bufnr) @@ -3539,20 +3790,22 @@ describe('LSP', function() vim.api.nvim_set_current_buf(bufnr) vim.lsp.codelens.run() return cmd_called - ]], fake_uri) - eq({ command = 'Dummy', title = 'Lens1' }, cmd) - elseif ctx.method == 'shutdown' then - client.stop() + ]], + fake_uri + ) + eq({ command = 'Dummy', title = 'Lens1' }, cmd) + elseif ctx.method == 'shutdown' then + client.stop() end - end + end, } end) it('releases buffer refresh lock', function() local client local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } test_rpc_server { test_name = 'codelens_refresh_lock', @@ -3576,11 +3829,11 @@ describe('LSP', function() ]=]) end, on_exit = function(code, signal) - eq(0, code, "exit code") - eq(0, signal, "exit signal") + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') end, on_handler = function(err, result, ctx) - eq(table.remove(expected_handlers), {err, result, ctx}) + eq(table.remove(expected_handlers), { err, result, ctx }) if ctx.method == 'start' then -- 1. first codelens request errors local response = exec_lua([=[ @@ -3589,7 +3842,7 @@ describe('LSP', function() vim.wait(100, function () return CALLED end) return RESPONSE ]=]) - eq( { err = { code = -32002, message = "ServerNotInitialized" } }, response) + eq({ err = { code = -32002, message = 'ServerNotInitialized' } }, response) -- 2. second codelens request runs response = exec_lua([=[ @@ -3604,7 +3857,7 @@ describe('LSP', function() vim.wait(100, function () return cmd_called end) return cmd_called ]=]) - eq( { command = "Dummy", title = "Lens1" }, response) + eq({ command = 'Dummy', title = 'Lens1' }, response) -- 3. third codelens request runs response = exec_lua([=[ @@ -3619,20 +3872,20 @@ describe('LSP', function() vim.wait(100, function () return cmd_called end) return cmd_called ]=]) - eq( { command = "Dummy", title = "Lens2" }, response) - elseif ctx.method == 'shutdown' then - client.stop() + eq({ command = 'Dummy', title = 'Lens2' }, response) + elseif ctx.method == 'shutdown' then + client.stop() end - end + end, } end) end) - describe("vim.lsp.buf.format", function() - it("Aborts with notify if no client matches filter", function() + describe('vim.lsp.buf.format', function() + it('Aborts with notify if no client matches filter', function() local client test_rpc_server { - test_name = "basic_init", + test_name = 'basic_init', on_init = function(c) client = c end, @@ -3649,25 +3902,25 @@ describe('LSP', function() vim.notify = notify return notify_msg ]]) - eq("[LSP] Format request failed, no matching language servers.", notify_msg) + eq('[LSP] Format request failed, no matching language servers.', notify_msg) client.stop() end, } end) - it("Sends textDocument/formatting request to format buffer", function() + it('Sends textDocument/formatting request to format buffer', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_formatting", + test_name = 'basic_formatting', on_init = function(c) client = c end, on_handler = function(_, _, ctx) table.remove(expected_handlers) - if ctx.method == "start" then + if ctx.method == 'start' then local notify_msg = exec_lua([[ local bufnr = vim.api.nvim_get_current_buf() vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID) @@ -3681,7 +3934,7 @@ describe('LSP', function() return notify_msg ]]) eq(NIL, notify_msg) - elseif ctx.method == "shutdown" then + elseif ctx.method == 'shutdown' then client.stop() end end, @@ -3689,18 +3942,18 @@ describe('LSP', function() end) it('Can format async', function() local expected_handlers = { - {NIL, {}, {method="shutdown", client_id=1}}; - {NIL, {}, {method="start", client_id=1}}; + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, } local client test_rpc_server { - test_name = "basic_formatting", + test_name = 'basic_formatting', on_init = function(c) client = c end, on_handler = function(_, _, ctx) table.remove(expected_handlers) - if ctx.method == "start" then + if ctx.method == 'start' then local result = exec_lua([[ local bufnr = vim.api.nvim_get_current_buf() vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID) @@ -3724,8 +3977,8 @@ describe('LSP', function() vim.lsp.handlers['textDocument/formatting'] = handler return {notify = notify_msg, handler_called = handler_called} ]]) - eq({handler_called=true}, result) - elseif ctx.method == "shutdown" then + eq({ handler_called = true }, result) + elseif ctx.method == 'shutdown' then client.stop() end end, @@ -3749,7 +4002,7 @@ describe('LSP', function() vim.lsp.stop_client(client_id) return server.messages ]]) - eq("textDocument/rangeFormatting", result[3].method) + eq('textDocument/rangeFormatting', result[3].method) local expected_range = { start = { line = 0, character = 0 }, ['end'] = { line = 1, character = 4 }, @@ -3784,16 +4037,21 @@ describe('LSP', function() return server.messages ]]) local expected_methods = { - "initialize", - "initialized", - "textDocument/rangeFormatting", - "$/cancelRequest", - "textDocument/rangeFormatting", - "$/cancelRequest", - "shutdown", - "exit", + 'initialize', + 'initialized', + 'textDocument/rangeFormatting', + '$/cancelRequest', + 'textDocument/rangeFormatting', + '$/cancelRequest', + 'shutdown', + 'exit', } - eq(expected_methods, vim.tbl_map(function(x) return x.method end, result)) + eq( + expected_methods, + vim.tbl_map(function(x) + return x.method + end, result) + ) -- uses first column of start line and last column of end line local expected_range = { start = { line = 0, character = 0 }, @@ -3809,10 +4067,11 @@ describe('LSP', function() notify_msg = msg end ]]) - local fail_msg = "[LSP] Format request failed, no matching language servers." + local fail_msg = '[LSP] Format request failed, no matching language servers.' local function check_notify(name, formatting, range_formatting) - local timeout_msg = "[LSP][" .. name .. "] timeout" - exec_lua([[ + local timeout_msg = '[LSP][' .. name .. '] timeout' + exec_lua( + [[ local formatting, range_formatting, name = ... local server = _create_server({ capabilities = { documentFormattingProvider = formatting, @@ -3821,7 +4080,11 @@ describe('LSP', function() vim.lsp.start({ name = name, cmd = server.cmd }) notify_msg = nil vim.lsp.buf.format({ name = name, timeout_ms = 1 }) - ]], formatting, range_formatting, name) + ]], + formatting, + range_formatting, + name + ) eq(formatting and timeout_msg or fail_msg, exec_lua('return notify_msg')) exec_lua([[ notify_msg = nil @@ -3829,12 +4092,111 @@ describe('LSP', function() ]]) eq(range_formatting and timeout_msg or fail_msg, exec_lua('return notify_msg')) end - check_notify("none", false, false) - check_notify("formatting", true, false) - check_notify("rangeFormatting", false, true) - check_notify("both", true, true) + check_notify('none', false, false) + check_notify('formatting', true, false) + check_notify('rangeFormatting', false, true) + check_notify('both', true, true) + end) + end) + + describe('vim.lsp.tagfunc', function() + before_each(function() + clear() + ---@type lsp.Location[] + local mock_locations = { + { + range = { + ['start'] = { line = 5, character = 23 }, + ['end'] = { line = 10, character = 0 }, + }, + uri = 'test://buf', + }, + { + range = { + ['start'] = { line = 42, character = 10 }, + ['end'] = { line = 44, character = 0 }, + }, + uri = 'test://another-file', + }, + } + exec_lua(create_server_definition) + exec_lua( + [[ + _G.mock_locations = ... + _G.server = _create_server({ + ---@type lsp.ServerCapabilities + capabilities = { + definitionProvider = true, + workspaceSymbolProvider = true, + }, + handlers = { + ---@return lsp.Location[] + ['textDocument/definition'] = function() + return { _G.mock_locations[1] } + end, + ---@return lsp.WorkspaceSymbol[] + ['workspace/symbol'] = function(_, request) + assert(request.query == 'foobar') + return { + { + name = 'foobar', + kind = 13, ---@type lsp.SymbolKind + location = _G.mock_locations[1], + }, + { + name = 'vim.foobar', + kind = 12, ---@type lsp.SymbolKind + location = _G.mock_locations[2], + } + } + end, + }, + }) + _G.client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + ]], + mock_locations + ) + end) + after_each(function() + exec_lua [[ + vim.lsp.stop_client(_G.client_id) + ]] + end) + + it('with flags=c, returns matching tags using textDocument/definition', function() + local result = exec_lua [[ + return vim.lsp.tagfunc('foobar', 'c') + ]] + eq({ + { + cmd = '/\\%6l\\%1c/', -- for location (5, 23) + filename = 'test://buf', + name = 'foobar', + }, + }, result) + end) + + it('without flags=c, returns all matching tags using workspace/symbol', function() + local result = exec_lua [[ + return vim.lsp.tagfunc('foobar', '') + ]] + eq({ + { + cmd = '/\\%6l\\%1c/', -- for location (5, 23) + filename = 'test://buf', + kind = 'Variable', + name = 'foobar', + }, + { + cmd = '/\\%43l\\%1c/', -- for location (42, 10) + filename = 'test://another-file', + kind = 'Function', + name = 'vim.foobar', + }, + }, result) end) end) + describe('cmd', function() it('can connect to lsp server via rpc.connect', function() local result = exec_lua [[ @@ -3859,7 +4221,43 @@ describe('LSP', function() server:shutdown() return vim.json.decode(init) ]] - eq(result.method, "initialize") + eq(result.method, 'initialize') + end) + it('can connect to lsp server via rpc.domain_socket_connect', function() + local tmpfile + if is_os('win') then + tmpfile = '\\\\.\\\\pipe\\pipe.test' + else + tmpfile = tmpname() + os.remove(tmpfile) + end + local result = exec_lua( + [[ + local SOCK = ... + local uv = vim.uv + local server = uv.new_pipe(false) + server:bind(SOCK) + local init = nil + + server:listen(127, function(err) + assert(not err, err) + local client = uv.new_pipe() + server:accept(client) + client:read_start(require("vim.lsp.rpc").create_read_loop(function(body) + init = body + client:close() + end)) + end) + vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) }) + vim.wait(1000, function() return init ~= nil end) + assert(init, "server must receive `initialize` request") + server:close() + server:shutdown() + return vim.json.decode(init) + ]], + tmpfile + ) + eq(result.method, 'initialize') end) end) @@ -3926,9 +4324,9 @@ describe('LSP', function() { id = 10, jsonrpc = '2.0', - result = false - } - } + result = false, + }, + }, } eq(expected, result) end) @@ -3936,15 +4334,19 @@ describe('LSP', function() describe('#dynamic vim.lsp._dynamic', function() it('supports dynamic registration', function() - local root_dir = helpers.tmpname() + ---@type string + local root_dir = tmpname() os.remove(root_dir) mkdir(root_dir) local tmpfile = root_dir .. '/dynamic.foo' local file = io.open(tmpfile, 'w') - file:close() + if file then + file:close() + end exec_lua(create_server_definition) - local result = exec_lua([[ + local result = exec_lua( + [[ local root_dir, tmpfile = ... local server = _create_server() @@ -3952,6 +4354,9 @@ describe('LSP', function() name = 'dynamic-test', cmd = server.cmd, root_dir = root_dir, + get_language_id = function() + return "dummy-lang" + end, capabilities = { textDocument = { formatting = { @@ -3985,6 +4390,13 @@ describe('LSP', function() { id = 'range-formatting', method = 'textDocument/rangeFormatting', + registerOptions = { + documentSelector = { + { + language = "dummy-lang" + }, + } + } }, }, }, { client_id = client_id }) @@ -4002,7 +4414,11 @@ describe('LSP', function() local function check(method, fname) local bufnr = fname and vim.fn.bufadd(fname) or nil local client = vim.lsp.get_client_by_id(client_id) - result[#result + 1] = {method = method, fname = fname, supported = client.supports_method(method, {bufnr = bufnr})} + result[#result + 1] = { + method = method, + fname = fname, + supported = client.supports_method(method, {bufnr = bufnr}) + } end @@ -4013,120 +4429,161 @@ describe('LSP', function() check("textDocument/completion") return result - ]], root_dir, tmpfile) + ]], + root_dir, + tmpfile + ) eq(5, #result) - eq({method = 'textDocument/formatting', supported = false}, result[1]) - eq({method = 'textDocument/formatting', supported = true, fname = tmpfile}, result[2]) - eq({method = 'textDocument/rangeFormatting', supported = true}, result[3]) - eq({method = 'textDocument/rangeFormatting', supported = true, fname = tmpfile}, result[4]) - eq({method = 'textDocument/completion', supported = false}, result[5]) + eq({ method = 'textDocument/formatting', supported = false }, result[1]) + eq({ method = 'textDocument/formatting', supported = true, fname = tmpfile }, result[2]) + eq({ method = 'textDocument/rangeFormatting', supported = true }, result[3]) + eq({ method = 'textDocument/rangeFormatting', supported = true, fname = tmpfile }, result[4]) + eq({ method = 'textDocument/completion', supported = false }, result[5]) end) end) describe('vim.lsp._watchfiles', function() - it('sends notifications when files change', function() - skip(is_os('bsd'), "bsd only reports rename on folders if file inside change") - local root_dir = helpers.tmpname() - os.remove(root_dir) - mkdir(root_dir) + local function test_filechanges(watchfunc) + it( + string.format('sends notifications when files change (watchfunc=%s)', watchfunc), + function() + if watchfunc == 'fswatch' then + skip( + not is_ci() and fn.executable('fswatch') == 0, + 'fswatch not installed and not on CI' + ) + skip(is_os('win'), 'not supported on windows') + skip(is_os('mac'), 'flaky') + end - exec_lua(create_server_definition) - local result = exec_lua([[ - local root_dir = ... + skip( + is_os('bsd'), + 'kqueue only reports events on watched folder itself, not contained files #26110' + ) - local server = _create_server() - local client_id = vim.lsp.start({ - name = 'watchfiles-test', - cmd = server.cmd, - root_dir = root_dir, - capabilities = { - workspace = { - didChangeWatchedFiles = { - dynamicRegistration = true, + local root_dir = tmpname() + os.remove(root_dir) + mkdir(root_dir) + + exec_lua(create_server_definition) + local result = exec_lua( + [[ + local root_dir, watchfunc = ... + + local server = _create_server() + local client_id = vim.lsp.start({ + name = 'watchfiles-test', + cmd = server.cmd, + root_dir = root_dir, + capabilities = { + workspace = { + didChangeWatchedFiles = { + dynamicRegistration = true, + }, }, }, - }, - }) + }) - local expected_messages = 2 -- initialize, initialized + require('vim.lsp._watchfiles')._watchfunc = require('vim._watch')[watchfunc] - local watchfunc = require('vim.lsp._watchfiles')._watchfunc - local msg_wait_timeout = watchfunc == vim._watch.poll and 2500 or 200 - local function wait_for_messages() - assert(vim.wait(msg_wait_timeout, function() return #server.messages == expected_messages end), 'Timed out waiting for expected number of messages. Current messages seen so far: ' .. vim.inspect(server.messages)) - end + local expected_messages = 0 - wait_for_messages() + local msg_wait_timeout = watchfunc == 'watch' and 200 or 2500 - vim.lsp.handlers['client/registerCapability'](nil, { - registrations = { - { - id = 'watchfiles-test-0', - method = 'workspace/didChangeWatchedFiles', - registerOptions = { - watchers = { - { - globPattern = '**/watch', - kind = 7, + local function wait_for_message(incr) + expected_messages = expected_messages + (incr or 1) + assert( + vim.wait(msg_wait_timeout, function() + return #server.messages == expected_messages + end), + 'Timed out waiting for expected number of messages. Current messages seen so far: ' + .. vim.inspect(server.messages) + ) + end + + wait_for_message(2) -- initialize, initialized + + vim.lsp.handlers['client/registerCapability'](nil, { + registrations = { + { + id = 'watchfiles-test-0', + method = 'workspace/didChangeWatchedFiles', + registerOptions = { + watchers = { + { + globPattern = '**/watch', + kind = 7, + }, }, }, }, }, - }, - }, { client_id = client_id }) + }, { client_id = client_id }) - if watchfunc == vim._watch.poll then - vim.wait(100) - end + if watchfunc ~= 'watch' then + vim.wait(100) + end - local path = root_dir .. '/watch' - local file = io.open(path, 'w') - file:close() + local path = root_dir .. '/watch' + local tmp = vim.fn.tempname() + io.open(tmp, 'w'):close() + vim.uv.fs_rename(tmp, path) - expected_messages = expected_messages + 1 - wait_for_messages() + wait_for_message() - os.remove(path) + os.remove(path) - expected_messages = expected_messages + 1 - wait_for_messages() + wait_for_message() - return server.messages - ]], root_dir) + vim.lsp.stop_client(client_id) - local function watched_uri(fname) - return exec_lua([[ - local root_dir, fname = ... - return vim.uri_from_fname(root_dir .. '/' .. fname) - ]], root_dir, fname) - end + return server.messages + ]], + root_dir, + watchfunc + ) - eq(4, #result) - eq('workspace/didChangeWatchedFiles', result[3].method) - eq({ - changes = { - { - type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]), - uri = watched_uri('watch'), - }, - }, - }, result[3].params) - eq('workspace/didChangeWatchedFiles', result[4].method) - eq({ - changes = { - { - type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]), - uri = watched_uri('watch'), - }, - }, - }, result[4].params) - end) + local uri = vim.uri_from_fname(root_dir .. '/watch') + + eq(6, #result) + + eq({ + method = 'workspace/didChangeWatchedFiles', + params = { + changes = { + { + type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]), + uri = uri, + }, + }, + }, + }, result[3]) + + eq({ + method = 'workspace/didChangeWatchedFiles', + params = { + changes = { + { + type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]), + uri = uri, + }, + }, + }, + }, result[4]) + end + ) + end + + test_filechanges('watch') + test_filechanges('watchdirs') + test_filechanges('fswatch') it('correctly registers and unregisters', function() local root_dir = '/some_dir' exec_lua(create_server_definition) - local result = exec_lua([[ + local result = exec_lua( + [[ local root_dir = ... local server = _create_server() @@ -4217,13 +4674,19 @@ describe('LSP', function() wait_for_messages() return server.messages - ]], root_dir) + ]], + root_dir + ) local function watched_uri(fname) - return exec_lua([[ + return exec_lua( + [[ local root_dir, fname = ... return vim.uri_from_fname(root_dir .. '/' .. fname) - ]], root_dir, fname) + ]], + root_dir, + fname + ) end eq(4, #result) @@ -4250,7 +4713,8 @@ describe('LSP', function() it('correctly handles the registered watch kind', function() local root_dir = 'some_dir' exec_lua(create_server_definition) - local result = exec_lua([[ + local result = exec_lua( + [[ local root_dir = ... local server = _create_server() @@ -4323,13 +4787,18 @@ describe('LSP', function() wait_for_messages() return server.messages - ]], root_dir) + ]], + root_dir + ) local function watched_uri(fname) - return exec_lua([[ + return exec_lua( + [[ local fname = ... return vim.uri_from_fname('/dir/' .. fname) - ]], fname) + ]], + fname + ) end eq(3, #result) @@ -4391,7 +4860,8 @@ describe('LSP', function() it('prunes duplicate events', function() local root_dir = 'some_dir' exec_lua(create_server_definition) - local result = exec_lua([[ + local result = exec_lua( + [[ local root_dir = ... local server = _create_server() @@ -4449,12 +4919,17 @@ describe('LSP', function() wait_for_messages() return server.messages - ]], root_dir) + ]], + root_dir + ) local function watched_uri(fname) - return exec_lua([[ + return exec_lua( + [[ return vim.uri_from_fname(...) - ]], fname) + ]], + fname + ) end eq(3, #result) @@ -4489,7 +4964,8 @@ describe('LSP', function() ]]) local function check_registered(capabilities) - return exec_lua([[ + return exec_lua( + [[ watching = false local client_id = vim.lsp.start({ name = 'watchfiles-test', @@ -4528,31 +5004,41 @@ describe('LSP', function() vim.lsp.stop_client(client_id, true) return watching - ]], capabilities) + ]], + capabilities + ) end - eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities(). + eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities(). eq(false, check_registered(vim.empty_dict())) - eq(false, check_registered({ + eq( + false, + check_registered({ workspace = { ignoreMe = true, }, - })) - eq(false, check_registered({ + }) + ) + eq( + false, + check_registered({ workspace = { didChangeWatchedFiles = { dynamicRegistration = false, }, }, - })) - eq(true, check_registered({ + }) + ) + eq( + true, + check_registered({ workspace = { didChangeWatchedFiles = { dynamicRegistration = true, }, }, - })) + }) + ) end) end) end) - diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua index 815ddbc523..5bfa566729 100644 --- a/test/functional/plugin/man_spec.lua +++ b/test/functional/plugin/man_spec.lua @@ -3,13 +3,13 @@ local Screen = require('test.functional.ui.screen') local command, rawfeed = helpers.command, helpers.rawfeed local clear = helpers.clear local exec_lua = helpers.exec_lua -local funcs = helpers.funcs +local fn = helpers.fn local nvim_prog = helpers.nvim_prog local matches = helpers.matches local write_file = helpers.write_file local tmpname = helpers.tmpname local eq = helpers.eq -local pesc = helpers.pesc +local pesc = vim.pesc local skip = helpers.skip local is_ci = helpers.is_ci @@ -33,7 +33,7 @@ local function get_search_history(name) end clear() -if funcs.executable('man') == 0 then +if fn.executable('man') == 0 then pending('missing "man" command', function() end) return end @@ -49,7 +49,7 @@ describe(':Man', function() before_each(function() command('syntax on') command('set filetype=man') - command('syntax off') -- Ignore syntax groups + command('syntax off') -- Ignore syntax groups screen = Screen.new(52, 5) screen:set_default_attr_ids({ b = { bold = true }, @@ -58,80 +58,87 @@ describe(':Man', function() bi = { bold = true, italic = true }, biu = { bold = true, italic = true, underline = true }, c = { foreground = Screen.colors.Blue }, -- control chars - eob = { bold = true, foreground = Screen.colors.Blue } -- empty line '~'s + eob = { bold = true, foreground = Screen.colors.Blue }, -- empty line '~'s }) screen:attach() end) it('clears backspaces from text and adds highlights', function() - rawfeed([[ + rawfeed( + [[ ithis i<C-v><C-h>is<C-v><C-h>s a<C-v><C-h>a test - with _<C-v><C-h>o_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>c_<C-v><C-h>k text<ESC>]]) + with _<C-v><C-h>o_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>c_<C-v><C-h>k text<ESC>]] + ) - screen:expect{grid=[[ + screen:expect { + grid = [[ this i{c:^H}is{c:^H}s a{c:^H}a test | with _{c:^H}o_{c:^H}v_{c:^H}e_{c:^H}r_{c:^H}s_{c:^H}t_{c:^H}r_{c:^H}u_{c:^H}c_{c:^H}k tex^t | - {eob:~ }| - {eob:~ }| + {eob:~ }|*2 | - ]]} + ]], + } - exec_lua[[require'man'.init_pager()]] + exec_lua [[require'man'.init_pager()]] screen:expect([[ ^this {b:is} {b:a} test | with {i:overstruck} text | - {eob:~ }| - {eob:~ }| + {eob:~ }|*2 | ]]) end) it('clears escape sequences from text and adds highlights', function() - rawfeed([[ + rawfeed( + [[ ithis <C-v><ESC>[1mis <C-v><ESC>[3ma <C-v><ESC>[4mtest<C-v><ESC>[0m - <C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]]) + <C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]] + ) - screen:expect{grid=[=[ + screen:expect { + grid = [=[ this {c:^[}[1mis {c:^[}[3ma {c:^[}[4mtest{c:^[}[0m | {c:^[}[4mwith{c:^[}[24m {c:^[}[4mescaped{c:^[}[24m {c:^[}[4mtext{c:^[}[24^m | - {eob:~ }| - {eob:~ }| + {eob:~ }|*2 | - ]=]} + ]=], + } - exec_lua[[require'man'.init_pager()]] + exec_lua [[require'man'.init_pager()]] screen:expect([[ ^this {b:is }{bi:a }{biu:test} | {u:with} {u:escaped} {u:text} | - {eob:~ }| - {eob:~ }| + {eob:~ }|*2 | ]]) end) it('highlights multibyte text', function() - rawfeed([[ + rawfeed( + [[ ithis i<C-v><C-h>is<C-v><C-h>s あ<C-v><C-h>あ test - with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]]) - exec_lua[[require'man'.init_pager()]] + with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]] + ) + exec_lua [[require'man'.init_pager()]] screen:expect([[ ^this {b:is} {b:あ} test | with {i:överstrũck} te{i:xt¶} | - {eob:~ }| - {eob:~ }| + {eob:~ }|*2 | ]]) end) it('highlights underscores based on context', function() - rawfeed([[ + rawfeed( + [[ i_<C-v><C-h>_b<C-v><C-h>be<C-v><C-h>eg<C-v><C-h>gi<C-v><C-h>in<C-v><C-h>ns<C-v><C-h>s m<C-v><C-h>mi<C-v><C-h>id<C-v><C-h>d_<C-v><C-h>_d<C-v><C-h>dl<C-v><C-h>le<C-v><C-h>e - _<C-v><C-h>m_<C-v><C-h>i_<C-v><C-h>d_<C-v><C-h>__<C-v><C-h>d_<C-v><C-h>l_<C-v><C-h>e<ESC>]]) - exec_lua[[require'man'.init_pager()]] + _<C-v><C-h>m_<C-v><C-h>i_<C-v><C-h>d_<C-v><C-h>__<C-v><C-h>d_<C-v><C-h>l_<C-v><C-h>e<ESC>]] + ) + exec_lua [[require'man'.init_pager()]] screen:expect([[ {b:^_begins} | @@ -147,7 +154,7 @@ describe(':Man', function() i· ·<C-v><C-h>· +<C-v><C-h>o +<C-v><C-h>+<C-v><C-h>o<C-v><C-h>o double<ESC>]]) - exec_lua[[require'man'.init_pager()]] + exec_lua [[require'man'.init_pager()]] screen:expect([[ ^· {b:·} | @@ -164,7 +171,7 @@ describe(':Man', function() <C-v><C-[>[44m 4 <C-v><C-[>[45m 5 <C-v><C-[>[46m 6 <C-v><C-[>[47m 7 <C-v><C-[>[100m 8 <C-v><C-[>[101m 9 <C-v><C-[>[102m 10 <C-v><C-[>[103m 11 <C-v><C-[>[104m 12 <C-v><C-[>[105m 13 <C-v><C-[>[106m 14 <C-v><C-[>[107m 15 <C-v><C-[>[48:5:16m 16 <ESC>]]) - exec_lua[[require'man'.init_pager()]] + exec_lua [[require'man'.init_pager()]] screen:expect([[ ^ 0 1 2 3 | @@ -178,8 +185,14 @@ describe(':Man', function() it('q quits in "$MANPAGER mode" (:Man!) #18281', function() -- This will hang if #18281 regresses. - local args = {nvim_prog, '--headless', '+autocmd VimLeave * echo "quit works!!"', '+Man!', '+call nvim_input("q")'} - matches('quit works!!', funcs.system(args, {'manpage contents'})) + local args = { + nvim_prog, + '--headless', + '+autocmd VimLeave * echo "quit works!!"', + '+Man!', + '+call nvim_input("q")', + } + matches('quit works!!', fn.system(args, { 'manpage contents' })) end) it('reports non-existent man pages for absolute paths', function() @@ -188,41 +201,44 @@ describe(':Man', function() -- actual_file must be an absolute path to an existent file for us to test against it matches('^/.+', actual_file) write_file(actual_file, '') - local args = {nvim_prog, '--headless', '+:Man ' .. actual_file, '+q'} - matches(('Error detected while processing command line:\r\n' .. - 'man.lua: "no manual entry for %s"'):format(pesc(actual_file)), - funcs.system(args, {''})) + local args = { nvim_prog, '--headless', '+:Man ' .. actual_file, '+q' } + matches( + ('Error detected while processing command line:\r\n' .. 'man.lua: "no manual entry for %s"'):format( + pesc(actual_file) + ), + fn.system(args, { '' }) + ) os.remove(actual_file) end) it('tries variants with spaces, underscores #22503', function() eq({ - {'', 'NAME WITH SPACES'}, - {'', 'NAME_WITH_SPACES'}, - }, get_search_history('NAME WITH SPACES')) + { '', 'NAME WITH SPACES' }, + { '', 'NAME_WITH_SPACES' }, + }, get_search_history('NAME WITH SPACES')) eq({ - {'3', 'some other man'}, - {'3', 'some_other_man'}, - }, get_search_history('3 some other man')) + { '3', 'some other man' }, + { '3', 'some_other_man' }, + }, get_search_history('3 some other man')) eq({ - {'3x', 'some other man'}, - {'3x', 'some_other_man'}, - }, get_search_history('3X some other man')) + { '3x', 'some other man' }, + { '3x', 'some_other_man' }, + }, get_search_history('3X some other man')) eq({ - {'3tcl', 'some other man'}, - {'3tcl', 'some_other_man'}, - }, get_search_history('3tcl some other man')) + { '3tcl', 'some other man' }, + { '3tcl', 'some_other_man' }, + }, get_search_history('3tcl some other man')) eq({ - {'n', 'some other man'}, - {'n', 'some_other_man'}, - }, get_search_history('n some other man')) + { 'n', 'some other man' }, + { 'n', 'some_other_man' }, + }, get_search_history('n some other man')) eq({ - {'', '123some other man'}, - {'', '123some_other_man'}, - }, get_search_history('123some other man')) + { '', '123some other man' }, + { '', '123some_other_man' }, + }, get_search_history('123some other man')) eq({ - {'1', 'other_man'}, - {'1', 'other_man'}, - }, get_search_history('other_man(1)')) + { '1', 'other_man' }, + { '1', 'other_man' }, + }, get_search_history('other_man(1)')) end) end) diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua index 2670734c1a..530afd16e4 100644 --- a/test/functional/plugin/matchparen_spec.lua +++ b/test/functional/plugin/matchparen_spec.lua @@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command -local meths = helpers.meths +local api = helpers.api local feed = helpers.feed local eq = helpers.eq @@ -11,18 +11,18 @@ describe('matchparen', function() local screen before_each(function() - clear{args={'-u', 'NORC'}} - screen = Screen.new(20,5) + clear { args = { '-u', 'NORC' } } + screen = Screen.new(20, 5) screen:attach() - screen:set_default_attr_ids( { - [0] = {bold=true, foreground=255}, - [1] = {bold=true}, - } ) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = 255 }, + [1] = { bold = true }, + }) end) it('uses correct column after i_<Up>. Vim patch 7.4.1296', function() command('set noautoindent nosmartindent nocindent laststatus=0') - eq(1, meths.get_var('loaded_matchparen')) + eq(1, api.nvim_get_var('loaded_matchparen')) feed('ivoid f_test()<cr>') feed('{<cr>') feed('}') @@ -39,6 +39,5 @@ describe('matchparen', function() } | {1:-- INSERT --} | ]]) - end) end) diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index d841cb8ce0..8511e6c703 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -1,14 +1,16 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local meths = helpers.meths -local eq, nvim_eval, nvim_command, exc_exec = - helpers.eq, helpers.eval, helpers.command, helpers.exc_exec +local api = helpers.api +local eq = helpers.eq +local nvim_eval = helpers.eval +local nvim_command = helpers.command +local exc_exec = helpers.exc_exec local ok = helpers.ok -local NIL = helpers.NIL +local NIL = vim.NIL describe('autoload/msgpack.vim', function() before_each(function() - clear{args={'-u', 'NORC'}} + clear { args = { '-u', 'NORC' } } end) local sp = function(typ, val) @@ -16,16 +18,15 @@ describe('autoload/msgpack.vim', function() end local mapsp = function(...) local val = '' - for i=1,(select('#', ...)/2) do - val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), - select(i * 2, ...)) + for i = 1, (select('#', ...) / 2) do + val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), select(i * 2, ...)) end return sp('map', '[' .. val .. ']') end - local nan = -(1.0/0.0-1.0/0.0) - local inf = 1.0/0.0 - local minus_inf = -(1.0/0.0) + local nan = -(1.0 / 0.0 - 1.0 / 0.0) + local inf = 1.0 / 0.0 + local minus_inf = -(1.0 / 0.0) describe('function msgpack#equal', function() local msgpack_eq = function(expected, a, b) @@ -39,10 +40,8 @@ describe('autoload/msgpack.vim', function() msgpack_eq(0, '1', '0') end) it('compares integer specials correctly', function() - msgpack_eq(1, sp('integer', '[-1, 1, 0, 0]'), - sp('integer', '[-1, 1, 0, 0]')) - msgpack_eq(0, sp('integer', '[-1, 1, 0, 0]'), - sp('integer', '[ 1, 1, 0, 0]')) + msgpack_eq(1, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[-1, 1, 0, 0]')) + msgpack_eq(0, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[ 1, 1, 0, 0]')) end) it('compares integer specials with raw integer correctly', function() msgpack_eq(1, sp('integer', '[-1, 0, 0, 1]'), '-1') @@ -58,27 +57,21 @@ describe('autoload/msgpack.vim', function() msgpack_eq(0, '"abc\\ndef"', '"abc\\nghi"') end) it('compares binary specials correctly', function() - msgpack_eq(1, sp('binary', '["abc\\n", "def"]'), - sp('binary', '["abc\\n", "def"]')) - msgpack_eq(0, sp('binary', '["abc", "def"]'), - sp('binary', '["abc\\n", "def"]')) + msgpack_eq(1, sp('binary', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]')) + msgpack_eq(0, sp('binary', '["abc", "def"]'), sp('binary', '["abc\\n", "def"]')) end) it('compares binary specials with raw binaries correctly', function() msgpack_eq(1, sp('binary', '["abc", "def"]'), '"abc\\ndef"') msgpack_eq(0, sp('binary', '["abc", "def"]'), '"abcdef"') end) it('compares string specials correctly', function() - msgpack_eq(1, sp('string', '["abc\\n", "def"]'), - sp('string', '["abc\\n", "def"]')) - msgpack_eq(0, sp('string', '["abc", "def"]'), - sp('string', '["abc\\n", "def"]')) + msgpack_eq(1, sp('string', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]')) + msgpack_eq(0, sp('string', '["abc", "def"]'), sp('string', '["abc\\n", "def"]')) end) it('compares string specials with binary correctly', function() - msgpack_eq(0, sp('string', '["abc\\n", "def"]'), - sp('binary', '["abc\\n", "def"]')) + msgpack_eq(0, sp('string', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]')) msgpack_eq(0, sp('string', '["abc", "def"]'), '"abc\\ndef"') - msgpack_eq(0, sp('binary', '["abc\\n", "def"]'), - sp('string', '["abc\\n", "def"]')) + msgpack_eq(0, sp('binary', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]')) msgpack_eq(0, '"abc\\ndef"', sp('string', '["abc", "def"]')) end) it('compares ext specials correctly', function() @@ -97,44 +90,54 @@ describe('autoload/msgpack.vim', function() end) it('compares map specials correctly', function() msgpack_eq(1, mapsp(), mapsp()) - msgpack_eq(1, mapsp(sp('binary', '[""]'), '""'), - mapsp(sp('binary', '[""]'), '""')) - msgpack_eq(1, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('1', '1'), mapsp('1', '1'))) + msgpack_eq(1, mapsp(sp('binary', '[""]'), '""'), mapsp(sp('binary', '[""]'), '""')) + msgpack_eq( + 1, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('1', '1'), mapsp('1', '1')) + ) msgpack_eq(0, mapsp(), mapsp('1', '1')) - msgpack_eq(0, mapsp(sp('binary', '["a"]'), '""'), - mapsp(sp('binary', '[""]'), '""')) - msgpack_eq(0, mapsp(sp('binary', '[""]'), '"a"'), - mapsp(sp('binary', '[""]'), '""')) - msgpack_eq(0, mapsp(sp('binary', '["a"]'), '"a"'), - mapsp(sp('binary', '[""]'), '""')) - msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(sp('binary', '[""]'), mapsp('1', '1'))) - msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('2', '1'), mapsp('1', '1'))) - msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('1', '2'), mapsp('1', '1'))) - msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('1', '1'), mapsp('2', '1'))) - msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('1', '1'), mapsp('1', '2'))) - msgpack_eq(1, mapsp(mapsp('2', '1'), mapsp('1', '1'), - mapsp('1', '1'), mapsp('1', '1')), - mapsp(mapsp('1', '1'), mapsp('1', '1'), - mapsp('2', '1'), mapsp('1', '1'))) + msgpack_eq(0, mapsp(sp('binary', '["a"]'), '""'), mapsp(sp('binary', '[""]'), '""')) + msgpack_eq(0, mapsp(sp('binary', '[""]'), '"a"'), mapsp(sp('binary', '[""]'), '""')) + msgpack_eq(0, mapsp(sp('binary', '["a"]'), '"a"'), mapsp(sp('binary', '[""]'), '""')) + msgpack_eq( + 0, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(sp('binary', '[""]'), mapsp('1', '1')) + ) + msgpack_eq( + 0, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('2', '1'), mapsp('1', '1')) + ) + msgpack_eq( + 0, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('1', '2'), mapsp('1', '1')) + ) + msgpack_eq( + 0, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('1', '1'), mapsp('2', '1')) + ) + msgpack_eq( + 0, + mapsp(mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('1', '1'), mapsp('1', '2')) + ) + msgpack_eq( + 1, + mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1')), + mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1')) + ) end) it('compares map specials with raw maps correctly', function() msgpack_eq(1, mapsp(), '{}') msgpack_eq(1, mapsp(sp('string', '["1"]'), '1'), '{"1": 1}') - msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), - '{"1": 1}') - msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), - '{1: "1"}') - msgpack_eq(0, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), - '{"1": 1}') - msgpack_eq(0, - mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), - '{"1": 1}') + msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') + msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), '{1: "1"}') + msgpack_eq(0, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), '{"1": 1}') + msgpack_eq(0, mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), '{"1": 1}') msgpack_eq(0, mapsp(sp('string', '["1"]'), '1'), '{"1": 1, "2": 2}') end) it('compares raw arrays correctly', function() @@ -195,8 +198,7 @@ describe('autoload/msgpack.vim', function() end) it('compares float specials correctly', function() msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0')) - msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), - sp('float', '(1.0/0.0-1.0/0.0)')) + msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '(1.0/0.0-1.0/0.0)')) msgpack_eq(1, sp('float', '1.0/0.0'), sp('float', '1.0/0.0')) msgpack_eq(1, sp('float', '-(1.0/0.0)'), sp('float', '-(1.0/0.0)')) msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0')) @@ -206,10 +208,8 @@ describe('autoload/msgpack.vim', function() msgpack_eq(0, sp('float', '0.0'), sp('float', '-(1.0/0.0)')) msgpack_eq(0, sp('float', '1.0/0.0'), sp('float', '-(1.0/0.0)')) msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0)')) - msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), - sp('float', '-(1.0/0.0-1.0/0.0)')) - msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), - sp('float', '-(1.0/0.0-1.0/0.0)')) + msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)')) + msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)')) msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '1.0/0.0')) end) it('compares boolean specials correctly', function() @@ -219,8 +219,7 @@ describe('autoload/msgpack.vim', function() it('compares nil specials correctly', function() msgpack_eq(1, sp('nil', '1'), sp('nil', '0')) end) - it('compares nil, boolean and integer values with each other correctly', - function() + it('compares nil, boolean and integer values with each other correctly', function() msgpack_eq(0, sp('boolean', '1'), '1') msgpack_eq(0, sp('boolean', '1'), sp('nil', '0')) msgpack_eq(0, sp('boolean', '1'), sp('nil', '1')) @@ -238,16 +237,11 @@ describe('autoload/msgpack.vim', function() it('works', function() eq(1, nvim_eval('msgpack#is_int(1)')) eq(1, nvim_eval('msgpack#is_int(-1)')) - eq(1, nvim_eval(('msgpack#is_int(%s)'):format( - sp('integer', '[1, 0, 0, 1]')))) - eq(1, nvim_eval(('msgpack#is_int(%s)'):format( - sp('integer', '[-1, 0, 0, 1]')))) - eq(0, nvim_eval(('msgpack#is_int(%s)'):format( - sp('float', '0.0')))) - eq(0, nvim_eval(('msgpack#is_int(%s)'):format( - sp('boolean', '0')))) - eq(0, nvim_eval(('msgpack#is_int(%s)'):format( - sp('nil', '0')))) + eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[1, 0, 0, 1]')))) + eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[-1, 0, 0, 1]')))) + eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('float', '0.0')))) + eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('boolean', '0')))) + eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('nil', '0')))) eq(0, nvim_eval('msgpack#is_int("")')) end) end) @@ -256,16 +250,11 @@ describe('autoload/msgpack.vim', function() it('works', function() eq(1, nvim_eval('msgpack#is_uint(1)')) eq(0, nvim_eval('msgpack#is_uint(-1)')) - eq(1, nvim_eval(('msgpack#is_uint(%s)'):format( - sp('integer', '[1, 0, 0, 1]')))) - eq(0, nvim_eval(('msgpack#is_uint(%s)'):format( - sp('integer', '[-1, 0, 0, 1]')))) - eq(0, nvim_eval(('msgpack#is_uint(%s)'):format( - sp('float', '0.0')))) - eq(0, nvim_eval(('msgpack#is_uint(%s)'):format( - sp('boolean', '0')))) - eq(0, nvim_eval(('msgpack#is_uint(%s)'):format( - sp('nil', '0')))) + eq(1, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[1, 0, 0, 1]')))) + eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[-1, 0, 0, 1]')))) + eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('float', '0.0')))) + eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('boolean', '0')))) + eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('nil', '0')))) eq(0, nvim_eval('msgpack#is_uint("")')) end) end) @@ -274,18 +263,20 @@ describe('autoload/msgpack.vim', function() it('works', function() local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) eq(epoch, nvim_eval('msgpack#strftime("%Y-%m-%dT%H:%M:%S", 0)')) - eq(epoch, nvim_eval( - ('msgpack#strftime("%%Y-%%m-%%dT%%H:%%M:%%S", %s)'):format(sp( - 'integer', '[1, 0, 0, 0]')))) + eq( + epoch, + nvim_eval( + ('msgpack#strftime("%%Y-%%m-%%dT%%H:%%M:%%S", %s)'):format(sp('integer', '[1, 0, 0, 0]')) + ) + ) end) end) describe('function msgpack#strptime', function() it('works', function() - for _, v in ipairs({0, 10, 100000, 204, 1000000000}) do + for _, v in ipairs({ 0, 10, 100000, 204, 1000000000 }) do local time = os.date('%Y-%m-%dT%H:%M:%S', v) - eq(v, nvim_eval('msgpack#strptime("%Y-%m-%dT%H:%M:%S", ' - .. '"' .. time .. '")')) + eq(v, nvim_eval('msgpack#strptime("%Y-%m-%dT%H:%M:%S", ' .. '"' .. time .. '")')) end end) end) @@ -367,25 +358,27 @@ describe('autoload/msgpack.vim', function() string_eq('[[[[{}]]]]', sp('array', '[[[[{}]]]]')) string_eq('{}', sp('map', '[]')) string_eq('{2: 10}', sp('map', '[[2, 10]]')) - string_eq('{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', - mapsp(mapsp('2', '1'), mapsp('1', '1'), - mapsp('1', '1'), mapsp('1', '1'))) - string_eq('{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', - mapsp(mapsp('1', '1'), mapsp('1', '1'), - mapsp('2', '1'), mapsp('1', '1'))) - string_eq('{[1, 2, {{1: 2}: 1}]: [1, 2, {{1: 2}: 1}]}', - mapsp(('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')), - ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')))) + string_eq( + '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', + mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1')) + ) + string_eq( + '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}', + mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1')) + ) + string_eq( + '{[1, 2, {{1: 2}: 1}]: [1, 2, {{1: 2}: 1}]}', + mapsp( + ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')), + ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')) + ) + ) string_eq('0x0000000000000000', sp('integer', '[1, 0, 0, 0]')) string_eq('-0x0000000100000000', sp('integer', '[-1, 0, 2, 0]')) - string_eq('0x123456789abcdef0', - sp('integer', '[ 1, 0, 610839793, 448585456]')) - string_eq('-0x123456789abcdef0', - sp('integer', '[-1, 0, 610839793, 448585456]')) - string_eq('0xf23456789abcdef0', - sp('integer', '[ 1, 3, 1684581617, 448585456]')) - string_eq('-0x723456789abcdef0', - sp('integer', '[-1, 1, 1684581617, 448585456]')) + string_eq('0x123456789abcdef0', sp('integer', '[ 1, 0, 610839793, 448585456]')) + string_eq('-0x123456789abcdef0', sp('integer', '[-1, 0, 610839793, 448585456]')) + string_eq('0xf23456789abcdef0', sp('integer', '[ 1, 3, 1684581617, 448585456]')) + string_eq('-0x723456789abcdef0', sp('integer', '[-1, 1, 1684581617, 448585456]')) string_eq('0.0', sp('float', '0.0')) string_eq('inf', sp('float', '(1.0/0.0)')) string_eq('-inf', sp('float', '-(1.0/0.0)')) @@ -466,15 +459,15 @@ describe('autoload/msgpack.vim', function() nvim_command('let spbln._VAL = 1') nvim_command('let spnil._VAL = 1') - eq({_TYPE={}, _VAL={{{}}}}, nvim_eval('sparr2')) - eq({_TYPE={}, _VAL={{'abc', {{}}}}}, nvim_eval('spmap2')) - eq({_TYPE={}, _VAL={1, 0, 0, 0}}, nvim_eval('spint2')) - eq({_TYPE={}, _VAL=1.0}, nvim_eval('spflt2')) - eq({_TYPE={}, _VAL={2, {'abc', 'def'}}}, nvim_eval('spext2')) - eq({_TYPE={}, _VAL={'abc', 'def'}}, nvim_eval('spstr2')) - eq({_TYPE={}, _VAL={'abc', 'def'}}, nvim_eval('spbin2')) - eq({_TYPE={}, _VAL=0}, nvim_eval('spbln2')) - eq({_TYPE={}, _VAL=0}, nvim_eval('spnil2')) + eq({ _TYPE = {}, _VAL = { { {} } } }, nvim_eval('sparr2')) + eq({ _TYPE = {}, _VAL = { { 'abc', { {} } } } }, nvim_eval('spmap2')) + eq({ _TYPE = {}, _VAL = { 1, 0, 0, 0 } }, nvim_eval('spint2')) + eq({ _TYPE = {}, _VAL = 1.0 }, nvim_eval('spflt2')) + eq({ _TYPE = {}, _VAL = { 2, { 'abc', 'def' } } }, nvim_eval('spext2')) + eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spstr2')) + eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spbin2')) + eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spbln2')) + eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spnil2')) nvim_command('let sparr._TYPE = []') nvim_command('let spmap._TYPE = []') @@ -525,38 +518,40 @@ describe('autoload/msgpack.vim', function() nvim_command('let flt = 3.0') nvim_command('let bin = ""') - eq({{{}}}, nvim_eval('arr2')) - eq({['1']={}}, nvim_eval('map2')) + eq({ { {} } }, nvim_eval('arr2')) + eq({ ['1'] = {} }, nvim_eval('map2')) eq(1, nvim_eval('int2')) eq(2.0, nvim_eval('flt2')) eq('abc', nvim_eval('bin2')) end) it('works for special v: values like v:true', function() - meths.set_var('true', true) - meths.set_var('false', false) - meths.set_var('nil', NIL) + api.nvim_set_var('true', true) + api.nvim_set_var('false', false) + api.nvim_set_var('nil', NIL) nvim_command('let true2 = msgpack#deepcopy(true)') nvim_command('let false2 = msgpack#deepcopy(false)') nvim_command('let nil2 = msgpack#deepcopy(nil)') - eq(true, meths.get_var('true')) - eq(false, meths.get_var('false')) - eq(NIL, meths.get_var('nil')) + eq(true, api.nvim_get_var('true')) + eq(false, api.nvim_get_var('false')) + eq(NIL, api.nvim_get_var('nil')) end) end) describe('function msgpack#eval', function() local eval_eq = function(expected_type, expected_val, str, ...) - nvim_command(('let g:__val = msgpack#eval(\'%s\', %s)'):format(str:gsub( - '\'', '\'\''), select(1, ...) or '{}')) + nvim_command( + ("let g:__val = msgpack#eval('%s', %s)"):format(str:gsub("'", "''"), select(1, ...) or '{}') + ) eq(expected_type, nvim_eval('msgpack#type(g:__val)')) local expected_val_full = expected_val - if (not (({float=true, integer=true})[expected_type] - and type(expected_val) ~= 'table') - and expected_type ~= 'array') then - expected_val_full = {_TYPE={}, _VAL=expected_val_full} + if + not (({ float = true, integer = true })[expected_type] and type(expected_val) ~= 'table') + and expected_type ~= 'array' + then + expected_val_full = { _TYPE = {}, _VAL = expected_val_full } end if expected_val_full == expected_val_full then eq(expected_val_full, nvim_eval('g:__val')) @@ -570,68 +565,65 @@ describe('autoload/msgpack.vim', function() end it('correctly loads binary strings', function() - eval_eq('binary', {'abcdef'}, '"abcdef"') - eval_eq('binary', {'abc', 'def'}, '"abc\\ndef"') - eval_eq('binary', {'abc\ndef'}, '"abc\\0def"') - eval_eq('binary', {'\nabc\ndef\n'}, '"\\0abc\\0def\\0"') - eval_eq('binary', {'abc\n\n\ndef'}, '"abc\\0\\0\\0def"') - eval_eq('binary', {'abc\n', '\ndef'}, '"abc\\0\\n\\0def"') - eval_eq('binary', {'abc', '', '', 'def'}, '"abc\\n\\n\\ndef"') - eval_eq('binary', {'abc', '', '', 'def', ''}, '"abc\\n\\n\\ndef\\n"') - eval_eq('binary', {'', 'abc', '', '', 'def'}, '"\\nabc\\n\\n\\ndef"') - eval_eq('binary', {''}, '""') - eval_eq('binary', {'"'}, '"\\""') - eval_eq('binary', {'py3 print(sys.version_info)'}, - '"py3 print(sys.version_info)"') + eval_eq('binary', { 'abcdef' }, '"abcdef"') + eval_eq('binary', { 'abc', 'def' }, '"abc\\ndef"') + eval_eq('binary', { 'abc\ndef' }, '"abc\\0def"') + eval_eq('binary', { '\nabc\ndef\n' }, '"\\0abc\\0def\\0"') + eval_eq('binary', { 'abc\n\n\ndef' }, '"abc\\0\\0\\0def"') + eval_eq('binary', { 'abc\n', '\ndef' }, '"abc\\0\\n\\0def"') + eval_eq('binary', { 'abc', '', '', 'def' }, '"abc\\n\\n\\ndef"') + eval_eq('binary', { 'abc', '', '', 'def', '' }, '"abc\\n\\n\\ndef\\n"') + eval_eq('binary', { '', 'abc', '', '', 'def' }, '"\\nabc\\n\\n\\ndef"') + eval_eq('binary', { '' }, '""') + eval_eq('binary', { '"' }, '"\\""') + eval_eq('binary', { 'py3 print(sys.version_info)' }, '"py3 print(sys.version_info)"') end) it('correctly loads strings', function() - eval_eq('string', {'abcdef'}, '="abcdef"') - eval_eq('string', {'abc', 'def'}, '="abc\\ndef"') - eval_eq('string', {'abc\ndef'}, '="abc\\0def"') - eval_eq('string', {'\nabc\ndef\n'}, '="\\0abc\\0def\\0"') - eval_eq('string', {'abc\n\n\ndef'}, '="abc\\0\\0\\0def"') - eval_eq('string', {'abc\n', '\ndef'}, '="abc\\0\\n\\0def"') - eval_eq('string', {'abc', '', '', 'def'}, '="abc\\n\\n\\ndef"') - eval_eq('string', {'abc', '', '', 'def', ''}, '="abc\\n\\n\\ndef\\n"') - eval_eq('string', {'', 'abc', '', '', 'def'}, '="\\nabc\\n\\n\\ndef"') - eval_eq('string', {''}, '=""') - eval_eq('string', {'"'}, '="\\""') - eval_eq('string', {'py3 print(sys.version_info)'}, - '="py3 print(sys.version_info)"') + eval_eq('string', { 'abcdef' }, '="abcdef"') + eval_eq('string', { 'abc', 'def' }, '="abc\\ndef"') + eval_eq('string', { 'abc\ndef' }, '="abc\\0def"') + eval_eq('string', { '\nabc\ndef\n' }, '="\\0abc\\0def\\0"') + eval_eq('string', { 'abc\n\n\ndef' }, '="abc\\0\\0\\0def"') + eval_eq('string', { 'abc\n', '\ndef' }, '="abc\\0\\n\\0def"') + eval_eq('string', { 'abc', '', '', 'def' }, '="abc\\n\\n\\ndef"') + eval_eq('string', { 'abc', '', '', 'def', '' }, '="abc\\n\\n\\ndef\\n"') + eval_eq('string', { '', 'abc', '', '', 'def' }, '="\\nabc\\n\\n\\ndef"') + eval_eq('string', { '' }, '=""') + eval_eq('string', { '"' }, '="\\""') + eval_eq('string', { 'py3 print(sys.version_info)' }, '="py3 print(sys.version_info)"') end) it('correctly loads ext values', function() - eval_eq('ext', {0, {'abcdef'}}, '+(0)"abcdef"') - eval_eq('ext', {0, {'abc', 'def'}}, '+(0)"abc\\ndef"') - eval_eq('ext', {0, {'abc\ndef'}}, '+(0)"abc\\0def"') - eval_eq('ext', {0, {'\nabc\ndef\n'}}, '+(0)"\\0abc\\0def\\0"') - eval_eq('ext', {0, {'abc\n\n\ndef'}}, '+(0)"abc\\0\\0\\0def"') - eval_eq('ext', {0, {'abc\n', '\ndef'}}, '+(0)"abc\\0\\n\\0def"') - eval_eq('ext', {0, {'abc', '', '', 'def'}}, '+(0)"abc\\n\\n\\ndef"') - eval_eq('ext', {0, {'abc', '', '', 'def', ''}}, - '+(0)"abc\\n\\n\\ndef\\n"') - eval_eq('ext', {0, {'', 'abc', '', '', 'def'}}, - '+(0)"\\nabc\\n\\n\\ndef"') - eval_eq('ext', {0, {''}}, '+(0)""') - eval_eq('ext', {0, {'"'}}, '+(0)"\\""') - - eval_eq('ext', {-1, {'abcdef'}}, '+(-1)"abcdef"') - eval_eq('ext', {-1, {'abc', 'def'}}, '+(-1)"abc\\ndef"') - eval_eq('ext', {-1, {'abc\ndef'}}, '+(-1)"abc\\0def"') - eval_eq('ext', {-1, {'\nabc\ndef\n'}}, '+(-1)"\\0abc\\0def\\0"') - eval_eq('ext', {-1, {'abc\n\n\ndef'}}, '+(-1)"abc\\0\\0\\0def"') - eval_eq('ext', {-1, {'abc\n', '\ndef'}}, '+(-1)"abc\\0\\n\\0def"') - eval_eq('ext', {-1, {'abc', '', '', 'def'}}, '+(-1)"abc\\n\\n\\ndef"') - eval_eq('ext', {-1, {'abc', '', '', 'def', ''}}, - '+(-1)"abc\\n\\n\\ndef\\n"') - eval_eq('ext', {-1, {'', 'abc', '', '', 'def'}}, - '+(-1)"\\nabc\\n\\n\\ndef"') - eval_eq('ext', {-1, {''}}, '+(-1)""') - eval_eq('ext', {-1, {'"'}}, '+(-1)"\\""') - - eval_eq('ext', {42, {'py3 print(sys.version_info)'}}, - '+(42)"py3 print(sys.version_info)"') + eval_eq('ext', { 0, { 'abcdef' } }, '+(0)"abcdef"') + eval_eq('ext', { 0, { 'abc', 'def' } }, '+(0)"abc\\ndef"') + eval_eq('ext', { 0, { 'abc\ndef' } }, '+(0)"abc\\0def"') + eval_eq('ext', { 0, { '\nabc\ndef\n' } }, '+(0)"\\0abc\\0def\\0"') + eval_eq('ext', { 0, { 'abc\n\n\ndef' } }, '+(0)"abc\\0\\0\\0def"') + eval_eq('ext', { 0, { 'abc\n', '\ndef' } }, '+(0)"abc\\0\\n\\0def"') + eval_eq('ext', { 0, { 'abc', '', '', 'def' } }, '+(0)"abc\\n\\n\\ndef"') + eval_eq('ext', { 0, { 'abc', '', '', 'def', '' } }, '+(0)"abc\\n\\n\\ndef\\n"') + eval_eq('ext', { 0, { '', 'abc', '', '', 'def' } }, '+(0)"\\nabc\\n\\n\\ndef"') + eval_eq('ext', { 0, { '' } }, '+(0)""') + eval_eq('ext', { 0, { '"' } }, '+(0)"\\""') + + eval_eq('ext', { -1, { 'abcdef' } }, '+(-1)"abcdef"') + eval_eq('ext', { -1, { 'abc', 'def' } }, '+(-1)"abc\\ndef"') + eval_eq('ext', { -1, { 'abc\ndef' } }, '+(-1)"abc\\0def"') + eval_eq('ext', { -1, { '\nabc\ndef\n' } }, '+(-1)"\\0abc\\0def\\0"') + eval_eq('ext', { -1, { 'abc\n\n\ndef' } }, '+(-1)"abc\\0\\0\\0def"') + eval_eq('ext', { -1, { 'abc\n', '\ndef' } }, '+(-1)"abc\\0\\n\\0def"') + eval_eq('ext', { -1, { 'abc', '', '', 'def' } }, '+(-1)"abc\\n\\n\\ndef"') + eval_eq('ext', { -1, { 'abc', '', '', 'def', '' } }, '+(-1)"abc\\n\\n\\ndef\\n"') + eval_eq('ext', { -1, { '', 'abc', '', '', 'def' } }, '+(-1)"\\nabc\\n\\n\\ndef"') + eval_eq('ext', { -1, { '' } }, '+(-1)""') + eval_eq('ext', { -1, { '"' } }, '+(-1)"\\""') + + eval_eq( + 'ext', + { 42, { 'py3 print(sys.version_info)' } }, + '+(42)"py3 print(sys.version_info)"' + ) end) it('correctly loads floats', function() @@ -650,17 +642,17 @@ describe('autoload/msgpack.vim', function() it('correctly loads integers', function() eval_eq('integer', 10, '10') eval_eq('integer', -10, '-10') - eval_eq('integer', { 1, 0, 610839793, 448585456}, ' 0x123456789ABCDEF0') - eval_eq('integer', {-1, 0, 610839793, 448585456}, '-0x123456789ABCDEF0') - eval_eq('integer', { 1, 3, 1684581617, 448585456}, ' 0xF23456789ABCDEF0') - eval_eq('integer', {-1, 1, 1684581617, 448585456}, '-0x723456789ABCDEF0') - eval_eq('integer', { 1, 0, 0, 0x100}, '0x100') - eval_eq('integer', {-1, 0, 0, 0x100}, '-0x100') + eval_eq('integer', { 1, 0, 610839793, 448585456 }, ' 0x123456789ABCDEF0') + eval_eq('integer', { -1, 0, 610839793, 448585456 }, '-0x123456789ABCDEF0') + eval_eq('integer', { 1, 3, 1684581617, 448585456 }, ' 0xF23456789ABCDEF0') + eval_eq('integer', { -1, 1, 1684581617, 448585456 }, '-0x723456789ABCDEF0') + eval_eq('integer', { 1, 0, 0, 0x100 }, '0x100') + eval_eq('integer', { -1, 0, 0, 0x100 }, '-0x100') - eval_eq('integer', ('a'):byte(), '\'a\'') - eval_eq('integer', 0xAB, '\'«\'') - eval_eq('integer', 0, '\'\\0\'') - eval_eq('integer', 10246567, '\'\\10246567\'') + eval_eq('integer', ('a'):byte(), "'a'") + eval_eq('integer', 0xAB, "'«'") + eval_eq('integer', 0, "'\\0'") + eval_eq('integer', 10246567, "'\\10246567'") end) it('correctly loads constants', function() @@ -668,71 +660,94 @@ describe('autoload/msgpack.vim', function() eval_eq('boolean', 0, 'FALSE') eval_eq('nil', 0, 'NIL') eval_eq('nil', 0, 'NIL', '{"NIL": 1, "nan": 2, "T": 3}') - eval_eq('float', nan, 'nan', - '{"NIL": "1", "nan": "2", "T": "3"}') + eval_eq('float', nan, 'nan', '{"NIL": "1", "nan": "2", "T": "3"}') eval_eq('integer', 3, 'T', '{"NIL": "1", "nan": "2", "T": "3"}') - eval_eq('integer', {1, 0, 0, 0}, 'T', - ('{"NIL": "1", "nan": "2", "T": \'%s\'}'):format( - sp('integer', '[1, 0, 0, 0]'))) + eval_eq( + 'integer', + { 1, 0, 0, 0 }, + 'T', + ('{"NIL": "1", "nan": "2", "T": \'%s\'}'):format(sp('integer', '[1, 0, 0, 0]')) + ) end) it('correctly loads maps', function() eval_eq('map', {}, '{}') - eval_eq('map', {{{_TYPE={}, _VAL={{1, 2}}}, {_TYPE={}, _VAL={{3, 4}}}}}, - '{{1: 2}: {3: 4}}') - eval_eq('map', {{{_TYPE={}, _VAL={{1, 2}}}, {_TYPE={}, _VAL={{3, 4}}}}, - {1, 2}}, - '{{1: 2}: {3: 4}, 1: 2}') - - eval_eq('map', {{{_TYPE={}, _VAL={ - {{_TYPE={}, _VAL={'py3 print(sys.version_info)'}}, - 2}}}, - {_TYPE={}, _VAL={{3, 4}}}}, - {1, 2}}, - '{{"py3 print(sys.version_info)": 2}: {3: 4}, 1: 2}') + eval_eq( + 'map', + { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } } }, + '{{1: 2}: {3: 4}}' + ) + eval_eq( + 'map', + { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } }, { 1, 2 } }, + '{{1: 2}: {3: 4}, 1: 2}' + ) + + eval_eq('map', { + { + { + _TYPE = {}, + _VAL = { + { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } }, 2 }, + }, + }, + { _TYPE = {}, _VAL = { { 3, 4 } } }, + }, + { 1, 2 }, + }, '{{"py3 print(sys.version_info)": 2}: {3: 4}, 1: 2}') end) it('correctly loads arrays', function() eval_eq('array', {}, '[]') - eval_eq('array', {1}, '[1]') - eval_eq('array', {{_TYPE={}, _VAL=1}}, '[TRUE]') - eval_eq('array', {{{_TYPE={}, _VAL={{1, 2}}}}, {_TYPE={}, _VAL={{3, 4}}}}, - '[[{1: 2}], {3: 4}]') + eval_eq('array', { 1 }, '[1]') + eval_eq('array', { { _TYPE = {}, _VAL = 1 } }, '[TRUE]') + eval_eq( + 'array', + { { { _TYPE = {}, _VAL = { { 1, 2 } } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } }, + '[[{1: 2}], {3: 4}]' + ) - eval_eq('array', {{_TYPE={}, _VAL={'py3 print(sys.version_info)'}}}, - '["py3 print(sys.version_info)"]') + eval_eq( + 'array', + { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } } }, + '["py3 print(sys.version_info)"]' + ) end) it('errors out when needed', function() - eq('empty:Parsed string is empty', - exc_exec('call msgpack#eval("", {})')) - eq('unknown:Invalid non-space character: ^', - exc_exec('call msgpack#eval("^", {})')) - eq('char-invalid:Invalid integer character literal format: \'\'', - exc_exec('call msgpack#eval("\'\'", {})')) - eq('char-invalid:Invalid integer character literal format: \'ab\'', - exc_exec('call msgpack#eval("\'ab\'", {})')) - eq('char-invalid:Invalid integer character literal format: \'', - exc_exec('call msgpack#eval("\'", {})')) - eq('"-invalid:Invalid string: "', - exc_exec('call msgpack#eval("\\"", {})')) - eq('"-invalid:Invalid string: ="', - exc_exec('call msgpack#eval("=\\"", {})')) - eq('"-invalid:Invalid string: +(0)"', - exc_exec('call msgpack#eval("+(0)\\"", {})')) - eq('0.-nodigits:Decimal dot must be followed by digit(s): .e1', - exc_exec('call msgpack#eval("0.e1", {})')) - eq('0x-long:Must have at most 16 hex digits: FEDCBA98765432100', - exc_exec('call msgpack#eval("0xFEDCBA98765432100", {})')) - eq('0x-empty:Must have number after 0x: ', - exc_exec('call msgpack#eval("0x", {})')) - eq('name-unknown:Unknown name FOO: FOO', - exc_exec('call msgpack#eval("FOO", {})')) - - eq('name-unknown:Unknown name py3: py3 print(sys.version_info)', - exc_exec('call msgpack#eval("py3 print(sys.version_info)", {})')) - eq('name-unknown:Unknown name o: o', - exc_exec('call msgpack#eval("-info", {})')) + eq('empty:Parsed string is empty', exc_exec('call msgpack#eval("", {})')) + eq('unknown:Invalid non-space character: ^', exc_exec('call msgpack#eval("^", {})')) + eq( + "char-invalid:Invalid integer character literal format: ''", + exc_exec('call msgpack#eval("\'\'", {})') + ) + eq( + "char-invalid:Invalid integer character literal format: 'ab'", + exc_exec('call msgpack#eval("\'ab\'", {})') + ) + eq( + "char-invalid:Invalid integer character literal format: '", + exc_exec('call msgpack#eval("\'", {})') + ) + eq('"-invalid:Invalid string: "', exc_exec('call msgpack#eval("\\"", {})')) + eq('"-invalid:Invalid string: ="', exc_exec('call msgpack#eval("=\\"", {})')) + eq('"-invalid:Invalid string: +(0)"', exc_exec('call msgpack#eval("+(0)\\"", {})')) + eq( + '0.-nodigits:Decimal dot must be followed by digit(s): .e1', + exc_exec('call msgpack#eval("0.e1", {})') + ) + eq( + '0x-long:Must have at most 16 hex digits: FEDCBA98765432100', + exc_exec('call msgpack#eval("0xFEDCBA98765432100", {})') + ) + eq('0x-empty:Must have number after 0x: ', exc_exec('call msgpack#eval("0x", {})')) + eq('name-unknown:Unknown name FOO: FOO', exc_exec('call msgpack#eval("FOO", {})')) + + eq( + 'name-unknown:Unknown name py3: py3 print(sys.version_info)', + exc_exec('call msgpack#eval("py3 print(sys.version_info)", {})') + ) + eq('name-unknown:Unknown name o: o', exc_exec('call msgpack#eval("-info", {})')) end) end) end) diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index 8d37100607..1c20548321 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -1,25 +1,22 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear -local eq, meths, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf = - helpers.eq, helpers.meths, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec, - helpers.funcs, helpers.feed, helpers.curbuf +local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed = + helpers.eq, helpers.api, helpers.eval, helpers.command, helpers.exc_exec, helpers.fn, helpers.feed local neq = helpers.neq local read_file = helpers.read_file -local mpack = require('mpack') - local shada_helpers = require('test.functional.shada.helpers') local get_shada_rw = shada_helpers.get_shada_rw local function reset(shada_file) - clear{ args={'-u', 'NORC', '-i', shada_file or 'NONE', }} + clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } } end local mpack_eq = function(expected, mpack_result) - local mpack_keys = {'type', 'timestamp', 'length', 'value'} + local mpack_keys = { 'type', 'timestamp', 'length', 'value' } - local unpack = mpack.Unpacker() + local unpack = vim.mpack.Unpacker() local actual = {} local cur, val local i = 0 @@ -44,8 +41,7 @@ end local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada') -local wshada_tmp, _, fname_tmp = - get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f') +local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f') describe('autoload/shada.vim', function() local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) @@ -89,29 +85,38 @@ describe('autoload/shada.vim', function() it('works', function() eq({}, nvim_eval(mpack2sd('[]'))) - eq({{type=1, timestamp=5, length=1, data=7}}, - nvim_eval(mpack2sd('[1, 5, 1, 7]'))) - eq({{type=1, timestamp=5, length=1, data=7}, - {type=1, timestamp=10, length=1, data=5}}, - nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]'))) - eq('zero-uint:Entry 1 has type element which is zero', - exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]'))) - eq('zero-uint:Entry 1 has type element which is zero', - exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format( - sp('integer', '[1, 0, 0, 0]'))))) - eq('not-uint:Entry 1 has timestamp element which is not an unsigned integer', - exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]'))) - eq('not-uint:Entry 1 has length element which is not an unsigned integer', - exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]'))) - eq('not-uint:Entry 1 has type element which is not an unsigned integer', - exc_exec('call ' .. mpack2sd('["", 1, -1, 7]'))) + eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]'))) + eq({ + { type = 1, timestamp = 5, length = 1, data = 7 }, + { type = 1, timestamp = 10, length = 1, data = 5 }, + }, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]'))) + eq( + 'zero-uint:Entry 1 has type element which is zero', + exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]')) + ) + eq( + 'zero-uint:Entry 1 has type element which is zero', + exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]')))) + ) + eq( + 'not-uint:Entry 1 has timestamp element which is not an unsigned integer', + exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]')) + ) + eq( + 'not-uint:Entry 1 has length element which is not an unsigned integer', + exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]')) + ) + eq( + 'not-uint:Entry 1 has type element which is not an unsigned integer', + exc_exec('call ' .. mpack2sd('["", 1, -1, 7]')) + ) end) end) describe('function shada#sd_to_strings', function() local sd2strings_eq = function(expected, arg) if type(arg) == 'table' then - eq(expected, funcs['shada#sd_to_strings'](arg)) + eq(expected, fn['shada#sd_to_strings'](arg)) else eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg))) end @@ -124,15 +129,18 @@ describe('autoload/shada.vim', function() it('works with unknown items', function() sd2strings_eq({ 'Unknown (0x64) with timestamp ' .. epoch .. ':', - ' = 100' - }, {{type=100, timestamp=0, length=1, data=100}}) - - sd2strings_eq({ - 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':', - ' = 100' - }, ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format( - sp('integer', '[1, 1, 35, 6]') - )) + ' = 100', + }, { { type = 100, timestamp = 0, length = 1, data = 100 } }) + + sd2strings_eq( + { + 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':', + ' = 100', + }, + ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format( + sp('integer', '[1, 1, 35, 6]') + ) + ) end) it('works with multiple unknown items', function() @@ -141,8 +149,10 @@ describe('autoload/shada.vim', function() ' = 100', 'Unknown (0x65) with timestamp ' .. epoch .. ':', ' = 500', - }, {{type=100, timestamp=0, length=1, data=100}, - {type=101, timestamp=0, length=1, data=500}}) + }, { + { type = 100, timestamp = 0, length = 1, data = 100 }, + { type = 101, timestamp = 0, length = 1, data = 500 }, + }) end) it('works with header items', function() @@ -150,7 +160,7 @@ describe('autoload/shada.vim', function() 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', - }, {{type=1, timestamp=0, data={generator='test'}}}) + }, { { type = 1, timestamp = 0, data = { generator = 'test' } } }) sd2strings_eq({ 'Header with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -158,42 +168,44 @@ describe('autoload/shada.vim', function() ' + b 2', ' + c column 3', ' + d 4', - }, {{type=1, timestamp=0, data={a=1, b=2, c=3, d=4}}}) + }, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } }) sd2strings_eq({ 'Header with timestamp ' .. epoch .. ':', ' % Key Value', ' + t "test"', - }, {{type=1, timestamp=0, data={t='test'}}}) + }, { { type = 1, timestamp = 0, data = { t = 'test' } } }) sd2strings_eq({ 'Header with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=1, timestamp=0, data={1, 2, 3}}}) + }, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } }) end) it('processes standard keys correctly, even in header', function() - sd2strings_eq({ - 'Header with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' + c column 0', - ' + f file name "/tmp/foo"', - ' + l line number 10', - ' + n name \'@\'', - ' + rc contents ["abc", "def"]', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed FALSE', - ' + rw block width 10', - ' + sb search backward TRUE', - ' + sc smartcase value FALSE', - ' + se place cursor at end TRUE', - ' + sh v:hlsearch value TRUE', - ' + sl has line offset FALSE', - ' + sm magic value TRUE', - ' + so offset value 10', - ' + sp pattern "100"', - ' + ss is :s pattern TRUE', - ' + su is last used FALSE', - }, ([[ [{'type': 1, 'timestamp': 0, 'data': { + sd2strings_eq( + { + 'Header with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' + c column 0', + ' + f file name "/tmp/foo"', + ' + l line number 10', + " + n name '@'", + ' + rc contents ["abc", "def"]', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', + ' + rw block width 10', + ' + sb search backward TRUE', + ' + sc smartcase value FALSE', + ' + se place cursor at end TRUE', + ' + sh v:hlsearch value TRUE', + ' + sl has line offset FALSE', + ' + sm magic value TRUE', + ' + so offset value 10', + ' + sp pattern "100"', + ' + ss is :s pattern TRUE', + ' + su is last used FALSE', + }, + ([[ [{'type': 1, 'timestamp': 0, 'data': { 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, @@ -212,34 +224,37 @@ describe('autoload/shada.vim', function() 'l': 10, 'c': 0, 'f': '/tmp/foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Header with timestamp ' .. epoch .. ':', - ' % Key Description____ Value', - ' # Expected integer', - ' + c column "abc"', - ' # Expected no NUL bytes', - ' + f file name "abc\\0def"', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + n name -64', - ' # Expected array value', - ' + rc contents "10"', - ' # Unexpected enum value: expected one of ' - .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', - ' + rt type 10', - ' # Expected boolean', - ' + ru is_unnamed 10', - ' # Expected boolean', - ' + sc smartcase value NIL', - ' # Expected boolean', - ' + sm magic value "TRUE"', - ' # Expected integer', - ' + so offset value "TRUE"', - ' # Expected binary string', - ' + sp pattern ="abc"', - }, ([[ [{'type': 1, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Header with timestamp ' .. epoch .. ':', + ' % Key Description____ Value', + ' # Expected integer', + ' + c column "abc"', + ' # Expected no NUL bytes', + ' + f file name "abc\\0def"', + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + n name -64', + ' # Expected array value', + ' + rc contents "10"', + ' # Unexpected enum value: expected one of ' + .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', + ' + rt type 10', + ' # Expected boolean', + ' + ru is_unnamed 10', + ' # Expected boolean', + ' + sc smartcase value NIL', + ' # Expected boolean', + ' + sm magic value "TRUE"', + ' # Expected integer', + ' + so offset value "TRUE"', + ' # Expected binary string', + ' + sp pattern ="abc"', + }, + ([[ [{'type': 1, 'timestamp': 0, 'data': { 'sm': 'TRUE', 'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 'so': 'TRUE', @@ -251,29 +266,36 @@ describe('autoload/shada.vim', function() 'l': -10, 'c': 'abc', 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Header with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + f file name "abc\\0def"', - ' # Expected array of binary strings', - ' + rc contents ["abc", ="abc"]', - ' # Expected integer', - ' + rt type "ABC"', - }, ([[ [{'type': 1, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Header with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + f file name "abc\\0def"', + ' # Expected array of binary strings', + ' + rc contents ["abc", ="abc"]', + ' # Expected integer', + ' + rt type "ABC"', + }, + ([[ [{'type': 1, 'timestamp': 0, 'data': { 'rt': 'ABC', 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}], 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Header with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + rc contents ["abc", "a\\nd\\0"]', - }, ([[ [{'type': 1, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Header with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + rc contents ["abc", "a\\nd\\0"]', + }, + ([[ [{'type': 1, 'timestamp': 0, 'data': { 'rc': ["abc", {'_TYPE': v:msgpack_types.binary, '_VAL': ["a", "d\n"]}], - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with search pattern items', function() @@ -281,59 +303,67 @@ describe('autoload/shada.vim', function() 'Search pattern with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=2, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' + sp pattern "abc"', - ' + sh v:hlsearch value FALSE', - ' + ss is :s pattern FALSE', - ' + sb search backward FALSE', - ' + sm magic value TRUE', - ' + sc smartcase value FALSE', - ' + sl has line offset FALSE', - ' + se place cursor at end FALSE', - ' + so offset value 0', - ' + su is last used TRUE', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { + }, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' + sp pattern "abc"', + ' + sh v:hlsearch value FALSE', + ' + ss is :s pattern FALSE', + ' + sb search backward FALSE', + ' + sm magic value TRUE', + ' + sc smartcase value FALSE', + ' + sl has line offset FALSE', + ' + se place cursor at end FALSE', + ' + so offset value 0', + ' + su is last used TRUE', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { 'sp': 'abc', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' + sp pattern "abc"', - ' + sh v:hlsearch value FALSE', - ' + ss is :s pattern FALSE', - ' + sb search backward FALSE', - ' + sm magic value TRUE', - ' + sc smartcase value FALSE', - ' + sl has line offset FALSE', - ' + se place cursor at end FALSE', - ' + so offset value 0', - ' + su is last used TRUE', - ' + sX NIL', - ' + sY NIL', - ' + sZ NIL', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' + sp pattern "abc"', + ' + sh v:hlsearch value FALSE', + ' + ss is :s pattern FALSE', + ' + sb search backward FALSE', + ' + sm magic value TRUE', + ' + sc smartcase value FALSE', + ' + sl has line offset FALSE', + ' + se place cursor at end FALSE', + ' + so offset value 0', + ' + su is last used TRUE', + ' + sX NIL', + ' + sY NIL', + ' + sZ NIL', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { 'sp': 'abc', 'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, 'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' + sp pattern "abc"', - ' + sh v:hlsearch value FALSE', - ' + ss is :s pattern FALSE', - ' + sb search backward FALSE', - ' + sm magic value TRUE', - ' + sc smartcase value FALSE', - ' + sl has line offset FALSE', - ' + se place cursor at end FALSE', - ' + so offset value 0', - ' + su is last used TRUE', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' + sp pattern "abc"', + ' + sh v:hlsearch value FALSE', + ' + ss is :s pattern FALSE', + ' + sb search backward FALSE', + ' + sm magic value TRUE', + ' + sc smartcase value FALSE', + ' + sl has line offset FALSE', + ' + se place cursor at end FALSE', + ' + so offset value 0', + ' + su is last used TRUE', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { 'sp': 'abc', 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, @@ -344,36 +374,42 @@ describe('autoload/shada.vim', function() 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, 'so': 0, 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' # Required key missing: sp', - ' + sh v:hlsearch value FALSE', - ' + ss is :s pattern FALSE', - ' + sb search backward FALSE', - ' + sm magic value TRUE', - ' + sc smartcase value FALSE', - ' + sl has line offset FALSE', - ' + se place cursor at end FALSE', - ' + so offset value 0', - ' + su is last used TRUE', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' + sp pattern ""', - ' + sh v:hlsearch value TRUE', - ' + ss is :s pattern TRUE', - ' + sb search backward TRUE', - ' + sm magic value FALSE', - ' + sc smartcase value TRUE', - ' + sl has line offset TRUE', - ' + se place cursor at end TRUE', - ' + so offset value -10', - ' + su is last used FALSE', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' # Required key missing: sp', + ' + sh v:hlsearch value FALSE', + ' + ss is :s pattern FALSE', + ' + sb search backward FALSE', + ' + sm magic value TRUE', + ' + sc smartcase value FALSE', + ' + sl has line offset FALSE', + ' + se place cursor at end FALSE', + ' + so offset value 0', + ' + su is last used TRUE', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' + sp pattern ""', + ' + sh v:hlsearch value TRUE', + ' + ss is :s pattern TRUE', + ' + sb search backward TRUE', + ' + sm magic value FALSE', + ' + sc smartcase value TRUE', + ' + sl has line offset TRUE', + ' + se place cursor at end TRUE', + ' + so offset value -10', + ' + su is last used FALSE', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { 'sp': '', 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, @@ -384,31 +420,34 @@ describe('autoload/shada.vim', function() 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, 'so': -10, 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Search pattern with timestamp ' .. epoch .. ':', - ' % Key Description________ Value', - ' # Expected binary string', - ' + sp pattern 0', - ' # Expected boolean', - ' + sh v:hlsearch value 0', - ' # Expected boolean', - ' + ss is :s pattern 0', - ' # Expected boolean', - ' + sb search backward 0', - ' # Expected boolean', - ' + sm magic value 0', - ' # Expected boolean', - ' + sc smartcase value 0', - ' # Expected boolean', - ' + sl has line offset 0', - ' # Expected boolean', - ' + se place cursor at end 0', - ' # Expected integer', - ' + so offset value ""', - ' # Expected boolean', - ' + su is last used 0', - }, ([[ [{'type': 2, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' % Key Description________ Value', + ' # Expected binary string', + ' + sp pattern 0', + ' # Expected boolean', + ' + sh v:hlsearch value 0', + ' # Expected boolean', + ' + ss is :s pattern 0', + ' # Expected boolean', + ' + sb search backward 0', + ' # Expected boolean', + ' + sm magic value 0', + ' # Expected boolean', + ' + sc smartcase value 0', + ' # Expected boolean', + ' + sl has line offset 0', + ' # Expected boolean', + ' + se place cursor at end 0', + ' # Expected integer', + ' + so offset value ""', + ' # Expected boolean', + ' + su is last used 0', + }, + ([[ [{'type': 2, 'timestamp': 0, 'data': { 'sp': 0, 'sh': 0, 'ss': 0, @@ -419,7 +458,8 @@ describe('autoload/shada.vim', function() 'se': 0, 'so': '', 'su': 0, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with replacement string items', function() @@ -427,45 +467,60 @@ describe('autoload/shada.vim', function() 'Replacement string with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', - }, {{type=3, timestamp=0, data={a={10}}}}) - sd2strings_eq({ - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' # Expected more elements in list' - }, ([[ [{'type': 3, 'timestamp': 0, 'data': [ - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' # Expected binary string', - ' - :s replacement string 0', - }, ([[ [{'type': 3, 'timestamp': 0, 'data': [ + }, { { type = 3, timestamp = 0, data = { a = { 10 } } } }) + sd2strings_eq( + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' # Expected more elements in list', + }, + ([[ [{'type': 3, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' # Expected binary string', + ' - :s replacement string 0', + }, + ([[ [{'type': 3, 'timestamp': 0, 'data': [ 0, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' # Expected no NUL bytes', - ' - :s replacement string "abc\\0def"', - }, ([[ [{'type': 3, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' # Expected no NUL bytes', + ' - :s replacement string "abc\\0def"', + }, + ([[ [{'type': 3, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' - :s replacement string "abc\\ndef"', - }, ([[ [{'type': 3, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' - :s replacement string "abc\\ndef"', + }, + ([[ [{'type': 3, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' - :s replacement string "abc\\ndef"', - ' - 0', - }, ([[ [{'type': 3, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' - :s replacement string "abc\\ndef"', + ' - 0', + }, + ([[ [{'type': 3, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]}, 0, - ]}] ]]):gsub('\n', '')) + ]}] ]]):gsub('\n', '') + ) end) it('works with history entry items', function() @@ -473,161 +528,206 @@ describe('autoload/shada.vim', function() 'History entry with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', - }, {{type=4, timestamp=0, data={a={10}}}}) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' # Expected more elements in list' - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' # Expected integer', - ' - history type ""', - ' # Expected more elements in list' - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + }, { { type = 4, timestamp = 0, data = { a = { 10 } } } }) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' # Expected more elements in list', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' # Expected integer', + ' - history type ""', + ' # Expected more elements in list', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', - ' - history type 5', - ' - contents ""', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ' - history type 5', + ' - contents ""', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 5, '' - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', - ' - history type 5', - ' - contents ""', - ' - 32', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ' - history type 5', + ' - contents ""', + ' - 32', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 5, '', 0x20 - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type CMD', - ' - contents ""', - ' - 32', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type CMD', + ' - contents ""', + ' - 32', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 0, '', 0x20 - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents ""', - ' - separator \' \'', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents ""', + " - separator ' '", + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 1, '', 0x20 - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents ""', - ' # Expected more elements in list', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents ""', + ' # Expected more elements in list', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 1, '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type EXPR', - ' - contents ""', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type EXPR', + ' - contents ""', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 2, '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type INPUT', - ' - contents ""', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type INPUT', + ' - contents ""', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 3, '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type DEBUG', - ' - contents ""', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type DEBUG', + ' - contents ""', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 4, '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type DEBUG', - ' # Expected binary string', - ' - contents 10', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type DEBUG', + ' # Expected binary string', + ' - contents 10', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 4, 10, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type DEBUG', - ' # Expected no NUL bytes', - ' - contents "abc\\0def"', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type DEBUG', + ' # Expected no NUL bytes', + ' - contents "abc\\0def"', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 4, {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents "abc"', - ' # Expected integer', - ' - separator ""', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents "abc"', + ' # Expected integer', + ' - separator ""', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 1, 'abc', '', - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents "abc"', - ' # Value is negative', - ' - separator -1', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents "abc"', + ' # Value is negative', + ' - separator -1', + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 1, 'abc', -1, - ]}] ]]):gsub('\n', '')) + ]}] ]]):gsub('\n', '') + ) -- Regression: NUL separator must be properly supported - sd2strings_eq({ - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents ""', - ' - separator \'\\0\'', - }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + sd2strings_eq( + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents ""', + " - separator '\\0'", + }, + ([[ [{'type': 4, 'timestamp': 0, 'data': [ 1, '', 0x0 - ]}] ]]):gsub('\n', '')) + ]}] ]]):gsub('\n', '') + ) end) it('works with register items', function() @@ -635,145 +735,172 @@ describe('autoload/shada.vim', function() 'Register with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=5, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: n', - ' # Required key missing: rc', - ' + rw block width 0', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed FALSE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' # Required key missing: rc', - ' + rw block width 0', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed FALSE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: n', + ' # Required key missing: rc', + ' + rw block width 0', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' # Required key missing: rc', + ' + rw block width 0', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents ["abc", "def"]', - ' + rw block width 0', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed FALSE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents ["abc", "def"]', + ' + rw block width 0', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ["abc", "def"], 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents @', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' + rw block width 0', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed TRUE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' + rw block width 0', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed TRUE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents @', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' + rw block width 0', - ' + rt type CHARACTERWISE', - ' + ru is_unnamed FALSE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' + rw block width 0', + ' + rt type CHARACTERWISE', + ' + ru is_unnamed FALSE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'rw': 0, 'rt': 0, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents @', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' + rw block width 5', - ' + rt type LINEWISE', - ' + ru is_unnamed FALSE', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' + rw block width 5', + ' + rt type LINEWISE', + ' + ru is_unnamed FALSE', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'rw': 5, 'rt': 1, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents @', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' # Expected integer', - ' + rw block width ""', - ' + rt type BLOCKWISE', - ' # Expected boolean', - ' + ru is_unnamed ""', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' # Expected integer', + ' + rw block width ""', + ' + rt type BLOCKWISE', + ' # Expected boolean', + ' + ru is_unnamed ""', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'rw': "", 'rt': 2, 'ru': "" - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' # Expected array value', - ' + rc contents 0', - ' # Value is negative', - ' + rw block width -1', - ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' - .. '1 (LINEWISE), 2 (BLOCKWISE)', - ' + rt type 10', - ' # Expected boolean', - ' + ru is_unnamed ["abc", "def"]', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' # Expected array value', + ' + rc contents 0', + ' # Value is negative', + ' + rw block width -1', + ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' + .. '1 (LINEWISE), 2 (BLOCKWISE)', + ' + rt type 10', + ' # Expected boolean', + ' + ru is_unnamed ["abc", "def"]', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': 0, 'rw': -1, 'rt': 10, 'ru': ['abc', 'def'], - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Register with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \' \'', - ' + rc contents @', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' | - "abcdefghijklmnopqrstuvwxyz"', - ' + rw block width 5', - ' + rt type LINEWISE', - ' # Expected boolean', - ' + ru is_unnamed 0', - }, ([[ [{'type': 5, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Register with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name ' '", + ' + rc contents @', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' | - "abcdefghijklmnopqrstuvwxyz"', + ' + rw block width 5', + ' + rt type LINEWISE', + ' # Expected boolean', + ' + ru is_unnamed 0', + }, + ([[ [{'type': 5, 'timestamp': 0, 'data': { 'n': 0x20, 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'], 'rw': 5, 'rt': 1, 'ru': 0, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with variable items', function() @@ -781,59 +908,77 @@ describe('autoload/shada.vim', function() 'Variable with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', - }, {{type=6, timestamp=0, data={a={10}}}}) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' # Expected more elements in list' - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' # Expected binary string', - ' - name 1', - ' # Expected more elements in list', - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ + }, { { type = 6, timestamp = 0, data = { a = { 10 } } } }) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' # Expected more elements in list', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' # Expected binary string', + ' - name 1', + ' # Expected more elements in list', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ 1 - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' # Expected no NUL bytes', - ' - name "\\0"', - ' # Expected more elements in list', - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' # Expected no NUL bytes', + ' - name "\\0"', + ' # Expected more elements in list', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' - name "foo"', - ' # Expected more elements in list', - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' - name "foo"', + ' # Expected more elements in list', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' - name "foo"', - ' - value NIL', - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' - name "foo"', + ' - value NIL', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, - ]}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Variable with timestamp ' .. epoch .. ':', - ' @ Description Value', - ' - name "foo"', - ' - value NIL', - ' - NIL', - }, ([[ [{'type': 6, 'timestamp': 0, 'data': [ + ]}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Variable with timestamp ' .. epoch .. ':', + ' @ Description Value', + ' - name "foo"', + ' - value NIL', + ' - NIL', + }, + ([[ [{'type': 6, 'timestamp': 0, 'data': [ {'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]}, - ]}] ]]):gsub('\n', '')) + ]}] ]]):gsub('\n', '') + ) end) it('works with global mark items', function() @@ -841,110 +986,134 @@ describe('autoload/shada.vim', function() 'Global mark with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=7, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: n', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected integer', - ' + n name "foo"', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: n', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected integer', + ' + n name "foo"', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: n', - ' + f file name "foo"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: n', + ' + f file name "foo"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'f': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Value is negative', - ' + n name -10', - ' # Expected no NUL bytes', - ' + f file name "\\0"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Value is negative', + ' + n name -10', + ' # Expected no NUL bytes', + ' + f file name "\\0"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': -10, 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \'\\20\'', - ' + f file name "foo"', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + c column -10', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name '\\20'", + ' + f file name "foo"', + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + c column -10', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': 20, 'f': 'foo', 'l': -10, 'c': -10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name 128', - ' + f file name "foo"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + n name 128', + ' + f file name "foo"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': 128, 'f': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + n name \'\\20\'', - ' + f file name "foo"', - ' # Expected integer', - ' + l line number "FOO"', - ' # Expected integer', - ' + c column "foo"', - ' + mX 10', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + " + n name '\\20'", + ' + f file name "foo"', + ' # Expected integer', + ' + l line number "FOO"', + ' # Expected integer', + ' + c column "foo"', + ' + mX 10', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': 20, 'f': 'foo', 'l': 'FOO', 'c': 'foo', 'mX': 10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Global mark with timestamp ' .. epoch .. ':', - ' % Key________ Description Value', - ' + n name \'A\'', - ' + f file name "foo"', - ' + l line number 2', - ' + c column 200', - ' + mX 10', - ' + mYYYYYYYYYY 10', - }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key________ Description Value', + " + n name 'A'", + ' + f file name "foo"', + ' + l line number 2', + ' + c column 200', + ' + mX 10', + ' + mYYYYYYYYYY 10', + }, + ([[ [{'type': 7, 'timestamp': 0, 'data': { 'n': char2nr('A'), 'f': 'foo', 'l': 2, 'c': 200, 'mX': 10, 'mYYYYYYYYYY': 10, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with jump items', function() @@ -952,93 +1121,114 @@ describe('autoload/shada.vim', function() 'Jump with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=8, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - ' # Expected integer', - ' + n name "foo"', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + ' # Expected integer', + ' + n name "foo"', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'n': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'f': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + f file name "\\0"', - ' + l line number 1', - ' + c column 0', - ' # Value is negative', - ' + n name -10', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + f file name "\\0"', + ' + l line number 1', + ' + c column 0', + ' # Value is negative', + ' + n name -10', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'n': -10, 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + c column -10', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + c column -10', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'f': 'foo', 'l': -10, 'c': -10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' # Expected integer', - ' + l line number "FOO"', - ' # Expected integer', - ' + c column "foo"', - ' + mX 10', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' # Expected integer', + ' + l line number "FOO"', + ' # Expected integer', + ' + c column "foo"', + ' + mX 10', + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'f': 'foo', 'l': 'FOO', 'c': 'foo', 'mX': 10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Jump with timestamp ' .. epoch .. ':', - ' % Key________ Description Value', - ' + f file name "foo"', - ' + l line number 2', - ' + c column 200', - ' + mX 10', - ' + mYYYYYYYYYY 10', - ' + n name \' \'', - }, ([[ [{'type': 8, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Jump with timestamp ' .. epoch .. ':', + ' % Key________ Description Value', + ' + f file name "foo"', + ' + l line number 2', + ' + c column 200', + ' + mX 10', + ' + mYYYYYYYYYY 10', + " + n name ' '", + }, + ([[ [{'type': 8, 'timestamp': 0, 'data': { 'n': 0x20, 'f': 'foo', 'l': 2, 'c': 200, 'mX': 10, 'mYYYYYYYYYY': 10, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with buffer list items', function() @@ -1046,17 +1236,17 @@ describe('autoload/shada.vim', function() 'Buffer list with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', - }, {{type=9, timestamp=0, data={a={10}}}}) + }, { { type = 9, timestamp = 0, data = { a = { 10 } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' # Expected array of maps', ' = [[], []]', - }, {{type=9, timestamp=0, data={{}, {}}}}) + }, { { type = 9, timestamp = 0, data = { {}, {} } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' # Expected array of maps', ' = [{="a": 10}, []]', - }, {{type=9, timestamp=0, data={{a=10}, {}}}}) + }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -1064,7 +1254,7 @@ describe('autoload/shada.vim', function() ' + l line number 1', ' + c column 0', ' + a 10', - }, {{type=9, timestamp=0, data={{a=10}}}}) + }, { { type = 9, timestamp = 0, data = { { a = 10 } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -1074,7 +1264,7 @@ describe('autoload/shada.vim', function() ' # Expected integer', ' + c column "10"', ' + a 10', - }, {{type=9, timestamp=0, data={{l='10', c='10', a=10}}}}) + }, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -1082,7 +1272,7 @@ describe('autoload/shada.vim', function() ' + l line number 10', ' + c column 10', ' + a 10', - }, {{type=9, timestamp=0, data={{l=10, c=10, a=10}}}}) + }, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -1091,14 +1281,14 @@ describe('autoload/shada.vim', function() ' + l line number -10', ' # Value is negative', ' + c column -10', - }, {{type=9, timestamp=0, data={{l=-10, c=-10}}}}) + }, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' + f file name "abc"', ' + l line number 1', ' + c column 0', - }, {{type=9, timestamp=0, data={{f='abc'}}}}) + }, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } }) sd2strings_eq({ 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', @@ -1112,24 +1302,27 @@ describe('autoload/shada.vim', function() ' + f file name 20', ' + l line number 1', ' + c column 0', - }, {{type=9, timestamp=0, data={{f=10}, {f=20}}}}) - sd2strings_eq({ - 'Buffer list with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected binary string', - ' + f file name 10', - ' + l line number 1', - ' + c column 0', - '', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + f file name "\\0"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 9, 'timestamp': 0, 'data': [ + }, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } }) + sd2strings_eq( + { + 'Buffer list with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected binary string', + ' + f file name 10', + ' + l line number 1', + ' + c column 0', + '', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + f file name "\\0"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 9, 'timestamp': 0, 'data': [ {'f': 10}, {'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}}, - ]}] ]]):gsub('\n', '')) + ]}] ]]):gsub('\n', '') + ) end) it('works with local mark items', function() @@ -1137,99 +1330,120 @@ describe('autoload/shada.vim', function() 'Local mark with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=10, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + n name \'"\'', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' # Expected integer', - ' + n name "foo"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + " + n name '\"'", + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' # Expected integer', + ' + n name "foo"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'n': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' + n name \'"\'', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + " + n name '\"'", + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'f': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + f file name "\\0"', - ' # Value is negative', - ' + n name -10', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + f file name "\\0"', + ' # Value is negative', + ' + n name -10', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'n': -10, 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' + n name \'\\20\'', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + c column -10', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + " + n name '\\20'", + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + c column -10', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'n': 20, 'f': 'foo', 'l': -10, 'c': -10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' + n name \'\\20\'', - ' # Expected integer', - ' + l line number "FOO"', - ' # Expected integer', - ' + c column "foo"', - ' + mX 10', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + " + n name '\\20'", + ' # Expected integer', + ' + l line number "FOO"', + ' # Expected integer', + ' + c column "foo"', + ' + mX 10', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'n': 20, 'f': 'foo', 'l': 'FOO', 'c': 'foo', 'mX': 10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Local mark with timestamp ' .. epoch .. ':', - ' % Key________ Description Value', - ' + f file name "foo"', - ' + n name \'a\'', - ' + l line number 2', - ' + c column 200', - ' + mX 10', - ' + mYYYYYYYYYY 10', - }, ([[ [{'type': 10, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Local mark with timestamp ' .. epoch .. ':', + ' % Key________ Description Value', + ' + f file name "foo"', + " + n name 'a'", + ' + l line number 2', + ' + c column 200', + ' + mX 10', + ' + mYYYYYYYYYY 10', + }, + ([[ [{'type': 10, 'timestamp': 0, 'data': { 'n': char2nr('a'), 'f': 'foo', 'l': 2, 'c': 200, 'mX': 10, 'mYYYYYYYYYY': 10, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) it('works with change items', function() @@ -1237,93 +1451,114 @@ describe('autoload/shada.vim', function() 'Change with timestamp ' .. epoch .. ':', ' # Unexpected type: array instead of map', ' = [1, 2, 3]', - }, {{type=11, timestamp=0, data={1, 2, 3}}}) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + l line number 1', - ' + c column 0', - ' # Expected integer', - ' + n name "foo"', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } }) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' + l line number 1', + ' + c column 0', + ' # Expected integer', + ' + n name "foo"', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'n': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' + l line number 1', - ' + c column 0', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' + l line number 1', + ' + c column 0', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'f': 'foo', - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Expected no NUL bytes', - ' + f file name "\\0"', - ' + l line number 1', - ' + c column 0', - ' # Value is negative', - ' + n name -10', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Expected no NUL bytes', + ' + f file name "\\0"', + ' + l line number 1', + ' + c column 0', + ' # Value is negative', + ' + n name -10', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'n': -10, 'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + c column -10', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + c column -10', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'f': 'foo', 'l': -10, 'c': -10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' + f file name "foo"', - ' # Expected integer', - ' + l line number "FOO"', - ' # Expected integer', - ' + c column "foo"', - ' + mX 10', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + f file name "foo"', + ' # Expected integer', + ' + l line number "FOO"', + ' # Expected integer', + ' + c column "foo"', + ' + mX 10', + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'f': 'foo', 'l': 'FOO', 'c': 'foo', 'mX': 10, - }}] ]]):gsub('\n', '')) - sd2strings_eq({ - 'Change with timestamp ' .. epoch .. ':', - ' % Key________ Description Value', - ' + f file name "foo"', - ' + l line number 2', - ' + c column 200', - ' + mX 10', - ' + mYYYYYYYYYY 10', - ' + n name \' \'', - }, ([[ [{'type': 11, 'timestamp': 0, 'data': { + }}] ]]):gsub('\n', '') + ) + sd2strings_eq( + { + 'Change with timestamp ' .. epoch .. ':', + ' % Key________ Description Value', + ' + f file name "foo"', + ' + l line number 2', + ' + c column 200', + ' + mX 10', + ' + mYYYYYYYYYY 10', + " + n name ' '", + }, + ([[ [{'type': 11, 'timestamp': 0, 'data': { 'n': 0x20, 'f': 'foo', 'l': 2, 'c': 200, 'mX': 10, 'mYYYYYYYYYY': 10, - }}] ]]):gsub('\n', '')) + }}] ]]):gsub('\n', '') + ) end) end) @@ -1337,15 +1572,16 @@ describe('autoload/shada.vim', function() end) describe('function shada#strings_to_sd', function() - local strings2sd_eq = function(expected, input) - nvim('set_var', '__input', input) - nvim_command('let g:__actual = map(shada#strings_to_sd(g:__input), ' - .. '"filter(v:val, \\"v:key[0] isnot# \'_\' ' - .. '&& v:key isnot# \'length\'\\")")') + api.nvim_set_var('__input', input) + nvim_command( + 'let g:__actual = map(shada#strings_to_sd(g:__input), ' + .. '"filter(v:val, \\"v:key[0] isnot# \'_\' ' + .. '&& v:key isnot# \'length\'\\")")' + ) -- print() if type(expected) == 'table' then - nvim('set_var', '__expected', expected) + api.nvim_set_var('__expected', expected) nvim_command('let g:__expected = ModifyVal(g:__expected)') expected = 'g:__expected' -- print(nvim_eval('msgpack#string(g:__expected)')) @@ -1360,29 +1596,36 @@ describe('autoload/shada.vim', function() end it('works with multiple items', function() - strings2sd_eq({{ - type=11, timestamp=0, data={ - f='foo', - l=2, - c=200, - mX=10, - mYYYYYYYYYY=10, - n=(' '):byte(), - } + strings2sd_eq({ + { + type = 11, + timestamp = 0, + data = { + f = 'foo', + l = 2, + c = 200, + mX = 10, + mYYYYYYYYYY = 10, + n = (' '):byte(), + }, + }, + { + type = 1, + timestamp = 0, + data = { + c = 'abc', + f = { '!binary', { 'abc\ndef' } }, + l = -10, + n = -64, + rc = '10', + rt = 10, + sc = { '!nil', 0 }, + sm = 'TRUE', + so = 'TRUE', + sp = { '!string', { 'abc' } }, + }, + }, }, { - type=1, timestamp=0, data={ - c='abc', - f={'!binary', {'abc\ndef'}}, - l=-10, - n=-64, - rc='10', - rt=10, - sc={'!nil', 0}, - sm='TRUE', - so='TRUE', - sp={'!string', {'abc'}}, - } - }}, { 'Change with timestamp ' .. epoch .. ':', ' % Key________ Description Value', ' + f file name "foo"', @@ -1390,7 +1633,7 @@ describe('autoload/shada.vim', function() ' + c column 200', ' + mX 10', ' + mYYYYYYYYYY 10', - ' + n name \' \'', + " + n name ' '", 'Header with timestamp ' .. epoch .. ':', ' % Key Description____ Value', ' # Expected integer', @@ -1404,7 +1647,7 @@ describe('autoload/shada.vim', function() ' # Expected array value', ' + rc contents "10"', ' # Unexpected enum value: expected one of ' - .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', + .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', ' + rt type 10', ' # Expected boolean', ' + sc smartcase value NIL', @@ -1422,23 +1665,37 @@ describe('autoload/shada.vim', function() end) it('works with header items', function() - strings2sd_eq({{type=1, timestamp=0, data={ - generator='test', - }}}, { + strings2sd_eq({ { type = 1, timestamp = 0, data = { + generator = 'test', + } } }, { 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', }) - strings2sd_eq({{type=1, timestamp=0, data={ - 1, 2, 3, - }}}, { - 'Header with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=1, timestamp=0, data={ - a=1, b=2, c=3, d=4, - }}}, { + strings2sd_eq( + { { type = 1, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Header with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ + { + type = 1, + timestamp = 0, + data = { + a = 1, + b = 2, + c = 3, + d = 4, + }, + }, + }, { 'Header with timestamp ' .. epoch .. ':', ' % Key Description Value', ' + a 1', @@ -1446,18 +1703,24 @@ describe('autoload/shada.vim', function() ' + c column 3', ' + d 4', }) - strings2sd_eq({{type=1, timestamp=0, data={ - c='abc', - f={'!binary', {'abc\ndef'}}, - l=-10, - n=-64, - rc='10', - rt=10, - sc={'!nil', 0}, - sm='TRUE', - so='TRUE', - sp={'!string', {'abc'}}, - }}}, { + strings2sd_eq({ + { + type = 1, + timestamp = 0, + data = { + c = 'abc', + f = { '!binary', { 'abc\ndef' } }, + l = -10, + n = -64, + rc = '10', + rt = 10, + sc = { '!nil', 0 }, + sm = 'TRUE', + so = 'TRUE', + sp = { '!string', { 'abc' } }, + }, + }, + }, { 'Header with timestamp ' .. epoch .. ':', ' % Key Description____ Value', ' # Expected integer', @@ -1471,7 +1734,7 @@ describe('autoload/shada.vim', function() ' # Expected array value', ' + rc contents "10"', ' # Unexpected enum value: expected one of ' - .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', + .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)', ' + rt type 10', ' # Expected boolean', ' + sc smartcase value NIL', @@ -1485,16 +1748,21 @@ describe('autoload/shada.vim', function() end) it('works with search pattern items', function() - strings2sd_eq({{type=2, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Search pattern with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=2, timestamp=0, data={ - sp='abc', - }}}, { + strings2sd_eq( + { { type = 2, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Search pattern with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ { type = 2, timestamp = 0, data = { + sp = 'abc', + } } }, { 'Search pattern with timestamp ' .. epoch .. ':', ' % Key Description________ Value', ' + sp pattern "abc"', @@ -1507,12 +1775,18 @@ describe('autoload/shada.vim', function() ' + so offset value 0', ' + su is last used TRUE', }) - strings2sd_eq({{type=2, timestamp=0, data={ - sp='abc', - sX={'!nil', 0}, - sY={'!nil', 0}, - sZ={'!nil', 0}, - }}}, { + strings2sd_eq({ + { + type = 2, + timestamp = 0, + data = { + sp = 'abc', + sX = { '!nil', 0 }, + sY = { '!nil', 0 }, + sZ = { '!nil', 0 }, + }, + }, + }, { 'Search pattern with timestamp ' .. epoch .. ':', ' % Key Description________ Value', ' + sp pattern "abc"', @@ -1528,8 +1802,7 @@ describe('autoload/shada.vim', function() ' + sY NIL', ' + sZ NIL', }) - strings2sd_eq({{type=2, timestamp=0, data={'!map', { - }}}}, { + strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, { 'Search pattern with timestamp ' .. epoch .. ':', ' % Key Description________ Value', ' # Required key missing: sp', @@ -1542,17 +1815,23 @@ describe('autoload/shada.vim', function() ' + so offset value 0', ' + su is last used TRUE', }) - strings2sd_eq({{type=2, timestamp=0, data={ - sp='', - sh={'!boolean', 1}, - ss={'!boolean', 1}, - sc={'!boolean', 1}, - sl={'!boolean', 1}, - se={'!boolean', 1}, - sm={'!boolean', 0}, - su={'!boolean', 0}, - so=-10, - }}}, { + strings2sd_eq({ + { + type = 2, + timestamp = 0, + data = { + sp = '', + sh = { '!boolean', 1 }, + ss = { '!boolean', 1 }, + sc = { '!boolean', 1 }, + sl = { '!boolean', 1 }, + se = { '!boolean', 1 }, + sm = { '!boolean', 0 }, + su = { '!boolean', 0 }, + so = -10, + }, + }, + }, { 'Search pattern with timestamp ' .. epoch .. ':', ' % Key Description________ Value', ' + sp pattern ""', @@ -1565,17 +1844,23 @@ describe('autoload/shada.vim', function() ' + so offset value -10', ' + su is last used FALSE', }) - strings2sd_eq({{type=2, timestamp=0, data={ - sp=0, - sh=0, - ss=0, - sc=0, - sl=0, - se=0, - sm=0, - su=0, - so='', - }}}, { + strings2sd_eq({ + { + type = 2, + timestamp = 0, + data = { + sp = 0, + sh = 0, + ss = 0, + sc = 0, + sl = 0, + se = 0, + sm = 0, + su = 0, + so = '', + }, + }, + }, { 'Search pattern with timestamp ' .. epoch .. ':', ' % Key Description________ Value', ' # Expected binary string', @@ -1600,38 +1885,41 @@ describe('autoload/shada.vim', function() end) it('works with replacement string items', function() - strings2sd_eq({{type=3, timestamp=0, data={ - a={10} - }}}, { + strings2sd_eq({ { type = 3, timestamp = 0, data = { + a = { 10 }, + } } }, { 'Replacement string with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', }) - strings2sd_eq({{type=3, timestamp=0, data={ - }}}, { + strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, { 'Replacement string with timestamp ' .. epoch .. ':', ' @ Description__________ Value', - ' # Expected more elements in list' + ' # Expected more elements in list', }) - strings2sd_eq({{type=3, timestamp=0, data={ - 0 - }}}, { + strings2sd_eq({ { type = 3, timestamp = 0, data = { + 0, + } } }, { 'Replacement string with timestamp ' .. epoch .. ':', ' @ Description__________ Value', ' # Expected binary string', ' - :s replacement string 0', }) - strings2sd_eq({{type=3, timestamp=0, data={ - 'abc\ndef', 0, - }}}, { - 'Replacement string with timestamp ' .. epoch .. ':', - ' @ Description__________ Value', - ' - :s replacement string "abc\\ndef"', - ' - 0', - }) - strings2sd_eq({{type=3, timestamp=0, data={ + strings2sd_eq( + { { type = 3, timestamp = 0, data = { + 'abc\ndef', + 0, + } } }, + { + 'Replacement string with timestamp ' .. epoch .. ':', + ' @ Description__________ Value', + ' - :s replacement string "abc\\ndef"', + ' - 0', + } + ) + strings2sd_eq({ { type = 3, timestamp = 0, data = { 'abc\ndef', - }}}, { + } } }, { 'Replacement string with timestamp ' .. epoch .. ':', ' @ Description__________ Value', ' - :s replacement string "abc\\ndef"', @@ -1639,95 +1927,114 @@ describe('autoload/shada.vim', function() end) it('works with history entry items', function() - strings2sd_eq({{type=4, timestamp=0, data={ - a={10}, - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = { + a = { 10 }, + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', }) - strings2sd_eq({{type=4, timestamp=0, data={ - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', - ' # Expected more elements in list' + ' # Expected more elements in list', }) - strings2sd_eq({{type=4, timestamp=0, data={ + strings2sd_eq({ { type = 4, timestamp = 0, data = { '', - }}}, { + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' # Expected integer', ' - history type ""', - ' # Expected more elements in list' + ' # Expected more elements in list', }) - strings2sd_eq({{type=4, timestamp=0, data={ - 5, '', - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = { + 5, + '', + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' - .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', + .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', ' - history type 5', ' - contents ""', }) - strings2sd_eq({{type=4, timestamp=0, data={ - 5, '', 32, - }}}, { - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' + strings2sd_eq( + { { type = 4, timestamp = 0, data = { + 5, + '', + 32, + } } }, + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), ' .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)', - ' - history type 5', - ' - contents ""', - ' - 32', - }) - strings2sd_eq({{type=4, timestamp=0, data={ - 0, '', 32, - }}}, { - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type CMD', - ' - contents ""', - ' - 32', - }) - strings2sd_eq({{type=4, timestamp=0, data={ - 1, '', 32, - }}}, { - 'History entry with timestamp ' .. epoch .. ':', - ' @ Description_ Value', - ' - history type SEARCH', - ' - contents ""', - ' - separator \' \'', - }) - strings2sd_eq({{type=4, timestamp=0, data={ - 1, '', - }}}, { + ' - history type 5', + ' - contents ""', + ' - 32', + } + ) + strings2sd_eq( + { { type = 4, timestamp = 0, data = { + 0, + '', + 32, + } } }, + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type CMD', + ' - contents ""', + ' - 32', + } + ) + strings2sd_eq( + { { type = 4, timestamp = 0, data = { + 1, + '', + 32, + } } }, + { + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents ""', + " - separator ' '", + } + ) + strings2sd_eq({ { type = 4, timestamp = 0, data = { + 1, + '', + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' - history type SEARCH', ' - contents ""', ' # Expected more elements in list', }) - strings2sd_eq({{type=4, timestamp=0, data={ - 2, '', - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = { + 2, + '', + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' - history type EXPR', ' - contents ""', }) - strings2sd_eq({{type=4, timestamp=0, data={ - 3, '' - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = { + 3, + '', + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' - history type INPUT', ' - contents ""', }) - strings2sd_eq({{type=4, timestamp=0, data={ - 4, '' - }}}, { + strings2sd_eq({ { type = 4, timestamp = 0, data = { + 4, + '', + } } }, { 'History entry with timestamp ' .. epoch .. ':', ' @ Description_ Value', ' - history type DEBUG', @@ -1736,15 +2043,19 @@ describe('autoload/shada.vim', function() end) it('works with register items', function() - strings2sd_eq({{type=5, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Register with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=5, timestamp=0, data={'!map', { - }}}}, { + strings2sd_eq( + { { type = 5, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Register with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Required key missing: n', @@ -1752,121 +2063,166 @@ describe('autoload/shada.vim', function() ' + rw block width 0', ' + rt type CHARACTERWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte() - }}}, { + strings2sd_eq({ { type = 5, timestamp = 0, data = { + n = (' '):byte(), + } } }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' # Required key missing: rc', ' + rw block width 0', ' + rt type CHARACTERWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte(), rc={'abc', 'def'} - }}}, { + strings2sd_eq({ + { + type = 5, + timestamp = 0, + data = { + n = (' '):byte(), + rc = { 'abc', 'def' }, + }, + }, + }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' + rc contents ["abc", "def"]', ' + rw block width 0', ' + rt type CHARACTERWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte(), - rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'}, - }}}, { + strings2sd_eq({ + { + type = 5, + timestamp = 0, + data = { + n = (' '):byte(), + rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, + }, + }, + }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' + rc contents @', ' | - "abcdefghijklmnopqrstuvwxyz"', ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 0', ' + rt type CHARACTERWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte(), - rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'}, - rw=5, - rt=1, - }}}, { + strings2sd_eq({ + { + type = 5, + timestamp = 0, + data = { + n = (' '):byte(), + rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, + rw = 5, + rt = 1, + }, + }, + }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' + rc contents @', ' | - "abcdefghijklmnopqrstuvwxyz"', ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 5', ' + rt type LINEWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte(), - rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'}, - rw=5, - rt=2, - }}}, { + strings2sd_eq({ + { + type = 5, + timestamp = 0, + data = { + n = (' '):byte(), + rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' }, + rw = 5, + rt = 2, + }, + }, + }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' + rc contents @', ' | - "abcdefghijklmnopqrstuvwxyz"', ' | - "abcdefghijklmnopqrstuvwxyz"', ' + rw block width 5', ' + rt type BLOCKWISE', }) - strings2sd_eq({{type=5, timestamp=0, data={ - n=(' '):byte(), - rc=0, - rw=-1, - rt=10, - }}}, { + strings2sd_eq({ + { + type = 5, + timestamp = 0, + data = { + n = (' '):byte(), + rc = 0, + rw = -1, + rt = 10, + }, + }, + }, { 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' # Expected array value', ' + rc contents 0', ' # Value is negative', ' + rw block width -1', ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), ' - .. '1 (LINEWISE), 2 (BLOCKWISE)', + .. '1 (LINEWISE), 2 (BLOCKWISE)', ' + rt type 10', }) end) it('works with variable items', function() - strings2sd_eq({{type=6, timestamp=0, data={ - a={10} - }}}, { + strings2sd_eq({ { type = 6, timestamp = 0, data = { + a = { 10 }, + } } }, { 'Variable with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', }) - strings2sd_eq({{type=6, timestamp=0, data={ - }}}, { + strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, { 'Variable with timestamp ' .. epoch .. ':', ' @ Description Value', - ' # Expected more elements in list' + ' # Expected more elements in list', }) - strings2sd_eq({{type=6, timestamp=0, data={ + strings2sd_eq({ { type = 6, timestamp = 0, data = { 'foo', - }}}, { + } } }, { 'Variable with timestamp ' .. epoch .. ':', ' @ Description Value', ' - name "foo"', ' # Expected more elements in list', }) - strings2sd_eq({{type=6, timestamp=0, data={ - 'foo', {'!nil', 0}, - }}}, { + strings2sd_eq({ + { + type = 6, + timestamp = 0, + data = { + 'foo', + { '!nil', 0 }, + }, + }, + }, { 'Variable with timestamp ' .. epoch .. ':', ' @ Description Value', ' - name "foo"', ' - value NIL', }) - strings2sd_eq({{type=6, timestamp=0, data={ - 'foo', {'!nil', 0}, {'!nil', 0} - }}}, { + strings2sd_eq({ + { + type = 6, + timestamp = 0, + data = { + 'foo', + { '!nil', 0 }, + { '!nil', 0 }, + }, + }, + }, { 'Variable with timestamp ' .. epoch .. ':', ' @ Description Value', ' - name "foo"', @@ -1876,19 +2232,35 @@ describe('autoload/shada.vim', function() end) it('works with global mark items', function() - strings2sd_eq({{type=7, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Global mark with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=7, timestamp=0, data={ - n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10, - }}}, { + strings2sd_eq( + { { type = 7, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Global mark with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ + { + type = 7, + timestamp = 0, + data = { + n = ('A'):byte(), + f = 'foo', + l = 2, + c = 200, + mX = 10, + mYYYYYYYYYY = 10, + }, + }, + }, { 'Global mark with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name "foo"', ' + l line number 2', ' + c column 200', @@ -1898,19 +2270,35 @@ describe('autoload/shada.vim', function() end) it('works with jump items', function() - strings2sd_eq({{type=8, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Jump with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=8, timestamp=0, data={ - n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10, - }}}, { + strings2sd_eq( + { { type = 8, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Jump with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ + { + type = 8, + timestamp = 0, + data = { + n = ('A'):byte(), + f = 'foo', + l = 2, + c = 200, + mX = 10, + mYYYYYYYYYY = 10, + }, + }, + }, { 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name "foo"', ' + l line number 2', ' + c column 200', @@ -1920,23 +2308,27 @@ describe('autoload/shada.vim', function() end) it('works with buffer list items', function() - strings2sd_eq({{type=9, timestamp=0, data={ - a={10} - }}}, { + strings2sd_eq({ { type = 9, timestamp = 0, data = { + a = { 10 }, + } } }, { 'Buffer list with timestamp ' .. epoch .. ':', ' # Unexpected type: map instead of array', ' = {="a": [10]}', }) - strings2sd_eq({{type=9, timestamp=0, data={ - {a=10}, {} - }}}, { - 'Buffer list with timestamp ' .. epoch .. ':', - ' # Expected array of maps', - ' = [{="a": 10}, []]', - }) - strings2sd_eq({{type=9, timestamp=0, data={ - {a=10}, - }}}, { + strings2sd_eq( + { { type = 9, timestamp = 0, data = { + { a = 10 }, + {}, + } } }, + { + 'Buffer list with timestamp ' .. epoch .. ':', + ' # Expected array of maps', + ' = [{="a": 10}, []]', + } + ) + strings2sd_eq({ { type = 9, timestamp = 0, data = { + { a = 10 }, + } } }, { 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Required key missing: f', @@ -1944,9 +2336,15 @@ describe('autoload/shada.vim', function() ' + c column 0', ' + a 10', }) - strings2sd_eq({{type=9, timestamp=0, data={ - {l='10', c='10', a=10}, - }}}, { + strings2sd_eq({ + { + type = 9, + timestamp = 0, + data = { + { l = '10', c = '10', a = 10 }, + }, + }, + }, { 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Required key missing: f', @@ -1956,59 +2354,79 @@ describe('autoload/shada.vim', function() ' + c column "10"', ' + a 10', }) - strings2sd_eq({{type=9, timestamp=0, data={ - {l=10, c=10, a=10}, - }}}, { - 'Buffer list with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' + l line number 10', - ' + c column 10', - ' + a 10', - }) - strings2sd_eq({{type=9, timestamp=0, data={ - {l=-10, c=-10}, - }}}, { - 'Buffer list with timestamp ' .. epoch .. ':', - ' % Key Description Value', - ' # Required key missing: f', - ' # Value is negative', - ' + l line number -10', - ' # Value is negative', - ' + c column -10', - }) - strings2sd_eq({{type=9, timestamp=0, data={ - {f='abc'}, - }}}, { + strings2sd_eq( + { { type = 9, timestamp = 0, data = { + { l = 10, c = 10, a = 10 }, + } } }, + { + 'Buffer list with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' + l line number 10', + ' + c column 10', + ' + a 10', + } + ) + strings2sd_eq( + { { type = 9, timestamp = 0, data = { + { l = -10, c = -10 }, + } } }, + { + 'Buffer list with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' # Required key missing: f', + ' # Value is negative', + ' + l line number -10', + ' # Value is negative', + ' + c column -10', + } + ) + strings2sd_eq({ { type = 9, timestamp = 0, data = { + { f = 'abc' }, + } } }, { 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' + f file name "abc"', ' + l line number 1', ' + c column 0', }) - strings2sd_eq({{type=9, timestamp=0, data={ - {f=10}, {f=20}, - }}}, { + strings2sd_eq({ + { + type = 9, + timestamp = 0, + data = { + { f = 10 }, + { f = 20 }, + }, + }, + }, { 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Expected binary string', - ' + f file name \'\\10\'', + " + f file name '\\10'", ' + l line number 1', ' + c column 0', '', ' % Key Description Value', ' # Expected binary string', - ' + f file name \'\\20\'', + " + f file name '\\20'", ' + l line number 1', ' + c column 0', }) - strings2sd_eq({{type=9, timestamp=0, data={ - {f=10}, {f={'!binary', {'\n'}}}, - }}}, { + strings2sd_eq({ + { + type = 9, + timestamp = 0, + data = { + { f = 10 }, + { f = { '!binary', { '\n' } } }, + }, + }, + }, { 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Expected binary string', - ' + f file name \'\\10\'', + " + f file name '\\10'", ' + l line number 1', ' + c column 0', '', @@ -2021,19 +2439,35 @@ describe('autoload/shada.vim', function() end) it('works with local mark items', function() - strings2sd_eq({{type=10, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Local mark with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=10, timestamp=0, data={ - n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10, - }}}, { + strings2sd_eq( + { { type = 10, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Local mark with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ + { + type = 10, + timestamp = 0, + data = { + n = ('A'):byte(), + f = 'foo', + l = 2, + c = 200, + mX = 10, + mYYYYYYYYYY = 10, + }, + }, + }, { 'Local mark with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name "foo"', ' + l line number 2', ' + c column 200', @@ -2043,19 +2477,35 @@ describe('autoload/shada.vim', function() end) it('works with change items', function() - strings2sd_eq({{type=11, timestamp=0, data={ - 1, 2, 3 - }}}, { - 'Change with timestamp ' .. epoch .. ':', - ' # Unexpected type: array instead of map', - ' = [1, 2, 3]', - }) - strings2sd_eq({{type=11, timestamp=0, data={ - n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10, - }}}, { + strings2sd_eq( + { { type = 11, timestamp = 0, data = { + 1, + 2, + 3, + } } }, + { + 'Change with timestamp ' .. epoch .. ':', + ' # Unexpected type: array instead of map', + ' = [1, 2, 3]', + } + ) + strings2sd_eq({ + { + type = 11, + timestamp = 0, + data = { + n = ('A'):byte(), + f = 'foo', + l = 2, + c = 200, + mX = 10, + mYYYYYYYYYY = 10, + }, + }, + }, { 'Change with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name "foo"', ' + l line number 2', ' + c column 200', @@ -2067,7 +2517,7 @@ describe('autoload/shada.vim', function() describe('function shada#get_binstrings', function() local getbstrings_eq = function(expected, input) - local result = funcs['shada#get_binstrings'](input) + local result = fn['shada#get_binstrings'](input) for i, s in ipairs(result) do result[i] = s:gsub('\n', '\0') end @@ -2076,53 +2526,75 @@ describe('autoload/shada.vim', function() end it('works', function() - local version = nvim('get_vvar', 'version') - getbstrings_eq({{timestamp='current', type=1, value={ - generator='shada.vim', - version=version, - }}}, {}) + local version = api.nvim_get_vvar('version') getbstrings_eq({ - {timestamp='current', type=1, value={ - generator='shada.vim', version=version - }}, - {timestamp=0, type=1, value={generator='test'}} + { + timestamp = 'current', + type = 1, + value = { + generator = 'shada.vim', + version = version, + }, + }, + }, {}) + getbstrings_eq({ + { + timestamp = 'current', + type = 1, + value = { + generator = 'shada.vim', + version = version, + }, + }, + { timestamp = 0, type = 1, value = { generator = 'test' } }, }, { 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', }) - nvim('set_var', 'shada#add_own_header', 1) - getbstrings_eq({{timestamp='current', type=1, value={ - generator='shada.vim', - version=version, - }}}, {}) + api.nvim_set_var('shada#add_own_header', 1) + getbstrings_eq({ + { + timestamp = 'current', + type = 1, + value = { + generator = 'shada.vim', + version = version, + }, + }, + }, {}) getbstrings_eq({ - {timestamp='current', type=1, value={ - generator='shada.vim', version=version - }}, - {timestamp=0, type=1, value={generator='test'}} + { + timestamp = 'current', + type = 1, + value = { + generator = 'shada.vim', + version = version, + }, + }, + { timestamp = 0, type = 1, value = { generator = 'test' } }, }, { 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', }) - nvim('set_var', 'shada#add_own_header', 0) + api.nvim_set_var('shada#add_own_header', 0) getbstrings_eq({}, {}) - getbstrings_eq({{timestamp=0, type=1, value={generator='test'}}}, { + getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, { 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', }) - nvim('set_var', 'shada#keep_old_header', 0) + api.nvim_set_var('shada#keep_old_header', 0) getbstrings_eq({}, { 'Header with timestamp ' .. epoch .. ':', ' % Key______ Value', ' + generator "test"', }) getbstrings_eq({ - {type=3, timestamp=0, value={'abc\ndef'}}, - {type=3, timestamp=0, value={'abc\ndef'}}, - {type=3, timestamp=0, value={'abc\ndef'}}, + { type = 3, timestamp = 0, value = { 'abc\ndef' } }, + { type = 3, timestamp = 0, value = { 'abc\ndef' } }, + { type = 3, timestamp = 0, value = { 'abc\ndef' } }, }, { 'Replacement string with timestamp ' .. epoch .. ':', ' @ Description__________ Value', @@ -2164,8 +2636,8 @@ describe('plugin/shada.vim', function() wshada('\004\000\009\147\000\196\002ab\196\001a') wshada_tmp('\004\000\009\147\000\196\002ab\196\001b') - - local bufread_commands = meths.get_autocmds({ group = "ShaDaCommands", event = "BufReadCmd" }) + local bufread_commands = + api.nvim_get_autocmds({ group = 'ShaDaCommands', event = 'BufReadCmd' }) eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]]) -- Need to set nohidden so that the buffer containing 'fname' is not unloaded @@ -2181,8 +2653,8 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "a"', }, nvim_eval('getline(1, "$")')) - eq(false, nvim('get_option_value', 'modified', {})) - eq('shada', nvim('get_option_value', 'filetype', {})) + eq(false, api.nvim_get_option_value('modified', {})) + eq('shada', api.nvim_get_option_value('filetype', {})) nvim_command('edit ' .. fname_tmp) eq({ 'History entry with timestamp ' .. epoch .. ':', @@ -2191,8 +2663,8 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "b"', }, nvim_eval('getline(1, "$")')) - eq(false, nvim('get_option_value', 'modified', {})) - eq('shada', nvim('get_option_value', 'filetype', {})) + eq(false, api.nvim_get_option_value('modified', {})) + eq('shada', api.nvim_get_option_value('filetype', {})) eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname)) neq({ 'History entry with timestamp ' .. epoch .. ':', @@ -2201,7 +2673,7 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "a"', }, nvim_eval('getline(1, "$")')) - neq(true, nvim('get_option_value', 'modified', {})) + neq(true, api.nvim_get_option_value('modified', {})) end) it('event FileReadCmd', function() @@ -2217,8 +2689,8 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "a"', }, nvim_eval('getline(1, "$")')) - eq(true, nvim('get_option_value', 'modified', {})) - neq('shada', nvim('get_option_value', 'filetype', {})) + eq(true, api.nvim_get_option_value('modified', {})) + neq('shada', api.nvim_get_option_value('filetype', {})) nvim_command('1,$read ' .. fname_tmp) eq({ '', @@ -2233,9 +2705,9 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "b"', }, nvim_eval('getline(1, "$")')) - eq(true, nvim('get_option_value', 'modified', {})) - neq('shada', nvim('get_option_value', 'filetype', {})) - nvim('set_option_value', 'modified', false, {}) + eq(true, api.nvim_get_option_value('modified', {})) + neq('shada', api.nvim_get_option_value('filetype', {})) + api.nvim_set_option_value('modified', false, {}) eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname)) eq({ '', @@ -2250,22 +2722,22 @@ describe('plugin/shada.vim', function() ' - contents "ab"', ' - "b"', }, nvim_eval('getline(1, "$")')) - neq(true, nvim('get_option_value', 'modified', {})) + neq(true, api.nvim_get_option_value('modified', {})) end) it('event BufWriteCmd', function() reset() - nvim('set_var', 'shada#add_own_header', 0) - curbuf('set_lines', 0, 1, true, { + api.nvim_set_var('shada#add_own_header', 0) + api.nvim_buf_set_lines(0, 0, 1, true, { 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', @@ -2277,50 +2749,56 @@ describe('plugin/shada.vim', function() eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', }, eol) .. eol, read_file(fname .. '.tst')) - shada_eq({{ - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }}, fname) - shada_eq({{ - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }}, fname_tmp) + shada_eq({ + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + }, fname) + shada_eq({ + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + }, fname_tmp) end) it('event FileWriteCmd', function() reset() - nvim('set_var', 'shada#add_own_header', 0) - curbuf('set_lines', 0, 1, true, { + api.nvim_set_var('shada#add_own_header', 0) + api.nvim_buf_set_lines(0, 0, 1, true, { 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', @@ -2332,40 +2810,46 @@ describe('plugin/shada.vim', function() eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", }, eol) .. eol, read_file(fname .. '.tst')) - shada_eq({{ - timestamp=0, - type=8, - value={n=('A'):byte()}, - }}, fname) - shada_eq({{ - timestamp=0, - type=8, - value={n=('A'):byte()}, - }}, fname_tmp) + shada_eq( + { { + timestamp = 0, + type = 8, + value = { n = ('A'):byte() }, + } }, + fname + ) + shada_eq( + { { + timestamp = 0, + type = 8, + value = { n = ('A'):byte() }, + } }, + fname_tmp + ) end) it('event FileAppendCmd', function() reset() - nvim('set_var', 'shada#add_own_header', 0) - curbuf('set_lines', 0, 1, true, { + api.nvim_set_var('shada#add_own_header', 0) + api.nvim_buf_set_lines(0, 0, 1, true, { 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', }) - funcs.writefile({''}, fname .. '.tst', 'b') - funcs.writefile({''}, fname, 'b') - funcs.writefile({''}, fname_tmp, 'b') + fn.writefile({ '' }, fname .. '.tst', 'b') + fn.writefile({ '' }, fname, 'b') + fn.writefile({ '' }, fname_tmp, 'b') nvim_command('1,3w >> ' .. fname .. '.tst') nvim_command('1,3w >> ' .. fname) nvim_command('1,3w >> ' .. fname_tmp) @@ -2376,59 +2860,67 @@ describe('plugin/shada.vim', function() eq(table.concat({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', }, eol) .. eol, read_file(fname .. '.tst')) - shada_eq({{ - timestamp=0, - type=8, - value={n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }}, fname) - shada_eq({{ - timestamp=0, - type=8, - value={n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }, { - timestamp=0, - type=8, - value={c=-200, f={'foo'}, l=2, n=('A'):byte()}, - }}, fname_tmp) + shada_eq({ + { + timestamp = 0, + type = 8, + value = { n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + }, fname) + shada_eq({ + { + timestamp = 0, + type = 8, + value = { n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + { + timestamp = 0, + type = 8, + value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() }, + }, + }, fname_tmp) end) it('event SourceCmd', function() reset(fname) finally(function() - nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit + nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit end) wshada('\004\000\006\146\000\196\002ab') wshada_tmp('\004\001\006\146\000\196\002bc') eq(0, exc_exec('source ' .. fname)) eq(0, exc_exec('source ' .. fname_tmp)) - eq('bc', funcs.histget(':', -1)) - eq('ab', funcs.histget(':', -2)) + eq('bc', fn.histget(':', -1)) + eq('ab', fn.histget(':', -2)) end) end) @@ -2439,10 +2931,10 @@ describe('ftplugin/shada.vim', function() it('sets indentexpr correctly', function() nvim_command('filetype plugin indent on') nvim_command('setlocal filetype=shada') - funcs.setline(1, { + fn.setline(1, { 'Jump with timestamp ' .. epoch .. ':', '% Key________ Description Value', - '+ n name \'A\'', + "+ n name 'A'", '+ f file name "foo"', '+ l line number 2', '+ c column 200', @@ -2450,7 +2942,7 @@ describe('ftplugin/shada.vim', function() '+ mYYYYYYYYYY 10', 'Register with timestamp ' .. epoch .. ':', '% Key Description Value', - '+ n name \' \'', + "+ n name ' '", '+ rc contents @', '| - "abcdefghijklmnopqrstuvwxyz"', '| - "abcdefghijklmnopqrstuvwxyz"', @@ -2479,7 +2971,7 @@ describe('ftplugin/shada.vim', function() eq({ 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name "foo"', ' + l line number 2', ' + c column 200', @@ -2487,7 +2979,7 @@ describe('ftplugin/shada.vim', function() ' + mYYYYYYYYYY 10', 'Register with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name \' \'', + " + n name ' '", ' + rc contents @', ' | - "abcdefghijklmnopqrstuvwxyz"', ' | - "abcdefghijklmnopqrstuvwxyz"', @@ -2511,34 +3003,34 @@ describe('ftplugin/shada.vim', function() ' + f file name 20', ' + l line number 1', ' + c column 0', - }, funcs.getline(1, funcs.line('$'))) + }, fn.getline(1, fn.line('$'))) end) it('sets options correctly', function() nvim_command('filetype plugin indent on') nvim_command('setlocal filetype=shada') - eq(true, nvim('get_option_value', 'expandtab', {})) - eq(2, nvim('get_option_value', 'tabstop', {})) - eq(2, nvim('get_option_value', 'softtabstop', {})) - eq(2, nvim('get_option_value', 'shiftwidth', {})) + eq(true, api.nvim_get_option_value('expandtab', {})) + eq(2, api.nvim_get_option_value('tabstop', {})) + eq(2, api.nvim_get_option_value('softtabstop', {})) + eq(2, api.nvim_get_option_value('shiftwidth', {})) end) it('sets indentkeys correctly', function() nvim_command('filetype plugin indent on') nvim_command('setlocal filetype=shada') - funcs.setline(1, ' Replacement with timestamp ' .. epoch) + fn.setline(1, ' Replacement with timestamp ' .. epoch) nvim_feed('ggA:\027') - eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_lines', 0, 1, true)[1]) + eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1]) nvim_feed('o-\027') - eq({' -'}, curbuf('get_lines', 1, 2, true)) + eq({ ' -' }, api.nvim_buf_get_lines(0, 1, 2, true)) nvim_feed('ggO+\027') - eq({'+'}, curbuf('get_lines', 0, 1, true)) + eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true)) nvim_feed('GO*\027') - eq({' *'}, curbuf('get_lines', 2, 3, true)) + eq({ ' *' }, api.nvim_buf_get_lines(0, 2, 3, true)) nvim_feed('ggO /\027') - eq({' /'}, curbuf('get_lines', 0, 1, true)) + eq({ ' /' }, api.nvim_buf_get_lines(0, 0, 1, true)) nvim_feed('ggOx\027') - eq({'x'}, curbuf('get_lines', 0, 1, true)) + eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true)) end) end) @@ -2552,24 +3044,24 @@ describe('syntax/shada.vim', function() nvim_command('set laststatus&') local screen = Screen.new(60, 37) screen:set_default_attr_ids { - [1] = {bold = true, foreground = Screen.colors.Brown}; - [2] = {foreground = tonumber('0x6a0dad')}; - [3] = {foreground = Screen.colors.Fuchsia}; - [4] = {foreground = Screen.colors.Blue1}; - [5] = {bold = true, foreground = Screen.colors.SeaGreen4}; - [6] = {foreground = Screen.colors.SlateBlue}; - [7] = {bold = true, reverse = true}; - [8] = {bold = true, foreground = Screen.colors.Blue}; + [1] = { bold = true, foreground = Screen.colors.Brown }, + [2] = { foreground = tonumber('0x6a0dad') }, + [3] = { foreground = Screen.colors.Fuchsia }, + [4] = { foreground = Screen.colors.Blue1 }, + [5] = { bold = true, foreground = Screen.colors.SeaGreen4 }, + [6] = { foreground = Screen.colors.SlateBlue }, + [7] = { bold = true, reverse = true }, + [8] = { bold = true, foreground = Screen.colors.Blue }, } screen:attach() - curbuf('set_lines', 0, 1, true, { + api.nvim_buf_set_lines(0, 0, 1, true, { 'Header with timestamp ' .. epoch .. ':', ' % Key Value', ' + t "test"', 'Jump with timestamp ' .. epoch .. ':', ' % Key________ Description Value', - ' + n name \'A\'', + " + n name 'A'", ' + f file name ["foo"]', ' + l line number 2', ' + c column -200', @@ -2598,7 +3090,8 @@ describe('syntax/shada.vim', function() ' % Key Description________ Value', ' + se place cursor at end TRUE', }) - screen:expect{grid=[=[ + screen:expect { + grid = [=[ {1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: | {2: % Key Value} | {1: +} {3:t } {1:"}{3:test}{1:"} | @@ -2636,7 +3129,8 @@ describe('syntax/shada.vim', function() {8:~ }| {7:[No Name] [+] }| | - ]=]} + ]=], + } nvim_command([[ function GetSyntax() @@ -2657,15 +3151,20 @@ describe('syntax/shada.vim', function() return lines endfunction ]]) - local hname = function(s) return {{'ShaDaEntryHeader', 'ShaDaEntryName'}, - s} end - local h = function(s) return {{'ShaDaEntryHeader'}, s} end - local htsnum = function(s) return { - {'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber'}, - s - } end + local hname = function(s) + return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s } + end + local h = function(s) + return { { 'ShaDaEntryHeader' }, s } + end + local htsnum = function(s) + return { + { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' }, + s, + } + end local synhtssep = function(s) - return {{'ShaDaEntryHeader', 'ShaDaEntryTimestamp'}, s} + return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s } end local synepoch = { year = htsnum(os.date('%Y', 0)), @@ -2675,255 +3174,435 @@ describe('syntax/shada.vim', function() minute = htsnum(os.date('%M', 0)), second = htsnum(os.date('%S', 0)), } - local msh = function(s) return {{'ShaDaEntryMapShort', - 'ShaDaEntryMapHeader'}, s} end - local mlh = function(s) return {{'ShaDaEntryMapLong', - 'ShaDaEntryMapHeader'}, s} end - local ah = function(s) return {{'ShaDaEntryArray', - 'ShaDaEntryArrayHeader'}, s} end + local msh = function(s) + return { + { 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' }, + s, + } + end + local mlh = function(s) + return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s } + end + local ah = function(s) + return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s } + end -- luacheck: ignore - local mses = function(s) return {{'ShaDaEntryMapShort', - 'ShaDaEntryMapShortEntryStart'}, s} end - local mles = function(s) return {{'ShaDaEntryMapLong', - 'ShaDaEntryMapLongEntryStart'}, s} end - local act = funcs.GetSyntax() + local mses = function(s) + return { + { + 'ShaDaEntryMapShort', + 'ShaDaEntryMapShortEntryStart', + }, + s, + } + end + local mles = function(s) + return { + { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' }, + s, + } + end + local act = fn.GetSyntax() local ms = function(syn) return { - {'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart'}, ' + ' + { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' }, + ' + ', } end local as = function() - return {{'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart'}, ' - '} + return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, ' - ' } + end + local ad = function(s) + return { + { 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' }, + s, + } end - local ad = function(s) return {{'ShaDaEntryArray', - 'ShaDaEntryArrayDescription'}, s} end local mbas = function(syn) return { - {'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart'}, - ' | - ' + { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' }, + ' | - ', + } + end + local msk = function(s) + return { + { 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' }, + s, + } + end + local mlk = function(s) + return { + { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' }, + s, } end - local msk = function(s) return {{'ShaDaEntryMapShort', - 'ShaDaEntryMapShortKey'}, s} end - local mlk = function(s) return {{'ShaDaEntryMapLong', - 'ShaDaEntryMapLongKey'}, s} end - local mld = function(s) return {{'ShaDaEntryMapLong', - 'ShaDaEntryMapLongDescription'}, s} end - local c = function(s) return {{'ShaDaComment'}, s} end + local mld = function(s) + return { + { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' }, + s, + } + end + local c = function(s) + return { { 'ShaDaComment' }, s } + end local exp = { { - hname('Header'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Header'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { msh(' % Key Value'), }, { - ms('Short'), msk('t '), - {{'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString'}, 'test'}, - {{'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes'}, '"'}, + ms('Short'), + msk('t '), + { + { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' }, + '"', + }, + { { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' }, + { { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' }, }, { - hname('Jump'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Jump'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { mlh(' % Key________ Description Value'), }, { - ms('Long'), mlk('n '), mld('name '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter'}, '\'A\''}, + ms('Long'), + mlk('n '), + mld('name '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" }, }, { - ms('Long'), mlk('f '), mld('file name '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', - 'ShaDaMsgpackArrayBraces'}, '['}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString'}, - 'foo'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes'}, - '"'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces'}, ']'}, + ms('Long'), + mlk('f '), + mld('file name '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, + { + { + 'ShaDaEntryMapLong', + 'ShaDaMsgpackArray', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackStringQuotes', + }, + '"', + }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' }, }, { - ms('Long'), mlk('l '), mld('line number '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackInteger'}, '2'}, + ms('Long'), + mlk('l '), + mld('line number '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' }, }, { - ms('Long'), mlk('c '), mld('column '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackInteger'}, '-200'}, + ms('Long'), + mlk('c '), + mld('column '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' }, }, { - hname('Register'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Register'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { mlh(' % Key Description Value'), }, { - ms('Long'), mlk('rc '), mld('contents '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray'}, '@'}, + ms('Long'), + mlk('rc '), + mld('contents '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' }, }, { mbas('Long'), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces'}, - '{'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'abcdefghijklmnopqrstuvwxyz'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'}, - '"'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap'}, ' '}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat'}, '1.0'}, - {{'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces'}, '}'}, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' }, + { + { + 'ShaDaEntryMapLong', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackStringQuotes', + }, + '"', + }, + { + { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, + 'abcdefghijklmnopqrstuvwxyz', + }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' }, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' }, }, { - ms('Long'), mlk('rt '), mld('type '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'CHARACTERWISE'}, + ms('Long'), + mlk('rt '), + mld('type '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' }, }, { - ms('Long'), mlk('rt '), mld('type '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'LINEWISE'}, + ms('Long'), + mlk('rt '), + mld('type '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' }, }, { - ms('Long'), mlk('rt '), mld('type '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'BLOCKWISE'}, + ms('Long'), + mlk('rt '), + mld('type '), + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' }, }, { - hname('Replacement string'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Replacement string'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { ah(' @ Description__________ Value'), }, { - as(), ad(':s replacement string '), - {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'CMD'}, + as(), + ad(':s replacement string '), + { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' }, }, { - as(), ad(':s replacement string '), - {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'SEARCH'}, + as(), + ad(':s replacement string '), + { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' }, }, { - as(), ad(':s replacement string '), - {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'EXPR'}, + as(), + ad(':s replacement string '), + { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' }, }, { - as(), ad(':s replacement string '), - {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'INPUT'}, + as(), + ad(':s replacement string '), + { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' }, }, { - as(), ad(':s replacement string '), - {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'DEBUG'}, + as(), + ad(':s replacement string '), + { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' }, }, { - hname('Buffer list'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Buffer list'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { c(' # Expected array of maps'), }, { - {{'ShaDaEntryRawMsgpack'}, ' = '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'}, '['}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces'}, - '{'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString'}, '='}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'a'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'}, - '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt'}, '+('}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt', - 'ShaDaMsgpackExtType'}, '10'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt'}, ')'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'ac'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackBinaryStringEscape'}, - '\\0'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'df'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackBinaryStringEscape'}, - '\\n'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'gi'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackBinaryStringEscape'}, - '\\"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'}, - 'tt\\.'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'}, - '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma'}, ','}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword'}, - 'TRUE'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword'}, - 'FALSE'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces'}, '}'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackComma'}, ','}, - {{'ShaDaMsgpackArray'}, ' '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'}, - '['}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword'}, - 'NIL'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma'}, ','}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray'}, ' '}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt'}, '+('}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt', - 'ShaDaMsgpackExtType'}, '-10'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt'}, ')'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString', - 'ShaDaMsgpackStringQuotes'}, '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes'}, - '"'}, - {{'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'}, ']'}, - {{'ShaDaMsgpackArrayBraces'}, ']'}, + { { 'ShaDaEntryRawMsgpack' }, ' = ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString' }, '=' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackStringQuotes', + }, + '"', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackExt', + 'ShaDaMsgpackExtType', + }, + '10', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackStringQuotes', + }, + '"', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackBinaryStringEscape', + }, + '\\0', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackBinaryStringEscape', + }, + '\\n', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackMap', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackBinaryStringEscape', + }, + '\\"', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' }, + { { 'ShaDaMsgpackArray' }, ' ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackArray', + 'ShaDaMsgpackExt', + 'ShaDaMsgpackExtType', + }, + '-10', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' }, + { + { + 'ShaDaMsgpackArray', + 'ShaDaMsgpackArray', + 'ShaDaMsgpackBinaryString', + 'ShaDaMsgpackStringQuotes', + }, + '"', + }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' }, + { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' }, + { { 'ShaDaMsgpackArrayBraces' }, ']' }, }, { - hname('Buffer list'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Buffer list'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { mlh(' % Key Description Value'), }, - { - }, + {}, { mlh(' % Key Description Value'), }, { - hname('Header'), h(' with timestamp '), - synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'), - synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'), - synepoch.minute, synhtssep(':'), synepoch.second, h(':'), + hname('Header'), + h(' with timestamp '), + synepoch.year, + synhtssep('-'), + synepoch.month, + synhtssep('-'), + synepoch.day, + synhtssep('T'), + synepoch.hour, + synhtssep(':'), + synepoch.minute, + synhtssep(':'), + synepoch.second, + h(':'), }, { mlh(' % Key Description________ Value'), @@ -2932,7 +3611,7 @@ describe('syntax/shada.vim', function() mles(' + '), mlk('se '), mld('place cursor at end '), - {{'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword'}, 'TRUE'}, + { { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' }, }, } eq(exp, act) diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua new file mode 100644 index 0000000000..2ac0fe1fa3 --- /dev/null +++ b/test/functional/plugin/tohtml_spec.lua @@ -0,0 +1,372 @@ +local Screen = require('test.functional.ui.screen') +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local exec = helpers.exec +local exec_lua = helpers.exec_lua +local eq = helpers.eq +local fn = helpers.fn +local api = helpers.api +local insert = helpers.insert + +local function html_syntax_match() + local styles = + vim.split(api.nvim_exec2([[/<style>/+,/<\/style>/-p]], { output = true }).output, '\n') + local attrnames = { + ['font%-weight: bold'] = 'bold', + ['text%-decoration%-line: [^;]*underline'] = 'underline', + ['font%-style: italic'] = 'italic', + ['text%-decoration%-line: [^;]*line%-through'] = 'strikethrough', + } + local hls = {} + for _, style in ipairs(styles) do + local attr = {} + for match, attrname in pairs(attrnames) do + if style:find(match) then + ---@type boolean + attr[attrname] = true + end + end + if style:find('text%-decoration%-style: wavy') and attr.underline then + ---@type boolean + attr.underline = nil + attr.undercurl = true + end + attr.bg = style:match('background%-color: #(%x+)') + if attr.bg then + attr.bg = tonumber(attr.bg, 16) + end + attr.fg = style:match('[^%-]color: #(%x+)') + if attr.fg then + attr.fg = tonumber(attr.fg, 16) + end + if style:match('^%.(%w+)') then + ---@type table + hls[style:match('^%.(%w+)')] = attr + end + end + local whitelist = { + 'fg', + 'bg', + --'sp', + --'blend', + 'bold', + --'standout', + 'underline', + 'undercurl', + --'underdouble', + --'underdotted', + --'underdashed', + 'strikethrough', + 'italic', + --'reverse', + --'nocombine', + } + for name, attrs_old in + pairs(api.nvim_get_hl(0, { link = true }) --[[@as table<string,table>]]) + do + ---@type table + local other = hls[name:gsub('%.', '-'):gsub('@', '-')] + if other then + local attrs = {} + for _, attrname in ipairs(whitelist) do + ---@type table + attrs[attrname] = attrs_old[attrname] + end + eq(attrs, other) + end + end + return hls +end + +local function html_to_extmarks() + local buf = api.nvim_get_current_buf() + local ns = api.nvim_create_namespace 'test-namespace' + api.nvim_buf_clear_namespace(buf, ns, 0, -1) + exec 'silent! norm! ggd/^<pre>$\rddG3dk' + local stack = {} + exec [[set filetype=]] + exec [[silent! %s/</¤/g]] + exec [[silent! %s/"/"/g]] + exec [[silent! %s/&/\&/g]] + exec [[silent! %s/>/>/g]] + exec [[silent! %s/</</g]] + for _, match in + ipairs( + fn.matchbufline(buf, [[¤span class="\([^"]\+\)">\|¤/span>]], 1, '$', { submatches = true }) --[[@as (table[])]] + ) + do + if match.text == '¤/span>' then + local val = table.remove(stack) + api.nvim_buf_set_extmark(buf, ns, val.lnum - 1, val.byteidx, { + hl_group = val.submatches[1], + end_row = match.lnum - 1, + end_col = match.byteidx, + }) + else + table.insert(stack, match) + end + end + exec [[silent! %s/¤\/span>//g]] + exec [[silent! %s/¤span[^>]*>//g]] +end + +---@param screen test.functional.ui.screen +---@param func function? +local function run_tohtml_and_assert(screen, func) + exec('norm! ggO-;') + screen:expect({ any = vim.pesc('-^;') }) + exec('norm! :\rh') + screen:expect({ any = vim.pesc('^-;') }) + local expected = screen:get_snapshot() + do + (func or exec)('TOhtml') + end + exec('only') + html_syntax_match() + html_to_extmarks() + exec('norm! gg0f;') + screen:expect({ any = vim.pesc('-^;') }) + exec('norm! :\rh') + screen:expect({ grid = expected.grid, attr_ids = expected.attr_ids }) +end + +describe(':TOhtml', function() + --- @type test.functional.ui.screen + local screen + before_each(function() + clear({ args = { '--clean' } }) + screen = Screen.new(80, 80) + screen:attach({ term_name = 'xterm' }) + exec('colorscheme default') + end) + + it('expected internal html generated', function() + insert([[line]]) + exec('set termguicolors') + local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui') + local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui') + exec_lua [[ + local outfile = vim.fn.tempname() .. '.html' + local html = require('tohtml').tohtml(0,{title="title",font="dumyfont"}) + vim.fn.writefile(html, outfile) + vim.cmd.split(outfile) + ]] + local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf()) + eq({ + '<!DOCTYPE html>', + '<html>', + '<head>', + '<meta charset="UTF-8">', + '<title>title</title>', + ('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')), + '<style>', + '* {font-family: dumyfont,monospace}', + ('body {background-color: %s; color: %s}'):format(bg, fg), + '</style>', + '</head>', + '<body style="display: flex">', + '<pre>', + 'line', + '', + '</pre>', + '</body>', + '</html>', + }, fn.readfile(out_file)) + end) + + it('highlight attributes generated', function() + --Make sure to uncomment the attribute in `html_syntax_match()` + exec('hi LINE gui=' .. table.concat({ + 'bold', + 'underline', + 'italic', + 'strikethrough', + }, ',')) + exec('hi UNDERCURL gui=undercurl') + exec('syn keyword LINE line') + exec('syn keyword UNDERCURL undercurl') + insert('line\nundercurl') + run_tohtml_and_assert(screen) + end) + + it('syntax', function() + insert [[ + function main() + print("hello world") + end + ]] + exec('set termguicolors') + exec('syntax enable') + exec('setf lua') + run_tohtml_and_assert(screen) + end) + + it('diff', function() + exec('set diffopt=') + insert [[ + diffadd + nochage + diffchange1 + ]] + exec('new') + insert [[ + nochage + diffchange2 + diffremove + ]] + exec('set diff') + exec('close') + exec('set diff') + run_tohtml_and_assert(screen) + end) + + it('treesitter', function() + insert [[ + function main() + print("hello world") + end + ]] + exec('setf lua') + exec_lua('vim.treesitter.start()') + run_tohtml_and_assert(screen) + end) + + it('matchadd', function() + insert [[ + line + ]] + fn.matchadd('Visual', 'line') + run_tohtml_and_assert(screen) + end) + + describe('conceallevel', function() + local function run(level) + insert([[ + line0 + line1 + line2 + line3 + ]]) + local ns = api.nvim_create_namespace '' + fn.matchadd('Conceal', 'line1', 3, 5, { conceal = 'a' }) + api.nvim_buf_set_extmark(0, ns, 2, 0, { conceal = 'a', end_col = 5 }) + exec(':syntax match Conceal "line3" conceal cchar=a') + exec('set conceallevel=' .. level) + run_tohtml_and_assert(screen) + end + it('conceallevel=0', function() + run(0) + end) + it('conceallevel=1', function() + run(1) + end) + it('conceallevel=2', function() + run(2) + end) + it('conceallevel=3', function() + run(3) + end) + end) + + describe('extmarks', function() + it('virt_text', function() + insert [[ + line1 + line2 + line3 + line4 + ]] + local ns = api.nvim_create_namespace '' + api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'foo' } } }) + api.nvim_buf_set_extmark( + 0, + ns, + 1, + 0, + { virt_text = { { 'foo' } }, virt_text_pos = 'overlay' } + ) + api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { 'foo' } }, virt_text_pos = 'inline' }) + --api.nvim_buf_set_extmark(0,ns,3,0,{virt_text={{'foo'}},virt_text_pos='right_align'}) + run_tohtml_and_assert(screen) + end) + it('highlight', function() + insert [[ + line1 + ]] + local ns = api.nvim_create_namespace '' + api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 2, hl_group = 'Visual' }) + run_tohtml_and_assert(screen) + end) + it('virt_line', function() + insert [[ + line1 + line2 + ]] + local ns = api.nvim_create_namespace '' + api.nvim_buf_set_extmark(0, ns, 1, 0, { end_col = 2, virt_lines = { { { 'foo' } } } }) + run_tohtml_and_assert(screen) + end) + end) + + it('listchars', function() + exec('setlocal list') + exec( + 'setlocal listchars=eol:$,tab:<->,space:-,multispace:++,lead:_,leadmultispace:##,trail:&,nbsp:%' + ) + fn.setline(1, '\tfoo\t') + fn.setline(2, ' foo foo ') + fn.setline(3, ' foo foo ') + fn.setline(4, 'foo\194\160 \226\128\175foo') + run_tohtml_and_assert(screen) + exec('new|only') + fn.setline(1, '\tfoo\t') + exec('setlocal list') + exec('setlocal listchars=tab:a-') + run_tohtml_and_assert(screen) + end) + + it('folds', function() + insert([[ + line1 + line2 + ]]) + exec('set foldtext=foldtext()') + exec('%fo') + run_tohtml_and_assert(screen) + end) + + it('statuscol', function() + local function run() + local buf = api.nvim_get_current_buf() + run_tohtml_and_assert(screen, function() + exec_lua [[ + local outfile = vim.fn.tempname() .. '.html' + local html = require('tohtml').tohtml(0,{number_lines=true}) + vim.fn.writefile(html, outfile) + vim.cmd.split(outfile) + ]] + end) + api.nvim_set_current_buf(buf) + end + insert([[ + line1 + line2 + ]]) + exec('setlocal relativenumber') + run() + exec('setlocal norelativenumber') + exec('setlocal number') + run() + exec('setlocal relativenumber') + run() + exec('setlocal signcolumn=yes:2') + run() + exec('setlocal foldcolumn=2') + run() + exec('setlocal norelativenumber') + run() + exec('setlocal signcolumn=no') + run() + end) +end) diff --git a/test/functional/plugin/tutor_spec.lua b/test/functional/plugin/tutor_spec.lua index bd214e9c03..99538e1db0 100644 --- a/test/functional/plugin/tutor_spec.lua +++ b/test/functional/plugin/tutor_spec.lua @@ -25,7 +25,8 @@ describe(':Tutor', function() end) it('applies {unix:…,win:…} transform', function() - local expected = is_os('win') and [[ + local expected = is_os('win') + and [[ {0: }^ | {0: } 3. To verify that a file was retrieved, cursor back and notice that there | {0: } are now two copies of Lesson 5.3, the original and the retrieved version. | @@ -56,7 +57,8 @@ describe(':Tutor', function() {0: } 5. {2::r !dir} reads the output of the dir command and | {0: } puts it below the cursor position. | {0: } | - ]] or [[ + ]] + or [[ {0: }^ | {0: } 3. To verify that a file was retrieved, cursor back and notice that there | {0: } are now two copies of Lesson 5.3, the original and the retrieved version. | diff --git a/test/functional/plugin/vim_syntax_spec.lua b/test/functional/plugin/vim_syntax_spec.lua new file mode 100644 index 0000000000..9396bbce5c --- /dev/null +++ b/test/functional/plugin/vim_syntax_spec.lua @@ -0,0 +1,40 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local exec = helpers.exec +local api = helpers.api + +describe('Vimscript syntax highlighting', function() + local screen + + before_each(function() + clear() + helpers.add_builddir_to_rtp() + exec([[ + setfiletype vim + syntax on + ]]) + screen = Screen.new() + screen:set_default_attr_ids({ + [0] = { foreground = Screen.colors.Blue, bold = true }, + [1] = { foreground = Screen.colors.Brown, bold = true }, + [2] = { foreground = tonumber('0x6a0dad') }, + }) + screen:attach() + end) + + it('prefixed boolean options are highlighted properly', function() + api.nvim_buf_set_lines(0, 0, -1, true, { + 'set number incsearch hlsearch', + 'set nonumber noincsearch nohlsearch', + 'set invnumber invincsearch invhlsearch', + }) + screen:expect([[ + {1:^set} {2:number} {2:incsearch} {2:hlsearch} | + {1:set} {2:nonumber} {2:noincsearch} {2:nohlsearch} | + {1:set} {2:invnumber} {2:invincsearch} {2:invhlsearch} | + {0:~ }|*10 + | + ]]) + end) +end) |