diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-05-24 19:18:11 +0000 |
commit | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (patch) | |
tree | 729bbcb92231538fa61dab6c3d890b025484b7f5 /test | |
parent | 376914f419eb08fdf4c1a63a77e1f035898a0f10 (diff) | |
parent | 28c04948a1c887a1cc0cb64de79fa32631700466 (diff) | |
download | rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.gz rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.tar.bz2 rneovim-ff7ed8f586589d620a806c3758fac4a47a8e7e15.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'test')
546 files changed, 25391 insertions, 12401 deletions
diff --git a/test/README.md b/test/README.md index 3aafe1273e..45b3322305 100644 --- a/test/README.md +++ b/test/README.md @@ -37,6 +37,7 @@ Layout - `/test/benchmark` : benchmarks - `/test/functional` : functional tests - `/test/unit` : unit tests +- `/test/old/testdir` : old tests (from Vim) - `/test/config` : contains `*.in` files which are transformed into `*.lua` files using `configure_file` CMake command: this is for accessing CMake variables in lua tests. @@ -44,11 +45,13 @@ Layout parser: normally used to make macros not accessible via this mechanism accessible the other way. - `/test/*/preload.lua` : modules preloaded by busted `--helper` option -- `/test/**/helpers.lua` : common utility functions for test code +- `/test/**/testutil.lua` : common utility functions in the context of the test + runner +- `/test/**/testnvim.lua` : common utility functions in the context of the + test session (RPC channel to the Nvim child process created by clear() for each test) - `/test/*/**/*_spec.lua` : actual tests. Files that do not end with - `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they have + `_spec.lua` are libraries like `/test/**/testutil.lua`, except that they have some common topic. -- `/test/old/testdir` : old tests (from Vim) Running tests @@ -119,7 +122,7 @@ Debugging tests If `$VALGRIND` is also set it will pass `--vgdb=yes` to valgrind instead of starting gdbserver directly. - See [test/functional/helpers.lua](https://github.com/neovim/neovim/blob/9cadbf1d36b63f53f0de48c8c5ff6c752ff05d70/test/functional/helpers.lua#L52-L69) for details. + See `nvim_argv` in https://github.com/neovim/neovim/blob/master/test/functional/testnvim.lua. - Hanging tests can happen due to unexpected "press-enter" prompts. The default screen width is 50 columns. Commands that try to print lines longer @@ -218,7 +221,7 @@ Guidelines - Luajit needs to know about type and constant declarations used in function prototypes. The - [helpers.lua](https://github.com/neovim/neovim/blob/master/test/unit/helpers.lua) + [testutil.lua](https://github.com/neovim/neovim/blob/master/test/unit/testutil.lua) file automatically parses `types.h`, so types used in the tested functions could be moved to it to avoid having to rewrite the declarations in the test files. @@ -252,7 +255,7 @@ by the semantic component they are testing. - _Functional tests_ ([test/functional](https://github.com/neovim/neovim/tree/master/test/functional)) are higher-level (plugins and user input) than unit tests; they are organized - by concept. + by concept. - Try to find an existing `test/functional/*/*_spec.lua` group that makes sense, before creating a new one. @@ -276,9 +279,9 @@ the file). Configuration ============= -Test behaviour is affected by environment variables. Currently supported -(Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, -treated as Integer; when defined, treated as String; when defined, treated as +Test behaviour is affected by environment variables. Currently supported +(Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, +treated as Integer; when defined, treated as String; when defined, treated as Number; !must be defined to function properly): - `BUSTED_ARGS` (F) (U): arguments forwarded to `busted`. @@ -297,7 +300,7 @@ Number; !must be defined to function properly): - `VALGRIND` (F) (D): makes nvim instances to be run under `valgrind`. Log files are named `valgrind-%p.log` in this case. Note that non-empty valgrind log may fail tests. Valgrind arguments may be seen in - `/test/functional/helpers.lua`. May be used in conjunction with `GDB`. + `/test/functional/testnvim.lua`. May be used in conjunction with `GDB`. - `VALGRIND_LOG` (F) (S): overrides valgrind log file name used for `VALGRIND`. diff --git a/test/benchmark/autocmd_spec.lua b/test/benchmark/autocmd_spec.lua index b3421d86eb..af5fa1c258 100644 --- a/test/benchmark/autocmd_spec.lua +++ b/test/benchmark/autocmd_spec.lua @@ -1,7 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local exec_lua = helpers.exec_lua +local clear = n.clear +local exec_lua = n.exec_lua local N = 7500 diff --git a/test/benchmark/bench_regexp_spec.lua b/test/benchmark/bench_regexp_spec.lua index 4a7c50557b..2c2b8dc359 100644 --- a/test/benchmark/bench_regexp_spec.lua +++ b/test/benchmark/bench_regexp_spec.lua @@ -1,8 +1,9 @@ -- Test for benchmarking the RE engine. -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, command = helpers.clear, helpers.command +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, command = n.clear, n.command -- Temporary file for gathering benchmarking results for each regexp engine. local result_file = 'benchmark.out' diff --git a/test/benchmark/extmark_spec.lua b/test/benchmark/extmark_spec.lua new file mode 100644 index 0000000000..0d284b363c --- /dev/null +++ b/test/benchmark/extmark_spec.lua @@ -0,0 +1,45 @@ +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua + +describe('extmark perf', function() + before_each(function() + clear() + + exec_lua([[ + out = {} + function start() + ts = vim.uv.hrtime() + end + function stop(name) + out[#out+1] = ('%14.6f ms - %s'):format((vim.uv.hrtime() - ts) / 1000000, name) + end + ]]) + end) + + after_each(function() + for _, line in ipairs(exec_lua([[return out]])) do + print(line) + end + end) + + it('repeatedly calling nvim_buf_clear_namespace #28615', function() + exec_lua([[ + vim.api.nvim_buf_set_lines(0, 0, -1, true, { 'foo', 'bar' }) + local ns0 = vim.api.nvim_create_namespace('ns0') + local ns1 = vim.api.nvim_create_namespace('ns1') + + for _ = 1, 10000 do + vim.api.nvim_buf_set_extmark(0, ns0, 0, 0, {}) + end + vim.api.nvim_buf_set_extmark(0, ns1, 1, 0, {}) + + start() + for _ = 1, 10000 do + vim.api.nvim_buf_clear_namespace(0, ns1, 0, -1) + end + stop('nvim_buf_clear_namespace') + ]]) + end) +end) diff --git a/test/benchmark/preload.lua b/test/benchmark/preload.lua index 1971ef77cc..a7b815ddf8 100644 --- a/test/benchmark/preload.lua +++ b/test/benchmark/preload.lua @@ -1,4 +1,4 @@ -- Modules loaded here will not be cleared and reloaded by Busted. -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. -local helpers = require('test.functional.helpers') +local n = require('test.functional.testnvim') diff --git a/test/benchmark/screenpos_spec.lua b/test/benchmark/screenpos_spec.lua index 8a80712dfa..db8f918817 100644 --- a/test/benchmark/screenpos_spec.lua +++ b/test/benchmark/screenpos_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local api = n.api + local function rand_utf8(count, seed) math.randomseed(seed) local symbols = { 'i', 'À', 'Ⱡ', '𐀀' } @@ -78,7 +80,7 @@ local N = 10000 local function benchmark(lines, expected_value) local lnum = #lines - local results = helpers.exec_lua( + local results = n.exec_lua( [==[ local N, lnum = ... @@ -99,7 +101,7 @@ local function benchmark(lines, expected_value) ) for _, value in ipairs(results[1]) do - helpers.eq(expected_value, value) + t.eq(expected_value, value) end local stats = results[2] table.sort(stats) @@ -119,7 +121,7 @@ end local function benchmarks(benchmark_results) describe('screenpos() perf', function() - before_each(helpers.clear) + before_each(n.clear) -- no breakindent for li, lines_type in ipairs(benchmark_lines) do @@ -134,7 +136,7 @@ local function benchmarks(benchmark_results) screen:attach() api.nvim_buf_set_lines(0, 0, 1, false, lines) -- for smaller screen expect (last line always different, first line same as others) - helpers.feed('G$') + n.feed('G$') screen:expect(result.screen) benchmark(lines, result.value) end) @@ -153,9 +155,9 @@ local function benchmarks(benchmark_results) local screen = Screen.new(width, height + 1) screen:attach() api.nvim_buf_set_lines(0, 0, 1, false, lines) - helpers.command('set breakindent') + n.command('set breakindent') -- for smaller screen expect (last line always different, first line same as others) - helpers.feed('G$') + n.feed('G$') screen:expect(result.screen) benchmark(lines, result.value) end) diff --git a/test/benchmark/treesitter_spec.lua b/test/benchmark/treesitter_spec.lua index 7c9906a7b2..b13b0fd9da 100644 --- a/test/benchmark/treesitter_spec.lua +++ b/test/benchmark/treesitter_spec.lua @@ -1,7 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local exec_lua = helpers.exec_lua +local clear = n.clear +local exec_lua = n.exec_lua describe('treesitter perf', function() setup(function() @@ -9,7 +9,7 @@ describe('treesitter perf', function() end) it('can handle large folds', function() - helpers.command 'edit ./src/nvim/eval.c' + n.command 'edit ./src/nvim/eval.c' exec_lua [[ local parser = vim.treesitter.get_parser(0, "c", {}) vim.treesitter.highlighter.new(parser) diff --git a/test/busted/outputHandlers/TAP.lua b/test/busted/outputHandlers/TAP.lua index 5de48c0ad3..2439547050 100644 --- a/test/busted/outputHandlers/TAP.lua +++ b/test/busted/outputHandlers/TAP.lua @@ -1,13 +1,13 @@ -- Extends the upstream TAP handler, to display the log with suiteEnd. -local global_helpers = require('test.helpers') +local t_global = require('test.testutil') return function(options) local busted = require 'busted' local handler = require 'busted.outputHandlers.TAP'(options) local suiteEnd = function() - io.write(global_helpers.read_nvim_log(nil, true)) + io.write(t_global.read_nvim_log(nil, true)) return nil, true end busted.subscribe({ 'suite', 'end' }, suiteEnd) diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua index 28855df261..a090761b5d 100644 --- a/test/busted/outputHandlers/nvim.lua +++ b/test/busted/outputHandlers/nvim.lua @@ -1,5 +1,5 @@ local pretty = require 'pl.pretty' -local global_helpers = require('test.helpers') +local t_global = require('test.testutil') local colors = setmetatable({}, { __index = function() @@ -236,7 +236,7 @@ return function(options) io.write(suiteEndString:format(testCount, tests, fileCount, files, elapsedTime_ms)) io.write(getSummaryString()) if failureCount > 0 or errorCount > 0 then - io.write(global_helpers.read_nvim_log(nil, true)) + io.write(t_global.read_nvim_log(nil, true)) end io.flush() diff --git a/test/client/uv_stream.lua b/test/client/uv_stream.lua index 0540c44eb2..adf002ba1e 100644 --- a/test/client/uv_stream.lua +++ b/test/client/uv_stream.lua @@ -136,7 +136,7 @@ function ChildProcessStream.spawn(argv, env, io_extra) end --- @diagnostic disable-next-line:missing-fields self._proc, self._pid = uv.spawn(prog, { - stdio = { self._child_stdin, self._child_stdout, 2, io_extra }, + stdio = { self._child_stdin, self._child_stdout, 1, io_extra }, args = args, --- @diagnostic disable-next-line:assign-type-mismatch env = env, diff --git a/test/cmakeconfig/paths.lua.in b/test/cmakeconfig/paths.lua.in index a35dbe8901..ce0eb870e0 100644 --- a/test/cmakeconfig/paths.lua.in +++ b/test/cmakeconfig/paths.lua.in @@ -1,22 +1,22 @@ -local module = {} +local M = {} -module.include_paths = {} +M.include_paths = {} for p in ("${TEST_INCLUDE_DIRS}" .. ";"):gmatch("[^;]+") do - table.insert(module.include_paths, p) + table.insert(M.include_paths, p) end -module.test_build_dir = "${CMAKE_BINARY_DIR}" -module.test_source_path = "${CMAKE_SOURCE_DIR}" -module.test_lua_prg = "${LUA_PRG}" -module.test_luajit_prg = "" -if module.test_luajit_prg == '' then - if module.test_lua_prg:sub(-6) == 'luajit' then - module.test_luajit_prg = module.test_lua_prg +M.test_build_dir = "${CMAKE_BINARY_DIR}" +M.test_source_path = "${CMAKE_SOURCE_DIR}" +M.test_lua_prg = "${LUA_PRG}" +M.test_luajit_prg = "" +if M.test_luajit_prg == '' then + if M.test_lua_prg:sub(-6) == 'luajit' then + M.test_luajit_prg = M.test_lua_prg else - module.test_luajit_prg = nil + M.test_luajit_prg = nil end end -table.insert(module.include_paths, "${CMAKE_BINARY_DIR}/include") -table.insert(module.include_paths, "${CMAKE_BINARY_DIR}/src/nvim/auto") +table.insert(M.include_paths, "${CMAKE_BINARY_DIR}/include") +table.insert(M.include_paths, "${CMAKE_BINARY_DIR}/src/nvim/auto") -return module +return M diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua index e89abf6c64..3f9883f43f 100644 --- a/test/functional/api/autocmd_spec.lua +++ b/test/functional/api/autocmd_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local neq = helpers.neq -local exec_lua = helpers.exec_lua -local matches = helpers.matches -local api = helpers.api -local source = helpers.source -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local neq = t.neq +local exec_lua = n.exec_lua +local matches = t.matches +local api = n.api +local source = n.source +local pcall_err = t.pcall_err before_each(clear) @@ -355,6 +356,44 @@ describe('autocmd api', function() test({ 'list' }) test({ foo = 'bar' }) end) + + it('function in arbitrary data is passed to all autocmds #28353', function() + eq( + 1303, + exec_lua([[ + local res = 1 + + local fun = function(m, x) + res = res * m + x + end + + local group = vim.api.nvim_create_augroup('MyTest', { clear = false }) + + vim.api.nvim_create_autocmd('User', { + group = group, + callback = function(payload) + payload.data.fun(10, payload.data.x) + end, + pattern = 'MyEvent', + }) + vim.api.nvim_create_autocmd('User', { + group = group, + callback = function(payload) + payload.data.fun(100, payload.data.x) + end, + pattern = 'MyEvent', + }) + + vim.api.nvim_exec_autocmds('User', { + group = group, + pattern = 'MyEvent', + data = { x = 3, fun = fun }, + }) + + return res + ]]) + ) + end) end) describe('nvim_get_autocmds', function() @@ -610,15 +649,17 @@ describe('autocmd api', function() it('can retrieve a callback from an autocmd', function() local content = 'I Am A Callback' api.nvim_set_var('content', content) - - local result = exec_lua([[ + exec_lua([[ local cb = function() return vim.g.content end vim.api.nvim_create_autocmd("User", { pattern = "TestTrigger", desc = "A test autocommand with a callback", callback = cb, }) - local aus = vim.api.nvim_get_autocmds({ event = 'User', pattern = 'TestTrigger'}) + ]]) + + local result = exec_lua([[ + local aus = vim.api.nvim_get_autocmds({ event = 'User', pattern = 'TestTrigger' }) local first = aus[1] return { cb = { @@ -627,9 +668,14 @@ describe('autocmd api', function() } } ]]) + eq({ cb = { type = 'function', can_retrieve = true } }, result) - eq('function', result.cb.type) - eq(true, result.cb.can_retrieve) + -- Also test with Vimscript + source([[ + let s:aus = nvim_get_autocmds({'event': 'User', 'pattern': 'TestTrigger'}) + let g:result = s:aus[0].callback() + ]]) + eq(content, api.nvim_get_var('result')) end) it( diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 78d220ff57..cf69958fd8 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -1,21 +1,23 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local eq = helpers.eq -local ok = helpers.ok -local describe_lua_and_rpc = helpers.describe_lua_and_rpc(describe) -local api = helpers.api -local fn = helpers.fn -local request = helpers.request -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local feed_command = helpers.feed_command -local insert = helpers.insert + +local clear = n.clear +local eq = t.eq +local ok = t.ok +local describe_lua_and_rpc = n.describe_lua_and_rpc(describe) +local api = n.api +local fn = n.fn +local request = n.request +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local feed_command = n.feed_command +local insert = n.insert local NIL = vim.NIL -local command = helpers.command -local feed = helpers.feed -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive +local command = n.command +local feed = n.feed +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive describe('api/buf', function() before_each(clear) @@ -121,6 +123,65 @@ describe('api/buf', function() eq({ 5, 2 }, api.nvim_win_get_cursor(win2)) end) + it('cursor position is maintained consistently with viewport', function() + local screen = Screen.new(20, 12) + screen:set_default_attr_ids { + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + [2] = { reverse = true, bold = true }, + [3] = { reverse = true }, + } + screen:attach() + + local lines = { 'line1', 'line2', 'line3', 'line4', 'line5', 'line6' } + local buf = api.nvim_get_current_buf() + + api.nvim_buf_set_lines(buf, 0, -1, true, lines) + + command('6') + command('new') + screen:expect { + grid = [[ + ^ | + {1:~ }|*4 + {2:[No Name] }| + line5 | + line6 | + {1:~ }|*2 + {3:[No Name] [+] }| + | + ]], + } + + lines[5] = 'boogalo 5' + api.nvim_buf_set_lines(buf, 0, -1, true, lines) + screen:expect { + grid = [[ + ^ | + {1:~ }|*4 + {2:[No Name] }| + boogalo 5 | + line6 | + {1:~ }|*2 + {3:[No Name] [+] }| + | + ]], + } + + command('wincmd w') + screen:expect { + grid = [[ + | + {1:~ }|*4 + {3:[No Name] }| + boogalo 5 | + ^line6 | + {1:~ }|*2 + {2:[No Name] [+] }| + | + ]], + } + end) + it('line_count has defined behaviour for unloaded buffers', function() -- we'll need to know our bufnr for when it gets unloaded local bufnr = api.nvim_buf_get_number(0) @@ -323,20 +384,20 @@ describe('api/buf', function() ]], } - -- inserting just before topline scrolls up api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' }) screen:expect { grid = [[ ^ | {1:~ }|*4 {2:[No Name] }| - mmm | wwweeee | xxx | yyy | + zzz | {3:[No Name] [+] }| | ]], + unchanged = true, } end) @@ -402,7 +463,6 @@ describe('api/buf', function() ]], } - -- inserting just before topline scrolls up api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' }) screen:expect { grid = [[ @@ -412,10 +472,10 @@ describe('api/buf', function() mmm | wwweeee | {2:[No Name] [+] }| - mmm | wwweeee | xxx | yyy | + zzz | {3:[No Name] [+] }| | ]], @@ -1316,12 +1376,7 @@ describe('api/buf', function() -- immediate call to nvim_win_get_cursor should have returned the same position eq({ 2, 12 }, cursor) -- coladd should be 0 - eq( - 0, - exec_lua([[ - return vim.fn.winsaveview().coladd - ]]) - ) + eq(0, fn.winsaveview().coladd) end) it('does not change cursor screen column when cursor >EOL and row got shorter', function() @@ -1335,9 +1390,7 @@ describe('api/buf', function() -- turn on virtualedit command('set virtualedit=all') -- move cursor after eol - exec_lua([[ - vim.fn.winrestview({ coladd = 5 }) - ]]) + fn.winrestview({ coladd = 5 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { @@ -1356,12 +1409,7 @@ describe('api/buf', function() -- immediate call to nvim_win_get_cursor should have returned the same position eq({ 2, 26 }, cursor) -- coladd should be increased so that cursor stays in the same screen column - eq( - 13, - exec_lua([[ - return vim.fn.winsaveview().coladd - ]]) - ) + eq(13, fn.winsaveview().coladd) end) it( @@ -1377,9 +1425,7 @@ describe('api/buf', function() -- turn on virtualedit command('set virtualedit=all') -- move cursor after eol - exec_lua([[ - vim.fn.winrestview({ coladd = 21 }) - ]]) + fn.winrestview({ coladd = 21 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { @@ -1398,12 +1444,7 @@ describe('api/buf', function() -- immediate call to nvim_win_get_cursor should have returned the same position eq({ 1, 38 }, cursor) -- coladd should be increased so that cursor stays in the same screen column - eq( - 2, - exec_lua([[ - return vim.fn.winsaveview().coladd - ]]) - ) + eq(2, fn.winsaveview().coladd) end ) @@ -1420,9 +1461,7 @@ describe('api/buf', function() -- turn on virtualedit command('set virtualedit=all') -- move cursor after eol just a bit - exec_lua([[ - vim.fn.winrestview({ coladd = 3 }) - ]]) + fn.winrestview({ coladd = 3 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { @@ -1441,12 +1480,7 @@ describe('api/buf', function() -- immediate call to nvim_win_get_cursor should have returned the same position eq({ 1, 22 }, cursor) -- coladd should become 0 - eq( - 0, - exec_lua([[ - return vim.fn.winsaveview().coladd - ]]) - ) + eq(0, fn.winsaveview().coladd) end ) @@ -1464,9 +1498,7 @@ describe('api/buf', function() -- turn on virtualedit command('set virtualedit=all') -- move cursor after eol - exec_lua([[ - vim.fn.winrestview({ coladd = 28 }) - ]]) + fn.winrestview({ coladd = 28 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 3, 11, { @@ -1485,12 +1517,7 @@ describe('api/buf', function() -- immediate call to nvim_win_get_cursor should have returned the same position eq({ 2, 26 }, cursor) -- coladd should be increased so that cursor stays in the same screen column - eq( - 13, - exec_lua([[ - return vim.fn.winsaveview().coladd - ]]) - ) + eq(13, fn.winsaveview().coladd) end ) end) @@ -1686,12 +1713,11 @@ describe('api/buf', function() api.nvim_buf_set_text(0, 0, 0, 1, 3, { 'XXX', 'YYY' }) screen:expect([[ - XXX | - YYY | - ^ | - ~ | - | - + XXX | + YYY | + ^ | + {1:~ }| + | ]]) end) @@ -2024,6 +2050,37 @@ describe('api/buf', function() eq(1, fn.filereadable(new_name)) os.remove(new_name) end) + + describe("with 'autochdir'", function() + local topdir + local oldbuf + local newbuf + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + + oldbuf = api.nvim_get_current_buf() + command('vnew') + newbuf = api.nvim_get_current_buf() + command('set autochdir') + end) + + after_each(function() + n.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with non-current buffer', function() + api.nvim_buf_set_name(oldbuf, topdir .. '/Xacd/foo.txt') + eq(topdir, fn.getcwd()) + end) + + it('changes cwd with current buffer', function() + api.nvim_buf_set_name(newbuf, topdir .. '/Xacd/foo.txt') + eq(topdir .. '/Xacd', fn.getcwd()) + end) + end) end) describe('nvim_buf_is_loaded', function() diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua index 262ca40e28..e030b45396 100644 --- a/test/functional/api/buffer_updates_spec.lua +++ b/test/functional/api/buffer_updates_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq, ok = helpers.eq, helpers.ok -local fn = helpers.fn -local api = helpers.api -local command, eval, next_msg = helpers.command, helpers.eval, helpers.next_msg -local nvim_prog = helpers.nvim_prog -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq, ok = t.eq, t.ok +local fn = n.fn +local api = n.api +local command, eval, next_msg = n.command, n.eval, n.next_msg +local nvim_prog = n.nvim_prog +local pcall_err = t.pcall_err local sleep = vim.uv.sleep -local write_file = helpers.write_file +local write_file = t.write_file local origlines = { 'original line 1', @@ -34,7 +36,7 @@ local function sendkeys(keys) end local function open(activate, lines) - local filename = helpers.tmpname() + local filename = t.tmpname() write_file(filename, table.concat(lines, '\n') .. '\n', true) command('edit ' .. filename) local b = api.nvim_get_current_buf() @@ -511,11 +513,11 @@ describe('API: buffer events:', function() -- create several new sessions, in addition to our main API local sessions = {} - local pipe = helpers.new_pipename() + local pipe = n.new_pipename() eval("serverstart('" .. pipe .. "')") - sessions[1] = helpers.connect(pipe) - sessions[2] = helpers.connect(pipe) - sessions[3] = helpers.connect(pipe) + sessions[1] = n.connect(pipe) + sessions[2] = n.connect(pipe) + sessions[3] = n.connect(pipe) local function request(sessionnr, method, ...) local status, rv = sessions[sessionnr]:request(method, ...) @@ -814,7 +816,7 @@ describe('API: buffer events:', function() clear() sleep(250) -- response - eq(true, helpers.request('nvim_buf_attach', 0, false, {})) + eq(true, n.request('nvim_buf_attach', 0, false, {})) -- notification eq({ [1] = 'notification', diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua index f73b9c8b13..a16c6a88e3 100644 --- a/test/functional/api/command_spec.lua +++ b/test/functional/api/command_spec.lua @@ -1,17 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local NIL = vim.NIL -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local api = helpers.api -local matches = helpers.matches -local source = helpers.source -local pcall_err = helpers.pcall_err -local exec_lua = helpers.exec_lua -local assert_alive = helpers.assert_alive -local feed = helpers.feed -local fn = helpers.fn +local clear = n.clear +local command = n.command +local eq = t.eq +local api = n.api +local matches = t.matches +local source = n.source +local pcall_err = t.pcall_err +local exec_lua = n.exec_lua +local assert_alive = n.assert_alive +local feed = n.feed +local fn = n.fn describe('nvim_get_commands', function() local cmd_dict = { diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 2acfbfc949..7b2fe209ba 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -1,20 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local request = helpers.request -local eq = helpers.eq -local ok = helpers.ok -local pcall_err = helpers.pcall_err -local insert = helpers.insert -local feed = helpers.feed -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local api = helpers.api -local assert_alive = helpers.assert_alive +local request = n.request +local eq = t.eq +local ok = t.ok +local pcall_err = t.pcall_err +local insert = n.insert +local feed = n.feed +local clear = n.clear +local command = n.command +local exec = n.exec +local api = n.api +local assert_alive = n.assert_alive local function expect(contents) - return eq(contents, helpers.curbuf_contents()) + return eq(contents, n.curbuf_contents()) end local function set_extmark(ns_id, id, line, col, opts) @@ -460,7 +461,7 @@ describe('API/extmarks', function() -- This shouldn't seg fault screen:expect([[ 12345^ 1 | - ~ |*8 + {1:~ }|*8 | ]]) end) @@ -513,7 +514,7 @@ describe('API/extmarks', function() insert('abc') screen:expect([[ ab^c12345 | - ~ |*8 + {1:~ }|*8 | ]]) local rv = get_extmark_by_id(ns, marks[1]) @@ -1568,7 +1569,7 @@ describe('API/extmarks', function() sign_text = '>>', spell = true, virt_lines = { - { { 'lines', 'Macro' }, { '???' } }, + { { 'lines', 'Macro' }, { '???' }, { ';;;', '' } }, { { 'stack', { 'Type', 'Search' } }, { '!!!' } }, }, virt_lines_above = true, @@ -1603,7 +1604,7 @@ describe('API/extmarks', function() sign_text = '>>', spell = true, virt_lines = { - { { 'lines', 'Macro' }, { '???' } }, + { { 'lines', 'Macro' }, { '???' }, { ';;;', '' } }, { { 'stack', { 'Type', 'Search' } }, { '!!!' } }, }, virt_lines_above = true, @@ -1734,16 +1735,17 @@ describe('API/extmarks', function() command('d2') screen:expect([[ S2^aaa bbb ccc | - aaa bbb ccc |*3 - |*2 + {7: }aaa bbb ccc |*3 + {7: } | + | ]]) -- mark is restored with undo_restore == true command('silent undo') screen:expect([[ - S1 ^aaa bbb ccc | - S1S2aaa bbb ccc | - S2 aaa bbb ccc | - aaa bbb ccc |*2 + S1{7: }^aaa bbb ccc | + S2S1aaa bbb ccc | + S2{7: }aaa bbb ccc | + {7: }aaa bbb ccc |*2 | ]]) -- decor is not removed twice @@ -1894,6 +1896,24 @@ describe('Extmarks buffer api with many marks', function() end eq(ns_marks[ns1], get_marks(ns1)) eq(ns_marks[ns2], get_marks(ns2)) + + api.nvim_buf_clear_namespace(0, ns1, 0, 10) + for id, mark in pairs(ns_marks[ns1]) do + if mark[1] < 10 then + ns_marks[ns1][id] = nil + end + end + eq(ns_marks[ns1], get_marks(ns1)) + eq(ns_marks[ns2], get_marks(ns2)) + + api.nvim_buf_clear_namespace(0, ns1, 20, -1) + for id, mark in pairs(ns_marks[ns1]) do + if mark[1] >= 20 then + ns_marks[ns1][id] = nil + end + end + eq(ns_marks[ns1], get_marks(ns1)) + eq(ns_marks[ns2], get_marks(ns2)) end) it('can delete line', function() @@ -1964,7 +1984,7 @@ describe('API/win_extmark', function() grid = [[ non ui-watched line | ui-watched lin^e | - ~ | + {1:~ }| | ]], extmarks = { @@ -2052,7 +2072,7 @@ describe('API/win_extmark', function() grid = [[ ui-watched linupdat^e| e | - ~ | + {1:~ }| | ]], extmarks = { @@ -2079,9 +2099,9 @@ describe('API/win_extmark', function() grid = [[ ## grid 1 [4:--------------------]|*3 - [No Name] [+] | + {3:[No Name] [+] }| [2:--------------------]|*2 - [No Name] [+] | + {2:[No Name] [+] }| [3:--------------------]| ## grid 2 non ui-watched line | @@ -2091,7 +2111,7 @@ describe('API/win_extmark', function() ## grid 4 non ui-watched line | ui-watched lin^e | - ~ | + {1:~ }| ]], extmarks = { [2] = { @@ -2112,13 +2132,13 @@ describe('API/win_extmark', function() grid = [[ ## grid 1 [4:--------------------]|*3 - [No Name] [+] | + {3:[No Name] [+] }| [2:--------------------]|*2 - [No Name] [+] | + {2:[No Name] [+] }| [3:--------------------]| ## grid 2 non ui-watched line | - ui-watched linupd@@@| + ui-watched linupd{1:@@@}| ## grid 3 | ## grid 4 diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 1973d3e1c7..dd0611f184 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq, eval = helpers.eq, helpers.eval -local command = helpers.command -local exec_capture = helpers.exec_capture -local api = helpers.api -local fn = helpers.fn -local pcall_err = helpers.pcall_err -local ok = helpers.ok -local assert_alive = helpers.assert_alive + +local clear = n.clear +local eq, eval = t.eq, n.eval +local command = n.command +local exec_capture = n.exec_capture +local api = n.api +local fn = n.fn +local pcall_err = t.pcall_err +local ok = t.ok +local assert_alive = n.assert_alive describe('API: highlight', function() clear() diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index 0decd710e9..995711507f 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local eq, neq = helpers.eq, helpers.neq -local exec_lua = helpers.exec_lua -local exec = helpers.exec -local feed = helpers.feed -local fn = helpers.fn -local api = helpers.api -local source = helpers.source -local pcall_err = helpers.pcall_err - -local shallowcopy = helpers.shallowcopy +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq, neq = t.eq, t.neq +local exec_lua = n.exec_lua +local exec = n.exec +local feed = n.feed +local fn = n.fn +local api = n.api +local matches = t.matches +local source = n.source +local pcall_err = t.pcall_err + +local shallowcopy = t.shallowcopy local sleep = vim.uv.sleep local sid_api_client = -9 @@ -398,7 +400,9 @@ describe('nvim_get_keymap', function() 0, exec_lua([[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]]) ) @@ -738,7 +742,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function() end end - it('can set mappings containing literal keycodes', function() + it('can set mappings containing C0 control codes', function() api.nvim_set_keymap('n', '\n\r\n', 'rhs', {}) local expected = generate_mapargs('n', '<NL><CR><NL>', 'rhs') eq(expected, get_mapargs('n', '<NL><CR><NL>')) @@ -951,7 +955,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -963,34 +969,38 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it(':map command shows lua mapping correctly', function() exec_lua [[ - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() print('jkl;') end, + }) ]] - assert.truthy( - string.match( - exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]], - '^\nn asdf <Lua %d+>' - ) + matches( + '^\nn asdf <Lua %d+>', + exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]] ) end) it('mapcheck() returns lua mapping correctly', function() exec_lua [[ - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() print('jkl;') end, + }) ]] - assert.truthy(string.match(fn.mapcheck('asdf', 'n'), '^<Lua %d+>')) + matches('^<Lua %d+>', fn.mapcheck('asdf', 'n')) end) - it('maparg() returns lua mapping correctly', function() + it('maparg() and maplist() return lua mapping correctly', function() eq( 0, exec_lua([[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]]) ) - assert.truthy(string.match(fn.maparg('asdf', 'n'), '^<Lua %d+>')) + matches('^<Lua %d+>', fn.maparg('asdf', 'n')) local mapargs = fn.maparg('asdf', 'n', false, true) mapargs.callback = nil @@ -1010,11 +1020,20 @@ describe('nvim_set_keymap, nvim_del_keymap', function() call maparg('asdf', 'n', v:false, v:true).callback() ]]) eq(2, exec_lua([[return GlobalCount]])) + + api.nvim_eval([[ + maplist()->filter({_, m -> m.lhs == 'asdf'})->foreach({_, m -> m.callback()}) + ]]) + eq(3, exec_lua([[return GlobalCount]])) end) it('can make lua expr mappings replacing keycodes', function() exec_lua [[ - vim.api.nvim_set_keymap('n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true }) + vim.api.nvim_set_keymap('n', 'aa', '', { + callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, + expr = true, + replace_keycodes = true, + }) ]] feed('aa') @@ -1024,7 +1043,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it('can make lua expr mappings without replacing keycodes', function() exec_lua [[ - vim.api.nvim_set_keymap('i', 'aa', '', {callback = function() return '<space>' end, expr = true }) + vim.api.nvim_set_keymap('i', 'aa', '', { + callback = function() return '<space>' end, + expr = true, + }) ]] feed('iaa<esc>') @@ -1034,7 +1056,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it('lua expr mapping returning nil is equivalent to returning an empty string', function() exec_lua [[ - vim.api.nvim_set_keymap('i', 'aa', '', {callback = function() return nil end, expr = true }) + vim.api.nvim_set_keymap('i', 'aa', '', { + callback = function() return nil end, + expr = true, + }) ]] feed('iaa<esc>') @@ -1047,7 +1072,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ VisibleCount = 0 - vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end}) + vim.api.nvim_set_keymap('i', '<F2>', '', { + callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end, + }) return VisibleCount ]] ) @@ -1060,7 +1087,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ OpCount = 0 - vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end}) + vim.api.nvim_set_keymap('o', '<F2>', '', { + callback = function() OpCount = OpCount + 1 end, + }) return OpCount ]] ) @@ -1075,7 +1104,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1085,7 +1116,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount - 1 end, + }) ]] feed('asdf\n') @@ -1098,7 +1131,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1107,14 +1142,12 @@ describe('nvim_set_keymap, nvim_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) - exec_lua [[ - vim.api.nvim_del_keymap('n', 'asdf' ) - ]] + exec_lua [[vim.api.nvim_del_keymap('n', 'asdf' )]] feed('asdf\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) + eq('\nNo mapping found', n.exec_capture('nmap asdf')) end) it('no double-free when unmapping simplifiable lua mappings', function() @@ -1122,7 +1155,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', '<C-I>', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1131,29 +1166,30 @@ describe('nvim_set_keymap, nvim_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) - exec_lua [[ - vim.api.nvim_del_keymap('n', '<C-I>') - ]] + exec_lua [[vim.api.nvim_del_keymap('n', '<C-I>')]] feed('<C-I>\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>')) + eq('\nNo mapping found', n.exec_capture('nmap <C-I>')) end) it('can set descriptions on mappings', function() api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' }) eq(generate_mapargs('n', 'lhs', 'rhs', { desc = 'map description' }), get_mapargs('n', 'lhs')) - eq('\nn lhs rhs\n map description', helpers.exec_capture('nmap lhs')) + eq('\nn lhs rhs\n map description', n.exec_capture('nmap lhs')) end) it('can define !-mode abbreviations with lua callbacks', function() exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('!a', 'foo', '', {expr = true, callback = function() - GlobalCount = GlobalCount + 1 - return tostring(GlobalCount) - end}) + vim.api.nvim_set_keymap('!a', 'foo', '', { + expr = true, + callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end, + }) ]] feed 'iThe foo and the bar and the foo again<esc>' @@ -1166,10 +1202,13 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it('can define insert mode abbreviations with lua callbacks', function() exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('ia', 'foo', '', {expr = true, callback = function() - GlobalCount = GlobalCount + 1 - return tostring(GlobalCount) - end}) + vim.api.nvim_set_keymap('ia', 'foo', '', { + expr = true, + callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end, + }) ]] feed 'iThe foo and the bar and the foo again<esc>' @@ -1182,10 +1221,13 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it('can define cmdline mode abbreviations with lua callbacks', function() exec_lua [[ GlobalCount = 0 - vim.api.nvim_set_keymap('ca', 'foo', '', {expr = true, callback = function() - GlobalCount = GlobalCount + 1 - return tostring(GlobalCount) - end}) + vim.api.nvim_set_keymap('ca', 'foo', '', { + expr = true, + callback = function() + GlobalCount = GlobalCount + 1 + return tostring(GlobalCount) + end, + }) ]] feed 'iThe foo and the bar and the foo again<esc>' @@ -1290,7 +1332,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() it('does not crash when setting mapping in a non-existing buffer #13541', function() pcall_err(api.nvim_buf_set_keymap, 100, '', 'lsh', 'irhs<Esc>', {}) - helpers.assert_alive() + n.assert_alive() end) it('can make lua mappings', function() @@ -1298,7 +1340,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1310,7 +1354,11 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() it('can make lua expr mappings replacing keycodes', function() exec_lua [[ - vim.api.nvim_buf_set_keymap(0, 'n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true }) + vim.api.nvim_buf_set_keymap(0, 'n', 'aa', '', { + callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, + expr = true, + replace_keycodes = true, + }) ]] feed('aa') @@ -1320,7 +1368,10 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() it('can make lua expr mappings without replacing keycodes', function() exec_lua [[ - vim.api.nvim_buf_set_keymap(0, 'i', 'aa', '', {callback = function() return '<space>' end, expr = true }) + vim.api.nvim_buf_set_keymap(0, 'i', 'aa', '', { + callback = function() return '<space>' end, + expr = true, + }) ]] feed('iaa<esc>') @@ -1333,7 +1384,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1343,7 +1396,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ - vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end }) + vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount - 1 end, + }) ]] feed('asdf\n') @@ -1356,7 +1411,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1365,14 +1422,12 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) - exec_lua [[ - vim.api.nvim_buf_del_keymap(0, 'n', 'asdf' ) - ]] + exec_lua [[vim.api.nvim_buf_del_keymap(0, 'n', 'asdf' )]] feed('asdf\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) + eq('\nNo mapping found', n.exec_capture('nmap asdf')) end) it('no double-free when unmapping simplifiable lua mappings', function() @@ -1380,7 +1435,9 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() 0, exec_lua [[ GlobalCount = 0 - vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]] ) @@ -1389,13 +1446,11 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() eq(1, exec_lua [[return GlobalCount]]) - exec_lua [[ - vim.api.nvim_buf_del_keymap(0, 'n', '<C-I>') - ]] + exec_lua [[vim.api.nvim_buf_del_keymap(0, 'n', '<C-I>')]] feed('<C-I>\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>')) + eq('\nNo mapping found', n.exec_capture('nmap <C-I>')) end) end) diff --git a/test/functional/api/menu_spec.lua b/test/functional/api/menu_spec.lua index 44b9039393..76eef164c9 100644 --- a/test/functional/api/menu_spec.lua +++ b/test/functional/api/menu_spec.lua @@ -1,9 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed +local clear = n.clear +local command = n.command +local feed = n.feed describe('update_menu notification', function() local screen diff --git a/test/functional/api/proc_spec.lua b/test/functional/api/proc_spec.lua index 50c441792c..d2dd655b17 100644 --- a/test/functional/api/proc_spec.lua +++ b/test/functional/api/proc_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local fn = helpers.fn -local neq = helpers.neq -local nvim_argv = helpers.nvim_argv -local request = helpers.request -local retry = helpers.retry +local clear = n.clear +local eq = t.eq +local fn = n.fn +local neq = t.neq +local nvim_argv = n.nvim_argv +local request = n.request +local retry = t.retry local NIL = vim.NIL -local is_os = helpers.is_os +local is_os = t.is_os describe('API', function() before_each(clear) diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index d1608a951c..7b4c4e8312 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_log = helpers.assert_log -local eq, clear, eval, command, next_msg = - helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.next_msg -local api = helpers.api -local exec_lua = helpers.exec_lua -local retry = helpers.retry -local assert_alive = helpers.assert_alive +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear, eval, command, next_msg = t.eq, n.clear, n.eval, n.command, n.next_msg +local api = n.api +local exec_lua = n.exec_lua +local retry = t.retry +local assert_alive = n.assert_alive +local check_close = n.check_close local testlog = 'Xtest-server-notify-log' @@ -18,6 +19,7 @@ describe('notify', function() end) after_each(function() + check_close() os.remove(testlog) end) @@ -31,18 +33,18 @@ describe('notify', function() end) end) - describe('passing 0 as the channel id', function() - it('sends the notification/args to all subscribed channels', function() - api.nvim_subscribe('event2') + describe('channel id 0', function() + it('broadcasts the notification/args to all channels', function() eval('rpcnotify(0, "event1", 1, 2, 3)') eval('rpcnotify(0, "event2", 4, 5, 6)') eval('rpcnotify(0, "event2", 7, 8, 9)') + eq({ 'notification', 'event1', { 1, 2, 3 } }, next_msg()) eq({ 'notification', 'event2', { 4, 5, 6 } }, next_msg()) eq({ 'notification', 'event2', { 7, 8, 9 } }, next_msg()) - api.nvim_unsubscribe('event2') - api.nvim_subscribe('event1') + eval('rpcnotify(0, "event2", 10, 11, 12)') eval('rpcnotify(0, "event1", 13, 14, 15)') + eq({ 'notification', 'event2', { 10, 11, 12 } }, next_msg()) eq({ 'notification', 'event1', { 13, 14, 15 } }, next_msg()) end) @@ -75,17 +77,6 @@ describe('notify', function() end) end) - it('unsubscribe non-existing event #8745', function() - clear { env = { - NVIM_LOG_FILE = testlog, - } } - api.nvim_subscribe('event1') - api.nvim_unsubscribe('doesnotexist') - assert_log("tried to unsubscribe unknown event 'doesnotexist'", testlog, 10) - api.nvim_unsubscribe('event1') - assert_alive() - end) - it('cancels stale events on channel close', function() local catchan = eval("jobstart(['cat'], {'rpc': v:true})") local catpath = eval('exepath("cat")') @@ -94,7 +85,6 @@ describe('notify', function() exec_lua( [[ vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'}) - vim.rpcnotify(..., "nvim_subscribe", "daily_rant") return vim.api.nvim_get_chan_info(...) ]], catchan diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 298dbac217..bdd340f6c6 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -1,17 +1,18 @@ -- Test server -> client RPC scenarios. Note: unlike `rpcnotify`, to evaluate -- `rpcrequest` calls we need the client event loop to be running. -local helpers = require('test.functional.helpers')(after_each) - -local clear, eval = helpers.clear, helpers.eval -local eq, neq, run, stop = helpers.eq, helpers.neq, helpers.run, helpers.stop -local nvim_prog, command, fn = helpers.nvim_prog, helpers.command, helpers.fn -local source, next_msg = helpers.source, helpers.next_msg -local ok = helpers.ok -local api = helpers.api -local spawn, merge_args = helpers.spawn, helpers.merge_args -local set_session = helpers.set_session -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval = n.clear, n.eval +local eq, neq, run, stop = t.eq, t.neq, n.run, n.stop +local nvim_prog, command, fn = n.nvim_prog, n.command, n.fn +local source, next_msg = n.source, n.next_msg +local ok = t.ok +local api = n.api +local spawn, merge_args = n.spawn, n.merge_args +local set_session = n.set_session +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive describe('server -> client', function() local cid @@ -91,19 +92,19 @@ describe('server -> client', function() local function on_request(method, args) eq('rcall', method) - local n = unpack(args) * 2 - if n <= 16 then + local _n = unpack(args) * 2 + if _n <= 16 then local cmd - if n == 4 then - cmd = 'let g:result2 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' - elseif n == 8 then - cmd = 'let g:result3 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' - elseif n == 16 then - cmd = 'let g:result4 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' + if _n == 4 then + cmd = 'let g:result2 = rpcrequest(' .. cid .. ', "rcall", ' .. _n .. ')' + elseif _n == 8 then + cmd = 'let g:result3 = rpcrequest(' .. cid .. ', "rcall", ' .. _n .. ')' + elseif _n == 16 then + cmd = 'let g:result4 = rpcrequest(' .. cid .. ', "rcall", ' .. _n .. ')' end command(cmd) end - return n + return _n end run(on_request, nil, on_setup) end) @@ -259,7 +260,7 @@ describe('server -> client', function() pcall(fn.jobstop, jobid) end) - if helpers.skip(helpers.is_os('win')) then + if t.skip(t.is_os('win')) then return end @@ -280,7 +281,7 @@ describe('server -> client', function() end) describe('connecting to another (peer) nvim', function() - local nvim_argv = merge_args(helpers.nvim_argv, { '--headless' }) + local nvim_argv = merge_args(n.nvim_argv, { '--headless' }) local function connect_test(server, mode, address) local serverpid = fn.getpid() local client = spawn(nvim_argv, false, nil, true) @@ -363,6 +364,24 @@ describe('server -> client', function() server:close() client:close() end) + + it('via stdio, with many small flushes does not crash #23781', function() + source([[ + let chan = jobstart([v:progpath, '--embed', '--headless', '-n', '-u', 'NONE', '-i', 'NONE'], { 'rpc':v:false }) + call chansend(chan, 0Z94) + sleep 50m + call chansend(chan, 0Z00) + call chansend(chan, 0Z01) + call chansend(chan, 0ZAC) + call chansend(chan, 0Z6E76696D5F636F6D6D616E64) + call chansend(chan, 0Z91) + call chansend(chan, 0ZA5) + call chansend(chan, 0Z71616C6C21) + let g:statuses = jobwait([chan]) + ]]) + eq(eval('g:statuses'), { 0 }) + assert_alive() + end) end) describe('connecting to its own pipe address', function() diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index 36955c4ace..74858475c8 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -1,11 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok -local api = helpers.api -local fn = helpers.fn -local request = helpers.request +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, ok = n.clear, t.eq, t.ok +local exec = n.exec +local feed = n.feed +local api = n.api +local fn = n.fn +local request = n.request local NIL = vim.NIL -local pcall_err = helpers.pcall_err -local command = helpers.command +local pcall_err = t.pcall_err +local command = n.command describe('api/tabpage', function() before_each(clear) @@ -86,6 +90,30 @@ describe('api/tabpage', function() pcall_err(api.nvim_tabpage_set_win, tab1, win3) ) end) + + it('does not switch window when textlocked or in the cmdwin', function() + local target_win = api.nvim_get_current_win() + feed('q:') + local cur_win = api.nvim_get_current_win() + eq( + 'Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_tabpage_set_win, 0, target_win) + ) + eq(cur_win, api.nvim_get_current_win()) + command('quit!') + + exec(([[ + new + call setline(1, 'foo') + setlocal debug=throw indentexpr=nvim_tabpage_set_win(0,%d) + ]]):format(target_win)) + cur_win = api.nvim_get_current_win() + eq( + 'Vim(normal):E5555: API call: Vim:E565: Not allowed to change text or change window', + pcall_err(command, 'normal! ==') + ) + eq(cur_win, api.nvim_get_current_win()) + end) end) describe('{get,set,del}_var', function() diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua index 3e1f1ec965..2145db7f8a 100644 --- a/test/functional/api/ui_spec.lua +++ b/test/functional/api/ui_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local exec = helpers.exec -local feed = helpers.feed -local api = helpers.api -local request = helpers.request -local pcall_err = helpers.pcall_err + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local exec = n.exec +local feed = n.feed +local api = n.api +local request = n.request +local pcall_err = t.pcall_err describe('nvim_ui_attach()', function() before_each(function() diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index c304f1aa88..5dad9978b7 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, fn, eq = helpers.clear, helpers.fn, helpers.eq -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, fn, eq = n.clear, n.fn, t.eq +local api = n.api local function read_mpack_file(fname) local fd = io.open(fname, 'rb') diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 9a4a457637..fd0535aa51 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,42 +1,43 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') local uv = vim.uv local fmt = string.format -local dedent = helpers.dedent -local assert_alive = helpers.assert_alive +local dedent = t.dedent +local assert_alive = n.assert_alive local NIL = vim.NIL -local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq -local command = helpers.command -local command_output = helpers.api.nvim_command_output -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local eval = helpers.eval -local expect = helpers.expect -local fn = helpers.fn -local api = helpers.api -local matches = helpers.matches +local clear, eq, neq = n.clear, t.eq, t.neq +local command = n.command +local command_output = n.api.nvim_command_output +local exec = n.exec +local exec_capture = n.exec_capture +local eval = n.eval +local expect = n.expect +local fn = n.fn +local api = n.api +local matches = t.matches local pesc = vim.pesc -local mkdir_p = helpers.mkdir_p -local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed -local async_meths = helpers.async_meths -local is_os = helpers.is_os -local parse_context = helpers.parse_context -local request = helpers.request -local rmdir = helpers.rmdir -local source = helpers.source -local next_msg = helpers.next_msg -local tmpname = helpers.tmpname -local write_file = helpers.write_file -local exec_lua = helpers.exec_lua -local exc_exec = helpers.exc_exec -local insert = helpers.insert -local skip = helpers.skip - -local pcall_err = helpers.pcall_err +local mkdir_p = n.mkdir_p +local ok, nvim_async, feed = t.ok, n.nvim_async, n.feed +local async_meths = n.async_meths +local is_os = t.is_os +local parse_context = n.parse_context +local request = n.request +local rmdir = n.rmdir +local source = n.source +local next_msg = n.next_msg +local tmpname = t.tmpname +local write_file = t.write_file +local exec_lua = n.exec_lua +local exc_exec = n.exc_exec +local insert = n.insert +local skip = t.skip + +local pcall_err = t.pcall_err local format_string = require('test.format_string').format_string -local intchar2lua = helpers.intchar2lua -local mergedicts_copy = helpers.mergedicts_copy +local intchar2lua = t.intchar2lua +local mergedicts_copy = t.mergedicts_copy local endswith = vim.endswith describe('API', function() @@ -559,6 +560,16 @@ describe('API', function() eq('Vim:E121: Undefined variable: bogus', pcall_err(request, 'nvim_eval', 'bogus expression')) eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) + + it('can return Lua function to Lua code', function() + eq( + [["a string with \"double quotes\" and 'single quotes'"]], + exec_lua([=[ + local fun = vim.api.nvim_eval([[luaeval('string.format')]]) + return fun('%q', [[a string with "double quotes" and 'single quotes']]) + ]=]) + ) + end) end) describe('nvim_call_function', function() @@ -624,6 +635,16 @@ describe('API', function() pcall_err(request, 'nvim_call_function', 'Foo', too_many_args) ) end) + + it('can return Lua function to Lua code', function() + eq( + [["a string with \"double quotes\" and 'single quotes'"]], + exec_lua([=[ + local fun = vim.api.nvim_call_function('luaeval', { 'string.format' }) + return fun('%q', [[a string with "double quotes" and 'single quotes']]) + ]=]) + ) + end) end) describe('nvim_call_dict_function', function() @@ -702,18 +723,18 @@ describe('API', function() end) after_each(function() - helpers.rmdir('Xtestdir') + n.rmdir('Xtestdir') end) it('works', function() api.nvim_set_current_dir('Xtestdir') - eq(fn.getcwd(), start_dir .. helpers.get_pathsep() .. 'Xtestdir') + eq(start_dir .. n.get_pathsep() .. 'Xtestdir', fn.getcwd()) end) it('sets previous directory', function() api.nvim_set_current_dir('Xtestdir') command('cd -') - eq(fn.getcwd(), start_dir) + eq(start_dir, fn.getcwd()) end) end) @@ -1269,7 +1290,7 @@ describe('API', function() api.nvim_paste('', true, 3) screen:expect([[ | - ~ |*2 + {1:~ }|*2 :Foo^ | ]]) end) @@ -1280,8 +1301,8 @@ describe('API', function() api.nvim_paste('normal! \023\022\006\027', true, -1) screen:expect([[ | - ~ |*2 - :normal! ^W^V^F^[^ | + {1:~ }|*2 + :normal! {18:^W^V^F^[}^ | ]]) end) it('crlf=false does not break lines at CR, CRLF', function() @@ -1467,7 +1488,7 @@ describe('API', function() eq(NIL, api.nvim_get_var('Unknown_script_func')) -- Check if autoload works properly - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() local xconfig = 'Xhome' .. pathsep .. 'Xconfig' local xdata = 'Xhome' .. pathsep .. 'Xdata' local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep) @@ -1593,14 +1614,12 @@ describe('API', function() api.nvim_set_option_value('equalalways', false, {}) local status, rv = pcall(command_output, 'verbose set equalalways?') eq(true, status) - ok( - nil ~= string.find(rv, 'noequalalways\n' .. '\tLast set from API client %(channel id %d+%)') - ) + matches('noequalalways\n' .. '\tLast set from API client %(channel id %d+%)', rv) api.nvim_exec_lua('vim.api.nvim_set_option_value("equalalways", true, {})', {}) status, rv = pcall(command_output, 'verbose set equalalways?') eq(true, status) - eq(' equalalways\n\tLast set from Lua', rv) + eq(' equalalways\n\tLast set from Lua (run Nvim with -V1 for more details)', rv) end) it('updates whether the option has ever been set #25025', function() @@ -1953,7 +1972,7 @@ describe('API', function() describe('RPC (K_EVENT)', function() it('does not complete ("interrupt") normal-mode operator-pending #6166', function() - helpers.insert([[ + n.insert([[ FIRST LINE SECOND LINE]]) api.nvim_input('gg') @@ -1981,16 +2000,16 @@ describe('API', function() -- Make any RPC request (can be non-async: op-pending does not block). api.nvim_get_current_buf() screen:expect([[ - ^a$ | - b$ | - c$ | + ^a{1:$} | + b{1:$} | + c{1:$} | | ]]) end) it('does not complete ("interrupt") normal-mode map-pending #6166', function() command("nnoremap dd :let g:foo='it worked...'<CR>") - helpers.insert([[ + n.insert([[ FIRST LINE SECOND LINE]]) api.nvim_input('gg') @@ -2002,13 +2021,13 @@ describe('API', function() expect([[ FIRST LINE SECOND LINE]]) - eq('it worked...', helpers.eval('g:foo')) + eq('it worked...', n.eval('g:foo')) end) it('does not complete ("interrupt") insert-mode map-pending #6166', function() command('inoremap xx foo') command('set timeoutlen=9999') - helpers.insert([[ + n.insert([[ FIRST LINE SECOND LINE]]) api.nvim_input('ix') @@ -2155,35 +2174,32 @@ describe('API', function() describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() - eq('\128\254X', helpers.api.nvim_replace_termcodes('\128', true, true, true)) + eq('\128\254X', n.api.nvim_replace_termcodes('\128', true, true, true)) end) it('leaves non-K_SPECIAL string unchanged', function() - eq('abc', helpers.api.nvim_replace_termcodes('abc', true, true, true)) + eq('abc', n.api.nvim_replace_termcodes('abc', true, true, true)) end) it('converts <expressions>', function() - eq('\\', helpers.api.nvim_replace_termcodes('<Leader>', true, true, true)) + eq('\\', n.api.nvim_replace_termcodes('<Leader>', true, true, true)) end) it('converts <LeftMouse> to K_SPECIAL KS_EXTRA KE_LEFTMOUSE', function() -- K_SPECIAL KS_EXTRA KE_LEFTMOUSE -- 0x80 0xfd 0x2c -- 128 253 44 - eq('\128\253\44', helpers.api.nvim_replace_termcodes('<LeftMouse>', true, true, true)) + eq('\128\253\44', n.api.nvim_replace_termcodes('<LeftMouse>', true, true, true)) end) it('converts keycodes', function() - eq( - '\nx\27x\rx<x', - helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, true) - ) + eq('\nx\27x\rx<x', n.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, true)) end) it('does not convert keycodes if special=false', function() eq( '<NL>x<Esc>x<CR>x<lt>x', - helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, false) + n.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, false) ) end) @@ -2212,18 +2228,18 @@ describe('API', function() api.nvim_feedkeys(':let x1="…"\n', '', true) -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80 - local inp = helpers.api.nvim_replace_termcodes(':let x2="…"<CR>', true, true, true) + local inp = n.api.nvim_replace_termcodes(':let x2="…"<CR>', true, true, true) api.nvim_feedkeys(inp, '', true) -- escape_ks=true -- nvim_feedkeys with K_SPECIAL escaping disabled - inp = helpers.api.nvim_replace_termcodes(':let x3="…"<CR>', true, true, true) + inp = n.api.nvim_replace_termcodes(':let x3="…"<CR>', true, true, true) api.nvim_feedkeys(inp, '', false) -- escape_ks=false - helpers.stop() + n.stop() end -- spin the loop a bit - helpers.run(nil, nil, on_setup) + n.run(nil, nil, on_setup) eq('…', api.nvim_get_var('x1')) -- Because of the double escaping this is neq @@ -2366,7 +2382,7 @@ describe('API', function() {0:~ }|*6 {1:very fail} | ]]) - helpers.poke_eventloop() + n.poke_eventloop() -- shows up to &cmdheight lines async_meths.nvim_err_write('more fail\ntoo fail\n') @@ -2678,7 +2694,7 @@ describe('API', function() describe('nvim_list_runtime_paths', function() setup(function() - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() mkdir_p('Xtest' .. pathsep .. 'a') mkdir_p('Xtest' .. pathsep .. 'b') end) @@ -2723,7 +2739,7 @@ describe('API', function() it('can throw exceptions', function() local status, err = pcall(api.nvim_get_option_value, 'invalid-option', {}) eq(false, status) - ok(err:match("Unknown option 'invalid%-option'") ~= nil) + matches("Unknown option 'invalid%-option'", err) end) it('does not truncate error message <1 MB #5984', function() @@ -2736,10 +2752,7 @@ describe('API', function() it('does not leak memory on incorrect argument types', function() local status, err = pcall(api.nvim_set_current_dir, { 'not', 'a', 'dir' }) eq(false, status) - ok( - err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String') - ~= nil - ) + matches(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String', err) end) describe('nvim_parse_expression', function() @@ -3135,10 +3148,60 @@ describe('API', function() -- nowadays this works because we don't execute any spurious autocmds at all #24824 assert_alive() end) + + it('no memory leak when autocommands load the buffer immediately', function() + exec([[ + autocmd BufNew * ++once call bufload(expand("<abuf>")->str2nr()) + \| let loaded = bufloaded(expand("<abuf>")->str2nr()) + ]]) + api.nvim_create_buf(false, true) + eq(1, eval('g:loaded')) + end) + + it('creating scratch buffer where autocommands set &swapfile works', function() + exec([[ + autocmd BufNew * ++once execute expand("<abuf>") "buffer" + \| file foobar + \| setlocal swapfile + ]]) + local new_buf = api.nvim_create_buf(false, true) + neq('', fn.swapname(new_buf)) + end) + + it('fires expected autocommands', function() + exec([=[ + " Append the &buftype to check autocommands trigger *after* the buffer was configured to be + " scratch, if applicable. + autocmd BufNew * let fired += [["BufNew", expand("<abuf>")->str2nr(), + \ getbufvar(expand("<abuf>")->str2nr(), "&buftype")]] + autocmd BufAdd * let fired += [["BufAdd", expand("<abuf>")->str2nr(), + \ getbufvar(expand("<abuf>")->str2nr(), "&buftype")]] + + " Don't want to see OptionSet; buffer options set from passing true for "scratch", etc. + " should be configured invisibly, and before autocommands. + autocmd OptionSet * let fired += [["OptionSet", expand("<amatch>")]] + + let fired = [] + ]=]) + local new_buf = api.nvim_create_buf(false, false) + eq({ { 'BufNew', new_buf, '' } }, eval('g:fired')) + + command('let fired = []') + new_buf = api.nvim_create_buf(false, true) + eq({ { 'BufNew', new_buf, 'nofile' } }, eval('g:fired')) + + command('let fired = []') + new_buf = api.nvim_create_buf(true, false) + eq({ { 'BufNew', new_buf, '' }, { 'BufAdd', new_buf, '' } }, eval('g:fired')) + + command('let fired = []') + new_buf = api.nvim_create_buf(true, true) + eq({ { 'BufNew', new_buf, 'nofile' }, { 'BufAdd', new_buf, 'nofile' } }, eval('g:fired')) + end) end) describe('nvim_get_runtime_file', function() - local p = helpers.alter_slashes + local p = n.alter_slashes it('can find files', function() eq({}, api.nvim_get_runtime_file('bork.borkbork', false)) eq({}, api.nvim_get_runtime_file('bork.borkbork', true)) @@ -3365,13 +3428,13 @@ describe('API', function() {desc="(global option, fallback requested) points to global", linenr=9, sid=1, args={'completeopt', {}}}, } - for _, t in pairs(tests) do - it(t.desc, function() + for _, test in pairs(tests) do + it(test.desc, function() -- Switch to the target buffer/window so that curbuf/curwin are used. api.nvim_set_current_win(wins[2]) - local info = api.nvim_get_option_info2(unpack(t.args)) - eq(t.linenr, info.last_set_linenr) - eq(t.sid, info.last_set_sid) + local info = api.nvim_get_option_info2(unpack(test.args)) + eq(test.linenr, info.last_set_linenr) + eq(test.sid, info.last_set_sid) end) end @@ -3492,9 +3555,9 @@ describe('API', function() false, { width = 79, height = 31, row = 1, col = 1, relative = 'editor' } ) - local t = api.nvim_open_term(b, {}) + local term = api.nvim_open_term(b, {}) - api.nvim_chan_send(t, io.open('test/functional/fixtures/smile2.cat', 'r'):read('*a')) + api.nvim_chan_send(term, io.open('test/functional/fixtures/smile2.cat', 'r'):read('*a')) screen:expect { grid = [[ ^ | @@ -3620,7 +3683,7 @@ describe('API', function() api.nvim_buf_set_name(buf, 'mybuf') local mark = api.nvim_get_mark('F', {}) -- Compare the path tail only - assert(string.find(mark[4], 'mybuf$')) + matches('mybuf$', mark[4]) eq({ 2, 2, buf, mark[4] }, mark) end) it('validation', function() @@ -3855,13 +3918,13 @@ describe('API', function() norm 4G ]]) eq({ - str = '││aabb 4 ', + str = '││bbaa 4 ', width = 9, highlights = { { group = 'CursorLineFold', start = 0 }, { group = 'Normal', start = 6 }, - { group = 'IncSearch', start = 6 }, - { group = 'ErrorMsg', start = 8 }, + { group = 'ErrorMsg', start = 6 }, + { group = 'IncSearch', start = 8 }, { group = 'Normal', start = 10 }, }, }, api.nvim_eval_statusline( @@ -4953,4 +5016,218 @@ describe('API', function() eq(false, exec_lua('return _G.success')) end) end) + + it('nvim__redraw', function() + local screen = Screen.new(60, 5) + screen:attach() + local win = api.nvim_get_current_win() + eq('at least one action required', pcall_err(api.nvim__redraw, {})) + eq('at least one action required', pcall_err(api.nvim__redraw, { buf = 0 })) + eq('at least one action required', pcall_err(api.nvim__redraw, { win = 0 })) + eq("cannot use both 'buf' and 'win'", pcall_err(api.nvim__redraw, { buf = 0, win = 0 })) + feed(':echo getchar()<CR>') + fn.setline(1, 'foobar') + command('vnew') + fn.setline(1, 'foobaz') + -- Can flush pending screen updates + api.nvim__redraw({ flush = true }) + screen:expect({ + grid = [[ + foobaz │foobar | + {1:~ }│{1:~ }|*2 + {3:[No Name] [+] }{2:[No Name] [+] }| + ^:echo getchar() | + ]], + }) + -- Can update the grid cursor position #20793 + api.nvim__redraw({ cursor = true }) + screen:expect({ + grid = [[ + ^foobaz │foobar | + {1:~ }│{1:~ }|*2 + {3:[No Name] [+] }{2:[No Name] [+] }| + :echo getchar() | + ]], + }) + -- Also in non-current window + api.nvim__redraw({ cursor = true, win = win }) + screen:expect({ + grid = [[ + foobaz │^foobar | + {1:~ }│{1:~ }|*2 + {3:[No Name] [+] }{2:[No Name] [+] }| + :echo getchar() | + ]], + }) + -- Can update the 'statusline' in a single window + api.nvim_set_option_value('statusline', 'statusline1', { win = 0 }) + api.nvim_set_option_value('statusline', 'statusline2', { win = win }) + api.nvim__redraw({ cursor = true, win = 0, statusline = true }) + screen:expect({ + grid = [[ + ^foobaz │foobar | + {1:~ }│{1:~ }|*2 + {3:statusline1 }{2:[No Name] [+] }| + :echo getchar() | + ]], + }) + api.nvim__redraw({ win = win, statusline = true }) + screen:expect({ + grid = [[ + ^foobaz │foobar | + {1:~ }│{1:~ }|*2 + {3:statusline1 }{2:statusline2 }| + :echo getchar() | + ]], + }) + -- Can update the 'statusline' in all windows + api.nvim_set_option_value('statusline', '', { win = win }) + api.nvim_set_option_value('statusline', 'statusline3', {}) + api.nvim__redraw({ statusline = true }) + screen:expect({ + grid = [[ + ^foobaz │foobar | + {1:~ }│{1:~ }|*2 + {3:statusline3 }{2:statusline3 }| + :echo getchar() | + ]], + }) + -- Can update the 'statuscolumn' + api.nvim_set_option_value('statuscolumn', 'statuscolumn', { win = win }) + api.nvim__redraw({ statuscolumn = true }) + screen:expect({ + grid = [[ + ^foobaz │{8:statuscolumn}foobar | + {1:~ }│{1:~ }|*2 + {3:statusline3 }{2:statusline3 }| + :echo getchar() | + ]], + }) + -- Can update the 'winbar' + api.nvim_set_option_value('winbar', 'winbar', { win = 0 }) + api.nvim__redraw({ win = 0, winbar = true }) + screen:expect({ + grid = [[ + {5:^winbar }│{8:statuscolumn}foobar | + foobaz │{1:~ }| + {1:~ }│{1:~ }| + {3:statusline3 }{2:statusline3 }| + :echo getchar() | + ]], + }) + -- Can update the 'tabline' + api.nvim_set_option_value('showtabline', 2, {}) + api.nvim_set_option_value('tabline', 'tabline', {}) + api.nvim__redraw({ tabline = true }) + screen:expect({ + grid = [[ + {2:^tabline }| + {5:winbar }│{8:statuscolumn}foobar | + foobaz │{1:~ }| + {3:statusline3 }{2:statusline3 }| + :echo getchar() | + ]], + }) + -- Can update multiple status widgets + api.nvim_set_option_value('tabline', 'tabline2', {}) + api.nvim_set_option_value('statusline', 'statusline4', {}) + api.nvim__redraw({ statusline = true, tabline = true }) + screen:expect({ + grid = [[ + {2:^tabline2 }| + {5:winbar }│{8:statuscolumn}foobar | + foobaz │{1:~ }| + {3:statusline4 }{2:statusline4 }| + :echo getchar() | + ]], + }) + -- Can update all status widgets + api.nvim_set_option_value('tabline', 'tabline3', {}) + api.nvim_set_option_value('statusline', 'statusline5', {}) + api.nvim_set_option_value('statuscolumn', 'statuscolumn2', {}) + api.nvim_set_option_value('winbar', 'winbar2', {}) + api.nvim__redraw({ statuscolumn = true, statusline = true, tabline = true, winbar = true }) + screen:expect({ + grid = [[ + {2:^tabline3 }| + {5:winbar2 }│{5:winbar2 }| + {8:statuscolumn2}foobaz │{8:statuscolumn}foobar | + {3:statusline5 }{2:statusline5 }| + :echo getchar() | + ]], + }) + -- Can update status widget for a specific window + feed('<CR><CR>') + command('let g:status=0') + api.nvim_set_option_value('statusline', '%{%g:status%}', { win = 0 }) + command('vsplit') + screen:expect({ + grid = [[ + {2:tabline3 }| + {5:winbar2 }│{5:winbar2 }│{5:winbar2 }| + {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | + {3:0 }{2:0 statusline5 }| + 13 | + ]], + }) + command('let g:status=1') + api.nvim__redraw({ win = 0, statusline = true }) + screen:expect({ + grid = [[ + {2:tabline3 }| + {5:winbar2 }│{5:winbar2 }│{5:winbar2 }| + {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | + {3:1 }{2:0 statusline5 }| + 13 | + ]], + }) + -- Can update status widget for a specific buffer + command('let g:status=2') + api.nvim__redraw({ buf = 0, statusline = true }) + screen:expect({ + grid = [[ + {2:tabline3 }| + {5:winbar2 }│{5:winbar2 }│{5:winbar2 }| + {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | + {3:2 }{2:2 statusline5 }| + 13 | + ]], + }) + -- valid = true does not draw any lines on its own + exec_lua([[ + _G.lines = 0 + ns = vim.api.nvim_create_namespace('') + vim.api.nvim_set_decoration_provider(ns, { + on_win = function() + if _G.do_win then + vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { hl_group = 'IncSearch', end_col = 6 }) + end + end, + on_line = function() + _G.lines = _G.lines + 1 + end, + }) + ]]) + local lines = exec_lua('return lines') + api.nvim__redraw({ buf = 0, valid = true, flush = true }) + eq(lines, exec_lua('return _G.lines')) + -- valid = false does + api.nvim__redraw({ buf = 0, valid = false, flush = true }) + neq(lines, exec_lua('return _G.lines')) + -- valid = true does redraw lines if affected by on_win callback + exec_lua('_G.do_win = true') + api.nvim__redraw({ buf = 0, valid = true, flush = true }) + screen:expect({ + grid = [[ + {2:tabline3 }| + {5:winbar2 }│{5:winbar2 }│{5:winbar2 }| + {8:statuscolumn2}{2:^foobaz} │{8:statuscolumn2}{2:foobaz}│{8:statuscolumn}foobar | + {3:2 }{2:2 statusline5 }| + 13 | + ]], + }) + -- takes buffer line count from correct buffer with "win" and {0, -1} "range" + api.nvim__redraw({ win = 0, range = { 0, -1 } }) + n.assert_alive() + end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 097a546ef2..15b9b0945c 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,27 +1,29 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') + local clear, curbuf, curbuf_contents, curwin, eq, neq, matches, ok, feed, insert, eval = - helpers.clear, - helpers.api.nvim_get_current_buf, - helpers.curbuf_contents, - helpers.api.nvim_get_current_win, - helpers.eq, - helpers.neq, - helpers.matches, - helpers.ok, - helpers.feed, - helpers.insert, - helpers.eval -local poke_eventloop = helpers.poke_eventloop -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local fn = helpers.fn -local request = helpers.request + n.clear, + n.api.nvim_get_current_buf, + n.curbuf_contents, + n.api.nvim_get_current_win, + t.eq, + t.neq, + t.matches, + t.ok, + n.feed, + n.insert, + n.eval +local poke_eventloop = n.poke_eventloop +local exec = n.exec +local exec_lua = n.exec_lua +local fn = n.fn +local request = n.request local NIL = vim.NIL -local api = helpers.api -local command = helpers.command -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive +local api = n.api +local command = n.command +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive describe('API/win', function() before_each(clear) @@ -111,6 +113,44 @@ describe('API/win', function() api.nvim_win_set_buf(new_win, next_buf) eq(next_buf, api.nvim_win_get_buf(new_win)) end) + + describe("with 'autochdir'", function() + local topdir + local otherbuf + local oldwin + local newwin + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + t.mkdir(topdir .. '/Xacd/foo') + otherbuf = api.nvim_create_buf(false, true) + api.nvim_buf_set_name(otherbuf, topdir .. '/Xacd/baz.txt') + + command('set autochdir') + command('edit Xacd/foo/bar.txt') + eq(topdir .. '/Xacd/foo', fn.getcwd()) + + oldwin = api.nvim_get_current_win() + command('vsplit') + newwin = api.nvim_get_current_win() + end) + + after_each(function() + n.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with non-current window', function() + api.nvim_win_set_buf(oldwin, otherbuf) + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + it('changes cwd with current window', function() + api.nvim_win_set_buf(newwin, otherbuf) + eq(topdir .. '/Xacd', fn.getcwd()) + end) + end) end) describe('{get,set}_cursor', function() @@ -1147,27 +1187,6 @@ describe('API/win', function() end) describe('open_win', function() - it('noautocmd option works', function() - command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1') - api.nvim_open_win(api.nvim_create_buf(true, true), true, { - relative = 'win', - row = 3, - col = 3, - width = 12, - height = 3, - noautocmd = true, - }) - eq(0, fn.exists('g:fired')) - api.nvim_open_win(api.nvim_create_buf(true, true), true, { - relative = 'win', - row = 3, - col = 3, - width = 12, - height = 3, - }) - eq(1, fn.exists('g:fired')) - end) - it('disallowed in cmdwin if enter=true or buf=cmdwin_buf', function() local new_buf = api.nvim_create_buf(true, true) feed('q:') @@ -1233,81 +1252,151 @@ describe('API/win', function() eq(wins_before, api.nvim_list_wins()) end) - it('creates a split window', function() - local win = api.nvim_open_win(0, true, { - vertical = false, - }) - eq('', api.nvim_win_get_config(win).relative) + describe('creates a split window above', function() + local function test_open_win_split_above(key, val) + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + [key] = val, + height = 10, + }) + eq('', api.nvim_win_get_config(win).relative) + eq(10, api.nvim_win_get_height(win)) + local layout = fn.winlayout() + eq({ + 'col', + { + { 'leaf', win }, + { 'leaf', initial_win }, + }, + }, layout) + end + + it("with split = 'above'", function() + test_open_win_split_above('split', 'above') + end) + + it("with vertical = false and 'nosplitbelow'", function() + api.nvim_set_option_value('splitbelow', false, {}) + test_open_win_split_above('vertical', false) + end) end) - it('creates split windows in the correct direction', function() - local initial_win = api.nvim_get_current_win() - local win = api.nvim_open_win(0, true, { - vertical = true, - }) - eq('', api.nvim_win_get_config(win).relative) + describe('creates a split window below', function() + local function test_open_win_split_below(key, val) + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + [key] = val, + height = 15, + }) + eq('', api.nvim_win_get_config(win).relative) + eq(15, api.nvim_win_get_height(win)) + local layout = fn.winlayout() + eq({ + 'col', + { + { 'leaf', initial_win }, + { 'leaf', win }, + }, + }, layout) + end - local layout = fn.winlayout() + it("with split = 'below'", function() + test_open_win_split_below('split', 'below') + end) - eq({ - 'row', - { - { 'leaf', win }, - { 'leaf', initial_win }, - }, - }, layout) + it("with vertical = false and 'splitbelow'", function() + api.nvim_set_option_value('splitbelow', true, {}) + test_open_win_split_below('vertical', false) + end) end) - it("respects the 'split' option", function() - local initial_win = api.nvim_get_current_win() - local win = api.nvim_open_win(0, true, { - split = 'below', - }) - eq('', api.nvim_win_get_config(win).relative) + describe('creates a split window to the left', function() + local function test_open_win_split_left(key, val) + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + [key] = val, + width = 25, + }) + eq('', api.nvim_win_get_config(win).relative) + eq(25, api.nvim_win_get_width(win)) + local layout = fn.winlayout() + eq({ + 'row', + { + { 'leaf', win }, + { 'leaf', initial_win }, + }, + }, layout) + end - local layout = fn.winlayout() + it("with split = 'left'", function() + test_open_win_split_left('split', 'left') + end) - eq({ - 'col', - { - { 'leaf', initial_win }, - { 'leaf', win }, - }, - }, layout) + it("with vertical = true and 'nosplitright'", function() + api.nvim_set_option_value('splitright', false, {}) + test_open_win_split_left('vertical', true) + end) end) - it( - "doesn't change tp_curwin when splitting window in non-current tab with enter=false", - function() - local tab1 = api.nvim_get_current_tabpage() - local tab1_win = api.nvim_get_current_win() + describe('creates a split window to the right', function() + local function test_open_win_split_right(key, val) + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + [key] = val, + width = 30, + }) + eq('', api.nvim_win_get_config(win).relative) + eq(30, api.nvim_win_get_width(win)) + local layout = fn.winlayout() + eq({ + 'row', + { + { 'leaf', initial_win }, + { 'leaf', win }, + }, + }, layout) + end + + it("with split = 'right'", function() + test_open_win_split_right('split', 'right') + end) - helpers.command('tabnew') - local tab2 = api.nvim_get_current_tabpage() - local tab2_win = api.nvim_get_current_win() + it("with vertical = true and 'splitright'", function() + api.nvim_set_option_value('splitright', true, {}) + test_open_win_split_right('vertical', true) + end) + end) - eq({ tab1_win, tab2_win }, api.nvim_list_wins()) - eq({ tab1, tab2 }, api.nvim_list_tabpages()) + it("doesn't change tp_curwin when splitting window in another tab with enter=false", function() + local tab1 = api.nvim_get_current_tabpage() + local tab1_win = api.nvim_get_current_win() - api.nvim_set_current_tabpage(tab1) - eq(tab1_win, api.nvim_get_current_win()) + n.command('tabnew') + local tab2 = api.nvim_get_current_tabpage() + local tab2_win = api.nvim_get_current_win() - local tab2_prevwin = fn.tabpagewinnr(tab2, '#') + eq({ tab1_win, tab2_win }, api.nvim_list_wins()) + eq({ tab1, tab2 }, api.nvim_list_tabpages()) - -- split in tab2 whine in tab2, with enter = false - local tab2_win2 = api.nvim_open_win(api.nvim_create_buf(false, true), false, { - win = tab2_win, - split = 'right', - }) - eq(tab1_win, api.nvim_get_current_win()) -- we should still be in the first tp - eq(tab1_win, api.nvim_tabpage_get_win(tab1)) + api.nvim_set_current_tabpage(tab1) + eq(tab1_win, api.nvim_get_current_win()) - eq(tab2_win, api.nvim_tabpage_get_win(tab2)) -- tab2's tp_curwin should not have changed - eq(tab2_prevwin, fn.tabpagewinnr(tab2, '#')) -- tab2's tp_prevwin should not have changed - eq({ tab1_win, tab2_win, tab2_win2 }, api.nvim_list_wins()) - eq({ tab2_win, tab2_win2 }, api.nvim_tabpage_list_wins(tab2)) - end - ) + local tab2_prevwin = fn.tabpagewinnr(tab2, '#') + + -- split in tab2 whine in tab2, with enter = false + local tab2_win2 = api.nvim_open_win(api.nvim_create_buf(false, true), false, { + win = tab2_win, + split = 'right', + }) + eq(tab1_win, api.nvim_get_current_win()) -- we should still be in the first tp + eq(tab1_win, api.nvim_tabpage_get_win(tab1)) + + eq(tab2_win, api.nvim_tabpage_get_win(tab2)) -- tab2's tp_curwin should not have changed + eq(tab2_prevwin, fn.tabpagewinnr(tab2, '#')) -- tab2's tp_prevwin should not have changed + eq({ tab1_win, tab2_win, tab2_win2 }, api.nvim_list_wins()) + eq({ tab2_win, tab2_win2 }, api.nvim_tabpage_list_wins(tab2)) + end) it('creates splits in the correct location', function() local first_win = api.nvim_get_current_win() @@ -1364,6 +1453,400 @@ describe('API/win', function() }, }, layout) end) + + it('opens floating windows in other tabpages', function() + local first_win = api.nvim_get_current_win() + local first_tab = api.nvim_get_current_tabpage() + + command('tabnew') + local new_tab = api.nvim_get_current_tabpage() + local win = api.nvim_open_win(0, false, { + relative = 'win', + win = first_win, + width = 5, + height = 5, + row = 1, + col = 1, + }) + eq(api.nvim_win_get_tabpage(win), first_tab) + eq(api.nvim_get_current_tabpage(), new_tab) + end) + + it('switches to new windows in non-current tabpages when enter=true', function() + local first_win = api.nvim_get_current_win() + local first_tab = api.nvim_get_current_tabpage() + command('tabnew') + local win = api.nvim_open_win(0, true, { + relative = 'win', + win = first_win, + width = 5, + height = 5, + row = 1, + col = 1, + }) + eq(api.nvim_win_get_tabpage(win), first_tab) + eq(api.nvim_get_current_tabpage(), first_tab) + end) + + local function setup_tabbed_autocmd_test() + local info = {} + info.orig_buf = api.nvim_get_current_buf() + info.other_buf = api.nvim_create_buf(true, true) + info.tab1_curwin = api.nvim_get_current_win() + info.tab1 = api.nvim_get_current_tabpage() + command('tab split | split') + info.tab2_curwin = api.nvim_get_current_win() + info.tab2 = api.nvim_get_current_tabpage() + exec([=[ + tabfirst + let result = [] + autocmd TabEnter * let result += [["TabEnter", nvim_get_current_tabpage()]] + autocmd TabLeave * let result += [["TabLeave", nvim_get_current_tabpage()]] + autocmd WinEnter * let result += [["WinEnter", win_getid()]] + autocmd WinLeave * let result += [["WinLeave", win_getid()]] + autocmd WinNew * let result += [["WinNew", win_getid()]] + autocmd WinClosed * let result += [["WinClosed", str2nr(expand("<afile>"))]] + autocmd BufEnter * let result += [["BufEnter", win_getid(), bufnr()]] + autocmd BufLeave * let result += [["BufLeave", win_getid(), bufnr()]] + autocmd BufWinEnter * let result += [["BufWinEnter", win_getid(), bufnr()]] + autocmd BufWinLeave * let result += [["BufWinLeave", win_getid(), bufnr()]] + ]=]) + return info + end + + it('noautocmd option works', function() + local info = setup_tabbed_autocmd_test() + + api.nvim_open_win( + info.other_buf, + true, + { split = 'left', win = info.tab2_curwin, noautocmd = true } + ) + eq({}, eval('result')) + + api.nvim_open_win( + info.orig_buf, + true, + { relative = 'editor', row = 0, col = 0, width = 10, height = 10, noautocmd = true } + ) + eq({}, eval('result')) + end) + + it('fires expected autocmds when creating splits without entering', function() + local info = setup_tabbed_autocmd_test() + + -- For these, don't want BufWinEnter if visiting the same buffer, like :{s}buffer. + -- Same tabpage, same buffer. + local new_win = api.nvim_open_win(0, false, { split = 'left', win = info.tab1_curwin }) + eq({ + { 'WinNew', new_win }, + }, eval('result')) + eq(info.tab1_curwin, api.nvim_get_current_win()) + + -- Other tabpage, same buffer. + command('let result = []') + new_win = api.nvim_open_win(0, false, { split = 'left', win = info.tab2_curwin }) + eq({ + { 'WinNew', new_win }, + }, eval('result')) + eq(info.tab1_curwin, api.nvim_get_current_win()) + + -- Same tabpage, other buffer. + command('let result = []') + new_win = api.nvim_open_win(info.other_buf, false, { split = 'left', win = info.tab1_curwin }) + eq({ + { 'WinNew', new_win }, + { 'BufWinEnter', new_win, info.other_buf }, + }, eval('result')) + eq(info.tab1_curwin, api.nvim_get_current_win()) + + -- Other tabpage, other buffer. + command('let result = []') + new_win = api.nvim_open_win(info.other_buf, false, { split = 'left', win = info.tab2_curwin }) + eq({ + { 'WinNew', new_win }, + { 'BufWinEnter', new_win, info.other_buf }, + }, eval('result')) + eq(info.tab1_curwin, api.nvim_get_current_win()) + end) + + it('fires expected autocmds when creating and entering splits', function() + local info = setup_tabbed_autocmd_test() + + -- Same tabpage, same buffer. + local new_win = api.nvim_open_win(0, true, { split = 'left', win = info.tab1_curwin }) + eq({ + { 'WinNew', new_win }, + { 'WinLeave', info.tab1_curwin }, + { 'WinEnter', new_win }, + }, eval('result')) + + -- Same tabpage, other buffer. + api.nvim_set_current_win(info.tab1_curwin) + command('let result = []') + new_win = api.nvim_open_win(info.other_buf, true, { split = 'left', win = info.tab1_curwin }) + eq({ + { 'WinNew', new_win }, + { 'WinLeave', info.tab1_curwin }, + { 'WinEnter', new_win }, + { 'BufLeave', new_win, info.orig_buf }, + { 'BufEnter', new_win, info.other_buf }, + { 'BufWinEnter', new_win, info.other_buf }, + }, eval('result')) + + -- For these, the other tabpage's prevwin and curwin will change like we switched from its old + -- curwin to the new window, so the extra events near TabEnter reflect that. + -- Other tabpage, same buffer. + api.nvim_set_current_win(info.tab1_curwin) + command('let result = []') + new_win = api.nvim_open_win(0, true, { split = 'left', win = info.tab2_curwin }) + eq({ + { 'WinNew', new_win }, + { 'WinLeave', info.tab1_curwin }, + { 'TabLeave', info.tab1 }, + + { 'WinEnter', info.tab2_curwin }, + { 'TabEnter', info.tab2 }, + { 'WinLeave', info.tab2_curwin }, + { 'WinEnter', new_win }, + }, eval('result')) + + -- Other tabpage, other buffer. + api.nvim_set_current_win(info.tab2_curwin) + api.nvim_set_current_win(info.tab1_curwin) + command('let result = []') + new_win = api.nvim_open_win(info.other_buf, true, { split = 'left', win = info.tab2_curwin }) + eq({ + { 'WinNew', new_win }, + { 'WinLeave', info.tab1_curwin }, + { 'TabLeave', info.tab1 }, + + { 'WinEnter', info.tab2_curwin }, + { 'TabEnter', info.tab2 }, + { 'WinLeave', info.tab2_curwin }, + { 'WinEnter', new_win }, + + { 'BufLeave', new_win, info.orig_buf }, + { 'BufEnter', new_win, info.other_buf }, + { 'BufWinEnter', new_win, info.other_buf }, + }, eval('result')) + + -- Other tabpage, other buffer; but other tabpage's curwin has a new buffer active. + api.nvim_set_current_win(info.tab2_curwin) + local new_buf = api.nvim_create_buf(true, true) + api.nvim_set_current_buf(new_buf) + api.nvim_set_current_win(info.tab1_curwin) + command('let result = []') + new_win = api.nvim_open_win(info.other_buf, true, { split = 'left', win = info.tab2_curwin }) + eq({ + { 'WinNew', new_win }, + { 'BufLeave', info.tab1_curwin, info.orig_buf }, + { 'WinLeave', info.tab1_curwin }, + { 'TabLeave', info.tab1 }, + + { 'WinEnter', info.tab2_curwin }, + { 'TabEnter', info.tab2 }, + { 'BufEnter', info.tab2_curwin, new_buf }, + { 'WinLeave', info.tab2_curwin }, + { 'WinEnter', new_win }, + { 'BufLeave', new_win, new_buf }, + { 'BufEnter', new_win, info.other_buf }, + { 'BufWinEnter', new_win, info.other_buf }, + }, eval('result')) + end) + + it('OK when new window is moved to other tabpage by autocommands', function() + -- Use nvim_win_set_config in the autocommands, as other methods of moving a window to a + -- different tabpage (e.g: wincmd T) actually creates a new window. + local tab0 = api.nvim_get_current_tabpage() + local tab0_win = api.nvim_get_current_win() + command('tabnew') + local new_buf = api.nvim_create_buf(true, true) + local tab1 = api.nvim_get_current_tabpage() + local tab1_parent = api.nvim_get_current_win() + command( + 'tabfirst | autocmd WinNew * ++once call nvim_win_set_config(0, #{split: "left", win: ' + .. tab1_parent + .. '})' + ) + local new_win = api.nvim_open_win(new_buf, true, { split = 'left' }) + eq(tab1, api.nvim_get_current_tabpage()) + eq(new_win, api.nvim_get_current_win()) + eq(new_buf, api.nvim_get_current_buf()) + + -- nvim_win_set_config called after entering. It doesn't follow a curwin that is moved to a + -- different tabpage, but instead moves to the win filling the space, which is tab0_win. + command( + 'tabfirst | autocmd WinEnter * ++once call nvim_win_set_config(0, #{split: "left", win: ' + .. tab1_parent + .. '})' + ) + new_win = api.nvim_open_win(new_buf, true, { split = 'left' }) + eq(tab0, api.nvim_get_current_tabpage()) + eq(tab0_win, api.nvim_get_current_win()) + eq(tab1, api.nvim_win_get_tabpage(new_win)) + eq(new_buf, api.nvim_win_get_buf(new_win)) + + command( + 'tabfirst | autocmd BufEnter * ++once call nvim_win_set_config(0, #{split: "left", win: ' + .. tab1_parent + .. '})' + ) + new_win = api.nvim_open_win(new_buf, true, { split = 'left' }) + eq(tab0, api.nvim_get_current_tabpage()) + eq(tab0_win, api.nvim_get_current_win()) + eq(tab1, api.nvim_win_get_tabpage(new_win)) + eq(new_buf, api.nvim_win_get_buf(new_win)) + end) + + it('does not fire BufWinEnter if win_set_buf fails', function() + exec([[ + set nohidden modified + autocmd WinNew * ++once only! + let fired = v:false + autocmd BufWinEnter * ++once let fired = v:true + ]]) + eq( + 'Failed to set buffer 2', + pcall_err(api.nvim_open_win, api.nvim_create_buf(true, true), false, { split = 'left' }) + ) + eq(false, eval('fired')) + end) + + it('fires Buf* autocommands when `!enter` if window is entered via autocommands', function() + exec([[ + autocmd WinNew * ++once only! + let fired = v:false + autocmd BufEnter * ++once let fired = v:true + ]]) + api.nvim_open_win(api.nvim_create_buf(true, true), false, { split = 'left' }) + eq(true, eval('fired')) + end) + + it('no heap-use-after-free if target buffer deleted by autocommands', function() + local cur_buf = api.nvim_get_current_buf() + local new_buf = api.nvim_create_buf(true, true) + command('autocmd WinNew * ++once call nvim_buf_delete(' .. new_buf .. ', #{force: 1})') + api.nvim_open_win(new_buf, true, { split = 'left' }) + eq(cur_buf, api.nvim_get_current_buf()) + end) + + it('checks if splitting disallowed', function() + command('split | autocmd WinEnter * ++once call nvim_open_win(0, 0, #{split: "right"})') + matches("E242: Can't split a window while closing another$", pcall_err(command, 'quit')) + + command('only | autocmd BufHidden * ++once call nvim_open_win(0, 0, #{split: "left"})') + matches( + 'E1159: Cannot split a window when closing the buffer$', + pcall_err(command, 'new | quit') + ) + + local w = api.nvim_get_current_win() + command( + 'only | new | autocmd BufHidden * ++once call nvim_open_win(0, 0, #{split: "left", win: ' + .. w + .. '})' + ) + matches( + 'E1159: Cannot split a window when closing the buffer$', + pcall_err(api.nvim_win_close, w, true) + ) + + -- OK when using window to different buffer than `win`s. + w = api.nvim_get_current_win() + command( + 'only | autocmd BufHidden * ++once call nvim_open_win(0, 0, #{split: "left", win: ' + .. w + .. '})' + ) + command('new | quit') + end) + + it('restores last known cursor position if BufWinEnter did not move it', function() + -- This test mostly exists to ensure BufWinEnter is executed before enter_buffer's epilogue. + local buf = api.nvim_get_current_buf() + insert([[ + foo + bar baz .etc + i love autocommand bugs! + supercalifragilisticexpialidocious + marvim is actually a human + llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch + ]]) + api.nvim_win_set_cursor(0, { 5, 2 }) + command('set nostartofline | enew') + local new_win = api.nvim_open_win(buf, false, { split = 'left' }) + eq({ 5, 2 }, api.nvim_win_get_cursor(new_win)) + + exec([[ + only! + autocmd BufWinEnter * ++once normal! j6l + ]]) + new_win = api.nvim_open_win(buf, false, { split = 'left' }) + eq({ 2, 6 }, api.nvim_win_get_cursor(new_win)) + end) + + it('does not block all win_set_buf autocommands if !enter and !noautocmd', function() + local new_buf = fn.bufadd('foobarbaz') + exec([[ + let triggered = "" + autocmd BufReadCmd * ++once let triggered = bufname() + ]]) + api.nvim_open_win(new_buf, false, { split = 'left' }) + eq('foobarbaz', eval('triggered')) + end) + + it('sets error when no room', function() + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_open_win, 0, true, { split = 'above', win = 0 }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_open_win, 0, true, { split = 'below', win = 0 }) + ) + end) + + describe("with 'autochdir'", function() + local topdir + local otherbuf + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + t.mkdir(topdir .. '/Xacd/foo') + otherbuf = api.nvim_create_buf(false, true) + api.nvim_buf_set_name(otherbuf, topdir .. '/Xacd/baz.txt') + + command('set autochdir') + command('edit Xacd/foo/bar.txt') + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + after_each(function() + n.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with enter=false #15280', function() + api.nvim_open_win( + otherbuf, + false, + { relative = 'editor', height = 5, width = 5, row = 5, col = 5 } + ) + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + it('changes cwd with enter=true', function() + api.nvim_open_win( + otherbuf, + true, + { relative = 'editor', height = 5, width = 5, row = 5, col = 5 } + ) + eq(topdir .. '/Xacd', fn.getcwd()) + end) + end) end) describe('set_config', function() @@ -1471,6 +1954,15 @@ describe('API/win', function() config = api.nvim_win_get_config(win) eq('', config.relative) eq('below', config.split) + + eq( + "non-float with 'win' requires at least 'split' or 'vertical'", + pcall_err(api.nvim_win_set_config, 0, { win = 0 }) + ) + eq( + "non-float with 'win' requires at least 'split' or 'vertical'", + pcall_err(api.nvim_win_set_config, 0, { win = 0, relative = '' }) + ) end) it('creates top-level splits', function() @@ -1663,6 +2155,474 @@ describe('API/win', function() }, }, fn.winlayout()) end) + + it('closing new curwin when moving window to other tabpage works', function() + command('split | tabnew') + local t2_win = api.nvim_get_current_win() + command('tabfirst | autocmd WinEnter * ++once quit') + local t1_move_win = api.nvim_get_current_win() + -- win_set_config fails to switch away from "t1_move_win" because the WinEnter autocmd that + -- closed the window we're switched to returns us to "t1_move_win", as it filled the space. + eq( + 'Failed to switch away from window ' .. t1_move_win, + pcall_err(api.nvim_win_set_config, t1_move_win, { win = t2_win, split = 'left' }) + ) + eq(t1_move_win, api.nvim_get_current_win()) + + command('split | split | autocmd WinEnter * ++once quit') + t1_move_win = api.nvim_get_current_win() + -- In this case, we closed the window that we got switched to, but doing so didn't switch us + -- back to "t1_move_win", which is fine. + api.nvim_win_set_config(t1_move_win, { win = t2_win, split = 'left' }) + neq(t1_move_win, api.nvim_get_current_win()) + end) + + it('messing with "win" or "parent" when moving "win" to other tabpage', function() + command('split | tabnew') + local t2 = api.nvim_get_current_tabpage() + local t2_win1 = api.nvim_get_current_win() + command('split') + local t2_win2 = api.nvim_get_current_win() + command('split') + local t2_win3 = api.nvim_get_current_win() + + command('tabfirst | autocmd WinEnter * ++once call nvim_win_close(' .. t2_win1 .. ', 1)') + local cur_win = api.nvim_get_current_win() + eq( + 'Windows to split were closed', + pcall_err(api.nvim_win_set_config, 0, { win = t2_win1, split = 'left' }) + ) + eq(cur_win, api.nvim_get_current_win()) + + command('split | autocmd WinLeave * ++once quit!') + cur_win = api.nvim_get_current_win() + eq( + 'Windows to split were closed', + pcall_err(api.nvim_win_set_config, 0, { win = t2_win2, split = 'left' }) + ) + neq(cur_win, api.nvim_get_current_win()) + + exec([[ + split + autocmd WinLeave * ++once + \ call nvim_win_set_config(0, #{relative:'editor', row:0, col:0, width:5, height:5}) + ]]) + cur_win = api.nvim_get_current_win() + eq( + 'Floating state of windows to split changed', + pcall_err(api.nvim_win_set_config, 0, { win = t2_win3, split = 'left' }) + ) + eq('editor', api.nvim_win_get_config(0).relative) + eq(cur_win, api.nvim_get_current_win()) + + command('autocmd WinLeave * ++once wincmd J') + cur_win = api.nvim_get_current_win() + eq( + 'Floating state of windows to split changed', + pcall_err(api.nvim_win_set_config, 0, { win = t2_win3, split = 'left' }) + ) + eq('', api.nvim_win_get_config(0).relative) + eq(cur_win, api.nvim_get_current_win()) + + -- Try to make "parent" floating. This should give the same error as before, but because + -- changing a split from another tabpage into a float isn't supported yet, check for that + -- error instead for now. + -- Use ":silent!" to avoid the one second delay from printing the error message. + exec(([[ + autocmd WinLeave * ++once silent! + \ call nvim_win_set_config(%d, #{relative:'editor', row:0, col:0, width:5, height:5}) + ]]):format(t2_win3)) + cur_win = api.nvim_get_current_win() + api.nvim_win_set_config(0, { win = t2_win3, split = 'left' }) + matches( + 'Cannot change window from different tabpage into float$', + api.nvim_get_vvar('errmsg') + ) + -- The error doesn't abort moving the window (or maybe it should, if that's wanted?) + neq(cur_win, api.nvim_get_current_win()) + eq(t2, api.nvim_win_get_tabpage(cur_win)) + end) + + it('expected autocmds when moving window to other tabpage', function() + local new_curwin = api.nvim_get_current_win() + command('split') + local win = api.nvim_get_current_win() + command('tabnew') + local parent = api.nvim_get_current_win() + exec([[ + tabfirst + let result = [] + autocmd WinEnter * let result += ["Enter", win_getid()] + autocmd WinLeave * let result += ["Leave", win_getid()] + autocmd WinNew * let result += ["New", win_getid()] + ]]) + api.nvim_win_set_config(0, { win = parent, split = 'left' }) + -- Shouldn't see WinNew, as we're not creating any new windows, just moving existing ones. + eq({ 'Leave', win, 'Enter', new_curwin }, eval('result')) + end) + + it('no autocmds when moving window within same tabpage', function() + local parent = api.nvim_get_current_win() + exec([[ + split + let result = [] + autocmd WinEnter * let result += ["Enter", win_getid()] + autocmd WinLeave * let result += ["Leave", win_getid()] + autocmd WinNew * let result += ["New", win_getid()] + ]]) + api.nvim_win_set_config(0, { win = parent, split = 'left' }) + -- Shouldn't see any of those events, as we remain in the same window. + eq({}, eval('result')) + end) + + it('checks if splitting disallowed', function() + command('split | autocmd WinEnter * ++once call nvim_win_set_config(0, #{split: "right"})') + matches("E242: Can't split a window while closing another$", pcall_err(command, 'quit')) + + command('autocmd BufHidden * ++once call nvim_win_set_config(0, #{split: "left"})') + matches( + 'E1159: Cannot split a window when closing the buffer$', + pcall_err(command, 'new | quit') + ) + + -- OK when using window to different buffer. + local w = api.nvim_get_current_win() + command('autocmd BufHidden * ++once call nvim_win_set_config(' .. w .. ', #{split: "left"})') + command('new | quit') + end) + + --- Returns a function to get information about the window layout, sizes and positions of a + --- tabpage. + local function define_tp_info_function() + exec_lua([[ + function tp_info(tp) + return { + layout = vim.fn.winlayout(vim.api.nvim_tabpage_get_number(tp)), + pos_sizes = vim.tbl_map( + function(w) + local pos = vim.fn.win_screenpos(w) + return { + row = pos[1], + col = pos[2], + width = vim.fn.winwidth(w), + height = vim.fn.winheight(w) + } + end, + vim.api.nvim_tabpage_list_wins(tp) + ) + } + end + ]]) + + return function(tp) + return exec_lua('return tp_info(...)', tp) + end + end + + it('attempt to move window with no room', function() + -- Fill the 2nd tabpage full of windows until we run out of room. + -- Use &laststatus=0 to ensure restoring missing statuslines doesn't affect things. + command('set laststatus=0 | tabnew') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + command('vsplit | wincmd | | wincmd p') + local t2 = api.nvim_get_current_tabpage() + local t2_cur_win = api.nvim_get_current_win() + local t2_top_split = fn.win_getid(1) + local t2_bot_split = fn.win_getid(fn.winnr('$')) + local t2_float = api.nvim_open_win( + 0, + false, + { relative = 'editor', row = 0, col = 0, width = 10, height = 10 } + ) + local t2_float_config = api.nvim_win_get_config(t2_float) + local tp_info = define_tp_info_function() + local t2_info = tp_info(t2) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_top_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_top_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_bot_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_bot_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t2_float, { win = t2_top_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t2_float, { win = t2_top_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t2_float, { win = t2_bot_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t2_float, { win = t2_bot_split, split = 'below' }) + ) + eq(t2_cur_win, api.nvim_get_current_win()) + eq(t2_info, tp_info(t2)) + eq(t2_float_config, api.nvim_win_get_config(t2_float)) + + -- Try to move windows from the 1st tabpage to the 2nd. + command('tabfirst | split | wincmd _') + local t1 = api.nvim_get_current_tabpage() + local t1_cur_win = api.nvim_get_current_win() + local t1_float = api.nvim_open_win( + 0, + false, + { relative = 'editor', row = 5, col = 3, width = 7, height = 6 } + ) + local t1_float_config = api.nvim_win_get_config(t1_float) + local t1_info = tp_info(t1) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_top_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_top_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_bot_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, 0, { win = t2_bot_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t1_float, { win = t2_top_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t1_float, { win = t2_top_split, split = 'below' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t1_float, { win = t2_bot_split, split = 'above' }) + ) + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t1_float, { win = t2_bot_split, split = 'below' }) + ) + eq(t1_cur_win, api.nvim_get_current_win()) + eq(t1_info, tp_info(t1)) + eq(t1_float_config, api.nvim_win_get_config(t1_float)) + end) + + it('attempt to move window from other tabpage with no room', function() + -- Fill up the 1st tabpage with horizontal splits, then create a 2nd with only a few. Go back + -- to the 1st and try to move windows from the 2nd (while it's non-current) to it. Check that + -- window positions and sizes in the 2nd are unchanged. + command('set laststatus=0') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + + command('tab split') + local t2 = api.nvim_get_current_tabpage() + local t2_top = api.nvim_get_current_win() + command('belowright split') + local t2_mid_left = api.nvim_get_current_win() + command('belowright vsplit') + local t2_mid_right = api.nvim_get_current_win() + command('split | wincmd J') + local t2_bot = api.nvim_get_current_win() + local tp_info = define_tp_info_function() + local t2_info = tp_info(t2) + eq({ + 'col', + { + { 'leaf', t2_top }, + { + 'row', + { + { 'leaf', t2_mid_left }, + { 'leaf', t2_mid_right }, + }, + }, + { 'leaf', t2_bot }, + }, + }, t2_info.layout) + + local function try_move_t2_wins_to_t1() + for _, w in ipairs({ t2_bot, t2_mid_left, t2_mid_right, t2_top }) do + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, w, { win = 0, split = 'below' }) + ) + eq(t2_info, tp_info(t2)) + end + end + command('tabfirst') + try_move_t2_wins_to_t1() + -- Go to the 2nd tabpage to ensure nothing changes after win_comp_pos, last_status, .etc. + -- from enter_tabpage. + command('tabnext') + eq(t2_info, tp_info(t2)) + + -- Check things are fine with the global statusline too, for good measure. + -- Set it while the 2nd tabpage is current, so last_status runs for it. + command('set laststatus=3') + t2_info = tp_info(t2) + command('tabfirst') + try_move_t2_wins_to_t1() + end) + + it('handles cmdwin and textlock restrictions', function() + command('tabnew') + local t2 = api.nvim_get_current_tabpage() + local t2_win = api.nvim_get_current_win() + command('tabfirst') + local t1_move_win = api.nvim_get_current_win() + command('split') + + -- Can't move the cmdwin, or its old curwin to a different tabpage. + local old_curwin = api.nvim_get_current_win() + feed('q:') + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_set_config, 0, { split = 'left', win = t2_win }) + ) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_set_config, old_curwin, { split = 'left', win = t2_win }) + ) + -- But we can move other windows. + api.nvim_win_set_config(t1_move_win, { split = 'left', win = t2_win }) + eq(t2, api.nvim_win_get_tabpage(t1_move_win)) + command('quit!') + + -- Can't configure windows such that the cmdwin would become the only non-float. + command('only!') + feed('q:') + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err( + api.nvim_win_set_config, + old_curwin, + { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } + ) + ) + -- old_curwin is now no longer the only other non-float, so we can make it floating now. + local t1_new_win = api.nvim_open_win( + api.nvim_create_buf(true, true), + false, + { split = 'left', win = old_curwin } + ) + api.nvim_win_set_config( + old_curwin, + { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } + ) + eq('editor', api.nvim_win_get_config(old_curwin).relative) + -- ...which means we shouldn't be able to also make the new window floating too! + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err( + api.nvim_win_set_config, + t1_new_win, + { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } + ) + ) + -- Nothing ought to stop us from making the cmdwin itself floating, though... + api.nvim_win_set_config(0, { relative = 'editor', row = 0, col = 0, width = 5, height = 5 }) + eq('editor', api.nvim_win_get_config(0).relative) + -- We can't make our new window from before floating too, as it's now the only non-float. + eq( + 'Cannot change last window into float', + pcall_err( + api.nvim_win_set_config, + t1_new_win, + { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } + ) + ) + command('quit!') + + -- Can't switch away from window before moving it to a different tabpage during textlock. + exec(([[ + new + call setline(1, 'foo') + setlocal debug=throw indentexpr=nvim_win_set_config(0,#{split:'left',win:%d}) + ]]):format(t2_win)) + local cur_win = api.nvim_get_current_win() + matches( + 'E565: Not allowed to change text or change window$', + pcall_err(command, 'normal! ==') + ) + eq(cur_win, api.nvim_get_current_win()) + end) + + it('updates statusline when moving bottom split', function() + local screen = Screen.new(10, 10) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + [1] = { bold = true, reverse = true }, -- StatusLine + }) + screen:attach() + exec([[ + set laststatus=0 + belowright split + call nvim_win_set_config(0, #{split: 'above', win: win_getid(winnr('#'))}) + ]]) + screen:expect([[ + ^ | + {0:~ }|*3 + {1:[No Name] }| + | + {0:~ }|*3 + | + ]]) + end) + + it("updates tp_curwin of moved window's original tabpage", function() + local t1 = api.nvim_get_current_tabpage() + command('tab split | split') + local t2 = api.nvim_get_current_tabpage() + local t2_alt_win = api.nvim_get_current_win() + command('vsplit') + local t2_cur_win = api.nvim_get_current_win() + command('tabprevious') + eq(t2_cur_win, api.nvim_tabpage_get_win(t2)) + + -- tp_curwin is unchanged when moved within the same tabpage. + api.nvim_win_set_config(t2_cur_win, { split = 'left', win = t2_alt_win }) + eq(t2_cur_win, api.nvim_tabpage_get_win(t2)) + + -- Also unchanged if the move failed. + command('let &winwidth = &columns | let &winminwidth = &columns') + matches( + 'E36: Not enough room$', + pcall_err(api.nvim_win_set_config, t2_cur_win, { split = 'left', win = 0 }) + ) + eq(t2_cur_win, api.nvim_tabpage_get_win(t2)) + command('set winminwidth& winwidth&') + + -- But is changed if successfully moved to a different tabpage. + api.nvim_win_set_config(t2_cur_win, { split = 'left', win = 0 }) + eq(t2_alt_win, api.nvim_tabpage_get_win(t2)) + eq(t1, api.nvim_win_get_tabpage(t2_cur_win)) + + -- Now do it for a float, which has different altwin logic. + command('tabnext') + t2_cur_win = + api.nvim_open_win(0, true, { relative = 'editor', row = 5, col = 5, width = 5, height = 5 }) + eq(t2_alt_win, fn.win_getid(fn.winnr('#'))) + command('tabprevious') + eq(t2_cur_win, api.nvim_tabpage_get_win(t2)) + + api.nvim_win_set_config(t2_cur_win, { split = 'left', win = 0 }) + eq(t2_alt_win, api.nvim_tabpage_get_win(t2)) + eq(t1, api.nvim_win_get_tabpage(t2_cur_win)) + end) end) describe('get_config', function() diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua index 0243674f2d..1a3b723ac2 100644 --- a/test/functional/autocmd/autocmd_oldtest_spec.lua +++ b/test/functional/autocmd/autocmd_oldtest_spec.lua @@ -1,16 +1,27 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local eq = helpers.eq -local api = helpers.api -local fn = helpers.fn -local exec = helpers.exec -local feed = helpers.feed +local clear = n.clear +local eq = t.eq +local api = n.api +local fn = n.fn +local exec = n.exec +local feed = n.feed +local assert_log = t.assert_log +local check_close = n.check_close +local is_os = t.is_os + +local testlog = 'Xtest_autocmd_oldtest_log' describe('oldtests', function() before_each(clear) + after_each(function() + check_close() + os.remove(testlog) + end) + local exec_lines = function(str) return fn.split(fn.execute(str), '\n') end @@ -49,6 +60,7 @@ describe('oldtests', function() end) it('should fire on unload buf', function() + clear({ env = { NVIM_LOG_FILE = testlog } }) fn.writefile({ 'Test file Xxx1' }, 'Xxx1') fn.writefile({ 'Test file Xxx2' }, 'Xxx2') local fname = 'Xtest_functional_autocmd_unload' @@ -81,6 +93,10 @@ describe('oldtests', function() fn.delete('Xxx2') fn.delete(fname) fn.delete('Xout') + + if is_os('win') then + assert_log('stream write failed. RPC canceled; closing channel', testlog) + end end) -- oldtest: Test_delete_ml_get_errors() diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 5fffb70095..5e407a9986 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -1,24 +1,25 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_visible = helpers.assert_visible -local assert_alive = helpers.assert_alive -local dedent = helpers.dedent -local eq = helpers.eq -local neq = helpers.neq -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local matches = helpers.matches -local api = helpers.api -local pcall_err = helpers.pcall_err -local fn = helpers.fn -local expect = helpers.expect -local command = helpers.command -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local retry = helpers.retry -local source = helpers.source +local assert_visible = n.assert_visible +local assert_alive = n.assert_alive +local dedent = t.dedent +local eq = t.eq +local neq = t.neq +local eval = n.eval +local feed = n.feed +local clear = n.clear +local matches = t.matches +local api = n.api +local pcall_err = t.pcall_err +local fn = n.fn +local expect = n.expect +local command = n.command +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local retry = t.retry +local source = n.source describe('autocmd', function() before_each(clear) @@ -371,6 +372,31 @@ describe('autocmd', function() assert_alive() screen:expect_unchanged() + -- Also check with win_splitmove(). + exec_lua [[ + vim.api.nvim_buf_call(_G.buf, function() + vim.fn.win_splitmove(vim.fn.winnr(), vim.fn.win_getid(1)) + end) + ]] + screen:expect_unchanged() + + -- Also check with nvim_win_set_config(). + matches( + ': Failed to move window %d+ into split$', + pcall_err( + exec_lua, + [[ + vim.api.nvim_buf_call(_G.buf, function() + vim.api.nvim_win_set_config(0, { + vertical = true, + win = vim.fn.win_getid(1) + }) + end) + ]] + ) + ) + screen:expect_unchanged() + -- Ensure splitting still works from inside the aucmd_win. exec_lua [[vim.api.nvim_buf_call(_G.buf, function() vim.cmd "split" end)]] screen:expect [[ @@ -391,12 +417,12 @@ describe('autocmd', function() eq( 'editor', exec_lua [[ - vim.cmd "only" - vim.api.nvim_buf_call(_G.buf, function() - _G.config = vim.api.nvim_win_get_config(0) - end) - return _G.config.relative - ]] + vim.cmd "only" + vim.api.nvim_buf_call(_G.buf, function() + _G.config = vim.api.nvim_win_get_config(0) + end) + return _G.config.relative + ]] ) end) @@ -437,11 +463,11 @@ describe('autocmd', function() pcall_err( exec_lua, [[ - vim.api.nvim_buf_call(_G.buf, function() - local win = vim.api.nvim_get_current_win() - vim.api.nvim_win_close(win, true) - end) - ]] + vim.api.nvim_buf_call(_G.buf, function() + local win = vim.api.nvim_get_current_win() + vim.api.nvim_win_close(win, true) + end) + ]] ) ) matches( @@ -449,12 +475,12 @@ describe('autocmd', function() pcall_err( exec_lua, [[ - vim.api.nvim_buf_call(_G.buf, function() - local win = vim.api.nvim_get_current_win() - vim.cmd('tabnext') - vim.api.nvim_win_close(win, true) - end) - ]] + vim.api.nvim_buf_call(_G.buf, function() + local win = vim.api.nvim_get_current_win() + vim.cmd('tabnext') + vim.api.nvim_win_close(win, true) + end) + ]] ) ) matches( @@ -462,11 +488,11 @@ describe('autocmd', function() pcall_err( exec_lua, [[ - vim.api.nvim_buf_call(_G.buf, function() - local win = vim.api.nvim_get_current_win() - vim.api.nvim_win_hide(win) - end) - ]] + vim.api.nvim_buf_call(_G.buf, function() + local win = vim.api.nvim_get_current_win() + vim.api.nvim_win_hide(win) + end) + ]] ) ) matches( @@ -474,12 +500,12 @@ describe('autocmd', function() pcall_err( exec_lua, [[ - vim.api.nvim_buf_call(_G.buf, function() - local win = vim.api.nvim_get_current_win() - vim.cmd('tabnext') - vim.api.nvim_win_hide(win) - end) - ]] + vim.api.nvim_buf_call(_G.buf, function() + local win = vim.api.nvim_get_current_win() + vim.cmd('tabnext') + vim.api.nvim_win_hide(win) + end) + ]] ) ) end) diff --git a/test/functional/autocmd/bufenter_spec.lua b/test/functional/autocmd/bufenter_spec.lua index af0dd887fa..72e650cae4 100644 --- a/test/functional/autocmd/bufenter_spec.lua +++ b/test/functional/autocmd/bufenter_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local request = helpers.request -local source = helpers.source +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local request = n.request +local source = n.source describe('autocmd BufEnter', function() before_each(clear) @@ -33,7 +34,7 @@ describe('autocmd BufEnter', function() end) it('triggered by ":split normal|:help|:bw"', function() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() command('split normal') command('wincmd j') command('help') diff --git a/test/functional/autocmd/bufmodifiedset_spec.lua b/test/functional/autocmd/bufmodifiedset_spec.lua index 27fe9fcc94..fb8f160b05 100644 --- a/test/functional/autocmd/bufmodifiedset_spec.lua +++ b/test/functional/autocmd/bufmodifiedset_spec.lua @@ -1,10 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local source = helpers.source -local request = helpers.request +local clear = n.clear +local eq = t.eq +local eval = n.eval +local source = n.source +local request = n.request describe('BufModified', function() before_each(clear) diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua index 7428456656..ad3bc3576f 100644 --- a/test/functional/autocmd/cmdline_spec.lua +++ b/test/functional/autocmd/cmdline_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local expect = helpers.expect -local eval = helpers.eval -local next_msg = helpers.next_msg -local feed = helpers.feed -local api = helpers.api +local clear = n.clear +local command = n.command +local eq = t.eq +local expect = n.expect +local eval = n.eval +local next_msg = n.next_msg +local feed = n.feed +local api = n.api describe('cmdline autocommands', function() local channel diff --git a/test/functional/autocmd/completedone_spec.lua b/test/functional/autocmd/completedone_spec.lua new file mode 100644 index 0000000000..33beb16db2 --- /dev/null +++ b/test/functional/autocmd/completedone_spec.lua @@ -0,0 +1,41 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local call = n.call +local feed = n.feed +local eval = n.eval +local eq = t.eq + +describe('CompleteDone', function() + before_each(clear) + + describe('sets v:event.reason', function() + before_each(function() + clear() + command('autocmd CompleteDone * let g:donereason = v:event.reason') + feed('i') + call('complete', call('col', '.'), { 'foo', 'bar' }) + end) + + it('accept', function() + feed('<C-y>') + eq('accept', eval('g:donereason')) + end) + describe('cancel', function() + it('on <C-e>', function() + feed('<C-e>') + eq('cancel', eval('g:donereason')) + end) + it('on non-keyword character', function() + feed('<Esc>') + eq('cancel', eval('g:donereason')) + end) + it('when overriden by another complete()', function() + call('complete', call('col', '.'), { 'bar', 'baz' }) + eq('cancel', eval('g:donereason')) + end) + end) + end) +end) diff --git a/test/functional/autocmd/cursorhold_spec.lua b/test/functional/autocmd/cursorhold_spec.lua index fc2b65f53a..c2815be5c6 100644 --- a/test/functional/autocmd/cursorhold_spec.lua +++ b/test/functional/autocmd/cursorhold_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local feed = helpers.feed -local retry = helpers.retry -local exec = helpers.source +local clear = n.clear +local eq = t.eq +local feed = n.feed +local retry = t.retry +local exec = n.source local sleep = vim.uv.sleep -local api = helpers.api +local api = n.api before_each(clear) diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua index 302afe87b8..2cf02e00f3 100644 --- a/test/functional/autocmd/cursormoved_spec.lua +++ b/test/functional/autocmd/cursormoved_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local api = helpers.api -local source = helpers.source -local command = helpers.command +local clear = n.clear +local eq = t.eq +local eval = n.eval +local api = n.api +local source = n.source +local command = n.command describe('CursorMoved', function() before_each(clear) diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua index 7ad529891f..24ac737b5b 100644 --- a/test/functional/autocmd/dirchanged_spec.lua +++ b/test/functional/autocmd/dirchanged_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local request = helpers.request -local is_os = helpers.is_os +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local request = n.request +local is_os = t.is_os describe('autocmd DirChanged and DirChangedPre', function() local curdir = vim.uv.cwd():gsub('\\', '/') @@ -22,12 +23,12 @@ describe('autocmd DirChanged and DirChangedPre', function() setup(function() for _, dir in pairs(dirs) do - helpers.mkdir(dir) + t.mkdir(dir) end end) teardown(function() for _, dir in pairs(dirs) do - helpers.rmdir(dir) + n.rmdir(dir) end end) diff --git a/test/functional/autocmd/filetype_spec.lua b/test/functional/autocmd/filetype_spec.lua index 648f830f27..91843c7910 100644 --- a/test/functional/autocmd/filetype_spec.lua +++ b/test/functional/autocmd/filetype_spec.lua @@ -1,14 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local eval = helpers.eval -local clear = helpers.clear -local command = helpers.command +local eval = n.eval +local clear = n.clear +local command = n.command describe('autocmd FileType', function() before_each(clear) it('is triggered by :help only once', function() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() command('let g:foo = 0') command('autocmd FileType help let g:foo = g:foo + 1') command('help help') diff --git a/test/functional/autocmd/focus_spec.lua b/test/functional/autocmd/focus_spec.lua index 4f4a036ba8..5163b576db 100644 --- a/test/functional/autocmd/focus_spec.lua +++ b/test/functional/autocmd/focus_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local clear = helpers.clear -local feed_command = helpers.feed_command -local feed_data = thelpers.feed_data +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local tt = require('test.functional.terminal.testutil') -if helpers.skip(helpers.is_os('win')) then +local clear = n.clear +local feed_command = n.feed_command +local feed_data = tt.feed_data + +if t.skip(t.is_os('win')) then return end @@ -14,7 +16,7 @@ describe('autoread TUI FocusGained/FocusLost', function() before_each(function() clear() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -39,7 +41,7 @@ describe('autoread TUI FocusGained/FocusLost', function() line 4 ]] - helpers.write_file(path, '') + t.write_file(path, '') local atime = os.time() - 10 vim.uv.fs_utime(path, atime, atime) @@ -75,7 +77,7 @@ describe('autoread TUI FocusGained/FocusLost', function() unchanged = true, } - helpers.write_file(path, expected_addition) + t.write_file(path, expected_addition) feed_data('\027[I') diff --git a/test/functional/autocmd/modechanged_spec.lua b/test/functional/autocmd/modechanged_spec.lua index 8ad914a597..61ce15d91d 100644 --- a/test/functional/autocmd/modechanged_spec.lua +++ b/test/functional/autocmd/modechanged_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local feed, command = helpers.feed, helpers.command -local exec_lua = helpers.exec_lua +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval, eq = n.clear, n.eval, t.eq +local feed, command = n.feed, n.command +local exec_lua = n.exec_lua describe('ModeChanged', function() before_each(function() diff --git a/test/functional/autocmd/recording_spec.lua b/test/functional/autocmd/recording_spec.lua index b9aec774f1..6ee61c5676 100644 --- a/test/functional/autocmd/recording_spec.lua +++ b/test/functional/autocmd/recording_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local source_vim = helpers.source +local clear = n.clear +local eq = t.eq +local eval = n.eval +local source_vim = n.source describe('RecordingEnter', function() before_each(clear) diff --git a/test/functional/autocmd/safestate_spec.lua b/test/functional/autocmd/safestate_spec.lua index b5b7ab2f95..c45a64e373 100644 --- a/test/functional/autocmd/safestate_spec.lua +++ b/test/functional/autocmd/safestate_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local exec = helpers.exec -local feed = helpers.feed -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local exec = n.exec +local feed = n.feed +local api = n.api before_each(clear) diff --git a/test/functional/autocmd/searchwrapped_spec.lua b/test/functional/autocmd/searchwrapped_spec.lua index 0705b2d5de..0c0b3595ca 100644 --- a/test/functional/autocmd/searchwrapped_spec.lua +++ b/test/functional/autocmd/searchwrapped_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local api = helpers.api -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local api = n.api +local eq = t.eq +local eval = n.eval +local feed = n.feed describe('autocmd SearchWrapped', function() before_each(function() diff --git a/test/functional/autocmd/show_spec.lua b/test/functional/autocmd/show_spec.lua index 1a9dc8a337..7e1818c4fd 100644 --- a/test/functional/autocmd/show_spec.lua +++ b/test/functional/autocmd/show_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local dedent = helpers.dedent -local eq = helpers.eq -local fn = helpers.fn -local eval = helpers.eval -local exec = helpers.exec -local feed = helpers.feed +local clear = n.clear +local command = n.command +local dedent = t.dedent +local eq = t.eq +local fn = n.fn +local eval = n.eval +local exec = n.exec +local feed = n.feed describe(':autocmd', function() before_each(function() diff --git a/test/functional/autocmd/signal_spec.lua b/test/functional/autocmd/signal_spec.lua index c7087254e7..4416afb3ba 100644 --- a/test/functional/autocmd/signal_spec.lua +++ b/test/functional/autocmd/signal_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local fn = helpers.fn -local next_msg = helpers.next_msg -local is_os = helpers.is_os -local skip = helpers.skip +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local fn = n.fn +local next_msg = n.next_msg +local is_os = t.is_os +local skip = t.skip if skip(is_os('win'), 'Only applies to POSIX systems') then return diff --git a/test/functional/autocmd/tabclose_spec.lua b/test/functional/autocmd/tabclose_spec.lua index d0b2ac6a8d..fde72cf4d7 100644 --- a/test/functional/autocmd/tabclose_spec.lua +++ b/test/functional/autocmd/tabclose_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq = helpers.clear, helpers.eq -local api = helpers.api -local command = helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq = n.clear, t.eq +local api = n.api +local command = n.command describe('TabClosed', function() before_each(clear) diff --git a/test/functional/autocmd/tabnew_spec.lua b/test/functional/autocmd/tabnew_spec.lua index ad40954f76..80ab5a1944 100644 --- a/test/functional/autocmd/tabnew_spec.lua +++ b/test/functional/autocmd/tabnew_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval describe('autocmd TabNew', function() before_each(clear) diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index b888845e3b..fcfebd7af5 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -1,13 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local dedent = helpers.dedent -local eval = helpers.eval -local eq = helpers.eq -local feed = helpers.feed -local api = helpers.api -local exec_capture = helpers.exec_capture +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local dedent = t.dedent +local eval = n.eval +local eq = t.eq +local feed = n.feed +local api = n.api +local exec_capture = n.exec_capture describe('TabNewEntered', function() describe('au TabNewEntered', function() diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua index 982edfa06a..a63996ae36 100644 --- a/test/functional/autocmd/termxx_spec.lua +++ b/test/functional/autocmd/termxx_spec.lua @@ -1,17 +1,18 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local tt = require('test.functional.terminal.testutil') local uv = vim.uv -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') - -local clear, command, testprg = helpers.clear, helpers.command, helpers.testprg -local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry -local matches = helpers.matches -local ok = helpers.ok -local feed = helpers.feed -local api = helpers.api -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive -local skip = helpers.skip -local is_os = helpers.is_os + +local clear, command, testprg = n.clear, n.command, n.testprg +local eval, eq, neq, retry = n.eval, t.eq, t.neq, t.retry +local matches = t.matches +local ok = t.ok +local feed = n.feed +local api = n.api +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive +local skip = t.skip +local is_os = t.is_os describe('autocmd TermClose', function() before_each(function() @@ -198,11 +199,11 @@ end) describe('autocmd TextChangedT', function() clear() - local screen = thelpers.screen_setup() + local screen = tt.screen_setup() it('works', function() command('autocmd TextChangedT * ++once let g:called = 1') - thelpers.feed_data('a') + tt.feed_data('a') retry(nil, nil, function() eq(1, api.nvim_get_var('called')) end) @@ -210,7 +211,7 @@ describe('autocmd TextChangedT', function() it('cannot delete terminal buffer', function() command([[autocmd TextChangedT * call nvim_input('<CR>') | bwipe!]]) - thelpers.feed_data('a') + tt.feed_data('a') screen:expect({ any = 'E937: ' }) matches( '^E937: Attempt to delete a buffer that is in use: term://', diff --git a/test/functional/autocmd/textchanged_spec.lua b/test/functional/autocmd/textchanged_spec.lua index d501560dc1..7c679cd4c0 100644 --- a/test/functional/autocmd/textchanged_spec.lua +++ b/test/functional/autocmd/textchanged_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec = helpers.exec -local command = helpers.command -local feed = helpers.feed -local eq = helpers.eq -local neq = helpers.neq -local eval = helpers.eval -local poke_eventloop = helpers.poke_eventloop - -before_each(clear) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec = n.exec +local command = n.command +local feed = n.feed +local eq = t.eq +local neq = t.neq +local eval = n.eval +local poke_eventloop = n.poke_eventloop +local write_file = t.write_file -- oldtest: Test_ChangedP() it('TextChangedI and TextChangedP autocommands', function() + clear() -- The oldtest uses feedkeys() with 'x' flag, which never triggers TextChanged. -- So don't add TextChanged autocommand here. exec([[ @@ -93,6 +95,7 @@ end) -- oldtest: Test_TextChangedI_with_setline() it('TextChangedI with setline()', function() + clear() exec([[ let g:setline_handled = v:false func SetLineOne() @@ -118,76 +121,93 @@ it('TextChangedI with setline()', function() eq('', eval('getline(2)')) end) +-- oldtest: Test_TextChanged_with_norm() +it('TextChanged is triggered after :norm that enters Insert mode', function() + clear() + exec([[ + let g:a = 0 + au TextChanged * let g:a += 1 + ]]) + eq(0, eval('g:a')) + feed(':norm! ia<CR>') + eq(1, eval('g:a')) +end) + -- oldtest: Test_Changed_ChangedI() it('TextChangedI and TextChanged', function() + write_file('XTextChangedI2', 'one\ntwo\nthree') + finally(function() + os.remove('XTextChangedI2') + end) + clear('XTextChangedI2') + exec([[ - let [g:autocmd_i, g:autocmd_n] = ['',''] + let [g:autocmd_n, g:autocmd_i] = ['',''] - func! TextChangedAutocmdI(char) + func TextChangedAutocmd(char) let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick endfunc - augroup Test_TextChanged - au! - au TextChanged <buffer> :call TextChangedAutocmdI('N') - au TextChangedI <buffer> :call TextChangedAutocmdI('I') - augroup END + au TextChanged <buffer> :call TextChangedAutocmd('N') + au TextChangedI <buffer> :call TextChangedAutocmd('I') + + nnoremap <CR> o<Esc> ]]) + -- TextChanged should trigger if a mapping enters and leaves Insert mode. + feed('<CR>') + eq('N4', eval('g:autocmd_n')) + eq('', eval('g:autocmd_i')) + feed('i') - poke_eventloop() + eq('N4', eval('g:autocmd_n')) + eq('', eval('g:autocmd_i')) + -- TextChangedI should trigger if change is done in Insert mode. feed('f') - poke_eventloop() + eq('N4', eval('g:autocmd_n')) + eq('I5', eval('g:autocmd_i')) feed('o') - poke_eventloop() + eq('N4', eval('g:autocmd_n')) + eq('I6', eval('g:autocmd_i')) feed('o') - poke_eventloop() - feed('<esc>') - eq('', eval('g:autocmd_n')) - eq('I5', eval('g:autocmd_i')) + eq('N4', eval('g:autocmd_n')) + eq('I7', eval('g:autocmd_i')) + -- TextChanged shouldn't trigger when leaving Insert mode and TextChangedI + -- has been triggered. + feed('<Esc>') + eq('N4', eval('g:autocmd_n')) + eq('I7', eval('g:autocmd_i')) + -- TextChanged should trigger if change is done in Normal mode. feed('yyp') - eq('N6', eval('g:autocmd_n')) - eq('I5', eval('g:autocmd_i')) - - -- TextChangedI should only trigger if change was done in Insert mode - command([[let g:autocmd_i = '']]) - feed('yypi<esc>') - eq('', eval('g:autocmd_i')) + eq('N8', eval('g:autocmd_n')) + eq('I7', eval('g:autocmd_i')) - -- TextChanged should only trigger if change was done in Normal mode - command([[let g:autocmd_n = '']]) - feed('ibar<esc>') - eq('', eval('g:autocmd_n')) + -- TextChangedI shouldn't trigger if change isn't done in Insert mode. + feed('i') + eq('N8', eval('g:autocmd_n')) + eq('I7', eval('g:autocmd_i')) + feed('<Esc>') + eq('N8', eval('g:autocmd_n')) + eq('I7', eval('g:autocmd_i')) + -- TextChangedI should trigger if change is a mix of Normal and Insert modes. local function validate_mixed_textchangedi(keys) - feed('ifoo<esc>') - command([[let g:autocmd_i = '']]) - command([[let g:autocmd_n = '']]) - for _, s in ipairs(keys) do - feed(s) - poke_eventloop() - end + feed('ifoo<Esc>') + command(":let [g:autocmd_n, g:autocmd_i] = ['', '']") + feed(keys) + eq('', eval('g:autocmd_n')) neq('', eval('g:autocmd_i')) + feed('<Esc>') eq('', eval('g:autocmd_n')) + neq('', eval('g:autocmd_i')) end - validate_mixed_textchangedi({ 'o', '<esc>' }) - validate_mixed_textchangedi({ 'O', '<esc>' }) - validate_mixed_textchangedi({ 'ciw', '<esc>' }) - validate_mixed_textchangedi({ 'cc', '<esc>' }) - validate_mixed_textchangedi({ 'C', '<esc>' }) - validate_mixed_textchangedi({ 's', '<esc>' }) - validate_mixed_textchangedi({ 'S', '<esc>' }) -end) - --- oldtest: Test_TextChanged_with_norm() -it('TextChanged is triggered after :norm that enters Insert mode', function() - exec([[ - let g:a = 0 - au TextChanged * let g:a += 1 - ]]) - eq(0, eval('g:a')) - feed(':norm! ia<CR>') - eq(1, eval('g:a')) + validate_mixed_textchangedi('o') + validate_mixed_textchangedi('O') + validate_mixed_textchangedi('ciw') + validate_mixed_textchangedi('cc') + validate_mixed_textchangedi('C') + validate_mixed_textchangedi('s') + validate_mixed_textchangedi('S') end) diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua index 29cd62f586..cf8cbe25c1 100644 --- a/test/functional/autocmd/textyankpost_spec.lua +++ b/test/functional/autocmd/textyankpost_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local feed, command, expect = helpers.feed, helpers.command, helpers.expect -local api, fn, neq = helpers.api, helpers.fn, helpers.neq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval, eq = n.clear, n.eval, t.eq +local feed, command, expect = n.feed, n.command, n.expect +local api, fn, neq = n.api, n.fn, t.neq describe('TextYankPost', function() before_each(function() @@ -72,19 +74,19 @@ describe('TextYankPost', function() command('set debug=msg') -- the regcontents should not be changed without copy. local status, err = pcall(command, 'call extend(g:event.regcontents, ["more text"])') - eq(status, false) + eq(false, status) neq(nil, string.find(err, ':E742:')) -- can't mutate keys inside the autocommand command('autocmd! TextYankPost * let v:event.regcontents = 0') status, err = pcall(command, 'normal yy') - eq(status, false) + eq(false, status) neq(nil, string.find(err, ':E46:')) -- can't add keys inside the autocommand command('autocmd! TextYankPost * let v:event.mykey = 0') status, err = pcall(command, 'normal yy') - eq(status, false) + eq(false, status) neq(nil, string.find(err, ':E742:')) end) diff --git a/test/functional/autocmd/win_scrolled_resized_spec.lua b/test/functional/autocmd/win_scrolled_resized_spec.lua index d40dc37103..72bbc1e469 100644 --- a/test/functional/autocmd/win_scrolled_resized_spec.lua +++ b/test/functional/autocmd/win_scrolled_resized_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local exec = helpers.exec -local command = helpers.command -local feed = helpers.feed -local api = helpers.api -local assert_alive = helpers.assert_alive +local clear = n.clear +local eq = t.eq +local eval = n.eval +local exec = n.exec +local command = n.command +local feed = n.feed +local api = n.api +local assert_alive = n.assert_alive before_each(clear) diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua index 56a2f5a571..a98e190a60 100644 --- a/test/functional/core/channels_spec.lua +++ b/test/functional/core/channels_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, eval, next_msg, ok, source = - helpers.clear, helpers.eq, helpers.eval, helpers.next_msg, helpers.ok, helpers.source -local command, fn, api = helpers.command, helpers.fn, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, eval, next_msg, ok, source = n.clear, t.eq, n.eval, n.next_msg, t.ok, n.source +local command, fn, api = n.command, n.fn, n.api +local matches = t.matches local sleep = vim.uv.sleep -local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv -local get_session, set_session = helpers.get_session, helpers.set_session -local nvim_prog = helpers.nvim_prog -local is_os = helpers.is_os -local retry = helpers.retry -local expect_twostreams = helpers.expect_twostreams -local assert_alive = helpers.assert_alive -local pcall_err = helpers.pcall_err -local skip = helpers.skip +local spawn, nvim_argv = n.spawn, n.nvim_argv +local get_session, set_session = n.get_session, n.set_session +local nvim_prog = n.nvim_prog +local is_os = t.is_os +local retry = t.retry +local expect_twostreams = n.expect_twostreams +local assert_alive = n.assert_alive +local pcall_err = t.pcall_err +local skip = t.skip describe('channels', function() local init = [[ @@ -277,7 +279,7 @@ describe('channels', function() local _, err = pcall(command, "call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')") - ok(string.find(err, 'E906: invalid stream for channel') ~= nil) + matches('E906: invalid stream for channel', err) eq(1, eval("rpcrequest(id, 'nvim_eval', 'chanclose(v:stderr, \"stderr\")')")) eq({ 'notification', 'stderr', { 3, { '' } } }, next_msg()) diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua index d9e3cc3f31..34c3eedbd2 100644 --- a/test/functional/core/exit_spec.lua +++ b/test/functional/core/exit_spec.lua @@ -1,24 +1,25 @@ -local helpers = require('test.functional.helpers')(after_each) - -local assert_alive = helpers.assert_alive -local command = helpers.command -local feed_command = helpers.feed_command -local feed = helpers.feed -local eval = helpers.eval -local eq = helpers.eq -local run = helpers.run -local fn = helpers.fn -local nvim_prog = helpers.nvim_prog -local pcall_err = helpers.pcall_err -local exec_capture = helpers.exec_capture -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local command = n.command +local feed_command = n.feed_command +local feed = n.feed +local eval = n.eval +local eq = t.eq +local run = n.run +local fn = n.fn +local nvim_prog = n.nvim_prog +local pcall_err = t.pcall_err +local exec_capture = n.exec_capture +local poke_eventloop = n.poke_eventloop describe('v:exiting', function() local cid before_each(function() - helpers.clear() - cid = helpers.api.nvim_get_chan_info(0).id + n.clear() + cid = n.api.nvim_get_chan_info(0).id end) it('defaults to v:null', function() @@ -74,7 +75,7 @@ describe(':cquit', function() end before_each(function() - helpers.clear() + n.clear() end) it('exits with non-zero after :cquit', function() diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua index 928cab525c..5b0be1e83c 100644 --- a/test/functional/core/fileio_spec.lua +++ b/test/functional/core/fileio_spec.lua @@ -1,37 +1,38 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') local uv = vim.uv -local helpers = require('test.functional.helpers')(after_each) - -local assert_log = helpers.assert_log -local assert_nolog = helpers.assert_nolog -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local neq = helpers.neq -local ok = helpers.ok -local feed = helpers.feed -local fn = helpers.fn -local nvim_prog = helpers.nvim_prog -local request = helpers.request -local retry = helpers.retry -local rmdir = helpers.rmdir -local matches = helpers.matches -local api = helpers.api -local mkdir = helpers.mkdir + +local assert_log = t.assert_log +local assert_nolog = t.assert_nolog +local clear = n.clear +local command = n.command +local eq = t.eq +local neq = t.neq +local ok = t.ok +local feed = n.feed +local fn = n.fn +local nvim_prog = n.nvim_prog +local request = n.request +local retry = t.retry +local rmdir = n.rmdir +local matches = t.matches +local api = n.api +local mkdir = t.mkdir local sleep = vim.uv.sleep -local read_file = helpers.read_file +local read_file = t.read_file local trim = vim.trim -local currentdir = helpers.fn.getcwd -local assert_alive = helpers.assert_alive -local check_close = helpers.check_close -local expect_exit = helpers.expect_exit -local write_file = helpers.write_file -local Screen = require('test.functional.ui.screen') -local feed_command = helpers.feed_command -local skip = helpers.skip -local is_os = helpers.is_os -local is_ci = helpers.is_ci -local spawn = helpers.spawn -local set_session = helpers.set_session +local currentdir = n.fn.getcwd +local assert_alive = n.assert_alive +local check_close = n.check_close +local expect_exit = n.expect_exit +local write_file = t.write_file +local feed_command = n.feed_command +local skip = t.skip +local is_os = t.is_os +local is_ci = t.is_ci +local spawn = n.spawn +local set_session = n.set_session describe('fileio', function() before_each(function() end) @@ -54,7 +55,7 @@ describe('fileio', function() --- Starts a new nvim session and returns an attached screen. local function startup(extra_args) extra_args = extra_args or {} - local argv = vim.tbl_flatten({ args, '--embed', extra_args }) + local argv = vim.iter({ args, '--embed', extra_args }):flatten():totable() local screen_nvim = spawn(argv) set_session(screen_nvim) local screen = Screen.new(70, 10) @@ -100,7 +101,7 @@ describe('fileio', function() eq('foozubbaz', trim(read_file('Xtest_startup_file1'))) -- 4. Exit caused by deadly signal (+ 'swapfile'). - local j = fn.jobstart(vim.tbl_flatten({ args, '--embed' }), { rpc = true }) + local j = fn.jobstart(vim.iter({ args, '--embed' }):flatten():totable(), { rpc = true }) fn.rpcrequest( j, 'nvim_exec2', @@ -228,7 +229,7 @@ describe('fileio', function() local initial_content = 'foo' local backup_dir = 'Xtest_backupdir' - local sep = helpers.get_pathsep() + local sep = n.get_pathsep() local link_file_name = 'Xtest_startup_file2' local backup_file_name = backup_dir .. sep .. link_file_name .. '~' @@ -329,7 +330,7 @@ describe('tmpdir', function() before_each(function() -- Fake /tmp dir so that we can mess it up. - os_tmpdir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX') + os_tmpdir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname()) .. '/nvim_XXXXXXXXXX') end) after_each(function() diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 13f5f9a5e1..e1efc07452 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -1,40 +1,41 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') - -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local exc_exec = helpers.exc_exec -local feed_command = helpers.feed_command -local feed = helpers.feed -local insert = helpers.insert -local neq = helpers.neq -local next_msg = helpers.next_msg -local testprg = helpers.testprg -local ok = helpers.ok -local source = helpers.source -local write_file = helpers.write_file -local mkdir = helpers.mkdir -local rmdir = helpers.rmdir -local assert_alive = helpers.assert_alive -local command = helpers.command -local fn = helpers.fn -local os_kill = helpers.os_kill -local retry = helpers.retry -local api = helpers.api -local NIL = vim.NIL -local poke_eventloop = helpers.poke_eventloop -local get_pathsep = helpers.get_pathsep -local pathroot = helpers.pathroot -local exec_lua = helpers.exec_lua -local nvim_set = helpers.nvim_set -local expect_twostreams = helpers.expect_twostreams -local expect_msg_seq = helpers.expect_msg_seq -local pcall_err = helpers.pcall_err -local matches = helpers.matches +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local skip = helpers.skip -local is_os = helpers.is_os +local tt = require('test.functional.terminal.testutil') + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local exc_exec = n.exc_exec +local feed_command = n.feed_command +local feed = n.feed +local insert = n.insert +local neq = t.neq +local next_msg = n.next_msg +local testprg = n.testprg +local ok = t.ok +local source = n.source +local write_file = t.write_file +local mkdir = t.mkdir +local rmdir = n.rmdir +local assert_alive = n.assert_alive +local command = n.command +local fn = n.fn +local os_kill = n.os_kill +local retry = t.retry +local api = n.api +local NIL = vim.NIL +local poke_eventloop = n.poke_eventloop +local get_pathsep = n.get_pathsep +local pathroot = n.pathroot +local exec_lua = n.exec_lua +local nvim_set = n.nvim_set +local expect_twostreams = n.expect_twostreams +local expect_msg_seq = n.expect_msg_seq +local pcall_err = t.pcall_err +local matches = t.matches +local skip = t.skip +local is_os = t.is_os describe('jobs', function() local channel @@ -73,7 +74,7 @@ describe('jobs', function() command("let j = jobstart('env', g:job_opts)") end end) - ok(string.find(err, 'E475: Invalid argument: env') ~= nil) + matches('E475: Invalid argument: env', err) end) it('append environment #env', function() @@ -227,7 +228,7 @@ describe('jobs', function() command("let j = jobstart('pwd', g:job_opts)") end end) - ok(string.find(err, 'E475: Invalid argument: expected valid directory$') ~= nil) + matches('E475: Invalid argument: expected valid directory$', err) end) it('error on non-executable `cwd`', function() @@ -307,7 +308,7 @@ describe('jobs', function() it('preserves NULs', function() -- Make a file with NULs in it. - local filename = helpers.tmpname() + local filename = t.tmpname() write_file(filename, 'abc\0def\n') command("let j = jobstart(['cat', '" .. filename .. "'], g:job_opts)") @@ -732,7 +733,7 @@ describe('jobs', function() describe('jobwait()', function() before_each(function() if is_os('win') then - helpers.set_shell_powershell() + n.set_shell_powershell() end end) @@ -980,10 +981,7 @@ describe('jobs', function() command('let g:job_opts.pty = v:true') command('let g:job_opts.rpc = v:true') local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)") - ok( - string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set") - ~= nil - ) + matches("E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set", err) end) it('does not crash when repeatedly failing to start shell', function() @@ -1185,7 +1183,7 @@ describe('jobs', function() end) it('does not close the same handle twice on exit #25086', function() - local filename = string.format('%s.lua', helpers.tmpname()) + local filename = string.format('%s.lua', t.tmpname()) write_file( filename, [[ @@ -1198,7 +1196,7 @@ describe('jobs', function() ]] ) - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '--cmd', 'set notermguicolors', '-i', @@ -1233,15 +1231,16 @@ describe('pty process teardown', function() screen:attach() screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 | ]]) end) it('does not prevent/delay exit. #4798 #4900', function() + skip(fn.executable('sleep') == 0, 'missing "sleep" command') -- Use a nested nvim (in :term) to test without --headless. fn.termopen({ - helpers.nvim_prog, + n.nvim_prog, '-u', 'NONE', '-i', diff --git a/test/functional/core/log_spec.lua b/test/functional/core/log_spec.lua index 1637e683c1..cac61cda2d 100644 --- a/test/functional/core/log_spec.lua +++ b/test/functional/core/log_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_log = helpers.assert_log -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local expect_exit = helpers.expect_exit -local request = helpers.request +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_log = t.assert_log +local clear = n.clear +local command = n.command +local eq = t.eq +local exec_lua = n.exec_lua +local expect_exit = n.expect_exit +local request = n.request describe('log', function() local testlog = 'Xtest_logging' diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua index 9d8d64c82d..5e903726db 100644 --- a/test/functional/core/main_spec.lua +++ b/test/functional/core/main_spec.lua @@ -1,17 +1,18 @@ -local uv = vim.uv -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local uv = vim.uv -local eq = helpers.eq -local matches = helpers.matches -local feed = helpers.feed -local eval = helpers.eval -local clear = helpers.clear -local fn = helpers.fn -local nvim_prog_abs = helpers.nvim_prog_abs -local write_file = helpers.write_file -local is_os = helpers.is_os -local skip = helpers.skip +local eq = t.eq +local matches = t.matches +local feed = n.feed +local eval = n.eval +local clear = n.clear +local fn = n.fn +local nvim_prog_abs = n.nvim_prog_abs +local write_file = t.write_file +local is_os = t.is_os +local skip = t.skip describe('command-line option', function() describe('-s', function() @@ -120,9 +121,9 @@ describe('command-line option', function() feed('i:cq<CR>') screen:expect([[ | - [Process exited 1] | + [Process exited 1]{2: } | |*5 - -- TERMINAL -- | + {5:-- TERMINAL --} | ]]) --[=[ Example of incorrect output: screen:expect([[ diff --git a/test/functional/core/path_spec.lua b/test/functional/core/path_spec.lua index e98bfc0d45..d8e274019a 100644 --- a/test/functional/core/path_spec.lua +++ b/test/functional/core/path_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local fn = helpers.fn -local insert = helpers.insert -local is_os = helpers.is_os -local mkdir = helpers.mkdir -local rmdir = helpers.rmdir -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local fn = n.fn +local insert = n.insert +local is_os = t.is_os +local mkdir = t.mkdir +local rmdir = n.rmdir +local write_file = t.write_file local function join_path(...) local pathsep = (is_os('win') and '\\' or '/') diff --git a/test/functional/core/remote_spec.lua b/test/functional/core/remote_spec.lua index caff06f6ab..6cc28ddeef 100644 --- a/test/functional/core/remote_spec.lua +++ b/test/functional/core/remote_spec.lua @@ -1,20 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local exec_capture = helpers.exec_capture -local exec_lua = helpers.exec_lua -local expect = helpers.expect -local fn = helpers.fn -local insert = helpers.insert -local nvim_prog = helpers.nvim_prog -local new_argv = helpers.new_argv -local neq = helpers.neq -local set_session = helpers.set_session -local spawn = helpers.spawn -local tmpname = helpers.tmpname -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local exec_capture = n.exec_capture +local exec_lua = n.exec_lua +local expect = n.expect +local fn = n.fn +local insert = n.insert +local nvim_prog = n.nvim_prog +local new_argv = n.new_argv +local neq = t.neq +local set_session = n.set_session +local spawn = n.spawn +local tmpname = t.tmpname +local write_file = t.write_file describe('Remote', function() local fname, other_fname diff --git a/test/functional/core/spellfile_spec.lua b/test/functional/core/spellfile_spec.lua index 57953b8f80..e2ccb038e7 100644 --- a/test/functional/core/spellfile_spec.lua +++ b/test/functional/core/spellfile_spec.lua @@ -1,13 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local api = helpers.api -local exc_exec = helpers.exc_exec -local fn = helpers.fn -local rmdir = helpers.rmdir -local write_file = helpers.write_file -local mkdir = helpers.mkdir +local eq = t.eq +local clear = n.clear +local api = n.api +local exc_exec = n.exc_exec +local fn = n.fn +local rmdir = n.rmdir +local write_file = t.write_file +local mkdir = t.mkdir local testdir = 'Xtest-functional-spell-spellfile.d' diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index cc58226f48..a53625ab1b 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -1,37 +1,41 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local assert_log = helpers.assert_log -local clear = helpers.clear -local command = helpers.command -local ok = helpers.ok -local eq = helpers.eq -local matches = helpers.matches -local eval = helpers.eval -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local fn = helpers.fn +local assert_alive = n.assert_alive +local assert_log = t.assert_log +local clear = n.clear +local command = n.command +local ok = t.ok +local eq = t.eq +local matches = t.matches +local eval = n.eval +local exec = n.exec +local exec_capture = n.exec_capture +local exec_lua = n.exec_lua +local feed = n.feed +local fn = n.fn local pesc = vim.pesc -local mkdir = helpers.mkdir -local mkdir_p = helpers.mkdir_p -local nvim_prog = helpers.nvim_prog -local nvim_set = helpers.nvim_set -local read_file = helpers.read_file -local retry = helpers.retry -local rmdir = helpers.rmdir +local mkdir = t.mkdir +local mkdir_p = n.mkdir_p +local nvim_prog = n.nvim_prog +local nvim_set = n.nvim_set +local read_file = t.read_file +local retry = t.retry +local rmdir = n.rmdir local sleep = vim.uv.sleep local startswith = vim.startswith -local write_file = helpers.write_file -local api = helpers.api -local alter_slashes = helpers.alter_slashes -local is_os = helpers.is_os -local dedent = helpers.dedent +local write_file = t.write_file +local api = n.api +local alter_slashes = n.alter_slashes +local is_os = t.is_os +local dedent = t.dedent local tbl_map = vim.tbl_map local tbl_filter = vim.tbl_filter local endswith = vim.endswith +local check_close = n.check_close + +local testlog = 'Xtest-startupspec-log' describe('startup', function() it('--clean', function() @@ -83,6 +87,8 @@ describe('startup', function() local screen screen = Screen.new(60, 7) screen:attach() + -- not the same colors on windows for some reason + screen._default_attr_ids = nil local id = fn.termopen({ nvim_prog, '-u', @@ -97,15 +103,7 @@ describe('startup', function() VIMRUNTIME = os.getenv('VIMRUNTIME'), }, }) - screen:expect([[ - ^ | - | - Entering Debug mode. Type "cont" to continue. | - nvim_exec2() | - cmd: aunmenu * | - > | - | - ]]) + screen:expect({ any = pesc('Entering Debug mode. Type "cont" to continue.') }) fn.chansend(id, 'cont\n') screen:expect([[ ^ | @@ -119,6 +117,11 @@ end) describe('startup', function() before_each(clear) + after_each(function() + check_close() + os.remove(testlog) + end) + describe('-l Lua', function() local function assert_l_out(expected, nvim_args, lua_args, script, input) local args = { nvim_prog } @@ -326,6 +329,9 @@ describe('startup', function() local screen = Screen.new(25, 3) -- Remote UI connected by --embed. screen:attach() + -- TODO: a lot of tests in this file already use the new default color scheme. + -- once we do the batch update of tests to use it, remove this workarond + screen._default_attr_ids = nil command([[echo has('ttyin') has('ttyout')]]) screen:expect([[ ^ | @@ -337,6 +343,7 @@ describe('startup', function() it('in a TTY: has("ttyin")==1 has("ttyout")==1', function() local screen = Screen.new(25, 4) screen:attach() + screen._default_attr_ids = nil if is_os('win') then command([[set shellcmdflag=/s\ /c shellxquote=\"]]) end @@ -365,6 +372,7 @@ describe('startup', function() end) it('output to pipe: has("ttyin")==1 has("ttyout")==0', function() + clear({ env = { NVIM_LOG_FILE = testlog } }) if is_os('win') then command([[set shellcmdflag=/s\ /c shellxquote=\"]]) end @@ -392,9 +400,13 @@ describe('startup', function() read_file('Xtest_startup_ttyout') ) end) + if is_os('win') then + assert_log('stream write failed. RPC canceled; closing channel', testlog) + end end) it('input from pipe: has("ttyin")==0 has("ttyout")==1', function() + clear({ env = { NVIM_LOG_FILE = testlog } }) if is_os('win') then command([[set shellcmdflag=/s\ /c shellxquote=\"]]) end @@ -423,11 +435,16 @@ describe('startup', function() read_file('Xtest_startup_ttyout') ) end) + if is_os('win') then + assert_log('stream write failed. RPC canceled; closing channel', testlog) + end end) it('input from pipe (implicit) #7679', function() + clear({ env = { NVIM_LOG_FILE = testlog } }) local screen = Screen.new(25, 4) screen:attach() + screen._default_attr_ids = nil if is_os('win') then command([[set shellcmdflag=/s\ /c shellxquote=\"]]) end @@ -450,6 +467,9 @@ describe('startup', function() 0 1 | | ]]) + if not is_os('win') then + assert_log('Failed to get flags on descriptor 3: Bad file descriptor', testlog, 100) + end end) it('input from pipe + file args #7679', function() @@ -589,6 +609,7 @@ describe('startup', function() local screen screen = Screen.new(60, 6) screen:attach() + screen._default_attr_ids = nil local id = fn.termopen({ nvim_prog, '-u', @@ -974,7 +995,7 @@ describe('sysinit', function() local xdgdir = 'Xxdg' local vimdir = 'Xvim' local xhome = 'Xhome' - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() before_each(function() rmdir(xdgdir) @@ -1035,7 +1056,7 @@ end) describe('user config init', function() local xhome = 'Xhome' - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() local xconfig = xhome .. pathsep .. 'Xconfig' local xdata = xhome .. pathsep .. 'Xdata' local init_lua_path = table.concat({ xconfig, 'nvim', 'init.lua' }, pathsep) @@ -1123,6 +1144,7 @@ describe('user config init', function() local screen = Screen.new(50, 8) screen:attach() + screen._default_attr_ids = nil fn.termopen({ nvim_prog }, { env = { VIMRUNTIME = os.getenv('VIMRUNTIME'), @@ -1197,7 +1219,7 @@ end) describe('runtime:', function() local xhome = 'Xhome' - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() local xconfig = xhome .. pathsep .. 'Xconfig' local xdata = xhome .. pathsep .. 'Xdata' local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } @@ -1339,7 +1361,7 @@ end) describe('user session', function() local xhome = 'Xhome' - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() local session_file = table.concat({ xhome, 'session.lua' }, pathsep) before_each(function() diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua index 1fbdd1c142..3c58892731 100644 --- a/test/functional/editor/K_spec.lua +++ b/test/functional/editor/K_spec.lua @@ -1,6 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, clear, eval, feed, api, retry = - helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.api, helpers.retry +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear, eval, feed, api, retry = t.eq, n.clear, n.eval, n.feed, n.api, t.retry describe('K', function() local test_file = 'K_spec_out' @@ -13,19 +14,19 @@ describe('K', function() end) it("invokes colon-prefixed 'keywordprg' as Vim command", function() - helpers.source([[ + n.source([[ let @a='fnord' set keywordprg=:put]]) -- K on the text "a" resolves to `:put a`. feed('ia<ESC>K') - helpers.expect([[ + n.expect([[ a fnord]]) end) it("invokes non-prefixed 'keywordprg' as shell command", function() - helpers.source([[ + n.source([[ let @a='fnord' set keywordprg=echo\ fnord>>]]) @@ -43,7 +44,7 @@ describe('K', function() end) it("<esc> kills the buffer for a running 'keywordprg' command", function() - helpers.source('set keywordprg=less') + n.source('set keywordprg=less') eval('writefile(["hello", "world"], "' .. test_file .. '")') feed('i' .. test_file .. '<esc>K') eq('t', eval('mode()')) @@ -57,7 +58,7 @@ describe('K', function() local bufnr = eval('bufnr()') feed('<esc>') eq('n', eval('mode()')) - helpers.neq(bufnr, eval('bufnr()')) + t.neq(bufnr, eval('bufnr()')) end) it('empty string falls back to :help #19298', function() diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index 33d0d47499..62bb7e19f3 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local clear, feed = helpers.clear, helpers.feed -local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq -local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect -local fn = helpers.fn -local command = helpers.command -local api = helpers.api -local poke_eventloop = helpers.poke_eventloop + +local assert_alive = n.assert_alive +local clear, feed = n.clear, n.feed +local eval, eq, neq = n.eval, t.eq, t.neq +local feed_command, source, expect = n.feed_command, n.source, n.expect +local fn = n.fn +local command = n.command +local api = n.api +local poke_eventloop = n.poke_eventloop describe('completion', function() local screen diff --git a/test/functional/editor/count_spec.lua b/test/functional/editor/count_spec.lua index 94f741250a..d158497cb8 100644 --- a/test/functional/editor/count_spec.lua +++ b/test/functional/editor/count_spec.lua @@ -1,10 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local command = helpers.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local clear = n.clear +local command = n.command describe('v:count/v:count1', function() before_each(function() diff --git a/test/functional/editor/ctrl_c_spec.lua b/test/functional/editor/ctrl_c_spec.lua index e6a6ea808a..e1258c7df8 100644 --- a/test/functional/editor/ctrl_c_spec.lua +++ b/test/functional/editor/ctrl_c_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, source = helpers.clear, helpers.feed, helpers.source -local command = helpers.command -local poke_eventloop = helpers.poke_eventloop + +local clear, feed, source = n.clear, n.feed, n.source +local command = n.command +local poke_eventloop = n.poke_eventloop local sleep = vim.uv.sleep describe('CTRL-C (mapped)', function() @@ -16,7 +18,7 @@ describe('CTRL-C (mapped)', function() it('interrupts :global', function() -- Crashes luajit. - if helpers.skip_fragile(pending) then + if t.skip_fragile(pending) then return end @@ -66,8 +68,8 @@ describe('CTRL-C (mapped)', function() feed('i') screen:expect([[ ^ | - ~ |*4 - -- INSERT -- | + {1:~ }|*4 + {5:-- INSERT --} | ]]) end) @@ -81,8 +83,8 @@ describe('CTRL-C (mapped)', function() feed('i') screen:expect([[ ^ | - ~ |*4 - -- INSERT -- | + {1:~ }|*4 + {5:-- INSERT --} | ]]) end) end) diff --git a/test/functional/editor/fold_spec.lua b/test/functional/editor/fold_spec.lua index 7950f6aea4..ee3f268a2a 100644 --- a/test/functional/editor/fold_spec.lua +++ b/test/functional/editor/fold_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local insert = helpers.insert -local exec = helpers.exec -local feed = helpers.feed -local expect = helpers.expect -local command = helpers.command -local fn = helpers.fn -local eq = helpers.eq -local neq = helpers.neq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local insert = n.insert +local exec = n.exec +local feed = n.feed +local expect = n.expect +local command = n.command +local fn = n.fn +local eq = t.eq +local neq = t.neq describe('Folding', function() local tempfname = 'Xtest-fold.txt' @@ -301,7 +302,7 @@ a]], it('updates correctly on :read', function() -- luacheck: ignore 621 - helpers.write_file( + t.write_file( tempfname, [[ a @@ -376,7 +377,7 @@ a]], end) it('splits folds according to >N and <N with foldexpr', function() - helpers.source([[ + n.source([[ function TestFoldExpr(lnum) let thisline = getline(a:lnum) if thisline == 'a' @@ -391,7 +392,7 @@ a]], return 0 endfunction ]]) - helpers.write_file( + t.write_file( tempfname, [[ b diff --git a/test/functional/editor/jump_spec.lua b/test/functional/editor/jump_spec.lua index fe03d82164..880831d9f8 100644 --- a/test/functional/editor/jump_spec.lua +++ b/test/functional/editor/jump_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local dedent = helpers.dedent -local eq = helpers.eq -local fn = helpers.fn -local feed = helpers.feed -local exec_capture = helpers.exec_capture -local write_file = helpers.write_file -local api = helpers.api +local clear = n.clear +local command = n.command +local dedent = t.dedent +local eq = t.eq +local fn = n.fn +local feed = n.feed +local exec_capture = n.exec_capture +local write_file = t.write_file +local api = n.api describe('jumplist', function() local fname1 = 'Xtest-functional-normal-jump' diff --git a/test/functional/editor/lang_spec.lua b/test/functional/editor/lang_spec.lua index ee7cfac057..74d83bcfa8 100644 --- a/test/functional/editor/lang_spec.lua +++ b/test/functional/editor/lang_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, insert, eq = helpers.clear, helpers.insert, helpers.eq -local command, expect = helpers.command, helpers.expect -local feed, eval = helpers.feed, helpers.eval -local exc_exec = helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, insert, eq = n.clear, n.insert, t.eq +local command, expect = n.command, n.expect +local feed, eval = n.feed, n.eval +local exc_exec = n.exc_exec describe('gu and gU', function() before_each(clear) diff --git a/test/functional/editor/langmap_spec.lua b/test/functional/editor/langmap_spec.lua index b2a4b21a89..e50e19a468 100644 --- a/test/functional/editor/langmap_spec.lua +++ b/test/functional/editor/langmap_spec.lua @@ -1,10 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq, neq, call = helpers.eq, helpers.neq, helpers.call -local eval, feed, clear = helpers.eval, helpers.feed, helpers.clear -local command, insert, expect = helpers.command, helpers.insert, helpers.expect -local feed_command = helpers.feed_command -local curwin = helpers.api.nvim_get_current_win +local eq, neq, call = t.eq, t.neq, n.call +local eval, feed, clear = n.eval, n.feed, n.clear +local command, insert, expect = n.command, n.insert, n.expect +local feed_command = n.feed_command +local curwin = n.api.nvim_get_current_win describe("'langmap'", function() before_each(function() @@ -133,7 +134,7 @@ describe("'langmap'", function() hello]]) end) it('command-line CTRL-R', function() - helpers.source([[ + n.source([[ let i_value = 0 let j_value = 0 call setreg('i', 'i_value') @@ -171,7 +172,7 @@ describe("'langmap'", function() end) it('prompt for number', function() command('set langmap=12,21') - helpers.source([[ + n.source([[ let gotten_one = 0 function Map() let answer = inputlist(['a', '1.', '2.', '3.']) @@ -214,10 +215,7 @@ describe("'langmap'", function() end feed('qa' .. command_string .. 'q') expect(expect_string) - eq( - expect_macro or helpers.fn.nvim_replace_termcodes(command_string, true, true, true), - eval('@a') - ) + eq(expect_macro or n.fn.nvim_replace_termcodes(command_string, true, true, true), eval('@a')) if setup_function then setup_function() end diff --git a/test/functional/editor/macro_spec.lua b/test/functional/editor/macro_spec.lua index c97befdf07..27c5eddac8 100644 --- a/test/functional/editor/macro_spec.lua +++ b/test/functional/editor/macro_spec.lua @@ -1,19 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local expect = helpers.expect -local command = helpers.command -local fn = helpers.fn -local api = helpers.api -local insert = helpers.insert - -describe('macros', function() +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local eval = n.eval +local feed = n.feed +local clear = n.clear +local expect = n.expect +local command = n.command +local fn = n.fn +local api = n.api +local insert = n.insert + +describe('macros with default mappings', function() before_each(function() clear({ args_rm = { '--cmd' } }) end) + it('can be recorded and replayed', function() feed('qiahello<esc>q') expect('hello') @@ -22,6 +24,7 @@ describe('macros', function() expect('hellohello') eq('ahello', eval('@i')) end) + it('applies maps', function() command('imap x l') command('nmap l a') @@ -34,87 +37,147 @@ describe('macros', function() end) it('can be replayed with Q', function() - insert [[hello + insert [[ +hello hello hello]] feed [[gg]] feed [[qqAFOO<esc>q]] - eq({ 'helloFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOO +hello +hello]] feed [[Q]] - eq({ 'helloFOOFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOOFOO +hello +hello]] feed [[G3Q]] - eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOOFOO +hello +helloFOOFOOFOO]] feed [[ggV3jQ]] - eq( - { 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' }, - api.nvim_buf_get_lines(0, 0, -1, false) - ) + expect [[ +helloFOOFOOFOO +helloFOO +helloFOOFOOFOOFOO]] end) - it('can be replayed with @', function() - insert [[hello + it('can be replayed with Q and @@', function() + insert [[ +hello hello hello]] feed [[gg]] feed [[qqAFOO<esc>q]] - eq({ 'helloFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOO +hello +hello]] feed [[Q]] - eq({ 'helloFOOFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOOFOO +hello +hello]] feed [[G3@@]] - eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOOFOO +hello +helloFOOFOOFOO]] feed [[ggV2j@@]] - eq( - { 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' }, - api.nvim_buf_get_lines(0, 0, -1, false) - ) + expect [[ +helloFOOFOOFOO +helloFOO +helloFOOFOOFOOFOO]] end) - it('can be replayed with @q and @w', function() - insert [[hello + it('can be replayed with @ in linewise Visual mode', function() + insert [[ +hello hello hello]] feed [[gg]] feed [[qqAFOO<esc>qu]] - eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +hello +hello +hello]] feed [[qwA123<esc>qu]] - eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +hello +hello +hello]] feed [[V3j@q]] - eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +helloFOO +helloFOO +helloFOO]] + + feed [[ggVj@w]] + expect [[ +helloFOO123 +helloFOO123 +helloFOO]] + end) - feed [[gg]] - feed [[Vj@w]] - eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + it('can be recorded and replayed in Visual mode', function() + insert('foo BAR BAR foo BAR foo BAR BAR BAR foo BAR BAR') + feed('0vqifofRq') + eq({ 0, 1, 7, 0 }, fn.getpos('.')) + eq({ 0, 1, 1, 0 }, fn.getpos('v')) + feed('Q') + eq({ 0, 1, 19, 0 }, fn.getpos('.')) + eq({ 0, 1, 1, 0 }, fn.getpos('v')) + feed('Q') + eq({ 0, 1, 27, 0 }, fn.getpos('.')) + eq({ 0, 1, 1, 0 }, fn.getpos('v')) + feed('@i') + eq({ 0, 1, 43, 0 }, fn.getpos('.')) + eq({ 0, 1, 1, 0 }, fn.getpos('v')) end) - it('can be replayed with @q and @w visual-block', function() - insert [[hello + it('can be replayed with @ in blockwise Visual mode', function() + insert [[ +hello hello hello]] feed [[gg]] feed [[qqAFOO<esc>qu]] - eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +hello +hello +hello]] feed [[qwA123<esc>qu]] - eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false)) - - feed [[<C-v>3j@q]] - eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + expect [[ +hello +hello +hello]] - feed [[gg]] - feed [[<C-v>j@w]] - eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false)) + feed [[0<C-v>3jl@q]] + expect [[ +heFOOllo +heFOOllo +heFOOllo]] + + feed [[gg0<C-v>j@w]] + expect [[ +h123eFOOllo +h123eFOOllo +heFOOllo]] end) end) diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua index 6b20a736c0..69cb95e1c3 100644 --- a/test/functional/editor/mark_spec.lua +++ b/test/functional/editor/mark_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local api = helpers.api -local clear = helpers.clear -local command = helpers.command -local fn = helpers.fn -local eq = helpers.eq -local feed = helpers.feed -local write_file = helpers.write_file -local pcall_err = helpers.pcall_err + +local api = n.api +local clear = n.clear +local command = n.command +local fn = n.fn +local eq = t.eq +local feed = n.feed +local write_file = t.write_file +local pcall_err = t.pcall_err local cursor = function() - return helpers.api.nvim_win_get_cursor(0) + return n.api.nvim_win_get_cursor(0) end describe('named marks', function() @@ -39,59 +41,59 @@ describe('named marks', function() it('errors when set out of range with :mark', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, '1000mark x') + local err = pcall_err(n.exec_capture, '1000mark x') eq('nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x', err) end) it('errors when set out of range with :k', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, '1000kx') + local err = pcall_err(n.exec_capture, '1000kx') eq('nvim_exec2(): Vim(k):E16: Invalid range: 1000kx', err) end) it('errors on unknown mark name with :mark', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, 'mark #') + local err = pcall_err(n.exec_capture, 'mark #') eq('nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote', err) end) it("errors on unknown mark name with '", function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, "normal! '#") + local err = pcall_err(n.exec_capture, "normal! '#") eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err) end) it('errors on unknown mark name with `', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, 'normal! `#') + local err = pcall_err(n.exec_capture, 'normal! `#') eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err) end) it("errors when moving to a mark that is not set with '", function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, "normal! 'z") + local err = pcall_err(n.exec_capture, "normal! 'z") eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) - err = pcall_err(helpers.exec_capture, "normal! '.") + err = pcall_err(n.exec_capture, "normal! '.") eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) end) it('errors when moving to a mark that is not set with `', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, 'normal! `z') + local err = pcall_err(n.exec_capture, 'normal! `z') eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) - err = pcall_err(helpers.exec_capture, 'normal! `>') + err = pcall_err(n.exec_capture, 'normal! `>') eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) end) it("errors when moving to a global mark that is not set with '", function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, "normal! 'Z") + local err = pcall_err(n.exec_capture, "normal! 'Z") eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) end) it('errors when moving to a global mark that is not set with `', function() command('edit ' .. file1) - local err = pcall_err(helpers.exec_capture, 'normal! `Z') + local err = pcall_err(n.exec_capture, 'normal! `Z') eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) end) @@ -166,7 +168,7 @@ describe('named marks', function() feed('mA') command('next') command('bw! ' .. file1) - local err = pcall_err(helpers.exec_capture, "normal! 'A") + local err = pcall_err(n.exec_capture, "normal! 'A") eq('nvim_exec2(): Vim(normal):E92: Buffer 1 not found', err) os.remove(file1) end) @@ -420,12 +422,12 @@ describe('named marks view', function() feed("<C-w>p'a") screen:expect([[ | - ~ |*3 - [No Name] | + {1:~ }|*3 + {2:[No Name] }| 6 line | ^7 line | 8 line | - {MATCH:.*marks} | + {3:<itor-marks }| | ]]) end) @@ -453,7 +455,7 @@ describe('named marks view', function() command('bwipe!') screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 | ]]) command('rshada!') diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua index b57f5c3c35..87fe395608 100644 --- a/test/functional/editor/meta_key_spec.lua +++ b/test/functional/editor/meta_key_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command = helpers.command -local exec_lua = helpers.exec_lua -local eval = helpers.eval -local expect = helpers.expect -local fn = helpers.fn -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local command = n.command +local exec_lua = n.exec_lua +local eval = n.eval +local expect = n.expect +local fn = n.fn +local eq = t.eq describe('meta-keys #8226 #13042', function() before_each(function() @@ -141,4 +143,29 @@ describe('meta-keys #8226 #13042', function() // This is some text: bar // This is some text: baz]]) end) + + it('ALT/META with vim.on_key()', function() + feed('ifoo<CR>bar<CR>baz<Esc>gg0') + + exec_lua [[ + keys = {} + typed = {} + + vim.on_key(function(buf, typed_buf) + table.insert(keys, vim.fn.keytrans(buf)) + table.insert(typed, vim.fn.keytrans(typed_buf)) + end) + ]] + + -- <M-"> is reinterpreted as <Esc>" + feed('qrviw"ayc$FOO.<M-">apq') + expect([[ + FOO.foo + bar + baz]]) + + -- vim.on_key() callback should only receive <Esc>" + eq('qrviw"ayc$FOO.<Esc>"apq', exec_lua [[return table.concat(keys, '')]]) + eq('qrviw"ayc$FOO.<Esc>"apq', exec_lua [[return table.concat(typed, '')]]) + end) end) diff --git a/test/functional/editor/mode_cmdline_spec.lua b/test/functional/editor/mode_cmdline_spec.lua index 06efe53718..70bdc5d4c2 100644 --- a/test/functional/editor/mode_cmdline_spec.lua +++ b/test/functional/editor/mode_cmdline_spec.lua @@ -1,12 +1,13 @@ -- Cmdline-mode tests. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, insert, fn, eq, feed = - helpers.clear, helpers.insert, helpers.fn, helpers.eq, helpers.feed -local eval = helpers.eval -local command = helpers.command -local api = helpers.api + +local clear, insert, fn, eq, feed = n.clear, n.insert, n.fn, t.eq, n.feed +local eval = n.eval +local command = n.command +local api = n.api describe('cmdline', function() before_each(clear) diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua index e96813b6f7..fb3dda4bf4 100644 --- a/test/functional/editor/mode_insert_spec.lua +++ b/test/functional/editor/mode_insert_spec.lua @@ -1,13 +1,16 @@ -- Insert-mode tests. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local expect = helpers.expect -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local curbuf_contents = helpers.curbuf_contents + +local clear, feed, insert = n.clear, n.feed, n.insert +local expect = n.expect +local command = n.command +local eq = t.eq +local eval = n.eval +local curbuf_contents = n.curbuf_contents +local api = n.api describe('insert-mode', function() before_each(function() @@ -51,43 +54,34 @@ describe('insert-mode', function() end) it('double quote is removed after hit-enter prompt #22609', function() - local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Blue }, -- SpecialKey - [2] = { foreground = Screen.colors.SlateBlue }, - [3] = { bold = true }, -- ModeMsg - [4] = { reverse = true, bold = true }, -- MsgSeparator - [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - [6] = { foreground = Screen.colors.SeaGreen, bold = true }, -- MoreMsg - }) + local screen = Screen.new(50, 6) screen:attach() feed('i<C-R>') screen:expect([[ - {1:^"} | - {0:~ }|*4 - {3:-- INSERT --} | + {18:^"} | + {1:~ }|*4 + {5:-- INSERT --} | ]]) - feed('={}') + feed("=function('add')") screen:expect([[ - {1:"} | - {0:~ }|*4 - ={2:{}}^ | + {18:"} | + {1:~ }|*4 + ={25:function}{16:(}{26:'add'}{16:)}^ | ]]) feed('<CR>') screen:expect([[ - {1:"} | - {0:~ }| - {4: }| - ={2:{}} | - {5:E731: Using a Dictionary as a String} | - {6:Press ENTER or type command to continue}^ | + {18:"} | + {1:~ }| + {3: }| + ={25:function}{16:(}{26:'add'}{16:)} | + {9:E729: Using a Funcref as a String} | + {6:Press ENTER or type command to continue}^ | ]]) feed('<CR>') screen:expect([[ - ^ | - {0:~ }|*4 - {3:-- INSERT --} | + ^ | + {1:~ }|*4 + {5:-- INSERT --} | ]]) end) end) @@ -221,4 +215,146 @@ describe('insert-mode', function() ]], } end) + + describe('backspace', function() + local function set_lines(line_b, line_e, ...) + api.nvim_buf_set_lines(0, line_b, line_e, true, { ... }) + end + local function s(count) + return (' '):rep(count) + end + + local function test_cols(expected_cols) + local cols = { { n.fn.col('.'), n.fn.virtcol('.') } } + for _ = 2, #expected_cols do + feed('<BS>') + table.insert(cols, { n.fn.col('.'), n.fn.virtcol('.') }) + end + eq(expected_cols, cols) + end + + it('works with tabs and spaces', function() + local screen = Screen.new(30, 2) + screen:attach() + command('setl ts=4 sw=4') + set_lines(0, 1, '\t' .. s(4) .. '\t' .. s(9) .. '\t a') + feed('$i') + test_cols({ + { 18, 26 }, + { 17, 25 }, + { 15, 21 }, + { 11, 17 }, + { 7, 13 }, + { 6, 9 }, + { 2, 5 }, + { 1, 1 }, + }) + end) + + it('works with varsofttabstop', function() + local screen = Screen.new(30, 2) + screen:attach() + command('setl vsts=6,2,5,3') + set_lines(0, 1, 'a\t' .. s(4) .. '\t a') + feed('$i') + test_cols({ + { 9, 18 }, + { 8, 17 }, + { 8, 14 }, + { 3, 9 }, + { 7, 7 }, + { 2, 2 }, + { 1, 1 }, + }) + end) + + it('works with tab as ^I', function() + local screen = Screen.new(30, 2) + screen:attach() + command('set list listchars=space:.') + command('setl ts=4 sw=4') + set_lines(0, 1, '\t' .. s(4) .. '\t' .. s(9) .. '\t a') + feed('$i') + test_cols({ + { 18, 21 }, + { 15, 17 }, + { 11, 13 }, + { 7, 9 }, + { 4, 5 }, + { 1, 1 }, + }) + end) + + it('works in replace mode', function() + local screen = Screen.new(50, 2) + screen:attach() + command('setl ts=8 sw=8 sts=8') + set_lines(0, 1, '\t' .. s(4) .. '\t' .. s(9) .. '\t a') + feed('$R') + test_cols({ + { 18, 34 }, + { 17, 33 }, + { 15, 25 }, + { 7, 17 }, + { 2, 9 }, + { 1, 8 }, -- last screen cell of first tab is at vcol 8 + }) + end) + + it('works with breakindent', function() + local screen = Screen.new(17, 4) + screen:attach() + command('setl ts=4 sw=4 bri briopt=min:5') + set_lines(0, 1, '\t' .. s(4) .. '\t' .. s(9) .. '\t a') + feed('$i') + test_cols({ + { 18, 50 }, + { 17, 49 }, + { 15, 33 }, + { 11, 17 }, + { 7, 13 }, + { 6, 9 }, + { 2, 5 }, + { 1, 1 }, + }) + end) + + it('works with inline virtual text', function() + local screen = Screen.new(50, 2) + screen:attach() + command('setl ts=4 sw=4') + set_lines(0, 1, '\t' .. s(4) .. '\t' .. s(9) .. '\t a') + local ns = api.nvim_create_namespace('') + local vt_opts = { virt_text = { { 'text' } }, virt_text_pos = 'inline' } + api.nvim_buf_set_extmark(0, ns, 0, 2, vt_opts) + feed('$i') + test_cols({ + { 18, 30 }, + { 17, 29 }, + { 15, 25 }, + { 11, 21 }, + { 7, 17 }, + { 6, 13 }, + { 2, 9 }, + { 1, 5 }, + }) + end) + + it("works with 'revins'", function() + local screen = Screen.new(30, 3) + screen:attach() + command('setl ts=4 sw=4 revins') + set_lines(0, 1, ('a'):rep(16), s(3) .. '\t' .. s(4) .. '\t a') + feed('j$i') + test_cols({ + { 11, 14 }, + { 10, 13 }, + { 9, 9 }, + { 5, 5 }, + { 1, 1 }, + { 1, 1 }, -- backspace on empty line does nothing + }) + eq(2, api.nvim_win_get_cursor(0)[1]) + end) + end) end) diff --git a/test/functional/editor/mode_normal_spec.lua b/test/functional/editor/mode_normal_spec.lua index 89bab3f6c9..b3ef4866dc 100644 --- a/test/functional/editor/mode_normal_spec.lua +++ b/test/functional/editor/mode_normal_spec.lua @@ -1,11 +1,14 @@ -- Normal mode tests. -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local feed = helpers.feed -local fn = helpers.fn -local command = helpers.command -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') + +local clear = n.clear +local feed = n.feed +local fn = n.fn +local command = n.command +local eq = t.eq describe('Normal mode', function() before_each(clear) @@ -19,4 +22,23 @@ describe('Normal mode', function() feed('k') eq(pos, fn.getcurpos()) end) + + it('&showcmd does not crash with :startinsert #28419', function() + local screen = Screen.new(60, 17) + screen:attach() + fn.termopen( + { n.nvim_prog, '--clean', '--cmd', 'startinsert' }, + { env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } } + ) + screen:expect({ + grid = [[ + ^ | + ~ |*13 + [No Name] 0,1 All| + -- INSERT -- | + | + ]], + attr_ids = {}, + }) + end) end) diff --git a/test/functional/editor/put_spec.lua b/test/functional/editor/put_spec.lua index 414b289222..0f6936cd31 100644 --- a/test/functional/editor/put_spec.lua +++ b/test/functional/editor/put_spec.lua @@ -1,18 +1,19 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local insert = helpers.insert -local feed = helpers.feed -local expect = helpers.expect -local eq = helpers.eq +local clear = n.clear +local insert = n.insert +local feed = n.feed +local expect = n.expect +local eq = t.eq local map = vim.tbl_map local filter = vim.tbl_filter -local feed_command = helpers.feed_command -local command = helpers.command -local curbuf_contents = helpers.curbuf_contents -local fn = helpers.fn -local dedent = helpers.dedent +local feed_command = n.feed_command +local command = n.command +local curbuf_contents = n.curbuf_contents +local fn = n.fn +local dedent = t.dedent local function reset() command('bwipe! | new') @@ -75,7 +76,7 @@ describe('put command', function() extra_setup() end local orig_dotstr = fn.getreg('.') - helpers.ok(visual_marks_zero()) + t.ok(visual_marks_zero()) -- Make sure every test starts from the same conditions assert_no_change(test.exception_table, false) local was_cli = test.test_action() @@ -890,7 +891,7 @@ describe('put command', function() -- check bell is not set by nvim before the action screen:sleep(50) end - helpers.ok(not screen.bell and not screen.visualbell) + t.ok(not screen.bell and not screen.visualbell) actions() screen:expect { condition = function() diff --git a/test/functional/editor/search_spec.lua b/test/functional/editor/search_spec.lua index 46a3e298b7..770a4f387d 100644 --- a/test/functional/editor/search_spec.lua +++ b/test/functional/editor/search_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local pcall_err = t.pcall_err describe('search (/)', function() before_each(clear) diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua index 0cbc2dbf3d..0b26494436 100644 --- a/test/functional/editor/tabpage_spec.lua +++ b/test/functional/editor/tabpage_spec.lua @@ -1,17 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local neq = helpers.neq -local feed = helpers.feed -local eval = helpers.eval -local exec = helpers.exec -local fn = helpers.fn -local api = helpers.api -local curwin = helpers.api.nvim_get_current_win -local assert_alive = helpers.assert_alive +local clear = n.clear +local command = n.command +local eq = t.eq +local neq = t.neq +local feed = n.feed +local eval = n.eval +local exec = n.exec +local fn = n.fn +local api = n.api +local curwin = n.api.nvim_get_current_win +local assert_alive = n.assert_alive describe('tabpage', function() before_each(clear) diff --git a/test/functional/editor/undo_spec.lua b/test/functional/editor/undo_spec.lua index c101bf02a0..12056394d2 100644 --- a/test/functional/editor/undo_spec.lua +++ b/test/functional/editor/undo_spec.lua @@ -1,16 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local command = helpers.command -local eval = helpers.eval -local expect = helpers.expect -local eq = helpers.eq -local feed = helpers.feed -local feed_command = helpers.feed_command -local insert = helpers.insert -local fn = helpers.fn -local exec = helpers.exec -local exec_lua = helpers.exec_lua +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eval = n.eval +local expect = n.expect +local eq = t.eq +local feed = n.feed +local feed_command = n.feed_command +local insert = n.insert +local fn = n.fn +local exec = n.exec +local exec_lua = n.exec_lua local function lastmessage() local messages = fn.split(fn.execute('messages'), '\n') @@ -44,7 +45,7 @@ describe('u CTRL-R g- g+', function() local function undo_and_redo(hist_pos, undo, redo, expect_str) command('enew!') create_history(hist_pos) - local cur_contents = helpers.curbuf_contents() + local cur_contents = n.curbuf_contents() feed(undo) expect(expect_str) feed(redo) diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua index 5eb8d49c74..80fdcb3134 100644 --- a/test/functional/ex_cmds/append_spec.lua +++ b/test/functional/ex_cmds/append_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local dedent = helpers.dedent -local exec = helpers.exec -local feed = helpers.feed -local clear = helpers.clear -local fn = helpers.fn -local command = helpers.command -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local eq = t.eq +local dedent = t.dedent +local exec = n.exec +local feed = n.feed +local clear = n.clear +local fn = n.fn +local command = n.command +local api = n.api + local cmdtest = function(cmd, prep, ret1) describe(':' .. cmd, function() before_each(function() diff --git a/test/functional/ex_cmds/arg_spec.lua b/test/functional/ex_cmds/arg_spec.lua index 810b001ec0..9b89823dcc 100644 --- a/test/functional/ex_cmds/arg_spec.lua +++ b/test/functional/ex_cmds/arg_spec.lua @@ -1,7 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, command, fn = helpers.eq, helpers.command, helpers.fn -local ok = helpers.ok -local clear = helpers.clear +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, command, fn = t.eq, n.command, n.fn +local ok = t.ok +local matches = t.matches +local clear = n.clear describe(':argument', function() before_each(function() @@ -10,19 +13,19 @@ describe(':argument', function() it('does not restart :terminal buffer', function() command('terminal') - helpers.feed([[<C-\><C-N>]]) + n.feed([[<C-\><C-N>]]) command('argadd') - helpers.feed([[<C-\><C-N>]]) + n.feed([[<C-\><C-N>]]) local bufname_before = fn.bufname('%') local bufnr_before = fn.bufnr('%') - helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity + matches('^term://', bufname_before) -- sanity command('argument 1') - helpers.feed([[<C-\><C-N>]]) + n.feed([[<C-\><C-N>]]) local bufname_after = fn.bufname('%') local bufnr_after = fn.bufnr('%') - eq('[' .. bufname_before .. ']', helpers.eval('trim(execute("args"))')) + eq('[' .. bufname_before .. ']', n.eval('trim(execute("args"))')) ok(fn.line('$') > 1) eq(bufname_before, bufname_after) eq(bufnr_before, bufnr_after) diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 1815c672dc..0f95f2aca4 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -1,16 +1,17 @@ -- Specs for :cd, :tcd, :lcd and getcwd() -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local call = helpers.call -local clear = helpers.clear -local command = helpers.command -local exc_exec = helpers.exc_exec -local pathsep = helpers.get_pathsep() -local skip = helpers.skip -local is_os = helpers.is_os -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local call = n.call +local clear = n.clear +local command = n.command +local exc_exec = n.exc_exec +local pathsep = n.get_pathsep() +local skip = t.skip +local is_os = t.is_os +local mkdir = t.mkdir -- These directories will be created for testing local directories = { @@ -289,14 +290,14 @@ describe('getcwd()', function() end) after_each(function() - helpers.rmdir(directories.global) + n.rmdir(directories.global) end) it('returns empty string if working directory does not exist', function() skip(is_os('win')) command('cd ' .. directories.global) command("call delete('../" .. directories.global .. "', 'd')") - eq('', helpers.eval('getcwd()')) + eq('', n.eval('getcwd()')) end) it("works with 'autochdir' after local directory was set (#9892)", function() diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua index cb7d7340e2..6c1ac8eae5 100644 --- a/test/functional/ex_cmds/cmd_map_spec.lua +++ b/test/functional/ex_cmds/cmd_map_spec.lua @@ -1,16 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local feed = helpers.feed -local eq = helpers.eq -local expect = helpers.expect -local eval = helpers.eval -local fn = helpers.fn -local insert = helpers.insert -local write_file = helpers.write_file -local exc_exec = helpers.exc_exec -local command = helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local clear = n.clear +local feed = n.feed +local eq = t.eq +local expect = n.expect +local eval = n.eval +local fn = n.fn +local insert = n.insert +local write_file = t.write_file +local exc_exec = n.exc_exec +local command = n.command + describe('mappings with <Cmd>', function() local screen local tmpfile = 'X_ex_cmds_cmd_map' @@ -505,7 +507,7 @@ describe('mappings with <Cmd>', function() feed('"bd<F7>') expect([[ soest text]]) - eq(fn.getreg('b', 1, 1), { 'me short lines', 'of t' }) + eq({ 'me short lines', 'of t' }, fn.getreg('b', 1, 1)) -- startinsert aborts operator feed('d<F8>') @@ -561,7 +563,7 @@ describe('mappings with <Cmd>', function() of stuff test text]]) feed('<F5>') - eq(fn.getreg('a', 1, 1), { 'deed some short little lines', 'of stuff t' }) + eq({ 'deed some short little lines', 'of stuff t' }, fn.getreg('a', 1, 1)) -- still in insert screen:expect([[ diff --git a/test/functional/ex_cmds/debug_spec.lua b/test/functional/ex_cmds/debug_spec.lua index 85327c87e6..ebb3cdd38a 100644 --- a/test/functional/ex_cmds/debug_spec.lua +++ b/test/functional/ex_cmds/debug_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local clear = helpers.clear + +local feed = n.feed +local clear = n.clear describe(':debug', function() local screen diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua index fc7714d16b..b6068a86db 100644 --- a/test/functional/ex_cmds/dict_notifications_spec.lua +++ b/test/functional/ex_cmds/dict_notifications_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_alive = helpers.assert_alive -local clear, source = helpers.clear, helpers.source -local api = helpers.api -local insert = helpers.insert -local eq, next_msg = helpers.eq, helpers.next_msg -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local command = helpers.command -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local clear, source = n.clear, n.source +local api = n.api +local insert = n.insert +local eq, next_msg = t.eq, n.next_msg +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local command = n.command +local eval = n.eval describe('Vimscript dictionary notifications', function() local channel diff --git a/test/functional/ex_cmds/digraphs_spec.lua b/test/functional/ex_cmds/digraphs_spec.lua index 24b6f7c53b..fde25c028f 100644 --- a/test/functional/ex_cmds/digraphs_spec.lua +++ b/test/functional/ex_cmds/digraphs_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local clear = n.clear +local command = n.command +local feed = n.feed + describe(':digraphs', function() local screen before_each(function() diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua index cbda5aac98..54ddd79a35 100644 --- a/test/functional/ex_cmds/drop_spec.lua +++ b/test/functional/ex_cmds/drop_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local command = helpers.command +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command + +local command = n.command +local clear, feed, feed_command = n.clear, n.feed, n.feed_command +local exec = n.exec describe(':drop', function() local screen @@ -16,7 +18,7 @@ describe(':drop', function() [2] = { reverse = true }, [3] = { bold = true }, }) - command('set laststatus=2 shortmess-=F') + command('set nohidden laststatus=2 shortmess-=F') end) it('works like :e when called with only one window open', function() @@ -43,7 +45,6 @@ describe(':drop', function() end) it("splits off a new window when a buffer can't be abandoned", function() - command('set nohidden') feed_command('edit tmp1') feed_command('vsplit') feed_command('edit tmp2') @@ -59,4 +60,20 @@ describe(':drop', function() "tmp3" [New] | ]]) end) + + -- oldtest: Test_drop_modified_file() + it('does not cause E37 with modified same file', function() + exec([[ + edit Xdrop_modified.txt + call setline(1, 'The quick brown fox jumped over the lazy dogs') + ]]) + feed_command('drop Xdrop_modified.txt') + screen:expect([[ + ^The quick brown fox jumped over the| + lazy dogs | + {0:~ }|*6 + {1:Xdrop_modified.txt [+] }| + :drop Xdrop_modified.txt | + ]]) + end) end) diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua index e9176a6204..2f0bcb4d9d 100644 --- a/test/functional/ex_cmds/echo_spec.lua +++ b/test/functional/ex_cmds/echo_spec.lua @@ -1,17 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq +local eq = t.eq local NIL = vim.NIL -local eval = helpers.eval -local clear = helpers.clear -local api = helpers.api -local fn = helpers.fn -local source = helpers.source -local dedent = helpers.dedent -local command = helpers.command -local exc_exec = helpers.exc_exec -local exec_capture = helpers.exec_capture -local matches = helpers.matches +local eval = n.eval +local clear = n.clear +local api = n.api +local fn = n.fn +local source = n.source +local dedent = t.dedent +local command = n.command +local exc_exec = n.exc_exec +local exec_capture = n.exec_capture +local matches = t.matches describe(':echo :echon :echomsg :echoerr', function() local fn_tbl = { 'String', 'StringN', 'StringMsg', 'StringErr' } @@ -255,7 +256,7 @@ describe(':echo :echon :echomsg :echoerr', function() eval('add(l, l)') -- Regression: the below line used to crash (add returns original list and -- there was error in dumping partials). Tested explicitly in - -- test/unit/api/private_helpers_spec.lua. + -- test/unit/api/private_t_spec.lua. eval('add(l, function("Test1", l))') eq( dedent( @@ -349,8 +350,8 @@ describe(':echo :echon :echomsg :echoerr', function() end) describe('used to represent special values', function() - local function chr(n) - return ('%c'):format(n) + local function chr(_n) + return ('%c'):format(_n) end local function ctrl(c) return ('%c'):format(c:upper():byte() - 0x40) diff --git a/test/functional/ex_cmds/edit_spec.lua b/test/functional/ex_cmds/edit_spec.lua index b927fa418a..39849a202f 100644 --- a/test/functional/ex_cmds/edit_spec.lua +++ b/test/functional/ex_cmds/edit_spec.lua @@ -1,8 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, command, fn = helpers.eq, helpers.command, helpers.fn -local ok = helpers.ok -local clear = helpers.clear -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, command, fn = t.eq, n.command, n.fn +local ok = t.ok +local matches = t.matches +local clear = n.clear +local feed = n.feed describe(':edit', function() before_each(function() @@ -14,7 +17,7 @@ describe(':edit', function() feed([[<C-\><C-N>]]) local bufname_before = fn.bufname('%') local bufnr_before = fn.bufnr('%') - helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity + matches('^term://', bufname_before) -- sanity command('edit') diff --git a/test/functional/ex_cmds/encoding_spec.lua b/test/functional/ex_cmds/encoding_spec.lua index 8953fb8eaf..6b882253b9 100644 --- a/test/functional/ex_cmds/encoding_spec.lua +++ b/test/functional/ex_cmds/encoding_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, feed_command, feed = helpers.clear, helpers.feed_command, helpers.feed -local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed_command, feed = n.clear, n.feed_command, n.feed +local eq, neq, eval = t.eq, t.neq, n.eval describe('&encoding', function() before_each(function() diff --git a/test/functional/ex_cmds/excmd_spec.lua b/test/functional/ex_cmds/excmd_spec.lua index d16a52ee62..20ebb2dedb 100644 --- a/test/functional/ex_cmds/excmd_spec.lua +++ b/test/functional/ex_cmds/excmd_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local command = helpers.command -local eq = helpers.eq -local clear = helpers.clear -local fn = helpers.fn -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local command = n.command +local eq = t.eq +local clear = n.clear +local fn = n.fn +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive describe('Ex cmds', function() before_each(function() diff --git a/test/functional/ex_cmds/file_spec.lua b/test/functional/ex_cmds/file_spec.lua index a48c408600..0c51f1c17b 100644 --- a/test/functional/ex_cmds/file_spec.lua +++ b/test/functional/ex_cmds/file_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local fn = helpers.fn -local rmdir = helpers.rmdir -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local fn = n.fn +local rmdir = n.rmdir +local mkdir = t.mkdir describe(':file', function() local swapdir = vim.uv.cwd() .. '/Xtest-file_spec' diff --git a/test/functional/ex_cmds/grep_spec.lua b/test/functional/ex_cmds/grep_spec.lua index bf81ba2137..f7d0f43c62 100644 --- a/test/functional/ex_cmds/grep_spec.lua +++ b/test/functional/ex_cmds/grep_spec.lua @@ -1,6 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, feed_command, feed, ok, eval = - helpers.clear, helpers.feed_command, helpers.feed, helpers.ok, helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed_command, feed, ok, eval = n.clear, n.feed_command, n.feed, t.ok, n.eval describe(':grep', function() before_each(clear) diff --git a/test/functional/ex_cmds/help_spec.lua b/test/functional/ex_cmds/help_spec.lua index cee33de1a6..f0a7bea7e4 100644 --- a/test/functional/ex_cmds/help_spec.lua +++ b/test/functional/ex_cmds/help_spec.lua @@ -1,19 +1,20 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local fn = helpers.fn -local api = helpers.api -local mkdir = helpers.mkdir -local rmdir = helpers.rmdir -local write_file = helpers.write_file +local clear = n.clear +local command = n.command +local eq = t.eq +local fn = n.fn +local api = n.api +local mkdir = t.mkdir +local rmdir = n.rmdir +local write_file = t.write_file describe(':help', function() before_each(clear) it('window closed makes cursor return to a valid win/buf #9773', function() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() command('help help') eq(1001, fn.win_getid()) command('quit') diff --git a/test/functional/ex_cmds/highlight_spec.lua b/test/functional/ex_cmds/highlight_spec.lua index 897a2997bc..3cb6cc2579 100644 --- a/test/functional/ex_cmds/highlight_spec.lua +++ b/test/functional/ex_cmds/highlight_spec.lua @@ -1,11 +1,13 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local eq, command = helpers.eq, helpers.command -local clear = helpers.clear -local eval, exc_exec = helpers.eval, helpers.exc_exec -local exec = helpers.exec -local fn = helpers.fn -local api = helpers.api + +local eq, command = t.eq, n.command +local clear = n.clear +local eval, exc_exec = n.eval, n.exc_exec +local exec = n.exec +local fn = n.fn +local api = n.api describe(':highlight', function() local screen diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua index 5f59402d10..aab53f0634 100644 --- a/test/functional/ex_cmds/ls_spec.lua +++ b/test/functional/ex_cmds/ls_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local api = helpers.api -local testprg = helpers.testprg -local retry = helpers.retry +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local api = n.api +local testprg = n.testprg +local retry = t.retry describe(':ls', function() before_each(function() diff --git a/test/functional/ex_cmds/make_spec.lua b/test/functional/ex_cmds/make_spec.lua index dd47bdec58..d6164cec29 100644 --- a/test/functional/ex_cmds/make_spec.lua +++ b/test/functional/ex_cmds/make_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eval = helpers.eval -local has_powershell = helpers.has_powershell -local matches = helpers.matches -local api = helpers.api -local testprg = helpers.testprg +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eval = n.eval +local has_powershell = n.has_powershell +local matches = t.matches +local api = n.api +local testprg = n.testprg describe(':make', function() clear() @@ -18,7 +20,7 @@ describe(':make', function() return end before_each(function() - helpers.set_shell_powershell() + n.set_shell_powershell() end) it('captures stderr & non zero exit code #14349', function() diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua index d3b027e6f4..9ef0a8ec2e 100644 --- a/test/functional/ex_cmds/map_spec.lua +++ b/test/functional/ex_cmds/map_spec.lua @@ -1,16 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local feed = helpers.feed -local api = helpers.api -local clear = helpers.clear -local command = helpers.command -local expect = helpers.expect -local insert = helpers.insert -local eval = helpers.eval +local eq = t.eq +local exec = n.exec +local exec_capture = n.exec_capture +local feed = n.feed +local api = n.api +local clear = n.clear +local command = n.command +local expect = n.expect +local insert = n.insert +local eval = n.eval describe(':*map', function() before_each(clear) @@ -109,19 +110,19 @@ describe('Screen', function() command('map <expr> x input("> ")') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 | ]]) feed('x') screen:expect([[ | - ~ |*3 + {1:~ }|*3 > ^ | ]]) feed('\n') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 > | ]]) end) @@ -131,20 +132,20 @@ describe('Screen', function() feed('i') screen:expect([[ ^ | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('x') screen:expect([[ | - ~ |*3 + {1:~ }|*3 > ^ | ]]) feed('\n') screen:expect([[ ^ | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) end) @@ -153,7 +154,7 @@ describe('Screen', function() feed(':<F2>') screen:expect([[ | - ~ |*3 + {1:~ }|*3 :^ | ]]) end) @@ -181,7 +182,7 @@ describe('Screen', function() one | ^two | three | - [on] | + {9:[on] }| | ]]) end) @@ -191,15 +192,16 @@ describe('Screen', function() command('nmap <expr> <F2> execute("throw 42")') feed('<F2>') screen:expect([[ - |*2 - Error detected while processing : | - E605: Exception not caught: 42 | - Press ENTER or type command to continue^ | + | + {3: }| + {9:Error detected while processing :} | + {9:E605: Exception not caught: 42} | + {6:Press ENTER or type command to continue}^ | ]]) feed('<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 | ]]) end) @@ -210,32 +212,32 @@ describe('Screen', function() feed(':echo "foo') screen:expect([[ | - ~ |*3 + {1:~ }|*3 :echo "foo^ | ]]) feed('<F2>') screen:expect([[ - | + {3: }| :echo "foo | - Error detected while processing : | - E605: Exception not caught: 42 | + {9:Error detected while processing :} | + {9:E605: Exception not caught: 42} | :echo "foo^ | ]]) feed('"') screen:expect([[ - | + {3: }| :echo "foo | - Error detected while processing : | - E605: Exception not caught: 42 | + {9:Error detected while processing :} | + {9:E605: Exception not caught: 42} | :echo "foo"^ | ]]) feed('\n') screen:expect([[ :echo "foo | - Error detected while processing : | - E605: Exception not caught: 42 | + {9:Error detected while processing :} | + {9:E605: Exception not caught: 42} | foo | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) end) @@ -246,7 +248,7 @@ describe('Screen', function() feed(': nmap a<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 n a b | ]]) end) diff --git a/test/functional/ex_cmds/menu_spec.lua b/test/functional/ex_cmds/menu_spec.lua index bb6ef72787..e73f705a29 100644 --- a/test/functional/ex_cmds/menu_spec.lua +++ b/test/functional/ex_cmds/menu_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, command = helpers.clear, helpers.command -local expect, feed = helpers.expect, helpers.feed -local eq, eval = helpers.eq, helpers.eval -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, command = n.clear, n.command +local expect, feed = n.expect, n.feed +local eq, eval = t.eq, n.eval +local fn = n.fn describe(':emenu', function() before_each(function() diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 6f2e0be3d5..9b24854362 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -1,20 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local get_pathsep = helpers.get_pathsep -local eq = helpers.eq -local neq = helpers.neq -local fn = helpers.fn -local matches = helpers.matches +local clear = n.clear +local command = n.command +local get_pathsep = n.get_pathsep +local eq = t.eq +local neq = t.neq +local fn = n.fn +local matches = t.matches local pesc = vim.pesc -local rmdir = helpers.rmdir +local rmdir = n.rmdir local sleep = vim.uv.sleep -local api = helpers.api -local skip = helpers.skip -local is_os = helpers.is_os -local mkdir = helpers.mkdir +local api = n.api +local skip = t.skip +local is_os = t.is_os +local mkdir = t.mkdir local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' diff --git a/test/functional/ex_cmds/mkview_spec.lua b/test/functional/ex_cmds/mkview_spec.lua index de0a4fe0ea..7cc0b1da83 100644 --- a/test/functional/ex_cmds/mkview_spec.lua +++ b/test/functional/ex_cmds/mkview_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local get_pathsep = helpers.get_pathsep -local eq = helpers.eq -local fn = helpers.fn -local rmdir = helpers.rmdir -local mkdir = helpers.mkdir +local clear = n.clear +local command = n.command +local get_pathsep = n.get_pathsep +local eq = t.eq +local fn = n.fn +local rmdir = n.rmdir +local mkdir = t.mkdir local file_prefix = 'Xtest-functional-ex_cmds-mkview_spec' diff --git a/test/functional/ex_cmds/normal_spec.lua b/test/functional/ex_cmds/normal_spec.lua index 723bfefcf4..ccc649120f 100644 --- a/test/functional/ex_cmds/normal_spec.lua +++ b/test/functional/ex_cmds/normal_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local fn = helpers.fn -local feed = helpers.feed -local expect = helpers.expect -local eq = helpers.eq -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local fn = n.fn +local feed = n.feed +local expect = n.expect +local eq = t.eq +local eval = n.eval before_each(clear) diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua index 8d1469f343..927d780181 100644 --- a/test/functional/ex_cmds/oldfiles_spec.lua +++ b/test/functional/ex_cmds/oldfiles_spec.lua @@ -1,13 +1,14 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local expect_exit = helpers.expect_exit -local api, eq, feed_command = helpers.api, helpers.eq, helpers.feed_command -local feed, poke_eventloop = helpers.feed, helpers.poke_eventloop -local ok = helpers.ok -local eval = helpers.eval +local clear = n.clear +local command = n.command +local expect_exit = n.expect_exit +local api, eq, feed_command = n.api, t.eq, n.feed_command +local feed, poke_eventloop = n.feed, n.poke_eventloop +local ok = t.ok +local eval = n.eval local shada_file = 'Xtest.shada' @@ -38,6 +39,7 @@ describe(':oldfiles', function() it('shows most recently used files', function() local screen = Screen.new(100, 5) screen:attach() + screen._default_attr_ids = nil feed_command('edit testfile1') feed_command('edit testfile2') feed_command('wshada') @@ -65,12 +67,12 @@ describe(':oldfiles', function() feed_command('rshada!') local function get_oldfiles(cmd) - local t = eval([[split(execute(']] .. cmd .. [['), "\n")]]) - for i, _ in ipairs(t) do - t[i] = t[i]:gsub('^%d+:%s+', '') + local q = eval([[split(execute(']] .. cmd .. [['), "\n")]]) + for i, _ in ipairs(q) do + q[i] = q[i]:gsub('^%d+:%s+', '') end - table.sort(t) - return t + table.sort(q) + return q end local oldfiles = get_oldfiles('oldfiles') @@ -108,7 +110,7 @@ describe(':browse oldfiles', function() -- Ensure v:oldfiles isn't busted. Since things happen so fast, -- the ordering of v:oldfiles is unstable (it uses qsort() under-the-hood). -- Let's verify the contents and the length of v:oldfiles before moving on. - oldfiles = helpers.api.nvim_get_vvar('oldfiles') + oldfiles = n.api.nvim_get_vvar('oldfiles') eq(2, #oldfiles) ok(filename == oldfiles[1] or filename == oldfiles[2]) ok(filename2 == oldfiles[1] or filename2 == oldfiles[2]) diff --git a/test/functional/ex_cmds/print_commands_spec.lua b/test/functional/ex_cmds/print_commands_spec.lua index ba5ec7d2d1..8c164fd41b 100644 --- a/test/functional/ex_cmds/print_commands_spec.lua +++ b/test/functional/ex_cmds/print_commands_spec.lua @@ -1,5 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, command, fn = helpers.clear, helpers.eq, helpers.command, helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, command, fn = n.clear, t.eq, n.command, n.fn describe(':z^', function() before_each(clear) diff --git a/test/functional/ex_cmds/profile_spec.lua b/test/functional/ex_cmds/profile_spec.lua index f85dcc60ff..57e5c6b2dc 100644 --- a/test/functional/ex_cmds/profile_spec.lua +++ b/test/functional/ex_cmds/profile_spec.lua @@ -1,14 +1,15 @@ -require('os') +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local uv = vim.uv +require('os') -local helpers = require('test.functional.helpers')(after_each) -local eval = helpers.eval -local command = helpers.command -local eq, neq = helpers.eq, helpers.neq -local tempfile = helpers.tmpname() -local source = helpers.source -local matches = helpers.matches -local read_file = helpers.read_file +local eval = n.eval +local command = n.command +local eq, neq = t.eq, t.neq +local tempfile = t.tmpname() +local source = n.source +local matches = t.matches +local read_file = t.read_file -- tmpname() also creates the file on POSIX systems. Remove it again. -- We just need the name, ignoring any race conditions. @@ -25,10 +26,10 @@ local function assert_file_exists_not(filepath) end describe(':profile', function() - before_each(helpers.clear) + before_each(n.clear) after_each(function() - helpers.expect_exit(command, 'qall!') + n.expect_exit(command, 'qall!') if uv.fs_stat(tempfile).uid ~= nil then os.remove(tempfile) end diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua index 5af0198ffe..3df41b015e 100644 --- a/test/functional/ex_cmds/quickfix_commands_spec.lua +++ b/test/functional/ex_cmds/quickfix_commands_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local eq = helpers.eq -local clear = helpers.clear -local fn = helpers.fn -local command = helpers.command -local exc_exec = helpers.exc_exec -local write_file = helpers.write_file -local api = helpers.api -local source = helpers.source +local feed = n.feed +local eq = t.eq +local clear = n.clear +local fn = n.fn +local command = n.command +local exc_exec = n.exc_exec +local write_file = t.write_file +local api = n.api +local source = n.source local file_base = 'Xtest-functional-ex_cmds-quickfix_commands' diff --git a/test/functional/ex_cmds/quit_spec.lua b/test/functional/ex_cmds/quit_spec.lua index 5a1759dab3..83b1c5a540 100644 --- a/test/functional/ex_cmds/quit_spec.lua +++ b/test/functional/ex_cmds/quit_spec.lua @@ -1,5 +1,6 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear +local n = require('test.functional.testnvim')() + +local clear = n.clear describe(':qa', function() before_each(function() diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua index 4c963c5da7..d69fae11ce 100644 --- a/test/functional/ex_cmds/script_spec.lua +++ b/test/functional/ex_cmds/script_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local neq = helpers.neq -local command = helpers.command -local exec_capture = helpers.exec_capture -local write_file = helpers.write_file -local api = helpers.api -local clear = helpers.clear -local dedent = helpers.dedent -local exc_exec = helpers.exc_exec -local missing_provider = helpers.missing_provider +local eq = t.eq +local neq = t.neq +local command = n.command +local exec_capture = n.exec_capture +local write_file = t.write_file +local api = n.api +local clear = n.clear +local dedent = t.dedent +local exc_exec = n.exc_exec +local missing_provider = n.missing_provider local tmpfile = 'X_ex_cmds_script' diff --git a/test/functional/ex_cmds/sign_spec.lua b/test/functional/ex_cmds/sign_spec.lua index 06de7f23a9..1d1708a41c 100644 --- a/test/functional/ex_cmds/sign_spec.lua +++ b/test/functional/ex_cmds/sign_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, assert_alive = helpers.clear, helpers.eq, helpers.assert_alive -local command = helpers.command -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, assert_alive = n.clear, t.eq, n.assert_alive +local command = n.command +local api = n.api describe('sign', function() before_each(clear) diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua index 5ce0e395bd..0a6f44fab4 100644 --- a/test/functional/ex_cmds/source_spec.lua +++ b/test/functional/ex_cmds/source_spec.lua @@ -1,23 +1,25 @@ -local helpers = require('test.functional.helpers')(after_each) -local command = helpers.command -local insert = helpers.insert -local eq = helpers.eq -local clear = helpers.clear -local api = helpers.api -local feed = helpers.feed -local feed_command = helpers.feed_command -local write_file = helpers.write_file -local tmpname = helpers.tmpname -local exec = helpers.exec -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local eval = helpers.eval -local exec_capture = helpers.exec_capture -local neq = helpers.neq -local matches = helpers.matches -local mkdir = helpers.mkdir -local rmdir = helpers.rmdir -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local command = n.command +local insert = n.insert +local eq = t.eq +local clear = n.clear +local api = n.api +local feed = n.feed +local feed_command = n.feed_command +local write_file = t.write_file +local tmpname = t.tmpname +local exec = n.exec +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local eval = n.eval +local exec_capture = n.exec_capture +local neq = t.neq +local matches = t.matches +local mkdir = t.mkdir +local rmdir = n.rmdir +local is_os = t.is_os describe(':source', function() before_each(function() diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua index a6fdb919c5..5bb2a0181e 100644 --- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua +++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua @@ -1,29 +1,31 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) + local uv = vim.uv -local eq, eval, expect, exec = helpers.eq, helpers.eval, helpers.expect, helpers.exec -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local fn = helpers.fn -local nvim_prog = helpers.nvim_prog -local ok = helpers.ok -local rmdir = helpers.rmdir -local new_argv = helpers.new_argv -local new_pipename = helpers.new_pipename +local eq, eval, expect, exec = t.eq, n.eval, n.expect, n.exec +local assert_alive = n.assert_alive +local clear = n.clear +local command = n.command +local feed = n.feed +local fn = n.fn +local nvim_prog = n.nvim_prog +local ok = t.ok +local rmdir = n.rmdir +local new_argv = n.new_argv +local new_pipename = n.new_pipename local pesc = vim.pesc -local os_kill = helpers.os_kill -local set_session = helpers.set_session -local spawn = helpers.spawn -local async_meths = helpers.async_meths -local expect_msg_seq = helpers.expect_msg_seq -local pcall_err = helpers.pcall_err -local mkdir = helpers.mkdir -local poke_eventloop = helpers.poke_eventloop -local api = helpers.api -local retry = helpers.retry -local write_file = helpers.write_file +local os_kill = n.os_kill +local set_session = n.set_session +local spawn = n.spawn +local async_meths = n.async_meths +local expect_msg_seq = n.expect_msg_seq +local pcall_err = t.pcall_err +local mkdir = t.mkdir +local poke_eventloop = n.poke_eventloop +local api = n.api +local retry = t.retry +local write_file = t.write_file describe(':recover', function() before_each(clear) @@ -110,7 +112,7 @@ describe("preserve and (R)ecover with custom 'directory'", function() end) it('killing TUI process without :preserve #22096', function() - helpers.skip(helpers.is_os('win')) + t.skip(t.is_os('win')) local screen0 = Screen.new() screen0:attach() local child_server = new_pipename() @@ -118,7 +120,7 @@ describe("preserve and (R)ecover with custom 'directory'", function() env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, }) screen0:expect({ any = pesc('[No Name]') }) -- Wait for the child process to start. - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) set_session(child_session) local swappath1 = setup_swapname() set_session(nvim0) @@ -170,6 +172,7 @@ describe('swapfile detection', function() set_session(nvim2) local screen2 = Screen.new(256, 40) screen2:attach() + screen2._default_attr_ids = nil exec(init) command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog). diff --git a/test/functional/ex_cmds/syntax_spec.lua b/test/functional/ex_cmds/syntax_spec.lua index ccdd604c55..35b45fe800 100644 --- a/test/functional/ex_cmds/syntax_spec.lua +++ b/test/functional/ex_cmds/syntax_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local exc_exec = helpers.exc_exec +local eq = t.eq +local clear = n.clear +local exc_exec = n.exc_exec describe(':syntax', function() before_each(clear) diff --git a/test/functional/ex_cmds/trust_spec.lua b/test/functional/ex_cmds/trust_spec.lua index 2997b504fa..76248cf530 100644 --- a/test/functional/ex_cmds/trust_spec.lua +++ b/test/functional/ex_cmds/trust_spec.lua @@ -1,27 +1,28 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local clear = helpers.clear -local command = helpers.command -local exec_capture = helpers.exec_capture -local matches = helpers.matches -local pathsep = helpers.get_pathsep() -local is_os = helpers.is_os -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local clear = n.clear +local command = n.command +local exec_capture = n.exec_capture +local matches = t.matches +local pathsep = n.get_pathsep() +local is_os = t.is_os +local fn = n.fn describe(':trust', function() local xstate = 'Xstate' setup(function() - helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) end) teardown(function() - helpers.rmdir(xstate) + n.rmdir(xstate) end) before_each(function() - helpers.write_file('test_file', 'test') + t.write_file('test_file', 'test') clear { env = { XDG_STATE_HOME = xstate } } end) @@ -31,37 +32,37 @@ describe(':trust', function() it('trust then deny then remove a file using current buffer', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(t.read_file('test_file')) command('edit test_file') matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust')) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust)) matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny')) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove')) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format(''), vim.trim(trust)) end) it('deny then trust then remove a file using current buffer', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(t.read_file('test_file')) command('edit test_file') matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny')) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust')) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust)) matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove')) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format(''), vim.trim(trust)) end) @@ -69,14 +70,14 @@ describe(':trust', function() local cwd = fn.getcwd() matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny test_file')) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) matches( '^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove test_file') ) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') eq(string.format(''), vim.trim(trust)) end) end) diff --git a/test/functional/ex_cmds/undojoin_spec.lua b/test/functional/ex_cmds/undojoin_spec.lua index 7803906619..06b5973053 100644 --- a/test/functional/ex_cmds/undojoin_spec.lua +++ b/test/functional/ex_cmds/undojoin_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local insert = helpers.insert -local feed = helpers.feed -local expect = helpers.expect -local feed_command = helpers.feed_command -local exc_exec = helpers.exc_exec +local eq = t.eq +local clear = n.clear +local insert = n.insert +local feed = n.feed +local expect = n.expect +local feed_command = n.feed_command +local exc_exec = n.exc_exec describe(':undojoin command', function() before_each(function() diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua index 7ceb2460d3..0f99552935 100644 --- a/test/functional/ex_cmds/verbose_spec.lua +++ b/test/functional/ex_cmds/verbose_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local write_file = helpers.write_file -local call_viml_function = helpers.api.nvim_call_function +local clear = n.clear +local eq = t.eq +local exec = n.exec +local exec_capture = n.exec_capture +local write_file = t.write_file +local call_viml_function = n.api.nvim_call_function local function last_set_tests(cmd) local script_location, script_file @@ -15,7 +16,7 @@ local function last_set_tests(cmd) script_file = 'test_verbose.lua' local current_dir = call_viml_function('getcwd', {}) current_dir = call_viml_function('fnamemodify', { current_dir, ':~' }) - script_location = table.concat { current_dir, helpers.get_pathsep(), script_file } + script_location = table.concat { current_dir, n.get_pathsep(), script_file } write_file( script_file, @@ -32,21 +33,30 @@ vim.api.nvim_exec2("augroup test_group\ augroup END\ ", {}) +vim.api.nvim_create_autocmd('FileType', { + group = 'test_group', + pattern = 'cpp', + command = 'setl cindent', +}) + +vim.api.nvim_exec2(':highlight TestHL1 guibg=Blue', {}) +vim.api.nvim_set_hl(0, 'TestHL2', { bg = 'Green' }) + vim.api.nvim_command("command Bdelete :bd") vim.api.nvim_create_user_command("TestCommand", ":echo 'Hello'", {}) -vim.api.nvim_exec ("\ +vim.api.nvim_exec2 ("\ function Close_Window() abort\ wincmd -\ endfunction\ -", false) +", {}) -local ret = vim.api.nvim_exec ("\ +local ret = vim.api.nvim_exec2 ("\ function! s:return80()\ return 80\ endfunction\ let &tw = s:return80()\ -", true) +", {}) ]] ) exec(cmd .. ' ' .. script_file) @@ -109,7 +119,7 @@ n \key1 * :echo "test"<CR> ) end) - it('"Last set" for mapping set by vim.keymap', function() + it('"Last set" for mapping set by vim.keymap.set', function() local result = exec_capture(':verbose map <leader>key2') eq( string.format( @@ -123,7 +133,7 @@ n \key2 * :echo "test"<CR> ) end) - it('"Last set" for autocmd by vim.api.nvim_exec', function() + it('"Last set" for autocmd set by nvim_exec2', function() local result = exec_capture(':verbose autocmd test_group Filetype c') eq( string.format( @@ -138,6 +148,47 @@ test_group FileType ) end) + it('"Last set" for autocmd set by nvim_create_autocmd', function() + local result = exec_capture(':verbose autocmd test_group Filetype cpp') + eq( + string.format( + [[ +--- Autocommands --- +test_group FileType + cpp setl cindent + Last set from %s line 13]], + script_location + ), + result + ) + end) + + it('"Last set" for highlight group set by nvim_exec2', function() + local result = exec_capture(':verbose highlight TestHL1') + eq( + string.format( + [[ +TestHL1 xxx guibg=Blue + Last set from %s line 19]], + script_location + ), + result + ) + end) + + it('"Last set" for highlight group set by nvim_set_hl', function() + local result = exec_capture(':verbose highlight TestHL2') + eq( + string.format( + [[ +TestHL2 xxx guibg=Green + Last set from %s line 20]], + script_location + ), + result + ) + end) + it('"Last set" for command defined by nvim_command', function() if cmd == 'luafile' then pending('nvim_command does not set the script context') @@ -148,7 +199,7 @@ test_group FileType [[ Name Args Address Complete Definition Bdelete 0 :bd - Last set from %s line 13]], + Last set from %s line 22]], script_location ), result @@ -162,7 +213,7 @@ test_group FileType [[ Name Args Address Complete Definition TestCommand 0 :echo 'Hello' - Last set from %s line 14]], + Last set from %s line 23]], script_location ), result @@ -175,7 +226,7 @@ test_group FileType string.format( [[ function Close_Window() abort - Last set from %s line 16 + Last set from %s line 25 1 wincmd - endfunction]], script_location @@ -190,7 +241,7 @@ test_group FileType string.format( [[ textwidth=80 - Last set from %s line 22]], + Last set from %s line 31]], script_location ), result @@ -230,7 +281,7 @@ describe('lua verbose:', function() eq( [[ nohlsearch - Last set from Lua]], + Last set from Lua (run Nvim with -V1 for more details)]], result ) end) diff --git a/test/functional/ex_cmds/wincmd_spec.lua b/test/functional/ex_cmds/wincmd_spec.lua index 98c6358f45..283f0991cb 100644 --- a/test/functional/ex_cmds/wincmd_spec.lua +++ b/test/functional/ex_cmds/wincmd_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local fn = helpers.fn -local command = helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local fn = n.fn +local command = n.command it(':wincmd accepts a count', function() clear() diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua index f711731072..bb04bfa08a 100644 --- a/test/functional/ex_cmds/write_spec.lua +++ b/test/functional/ex_cmds/write_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local eq, eval, clear, write_file, source, insert = - helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.source, helpers.insert -local pcall_err = helpers.pcall_err -local command = helpers.command -local feed_command = helpers.feed_command -local fn = helpers.fn -local api = helpers.api -local skip = helpers.skip -local is_os = helpers.is_os -local is_ci = helpers.is_ci + t.eq, n.eval, n.clear, t.write_file, n.source, n.insert +local pcall_err = t.pcall_err +local command = n.command +local feed_command = n.feed_command +local fn = n.fn +local api = n.api +local skip = t.skip +local is_os = t.is_os +local is_ci = t.is_ci local fname = 'Xtest-functional-ex_cmds-write' local fname_bak = fname .. '~' diff --git a/test/functional/ex_cmds/wundo_spec.lua b/test/functional/ex_cmds/wundo_spec.lua index 78081fa45f..2299f33f06 100644 --- a/test/functional/ex_cmds/wundo_spec.lua +++ b/test/functional/ex_cmds/wundo_spec.lua @@ -1,13 +1,13 @@ -- Specs for :wundo and underlying functions -local helpers = require('test.functional.helpers')(after_each) -local command, clear, eval, spawn, nvim_prog, set_session = - helpers.command, - helpers.clear, - helpers.eval, - helpers.spawn, - helpers.nvim_prog, - helpers.set_session +local n = require('test.functional.testnvim')() + +local command = n.command +local clear = n.clear +local eval = n.eval +local spawn = n.spawn +local nvim_prog = n.nvim_prog +local set_session = n.set_session describe(':wundo', function() before_each(clear) diff --git a/test/functional/ex_cmds/wviminfo_spec.lua b/test/functional/ex_cmds/wviminfo_spec.lua index 23ae1440e6..7c76d92228 100644 --- a/test/functional/ex_cmds/wviminfo_spec.lua +++ b/test/functional/ex_cmds/wviminfo_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command, eq, neq, write_file = helpers.command, helpers.eq, helpers.neq, helpers.write_file -local read_file = helpers.read_file -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command, eq, neq, write_file = n.command, t.eq, t.neq, t.write_file +local read_file = t.read_file +local is_os = t.is_os describe(':wshada', function() local shada_file = 'wshada_test' diff --git a/test/functional/example_spec.lua b/test/functional/example_spec.lua index 5fc55f4aab..8db5c3d867 100644 --- a/test/functional/example_spec.lua +++ b/test/functional/example_spec.lua @@ -1,12 +1,13 @@ -- To run this test: -- TEST_FILE=test/functional/example_spec.lua make functionaltest -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local feed = helpers.feed +local clear = n.clear +local command = n.command +local eq = t.eq +local feed = n.feed describe('example', function() local screen diff --git a/test/functional/fixtures/api_level_12.mpack b/test/functional/fixtures/api_level_12.mpack Binary files differnew file mode 100644 index 0000000000..bab1b5111c --- /dev/null +++ b/test/functional/fixtures/api_level_12.mpack diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua index d9f44da0b4..f806869b40 100644 --- a/test/functional/fixtures/fake-lsp-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -110,7 +110,8 @@ local tests = {} function tests.basic_init() skeleton { - on_init = function(_) + on_init = function(params) + assert_eq(params.workDoneToken, '1') return { capabilities = { textDocumentSync = protocol.TextDocumentSyncKind.None, @@ -983,7 +984,7 @@ local test_name = arg[1] local timeout = arg[2] assert(type(test_name) == 'string', 'test_name must be specified as first arg.') -local kill_timer = vim.uv.new_timer() +local kill_timer = assert(vim.uv.new_timer()) kill_timer:start(timeout or 1e3, 0, function() kill_timer:stop() kill_timer:close() diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c index ef9f23e3f9..bd71e7d11b 100644 --- a/test/functional/fixtures/shell-test.c +++ b/test/functional/fixtures/shell-test.c @@ -49,6 +49,10 @@ int main(int argc, char **argv) help(); } +#ifdef _MSC_VER + SetConsoleOutputCP(CP_UTF8); +#endif + if (argc >= 2) { if (strcmp(argv[1], "-t") == 0) { if (argc < 3) { diff --git a/test/functional/legacy/002_filename_recognition_spec.lua b/test/functional/legacy/002_filename_recognition_spec.lua index 26a62d92fe..dd1335df94 100644 --- a/test/functional/legacy/002_filename_recognition_spec.lua +++ b/test/functional/legacy/002_filename_recognition_spec.lua @@ -1,9 +1,10 @@ -- Test if URLs are recognized as filenames by commands such as "gf". Here -- we'll use `expand("<cfile>")` since "gf" would need to open the file. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('filename recognition', function() setup(clear) diff --git a/test/functional/legacy/004_bufenter_with_modelines_spec.lua b/test/functional/legacy/004_bufenter_with_modelines_spec.lua index 9b0df024c8..6865153452 100644 --- a/test/functional/legacy/004_bufenter_with_modelines_spec.lua +++ b/test/functional/legacy/004_bufenter_with_modelines_spec.lua @@ -1,9 +1,10 @@ -- Test for autocommand that changes current buffer on BufEnter event. -- Check if modelines are interpreted for the correct buffer. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('BufEnter with modelines', function() setup(clear) diff --git a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua index 8e977aa73e..4d2d06f942 100644 --- a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua +++ b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua @@ -1,10 +1,11 @@ -- Test for autocommand that deletes the current buffer on BufLeave event. -- Also test deleting the last buffer, should give a new, empty buffer. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, expect = helpers.command, helpers.expect -local poke_eventloop = helpers.poke_eventloop +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local command, expect = n.command, n.expect +local poke_eventloop = n.poke_eventloop describe('test5', function() setup(clear) diff --git a/test/functional/legacy/007_ball_buffer_list_spec.lua b/test/functional/legacy/007_ball_buffer_list_spec.lua index d4e4547c43..15f3b0b9b8 100644 --- a/test/functional/legacy/007_ball_buffer_list_spec.lua +++ b/test/functional/legacy/007_ball_buffer_list_spec.lua @@ -1,8 +1,9 @@ -- Test for autocommand that changes the buffer list, when doing ":ball". -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe(':ball', function() setup(clear) diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua index 16f0216bc0..b7b411d631 100644 --- a/test/functional/legacy/008_autocommands_spec.lua +++ b/test/functional/legacy/008_autocommands_spec.lua @@ -1,13 +1,14 @@ -- Test for BufWritePre autocommand that deletes or unloads the buffer. -- Test for BufUnload autocommand that unloads all other buffers. -local helpers = require('test.functional.helpers')(after_each) -local source = helpers.source -local clear, command, expect, eq, eval = - helpers.clear, helpers.command, helpers.expect, helpers.eq, helpers.eval -local write_file, dedent = helpers.write_file, helpers.dedent -local read_file = helpers.read_file -local expect_exit = helpers.expect_exit +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local source = n.source +local clear, command, expect, eq, eval = n.clear, n.command, n.expect, t.eq, n.eval +local write_file, dedent = t.write_file, t.dedent +local read_file = t.read_file +local expect_exit = n.expect_exit describe('autocommands that delete and unload buffers:', function() local test_file = 'Xtest-008_autocommands.out' diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua index eba878b99a..45965d8791 100644 --- a/test/functional/legacy/011_autocommands_spec.lua +++ b/test/functional/legacy/011_autocommands_spec.lua @@ -12,19 +12,14 @@ -- Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz" -- being modified outside of Vim (noticed on Solaris). -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local clear, feed_command, expect, eq, neq, dedent, write_file, feed = - helpers.clear, - helpers.feed_command, - helpers.expect, - helpers.eq, - helpers.neq, - helpers.dedent, - helpers.write_file, - helpers.feed -local command = helpers.command -local read_file = helpers.read_file -local is_os = helpers.is_os + n.clear, n.feed_command, n.expect, t.eq, t.neq, t.dedent, t.write_file, n.feed +local command = n.command +local read_file = t.read_file +local is_os = t.is_os local function has_gzip() local null = is_os('win') and 'nul' or '/dev/null' diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua index b428318e3f..5c9185982f 100644 --- a/test/functional/legacy/012_directory_spec.lua +++ b/test/functional/legacy/012_directory_spec.lua @@ -3,19 +3,20 @@ -- - "./dir", in directory relative to file -- - "dir", in directory relative to current dir -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local neq = helpers.neq -local poke_eventloop = helpers.poke_eventloop -local fn = helpers.fn -local api = helpers.api -local clear = helpers.clear -local insert = helpers.insert -local command = helpers.command -local write_file = helpers.write_file -local expect_exit = helpers.expect_exit -local mkdir = helpers.mkdir +local eq = t.eq +local neq = t.neq +local poke_eventloop = n.poke_eventloop +local fn = n.fn +local api = n.api +local clear = n.clear +local insert = n.insert +local command = n.command +local write_file = t.write_file +local expect_exit = n.expect_exit +local mkdir = t.mkdir local function ls_dir_sorted(dirname) local files = {} @@ -44,8 +45,8 @@ describe("'directory' option", function() end) teardown(function() expect_exit(command, 'qall!') - helpers.rmdir('Xtest.je') - helpers.rmdir('Xtest2') + n.rmdir('Xtest.je') + n.rmdir('Xtest2') os.remove('Xtest1') end) diff --git a/test/functional/legacy/015_alignment_spec.lua b/test/functional/legacy/015_alignment_spec.lua index d73ff06972..ac90f3f98b 100644 --- a/test/functional/legacy/015_alignment_spec.lua +++ b/test/functional/legacy/015_alignment_spec.lua @@ -2,9 +2,10 @@ -- Also test formatting a paragraph. -- Also test undo after ":%s" and formatting. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('alignment', function() setup(clear) diff --git a/test/functional/legacy/018_unset_smart_indenting_spec.lua b/test/functional/legacy/018_unset_smart_indenting_spec.lua index 94fbb283f4..851b3264d3 100644 --- a/test/functional/legacy/018_unset_smart_indenting_spec.lua +++ b/test/functional/legacy/018_unset_smart_indenting_spec.lua @@ -1,12 +1,12 @@ -- Tests for not doing smart indenting when it isn't set. -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local feed = helpers.feed -local clear = helpers.clear -local insert = helpers.insert -local expect = helpers.expect -local feed_command = helpers.feed_command +local feed = n.feed +local clear = n.clear +local insert = n.insert +local expect = n.expect +local feed_command = n.feed_command describe('unset smart indenting', function() before_each(clear) diff --git a/test/functional/legacy/019_smarttab_expandtab_spec.lua b/test/functional/legacy/019_smarttab_expandtab_spec.lua index 7b03ee8e99..3bdc76c220 100644 --- a/test/functional/legacy/019_smarttab_expandtab_spec.lua +++ b/test/functional/legacy/019_smarttab_expandtab_spec.lua @@ -1,9 +1,10 @@ -- Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set. -- Also test that dv_ works correctly -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe([[performing "r<Tab>" with 'smarttab' and 'expandtab' set/not set, and "dv_"]], function() setup(clear) diff --git a/test/functional/legacy/020_blockwise_visual_spec.lua b/test/functional/legacy/020_blockwise_visual_spec.lua index 8d90b1c77d..f8df3dbf7e 100644 --- a/test/functional/legacy/020_blockwise_visual_spec.lua +++ b/test/functional/legacy/020_blockwise_visual_spec.lua @@ -2,9 +2,10 @@ -- First test for undo working properly when executing commands from a register. -- Also test this in an empty buffer. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('blockwise visual', function() setup(clear) diff --git a/test/functional/legacy/021_control_wi_spec.lua b/test/functional/legacy/021_control_wi_spec.lua index 94871433cd..64dbc47201 100644 --- a/test/functional/legacy/021_control_wi_spec.lua +++ b/test/functional/legacy/021_control_wi_spec.lua @@ -1,8 +1,9 @@ -- Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('CTRL-W CTRL-I', function() setup(clear) diff --git a/test/functional/legacy/023_edit_arguments_spec.lua b/test/functional/legacy/023_edit_arguments_spec.lua index 64b2f6fa95..97dc5b0153 100644 --- a/test/functional/legacy/023_edit_arguments_spec.lua +++ b/test/functional/legacy/023_edit_arguments_spec.lua @@ -1,9 +1,10 @@ -- Tests for complicated + argument to :edit command -local helpers = require('test.functional.helpers')(after_each) -local clear, insert = helpers.clear, helpers.insert -local command, expect = helpers.command, helpers.expect -local poke_eventloop = helpers.poke_eventloop +local n = require('test.functional.testnvim')() + +local clear, insert = n.clear, n.insert +local command, expect = n.command, n.expect +local poke_eventloop = n.poke_eventloop describe(':edit', function() setup(clear) diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua index 33bab05404..b7090662e6 100644 --- a/test/functional/legacy/025_jump_tag_hidden_spec.lua +++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua @@ -1,9 +1,11 @@ -- Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag. -- This only works for Unix, because of the symbolic link. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('jump to a tag with hidden set', function() setup(clear) @@ -23,7 +25,7 @@ describe('jump to a tag with hidden set', function() feed_command('set hidden') -- Create a link from test25.dir to the current directory. - if helpers.is_os('win') then + if t.is_os('win') then feed_command('!rd /q/s test25.dir') feed_command('!mklink /j test25.dir .') else @@ -33,7 +35,7 @@ describe('jump to a tag with hidden set', function() -- Create tags.text, with the current directory name inserted. feed_command('/tags line') - feed_command('r !' .. (helpers.is_os('win') and 'cd' or 'pwd')) + feed_command('r !' .. (t.is_os('win') and 'cd' or 'pwd')) feed('d$/test<cr>') feed('hP:.w! tags.test<cr>') @@ -44,7 +46,7 @@ describe('jump to a tag with hidden set', function() feed('G<C-]> x:yank a<cr>') feed_command("call delete('tags.test')") feed_command("call delete('Xxx')") - if helpers.is_os('win') then + if t.is_os('win') then feed_command('!rd /q test25.dir') else feed_command('!rm -f test25.dir') diff --git a/test/functional/legacy/026_execute_while_if_spec.lua b/test/functional/legacy/026_execute_while_if_spec.lua index ea8abed7ae..143985c726 100644 --- a/test/functional/legacy/026_execute_while_if_spec.lua +++ b/test/functional/legacy/026_execute_while_if_spec.lua @@ -1,11 +1,11 @@ -- Test for :execute, :while and :if -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local expect = helpers.expect -local source = helpers.source -local command = helpers.command +local clear = n.clear +local expect = n.expect +local source = n.source +local command = n.command describe(':execute, :while and :if', function() setup(clear) diff --git a/test/functional/legacy/028_source_ctrl_v_spec.lua b/test/functional/legacy/028_source_ctrl_v_spec.lua index fabf831341..17d4e7cc2e 100644 --- a/test/functional/legacy/028_source_ctrl_v_spec.lua +++ b/test/functional/legacy/028_source_ctrl_v_spec.lua @@ -1,8 +1,9 @@ -- Test for sourcing a file with CTRL-V's at the end of the line -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('CTRL-V at the end of the line', function() setup(clear) diff --git a/test/functional/legacy/029_join_spec.lua b/test/functional/legacy/029_join_spec.lua index c808a21afc..8d4cc70d8f 100644 --- a/test/functional/legacy/029_join_spec.lua +++ b/test/functional/legacy/029_join_spec.lua @@ -1,12 +1,12 @@ -- Test for joining lines with marks in them (and with 'joinspaces' set/reset) -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local feed = helpers.feed -local clear = helpers.clear -local insert = helpers.insert -local expect = helpers.expect -local feed_command = helpers.feed_command +local feed = n.feed +local clear = n.clear +local insert = n.insert +local expect = n.expect +local feed_command = n.feed_command describe('joining lines', function() before_each(clear) diff --git a/test/functional/legacy/030_fileformats_spec.lua b/test/functional/legacy/030_fileformats_spec.lua index e88afd9c47..1a44ed6cb6 100644 --- a/test/functional/legacy/030_fileformats_spec.lua +++ b/test/functional/legacy/030_fileformats_spec.lua @@ -1,9 +1,11 @@ -- Test for a lot of variations of the 'fileformats' option -local helpers = require('test.functional.helpers')(after_each) -local feed, clear, command = helpers.feed, helpers.clear, helpers.command -local eq, write_file = helpers.eq, helpers.write_file -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local feed, clear, command = n.feed, n.clear, n.command +local eq, write_file = t.eq, t.write_file +local poke_eventloop = n.poke_eventloop describe('fileformats option', function() setup(function() @@ -254,7 +256,7 @@ describe('fileformats option', function() command('set nobinary ff&') -- Assert buffer contents. This has to be done manually as - -- helpers.expect() calls helpers.dedent() which messes up the white space + -- n.expect() calls t.dedent() which messes up the white space -- and carriage returns. eq( 'unix\n'.. @@ -387,6 +389,6 @@ describe('fileformats option', function() '10\n'.. 'unix\n'.. 'unix', - helpers.curbuf_contents()) + n.curbuf_contents()) end) end) diff --git a/test/functional/legacy/031_close_commands_spec.lua b/test/functional/legacy/031_close_commands_spec.lua index 173ebf1cf4..974df0c21d 100644 --- a/test/functional/legacy/031_close_commands_spec.lua +++ b/test/functional/legacy/031_close_commands_spec.lua @@ -9,15 +9,15 @@ -- :buf -- :edit -local helpers = require('test.functional.helpers')(after_each) - -local feed = helpers.feed -local clear = helpers.clear -local source = helpers.source -local insert = helpers.insert -local expect = helpers.expect -local feed_command = helpers.feed_command -local expect_exit = helpers.expect_exit +local n = require('test.functional.testnvim')() + +local feed = n.feed +local clear = n.clear +local source = n.source +local insert = n.insert +local expect = n.expect +local feed_command = n.feed_command +local expect_exit = n.expect_exit describe('Commands that close windows and/or buffers', function() local function cleanup() diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua index b27de6c16d..e3d06be6bf 100644 --- a/test/functional/legacy/033_lisp_indent_spec.lua +++ b/test/functional/legacy/033_lisp_indent_spec.lua @@ -1,10 +1,11 @@ -- Test for 'lisp' -- If the lisp feature is not enabled, this will fail! -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, expect = helpers.command, helpers.expect -local poke_eventloop = helpers.poke_eventloop +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local command, expect = n.command, n.expect +local poke_eventloop = n.poke_eventloop describe('lisp indent', function() setup(clear) diff --git a/test/functional/legacy/034_user_function_spec.lua b/test/functional/legacy/034_user_function_spec.lua index c30c7275f2..89bf3b8920 100644 --- a/test/functional/legacy/034_user_function_spec.lua +++ b/test/functional/legacy/034_user_function_spec.lua @@ -3,9 +3,10 @@ -- Also test that a builtin function cannot be replaced. -- Also test for regression when calling arbitrary expression. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert, source = n.feed, n.insert, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe( 'user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions', diff --git a/test/functional/legacy/035_increment_and_decrement_spec.lua b/test/functional/legacy/035_increment_and_decrement_spec.lua index 84eb9c0eee..b6486a8a27 100644 --- a/test/functional/legacy/035_increment_and_decrement_spec.lua +++ b/test/functional/legacy/035_increment_and_decrement_spec.lua @@ -1,9 +1,10 @@ -- Test Ctrl-A and Ctrl-X, which increment and decrement decimal, hexadecimal, -- and octal numbers. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('increment and decrement commands', function() setup(clear) diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua index ed35b2b245..9c871e159c 100644 --- a/test/functional/legacy/036_regexp_character_classes_spec.lua +++ b/test/functional/legacy/036_regexp_character_classes_spec.lua @@ -1,8 +1,10 @@ -- Test character classes in regexp using regexpengine 0, 1, 2. -local helpers = require('test.functional.helpers')(after_each) -local clear, command, expect = helpers.clear, helpers.command, helpers.expect -local source, write_file = helpers.source, helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, command, expect = n.clear, n.command, n.expect +local source, write_file = n.source, t.write_file local function sixlines(text) local result = '' @@ -13,14 +15,14 @@ local function sixlines(text) end local function diff(text, nodedent) - local fname = helpers.tmpname() + local fname = t.tmpname() command('w! ' .. fname) - helpers.poke_eventloop() + n.poke_eventloop() local data = io.open(fname):read('*all') if nodedent then - helpers.eq(text, data) + t.eq(text, data) else - helpers.eq(helpers.dedent(text), data) + t.eq(t.dedent(text), data) end os.remove(fname) end diff --git a/test/functional/legacy/038_virtual_replace_spec.lua b/test/functional/legacy/038_virtual_replace_spec.lua index 2f85e7d5a3..b2edc5933f 100644 --- a/test/functional/legacy/038_virtual_replace_spec.lua +++ b/test/functional/legacy/038_virtual_replace_spec.lua @@ -1,8 +1,9 @@ -- Test Virtual replace mode. -local helpers = require('test.functional.helpers')(after_each) -local feed = helpers.feed -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed = n.feed +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('Virtual replace mode', function() setup(clear) diff --git a/test/functional/legacy/039_visual_block_mode_commands_spec.lua b/test/functional/legacy/039_visual_block_mode_commands_spec.lua index bc3fea765c..9fbf5ae774 100644 --- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua +++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua @@ -1,11 +1,13 @@ -- Test Visual block mode commands -- And test "U" in Visual mode, also on German sharp S. -local helpers = require('test.functional.helpers')(after_each) -local nvim, eq = helpers.api, helpers.eq -local insert, feed = helpers.insert, helpers.feed -local clear, expect = helpers.clear, helpers.expect -local feed_command = helpers.feed_command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local api, eq = n.api, t.eq +local insert, feed = n.insert, n.feed +local clear, expect = n.clear, n.expect +local feed_command = n.feed_command describe('Visual block mode', function() before_each(function() @@ -204,7 +206,7 @@ describe('Visual block mode', function() feed('G2l') feed('2k<C-v>$gj<ESC>') feed_command([[let cpos=getpos("'>")]]) - local cpos = nvim.nvim_get_var('cpos') + local cpos = api.nvim_get_var('cpos') local expected = { col = 4, off = 0, diff --git a/test/functional/legacy/043_magic_settings_spec.lua b/test/functional/legacy/043_magic_settings_spec.lua index a88ccc2b42..ba4c2dab02 100644 --- a/test/functional/legacy/043_magic_settings_spec.lua +++ b/test/functional/legacy/043_magic_settings_spec.lua @@ -1,8 +1,9 @@ -- Tests for regexp with various magic settings. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('regexp with magic settings', function() setup(clear) diff --git a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua index 074ee094b4..99cb64c7e5 100644 --- a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua +++ b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua @@ -3,9 +3,10 @@ -- -- This test contains both "test44" and "test99" from the old test suite. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect -- Runs the test protocol with the given 'regexpengine' setting. In the old test -- suite the test protocol was duplicated in test44 and test99, the only diff --git a/test/functional/legacy/046_multi_line_regexps_spec.lua b/test/functional/legacy/046_multi_line_regexps_spec.lua index 30ec76ea3e..a103b55581 100644 --- a/test/functional/legacy/046_multi_line_regexps_spec.lua +++ b/test/functional/legacy/046_multi_line_regexps_spec.lua @@ -1,9 +1,10 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for multi-line regexps with ":s" -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local expect = helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local expect = n.expect describe('multi-line regexp', function() setup(clear) diff --git a/test/functional/legacy/054_buffer_local_autocommands_spec.lua b/test/functional/legacy/054_buffer_local_autocommands_spec.lua index c8b9dfa98f..afde6f220a 100644 --- a/test/functional/legacy/054_buffer_local_autocommands_spec.lua +++ b/test/functional/legacy/054_buffer_local_autocommands_spec.lua @@ -1,10 +1,10 @@ -- Some tests for buffer-local autocommands -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local expect = helpers.expect -local command = helpers.command +local clear = n.clear +local expect = n.expect +local command = n.command local fname = 'Xtest-functional-legacy-054' diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua index e8ae60e350..21d6b07a2d 100644 --- a/test/functional/legacy/055_list_and_dict_types_spec.lua +++ b/test/functional/legacy/055_list_and_dict_types_spec.lua @@ -1,8 +1,9 @@ -- Tests for List and Dictionary types. -local helpers = require('test.functional.helpers')(after_each) -local feed, source = helpers.feed, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, source = n.feed, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('list and dictionary types', function() before_each(clear) diff --git a/test/functional/legacy/056_script_local_function_spec.lua b/test/functional/legacy/056_script_local_function_spec.lua index 084817ad7a..dd99224edb 100644 --- a/test/functional/legacy/056_script_local_function_spec.lua +++ b/test/functional/legacy/056_script_local_function_spec.lua @@ -1,9 +1,10 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for script-local function. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local expect = helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local expect = n.expect describe('source function', function() setup(clear) diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua index 9b4746591f..8b0664d50c 100644 --- a/test/functional/legacy/057_sort_spec.lua +++ b/test/functional/legacy/057_sort_spec.lua @@ -1,10 +1,11 @@ -- Tests for :sort command. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local insert, command, clear, expect, eq, poke_eventloop = - helpers.insert, helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.poke_eventloop -local exc_exec = helpers.exc_exec + n.insert, n.command, n.clear, n.expect, t.eq, n.poke_eventloop +local exc_exec = n.exc_exec describe(':sort', function() local text = [[ diff --git a/test/functional/legacy/060_exists_and_has_functions_spec.lua b/test/functional/legacy/060_exists_and_has_functions_spec.lua index 82fece3e84..ec29b6cf04 100644 --- a/test/functional/legacy/060_exists_and_has_functions_spec.lua +++ b/test/functional/legacy/060_exists_and_has_functions_spec.lua @@ -1,9 +1,11 @@ -- Tests for the exists() and has() functions. -local helpers = require('test.functional.helpers')(after_each) -local source = helpers.source -local clear, expect = helpers.clear, helpers.expect -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local source = n.source +local clear, expect = n.clear, n.expect +local write_file = t.write_file describe('exists() and has() functions', function() setup(function() diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua index b5af8f7d52..4177f908a1 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -1,18 +1,19 @@ -- Tests for undo tree and :earlier and :later. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local feed_command = helpers.feed_command -local write_file = helpers.write_file -local command = helpers.command -local source = helpers.source -local expect = helpers.expect -local clear = helpers.clear -local feed = helpers.feed -local eval = helpers.eval -local eq = helpers.eq +local feed_command = n.feed_command +local write_file = t.write_file +local command = n.command +local source = n.source +local expect = n.expect +local clear = n.clear +local feed = n.feed +local eval = n.eval +local eq = t.eq local function expect_empty_buffer() - -- The space will be removed by helpers.dedent but is needed because dedent + -- The space will be removed by t.dedent but is needed because dedent -- will fail if it can not find the common indent of the given lines. return expect(' ') end @@ -99,7 +100,7 @@ describe('undo tree:', function() expect_line('123456abc') end - helpers.retry(2, nil, test_earlier_later) + t.retry(2, nil, test_earlier_later) end) it('file-write specifications', function() diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua index 0c2b59932b..7515bcf182 100644 --- a/test/functional/legacy/063_match_and_matchadd_spec.lua +++ b/test/functional/legacy/063_match_and_matchadd_spec.lua @@ -1,10 +1,10 @@ -- Tests for adjusting window and contents -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, command = helpers.clear, helpers.command -local insert = helpers.insert +local clear, command = n.clear, n.command +local insert = n.insert describe('063: Test for ":match", "matchadd()" and related functions', function() setup(clear) @@ -12,10 +12,6 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( it('is working', function() local screen = Screen.new(40, 5) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Red }, - }) command('highlight MyGroup1 term=bold ctermbg=red guibg=red') command('highlight MyGroup2 term=italic ctermbg=green guibg=green') @@ -25,8 +21,8 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( insert('abcdefghijklmnopq') command("call matchaddpos('MyGroup1', [[1, 5], [1, 8, 3]], 10, 3)") screen:expect([[ - abcd{1:e}fg{1:hij}klmnop^q | - {0:~ }|*3 + abcd{30:e}fg{30:hij}klmnop^q | + {1:~ }|*3 | ]]) @@ -34,8 +30,8 @@ describe('063: Test for ":match", "matchadd()" and related functions', function( command("call setline(1, 'abcdΣabcdef')") command("call matchaddpos('MyGroup1', [[1, 4, 2], [1, 9, 2]])") screen:expect([[ - abc{1:dΣ}ab{1:cd}e^f | - {0:~ }|*3 + abc{30:dΣ}ab{30:cd}e^f | + {1:~ }|*3 | ]]) end) diff --git a/test/functional/legacy/065_float_and_logic_operators_spec.lua b/test/functional/legacy/065_float_and_logic_operators_spec.lua index ad1b004085..0835a3df52 100644 --- a/test/functional/legacy/065_float_and_logic_operators_spec.lua +++ b/test/functional/legacy/065_float_and_logic_operators_spec.lua @@ -1,8 +1,9 @@ -- Test for floating point and logical operators. -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, expect = n.clear, n.expect describe('floating point and logical operators', function() setup(clear) diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua index f10152d8ea..6e92bd4c65 100644 --- a/test/functional/legacy/066_visual_block_tab_spec.lua +++ b/test/functional/legacy/066_visual_block_tab_spec.lua @@ -1,9 +1,10 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for visual block shift and tab characters. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('visual block shift and tab characters', function() setup(clear) diff --git a/test/functional/legacy/067_augroup_exists_spec.lua b/test/functional/legacy/067_augroup_exists_spec.lua index 4a77bf838a..82b9c4bfa3 100644 --- a/test/functional/legacy/067_augroup_exists_spec.lua +++ b/test/functional/legacy/067_augroup_exists_spec.lua @@ -1,9 +1,10 @@ -- Test that groups and patterns are tested correctly when calling exists() for -- autocommands. -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command, expect = helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command, expect = n.command, n.expect describe('augroup when calling exists()', function() setup(clear) diff --git a/test/functional/legacy/068_text_formatting_spec.lua b/test/functional/legacy/068_text_formatting_spec.lua index 3a1b21bf87..179c15fb0f 100644 --- a/test/functional/legacy/068_text_formatting_spec.lua +++ b/test/functional/legacy/068_text_formatting_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local feed = helpers.feed -local clear = helpers.clear -local insert = helpers.insert -local feed_command = helpers.feed_command -local expect = helpers.expect +local feed = n.feed +local clear = n.clear +local insert = n.insert +local feed_command = n.feed_command +local expect = n.expect describe('text formatting', function() setup(clear) diff --git a/test/functional/legacy/069_multibyte_formatting_spec.lua b/test/functional/legacy/069_multibyte_formatting_spec.lua index 05e6aa1435..24a4692e6c 100644 --- a/test/functional/legacy/069_multibyte_formatting_spec.lua +++ b/test/functional/legacy/069_multibyte_formatting_spec.lua @@ -3,15 +3,11 @@ -- And test "ra" on multibyte characters. -- Also test byteidx() and byteidxcomp() -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local feed, insert, eq, eval, clear, feed_command, expect = - helpers.feed, - helpers.insert, - helpers.eq, - helpers.eval, - helpers.clear, - helpers.feed_command, - helpers.expect + n.feed, n.insert, t.eq, n.eval, n.clear, n.feed_command, n.expect describe('multibyte text', function() before_each(clear) diff --git a/test/functional/legacy/072_undo_file_spec.lua b/test/functional/legacy/072_undo_file_spec.lua index 80665027c3..f7185dacff 100644 --- a/test/functional/legacy/072_undo_file_spec.lua +++ b/test/functional/legacy/072_undo_file_spec.lua @@ -2,9 +2,10 @@ -- Since this script is sourced we need to explicitly break changes up in -- undo-able pieces. Do that by setting 'undolevels'. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('72', function() setup(clear) diff --git a/test/functional/legacy/074_global_var_in_viminfo_spec.lua b/test/functional/legacy/074_global_var_in_viminfo_spec.lua index 0a9ad330c2..d56a2654e3 100644 --- a/test/functional/legacy/074_global_var_in_viminfo_spec.lua +++ b/test/functional/legacy/074_global_var_in_viminfo_spec.lua @@ -1,8 +1,10 @@ -- Tests for storing global variables in the .shada file -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local clear, command, eq, neq, eval, poke_eventloop = - helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval, helpers.poke_eventloop + n.clear, n.command, t.eq, t.neq, n.eval, n.poke_eventloop describe('storing global variables in ShaDa files', function() local tempname = 'Xtest-functional-legacy-074' diff --git a/test/functional/legacy/078_swapfile_recover_spec.lua b/test/functional/legacy/078_swapfile_recover_spec.lua index dc5b1a8540..fa53482393 100644 --- a/test/functional/legacy/078_swapfile_recover_spec.lua +++ b/test/functional/legacy/078_swapfile_recover_spec.lua @@ -3,8 +3,9 @@ -- restored. We need about 10000 lines of 100 characters to get two levels of -- pointer blocks. -local helpers = require('test.functional.helpers')(after_each) -local clear, expect, source = helpers.clear, helpers.expect, helpers.source +local n = require('test.functional.testnvim')() + +local clear, expect, source = n.clear, n.expect, n.source describe('78', function() setup(clear) diff --git a/test/functional/legacy/081_coptions_movement_spec.lua b/test/functional/legacy/081_coptions_movement_spec.lua index d82c46a3d3..cfa65f5c8a 100644 --- a/test/functional/legacy/081_coptions_movement_spec.lua +++ b/test/functional/legacy/081_coptions_movement_spec.lua @@ -1,8 +1,9 @@ -- Test for t movement command and 'cpo-;' setting -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('coptions', function() setup(clear) diff --git a/test/functional/legacy/082_string_comparison_spec.lua b/test/functional/legacy/082_string_comparison_spec.lua index 311822c34f..3d91dc4b34 100644 --- a/test/functional/legacy/082_string_comparison_spec.lua +++ b/test/functional/legacy/082_string_comparison_spec.lua @@ -1,9 +1,10 @@ -- Tests for case-insensitive UTF-8 comparisons (utf_strnicmp() in mbyte.c) -- Also test "g~ap". -local helpers = require('test.functional.helpers')(after_each) -local feed, source = helpers.feed, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, source = n.feed, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('case-insensitive string comparison in UTF-8', function() setup(clear) diff --git a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua index 5e9c131c64..05154f660d 100644 --- a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua +++ b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua @@ -1,12 +1,14 @@ -- Tests for tag search with !_TAG_FILE_ENCODING. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local insert, source, clear, expect, write_file = - helpers.insert, helpers.source, helpers.clear, helpers.expect, helpers.write_file + n.insert, n.source, n.clear, n.expect, t.write_file local function has_iconv() clear() -- ensures session - return 1 == helpers.eval('has("iconv")') + return 1 == n.eval('has("iconv")') end describe('tag search with !_TAG_FILE_ENCODING', function() @@ -31,7 +33,7 @@ describe('tag search with !_TAG_FILE_ENCODING', function() ) -- The last file is very long but repetitive and can be generated on the -- fly. - local text = helpers.dedent([[ + local text = t.dedent([[ !_TAG_FILE_SORTED 1 // !_TAG_FILE_ENCODING cp932 // ]]) diff --git a/test/functional/legacy/090_sha256_spec.lua b/test/functional/legacy/090_sha256_spec.lua index 701b777df1..648eb65550 100644 --- a/test/functional/legacy/090_sha256_spec.lua +++ b/test/functional/legacy/090_sha256_spec.lua @@ -1,8 +1,9 @@ -- Tests for sha256() function. -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, expect = n.clear, n.expect describe('sha256()', function() setup(clear) diff --git a/test/functional/legacy/091_context_variables_spec.lua b/test/functional/legacy/091_context_variables_spec.lua index 3b9fdf740f..cc3ee6787a 100644 --- a/test/functional/legacy/091_context_variables_spec.lua +++ b/test/functional/legacy/091_context_variables_spec.lua @@ -1,8 +1,9 @@ -- Tests for getbufvar(), getwinvar(), gettabvar() and gettabwinvar(). -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, expect = n.clear, n.expect describe('context variables', function() setup(clear) diff --git a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua index 3c46c29951..d478545077 100644 --- a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua +++ b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua @@ -3,9 +3,10 @@ -- -- Same as legacy test 93 but using UTF-8 file encoding. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('store cursor position in session file in UTF-8', function() setup(clear) diff --git a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua index f09fd9a6e5..5e5e465c01 100644 --- a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua +++ b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua @@ -3,9 +3,10 @@ -- -- Same as legacy test 92 but using Latin-1 file encoding. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('store cursor position in session file in Latin-1', function() setup(clear) diff --git a/test/functional/legacy/094_visual_mode_operators_spec.lua b/test/functional/legacy/094_visual_mode_operators_spec.lua index ff1d3e7bec..279c6a432a 100644 --- a/test/functional/legacy/094_visual_mode_operators_spec.lua +++ b/test/functional/legacy/094_visual_mode_operators_spec.lua @@ -4,9 +4,10 @@ -- followed by an operator and those executed via Operator-pending mode. Also -- part of the test are mappings, counts, and repetition with the . command. -local helpers = require('test.functional.helpers')(after_each) -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert, source = n.feed, n.insert, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect -- Vim script user functions needed for some of the test cases. local function source_user_functions() diff --git a/test/functional/legacy/095_regexp_multibyte_spec.lua b/test/functional/legacy/095_regexp_multibyte_spec.lua index fad0dc8023..296bf00b58 100644 --- a/test/functional/legacy/095_regexp_multibyte_spec.lua +++ b/test/functional/legacy/095_regexp_multibyte_spec.lua @@ -3,9 +3,10 @@ -- A pattern that gives the expected result produces OK, so that we know it was -- actually tried. -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, expect = n.clear, n.expect describe('regex with multi-byte', function() setup(clear) diff --git a/test/functional/legacy/096_location_list_spec.lua b/test/functional/legacy/096_location_list_spec.lua index 2817d5d240..27bbe706bb 100644 --- a/test/functional/legacy/096_location_list_spec.lua +++ b/test/functional/legacy/096_location_list_spec.lua @@ -6,9 +6,10 @@ -- C. make sure that the location list window is not reused instead of the window -- it belongs to. -local helpers = require('test.functional.helpers')(after_each) -local source = helpers.source -local clear, command, expect = helpers.clear, helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local source = n.source +local clear, command, expect = n.clear, n.command, n.expect describe('location list', function() local test_file = 'Xtest-096_location_list.out' diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua index b335b3bf41..4d4bb9e78f 100644 --- a/test/functional/legacy/097_glob_path_spec.lua +++ b/test/functional/legacy/097_glob_path_spec.lua @@ -2,15 +2,17 @@ -- Test whether glob()/globpath() return correct results with certain escaped -- characters. -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command, expect = helpers.command, helpers.expect +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command, expect = n.command, n.expect describe('glob() and globpath()', function() setup(clear) setup(function() - if helpers.is_os('win') then + if t.is_os('win') then os.execute('md sautest\\autoload') os.execute('.>sautest\\autoload\\Test104.vim 2>nul') os.execute('.>sautest\\autoload\\footest.vim 2>nul') @@ -28,7 +30,7 @@ describe('glob() and globpath()', function() -- Consistent sorting of file names command('set nofileignorecase') - if helpers.is_os('win') then + if t.is_os('win') then command([[$put =glob('Xxx{')]]) command([[$put =glob('Xxx$')]]) @@ -72,7 +74,7 @@ describe('glob() and globpath()', function() end) teardown(function() - if helpers.is_os('win') then + if t.is_os('win') then os.execute('del /q/f Xxx{ Xxx$') os.execute('rd /q /s sautest') else diff --git a/test/functional/legacy/101_hlsearch_spec.lua b/test/functional/legacy/101_hlsearch_spec.lua index eff755221c..88f1c31b23 100644 --- a/test/functional/legacy/101_hlsearch_spec.lua +++ b/test/functional/legacy/101_hlsearch_spec.lua @@ -1,8 +1,9 @@ -- Test for v:hlsearch -local helpers = require('test.functional.helpers')(after_each) -local clear, feed = helpers.clear, helpers.feed -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed = n.clear, n.feed +local feed_command, expect = n.feed_command, n.expect describe('v:hlsearch', function() setup(clear) diff --git a/test/functional/legacy/102_fnameescape_spec.lua b/test/functional/legacy/102_fnameescape_spec.lua index 11bdbd7c9c..f0361c2f5a 100644 --- a/test/functional/legacy/102_fnameescape_spec.lua +++ b/test/functional/legacy/102_fnameescape_spec.lua @@ -1,8 +1,9 @@ -- Test if fnameescape is correct for special chars like! -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command, expect = helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command, expect = n.command, n.expect describe('fnameescape', function() setup(clear) diff --git a/test/functional/legacy/103_visual_mode_reset_spec.lua b/test/functional/legacy/103_visual_mode_reset_spec.lua index f5cd861019..b6fdf8cc68 100644 --- a/test/functional/legacy/103_visual_mode_reset_spec.lua +++ b/test/functional/legacy/103_visual_mode_reset_spec.lua @@ -1,8 +1,9 @@ -- Test for visual mode not being reset causing E315 error. -local helpers = require('test.functional.helpers')(after_each) -local feed, source = helpers.feed, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, source = n.feed, n.source +local clear, expect = n.clear, n.expect describe('E315 error', function() setup(clear) diff --git a/test/functional/legacy/106_errorformat_spec.lua b/test/functional/legacy/106_errorformat_spec.lua index 2a83d48c07..4189b568a2 100644 --- a/test/functional/legacy/106_errorformat_spec.lua +++ b/test/functional/legacy/106_errorformat_spec.lua @@ -1,8 +1,9 @@ -- Tests for errorformat. -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command, expect = helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command, expect = n.command, n.expect describe('errorformat', function() setup(clear) diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua index 5a8fdda32d..57ecf76f3a 100644 --- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua +++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua @@ -1,12 +1,12 @@ -- Tests for adjusting window and contents -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local poke_eventloop = helpers.poke_eventloop -local clear = helpers.clear -local insert = helpers.insert -local command = helpers.command +local poke_eventloop = n.poke_eventloop +local clear = n.clear +local insert = n.insert +local command = n.command describe('107', function() setup(clear) @@ -50,7 +50,7 @@ describe('107', function() [1, '1 '] | [50, '50 '] | ^[59, '59 '] | - ~ |*9 + {1:~ }|*9 3 more lines | ]]) end) diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua index ccdd0cd2be..d2ae785813 100644 --- a/test/functional/legacy/108_backtrace_debug_commands_spec.lua +++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua @@ -1,9 +1,10 @@ -- Tests for backtrace debug commands. -local helpers = require('test.functional.helpers')(after_each) -local command = helpers.command -local feed, clear = helpers.feed, helpers.clear -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local command = n.command +local feed, clear = n.feed, n.clear +local feed_command, expect = n.feed_command, n.expect describe('108', function() before_each(clear) diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua index 3e78d7ca5f..ac2a39a381 100644 --- a/test/functional/legacy/arglist_spec.lua +++ b/test/functional/legacy/arglist_spec.lua @@ -1,11 +1,13 @@ -- Test argument list commands -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, command, eq = helpers.clear, helpers.command, helpers.eq -local expect_exit = helpers.expect_exit -local feed = helpers.feed -local pcall_err = helpers.pcall_err + +local clear, command, eq = n.clear, n.command, t.eq +local expect_exit = n.expect_exit +local feed = n.feed +local pcall_err = t.pcall_err describe('argument list commands', function() before_each(clear) @@ -24,26 +26,26 @@ describe('argument list commands', function() feed(':confirm quit\n') screen:expect([[ | - ~ | - | + {1:~ }| + {3: }| :confirm quit | - 2 more files to edit. Quit anyway? | - [Y]es, (N)o: ^ | + {6:2 more files to edit. Quit anyway?} | + {6:[Y]es, (N)o: }^ | ]]) feed('N') screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 | ]]) feed(':confirm quit\n') screen:expect([[ | - ~ | - | + {1:~ }| + {3: }| :confirm quit | - 2 more files to edit. Quit anyway? | - [Y]es, (N)o: ^ | + {6:2 more files to edit. Quit anyway?} | + {6:[Y]es, (N)o: }^ | ]]) expect_exit(1000, feed, 'Y') end) diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 04c90281a7..47eea5e7d5 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -1,16 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) -local nvim, call = helpers.api, helpers.call -local clear, eq = helpers.clear, helpers.eq -local source, command = helpers.source, helpers.command -local exc_exec = helpers.exc_exec -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local api, call = n.api, n.call +local clear, eq = n.clear, t.eq +local source, command = n.source, n.command +local exc_exec = n.exc_exec +local eval = n.eval local function expected_errors(errors) - eq(errors, nvim.nvim_get_vvar('errors')) + eq(errors, api.nvim_get_vvar('errors')) end local function expected_empty() - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end describe('assert function:', function() diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua index e5980f5942..3bfa8bcd1e 100644 --- a/test/functional/legacy/autochdir_spec.lua +++ b/test/functional/legacy/autochdir_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, matches = helpers.clear, helpers.eq, helpers.matches -local eval, command, call, api = helpers.eval, helpers.command, helpers.call, helpers.api -local source, exec_capture = helpers.source, helpers.exec_capture -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, matches = n.clear, t.eq, t.matches +local eval, command, call, api = n.eval, n.command, n.call, n.api +local source, exec_capture = n.source, n.exec_capture +local mkdir = t.mkdir local function expected_empty() eq({}, api.nvim_get_vvar('errors')) @@ -18,7 +20,7 @@ describe('autochdir behavior', function() end) after_each(function() - helpers.rmdir(dir) + n.rmdir(dir) end) -- Tests vim/vim#777 without test_autochdir(). diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua index 9966df263b..9a1ad991f7 100644 --- a/test/functional/legacy/autocmd_option_spec.lua +++ b/test/functional/legacy/autocmd_option_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local nvim = helpers.api -local clear, eq, neq, eval = helpers.clear, helpers.eq, helpers.neq, helpers.eval -local api = helpers.api -local curbuf = helpers.api.nvim_get_current_buf -local curwin = helpers.api.nvim_get_current_win -local exec_capture = helpers.exec_capture -local source, command = helpers.source, helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, neq, eval = n.clear, t.eq, t.neq, n.eval +local api = n.api +local curbuf = n.api.nvim_get_current_buf +local curwin = n.api.nvim_get_current_win +local exec_capture = n.exec_capture +local source, command = n.source, n.command local function declare_hook_function() source([[ @@ -39,7 +40,7 @@ local function init_var() end local function get_result() - local ret = nvim.nvim_get_var('ret') + local ret = api.nvim_get_var('ret') init_var() return ret end @@ -697,24 +698,24 @@ describe('au OptionSet', function() it('should trigger if a boolean option be set globally', function() set_hook('autochdir') - nvim.nvim_set_option_value('autochdir', true, { scope = 'global' }) - eq(true, nvim.nvim_get_option_value('autochdir', { scope = 'global' })) + api.nvim_set_option_value('autochdir', true, { scope = 'global' }) + eq(true, api.nvim_get_option_value('autochdir', { scope = 'global' })) expected_combination({ 'autochdir', false, '', false, true, 'global', 'setglobal' }) end) it('should trigger if a number option be set globally', function() set_hook('cmdheight') - nvim.nvim_set_option_value('cmdheight', 5, { scope = 'global' }) - eq(5, nvim.nvim_get_option_value('cmdheight', { scope = 'global' })) + api.nvim_set_option_value('cmdheight', 5, { scope = 'global' }) + eq(5, api.nvim_get_option_value('cmdheight', { scope = 'global' })) expected_combination({ 'cmdheight', 1, '', 1, 5, 'global', 'setglobal' }) end) it('should trigger if a string option be set globally', function() set_hook('ambiwidth') - nvim.nvim_set_option_value('ambiwidth', 'double', { scope = 'global' }) - eq('double', nvim.nvim_get_option_value('ambiwidth', { scope = 'global' })) + api.nvim_set_option_value('ambiwidth', 'double', { scope = 'global' }) + eq('double', api.nvim_get_option_value('ambiwidth', { scope = 'global' })) expected_combination({ 'ambiwidth', 'single', diff --git a/test/functional/legacy/autocmd_spec.lua b/test/functional/legacy/autocmd_spec.lua index 97051f3d3f..4d82da6312 100644 --- a/test/functional/legacy/autocmd_spec.lua +++ b/test/functional/legacy/autocmd_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local write_file = helpers.write_file -local command = helpers.command -local feed = helpers.feed -local api = helpers.api -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local write_file = t.write_file +local command = n.command +local feed = n.feed +local api = n.api +local eq = t.eq before_each(clear) diff --git a/test/functional/legacy/autoformat_join_spec.lua b/test/functional/legacy/autoformat_join_spec.lua index 22b1c258fe..9a240c8bda 100644 --- a/test/functional/legacy/autoformat_join_spec.lua +++ b/test/functional/legacy/autoformat_join_spec.lua @@ -1,9 +1,10 @@ -- Tests for setting the '[,'] marks when joining lines. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, expect = helpers.command, helpers.expect -local poke_eventloop = helpers.poke_eventloop +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local command, expect = n.command, n.expect +local poke_eventloop = n.poke_eventloop describe('autoformat join', function() setup(clear) diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua index cf0065f394..8c3d73b17b 100644 --- a/test/functional/legacy/breakindent_spec.lua +++ b/test/functional/legacy/breakindent_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local exec = n.exec +local feed = n.feed before_each(clear) @@ -67,50 +68,43 @@ describe('breakindent', function() setlocal breakindent call setline(1, "\t" .. join(range(100))) ]]) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { bold = true, reverse = true }, -- StatusLine - [3] = { reverse = true }, -- StatusLineNC - [4] = { bold = true }, -- ModeMsg - }) screen:attach() feed('v$') screen:expect([[ - {0:<<<} {1: 93 94 95 96 97 98 99}^ | - {2:[No Name] [+] }| + {1:<<<} {17: 93 94 95 96 97 98 99}^ | + {3:[No Name] [+] }| | - {0:~ }| - {3:[No Name] }| - {4:-- VISUAL --} | + {1:~ }| + {2:[No Name] }| + {5:-- VISUAL --} | ]]) command('setlocal showbreak=+++') screen:expect([[ - {0:+++}{1: 90 91 92 93 94 95 96 97 98 99}^ | - {2:[No Name] [+] }| + {1:+++}{17: 90 91 92 93 94 95 96 97 98 99}^ | + {3:[No Name] [+] }| | - {0:~ }| - {3:[No Name] }| - {4:-- VISUAL --} | + {1:~ }| + {2:[No Name] }| + {5:-- VISUAL --} | ]]) command('setlocal breakindentopt+=sbr') screen:expect([[ - {0:+++} {1: 93 94 95 96 97 98 99}^ | - {2:[No Name] [+] }| + {1:+++} {17: 93 94 95 96 97 98 99}^ | + {3:[No Name] [+] }| | - {0:~ }| - {3:[No Name] }| - {4:-- VISUAL --} | + {1:~ }| + {2:[No Name] }| + {5:-- VISUAL --} | ]]) command('setlocal nobreakindent') screen:expect([[ - {0:+++}{1: 98 99}^ | - {2:[No Name] [+] }| + {1:+++}{17: 98 99}^ | + {3:[No Name] [+] }| | - {0:~ }| - {3:[No Name] }| - {4:-- VISUAL --} | + {1:~ }| + {2:[No Name] }| + {5:-- VISUAL --} | ]]) end) end) diff --git a/test/functional/legacy/buffer_spec.lua b/test/functional/legacy/buffer_spec.lua deleted file mode 100644 index b3964540f0..0000000000 --- a/test/functional/legacy/buffer_spec.lua +++ /dev/null @@ -1,59 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, source = helpers.clear, helpers.source -local call, eq, api = helpers.call, helpers.eq, helpers.api - -local function expected_empty() - eq({}, api.nvim_get_vvar('errors')) -end - -describe('buffer', function() - before_each(function() - clear() - api.nvim_ui_attach(80, 24, {}) - api.nvim_set_option_value('hidden', false, {}) - end) - - it('deleting a modified buffer with :confirm', function() - source([[ - func Test_bdel_with_confirm() - new - call setline(1, 'test') - call assert_fails('bdel', 'E89:') - call nvim_input('c') - confirm bdel - call assert_equal(2, winnr('$')) - call assert_equal(1, &modified) - call nvim_input('n') - confirm bdel - call assert_equal(1, winnr('$')) - endfunc - ]]) - call('Test_bdel_with_confirm') - expected_empty() - end) - - it('editing another buffer from a modified buffer with :confirm', function() - source([[ - func Test_goto_buf_with_confirm() - new Xfile - enew - call setline(1, 'test') - call assert_fails('b Xfile', 'E37:') - call nvim_input('c') - call assert_fails('confirm b Xfile', 'E37:') - call assert_equal(1, &modified) - call assert_equal('', @%) - call nvim_input('y') - call assert_fails('confirm b Xfile', 'E37:') - call assert_equal(1, &modified) - call assert_equal('', @%) - call nvim_input('n') - confirm b Xfile - call assert_equal('Xfile', @%) - close! - endfunc - ]]) - call('Test_goto_buf_with_confirm') - expected_empty() - end) -end) diff --git a/test/functional/legacy/changelist_spec.lua b/test/functional/legacy/changelist_spec.lua index b673e74128..e2f87351de 100644 --- a/test/functional/legacy/changelist_spec.lua +++ b/test/functional/legacy/changelist_spec.lua @@ -1,9 +1,10 @@ -- Test changelist position after splitting window -- Set 'undolevels' to make changelist for sourced file -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('changelist', function() setup(clear) diff --git a/test/functional/legacy/charsearch_spec.lua b/test/functional/legacy/charsearch_spec.lua index c1a59c9ee1..da13b61e0f 100644 --- a/test/functional/legacy/charsearch_spec.lua +++ b/test/functional/legacy/charsearch_spec.lua @@ -1,8 +1,9 @@ -- Test for character searches -local helpers = require('test.functional.helpers')(after_each) -local feed, insert = helpers.feed, helpers.insert -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert = n.feed, n.insert +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('charsearch', function() setup(clear) diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua index 930dae668a..0a08ad9fe6 100644 --- a/test/functional/legacy/close_count_spec.lua +++ b/test/functional/legacy/close_count_spec.lua @@ -1,13 +1,14 @@ -- Tests for :[count]close! and :[count]hide -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local poke_eventloop = helpers.poke_eventloop -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local command = helpers.command +local eq = t.eq +local poke_eventloop = n.poke_eventloop +local eval = n.eval +local feed = n.feed +local clear = n.clear +local command = n.command describe('close_count', function() setup(clear) diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua index 8c94451f9a..2e0e52117d 100644 --- a/test/functional/legacy/cmdline_spec.lua +++ b/test/functional/legacy/cmdline_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local feed_command = helpers.feed_command -local exec = helpers.exec -local api = helpers.api + +local clear = n.clear +local command = n.command +local feed = n.feed +local feed_command = n.feed_command +local exec = n.exec +local api = n.api local pesc = vim.pesc describe('cmdline', function() @@ -15,12 +16,6 @@ describe('cmdline', function() it('is cleared when switching tabs', function() local screen = Screen.new(30, 10) screen:attach() - screen:set_default_attr_ids { - [1] = { underline = true, background = Screen.colors.LightGrey }, - [2] = { bold = true }, - [3] = { reverse = true }, - [4] = { bold = true, foreground = Screen.colors.Blue1 }, - } feed_command([[call setline(1, range(30))]]) screen:expect([[ @@ -39,9 +34,9 @@ describe('cmdline', function() feed [[:tabnew<cr>]] screen:expect { grid = [[ - {1: + [No Name] }{2: [No Name] }{3: }{1:X}| + {24: + [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {4:~ }|*7 + {1:~ }|*7 :tabnew | ]], } @@ -49,9 +44,9 @@ describe('cmdline', function() feed [[<C-w>-<C-w>-]] screen:expect { grid = [[ - {1: + [No Name] }{2: [No Name] }{3: }{1:X}| + {24: + [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {4:~ }|*5 + {1:~ }|*5 |*3 ]], } @@ -59,7 +54,7 @@ describe('cmdline', function() feed [[gt]] screen:expect { grid = [[ - {2: + [No Name] }{1: [No Name] }{3: }{1:X}| + {5: + [No Name] }{24: [No Name] }{2: }{24:X}| ^0 | 1 | 2 | @@ -74,9 +69,9 @@ describe('cmdline', function() feed [[gt]] screen:expect([[ - {1: + [No Name] }{2: [No Name] }{3: }{1:X}| + {24: + [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {4:~ }|*5 + {1:~ }|*5 |*3 ]]) end) @@ -93,8 +88,8 @@ describe('cmdline', function() feed_command('DoSomething') screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| Executing: DoSomething | Executing: echo 'hello' |set ts=4 |let v = '123' |echo v | hello | @@ -102,17 +97,13 @@ describe('cmdline', function() Executing: let v = '123' |echo v | Executing: echo v | 123 | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) end) -- oldtest: Test_cmdline_redraw_tabline() it('tabline is redrawn on entering cmdline', function() local screen = Screen.new(30, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { reverse = true }, -- TabLineFill - }) screen:attach() exec([[ set showtabline=2 @@ -120,9 +111,9 @@ describe('cmdline', function() ]]) feed(':') screen:expect([[ - {1:foo }| + {2:foo }| | - {0:~ }|*3 + {1:~ }|*3 :^ | ]]) end) @@ -130,9 +121,6 @@ describe('cmdline', function() -- oldtest: Test_redraw_in_autocmd() it('cmdline cursor position is correct after :redraw with cmdheight=2', function() local screen = Screen.new(30, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() exec([[ set cmdheight=2 @@ -141,7 +129,7 @@ describe('cmdline', function() feed(':for i in range(3)<CR>') screen:expect([[ | - {0:~ }|*3 + {1:~ }|*3 :for i in range(3) | : ^ | ]]) @@ -149,7 +137,7 @@ describe('cmdline', function() -- Note: this may still be considered broken, ref #18140 screen:expect([[ | - {0:~ }|*3 + {1:~ }|*3 : :let i =^ | | ]]) @@ -157,10 +145,6 @@ describe('cmdline', function() it("setting 'cmdheight' works after outputting two messages vim-patch:9.0.0665", function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine - }) screen:attach() exec([[ set cmdheight=1 laststatus=2 @@ -175,15 +159,15 @@ describe('cmdline', function() feed(':call EchoTwo()') screen:expect([[ | - {0:~ }|*5 - {1:[No Name] }| + {1:~ }|*5 + {3:[No Name] }| :call EchoTwo()^ | ]]) feed('<CR>') screen:expect([[ ^ | - {0:~ }|*5 - {1:[No Name] }| + {1:~ }|*5 + {3:[No Name] }| | ]]) end) @@ -191,21 +175,15 @@ describe('cmdline', function() -- oldtest: Test_cmdheight_tabline() it("changing 'cmdheight' when there is a tabline", function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine - [2] = { bold = true }, -- TabLineSel - [3] = { reverse = true }, -- TabLineFill - }) screen:attach() api.nvim_set_option_value('laststatus', 2, {}) api.nvim_set_option_value('showtabline', 2, {}) api.nvim_set_option_value('cmdheight', 1, {}) screen:expect([[ - {2: [No Name] }{3: }| + {5: [No Name] }{2: }| ^ | - {0:~ }|*4 - {1:[No Name] }| + {1:~ }|*4 + {3:[No Name] }| | ]]) end) @@ -213,9 +191,6 @@ describe('cmdline', function() -- oldtest: Test_rulerformat_position() it("ruler has correct position with 'rulerformat' set", function() local screen = Screen.new(20, 3) - screen:set_default_attr_ids { - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - } screen:attach() api.nvim_set_option_value('ruler', true, {}) api.nvim_set_option_value('rulerformat', 'longish', {}) @@ -224,7 +199,7 @@ describe('cmdline', function() feed [[<C-W>v<C-W>|<C-W>p]] screen:expect [[ │^ | - {0:~ }│{0:~}| + {1:~ }│{1:~}| longish | ]] end) diff --git a/test/functional/legacy/command_count_spec.lua b/test/functional/legacy/command_count_spec.lua index 8707c0459c..a6be459a4d 100644 --- a/test/functional/legacy/command_count_spec.lua +++ b/test/functional/legacy/command_count_spec.lua @@ -1,8 +1,9 @@ -- Test for user command counts -local helpers = require('test.functional.helpers')(after_each) -local clear, source, expect = helpers.clear, helpers.source, helpers.expect -local feed_command = helpers.feed_command +local n = require('test.functional.testnvim')() + +local clear, source, expect = n.clear, n.source, n.expect +local feed_command = n.feed_command -- luacheck: ignore 613 (Trailing whitespace in a string) describe('command_count', function() diff --git a/test/functional/legacy/comparators_spec.lua b/test/functional/legacy/comparators_spec.lua index 32e830a0af..86df5b1c41 100644 --- a/test/functional/legacy/comparators_spec.lua +++ b/test/functional/legacy/comparators_spec.lua @@ -1,8 +1,10 @@ -- " Test for expression comparators. -local helpers = require('test.functional.helpers')(after_each) -local clear, eq = helpers.clear, helpers.eq -local eval, command = helpers.eval, helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq = n.clear, t.eq +local eval, command = n.eval, n.command describe('comparators', function() before_each(clear) diff --git a/test/functional/legacy/conceal_spec.lua b/test/functional/legacy/conceal_spec.lua index 9a23d16c5b..f4c1983bb7 100644 --- a/test/functional/legacy/conceal_spec.lua +++ b/test/functional/legacy/conceal_spec.lua @@ -1,12 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local exec = n.exec +local feed = n.feed +local api = n.api local expect_pos = function(row, col) - return helpers.eq({ row, col }, helpers.eval('[screenrow(), screencol()]')) + return t.eq({ row, col }, n.eval('[screenrow(), screencol()]')) end describe('Conceal', function() @@ -18,12 +21,6 @@ describe('Conceal', function() -- oldtest: Test_conceal_two_windows() it('works', function() local screen = Screen.new(75, 12) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine - [2] = { reverse = true }, -- StatusLineNC, IncSearch - [3] = { bold = true }, -- ModeMsg - }) screen:attach() exec([[ let lines = ["one one one one one", "two |hidden| here", "three |hidden| three"] @@ -47,12 +44,12 @@ describe('Conceal', function() two ^here | three three | Second window | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| one one one one one | two here | three three | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| /here | ]]) @@ -64,12 +61,12 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| one one one one one | two here | three three | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| /here | ]]) @@ -82,12 +79,12 @@ describe('Conceal', function() two |hidden| ^here | three three | Second window | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| one one one one one | two here | three three | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| /here | ]]) @@ -99,12 +96,12 @@ describe('Conceal', function() two here | three |hidden^| three | Second window | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| one one one one one | two here | three three | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| /here | ]]) @@ -116,13 +113,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| ^here | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| /here | ]]) @@ -133,13 +130,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two ^here | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| /here | ]]) feed('a') @@ -148,14 +145,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h^ere | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- INSERT --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Esc>/e') screen:expect([[ @@ -163,13 +160,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h{2:e}re | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| /e^ | ]]) feed('<Esc>v') @@ -178,14 +175,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| ^here | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- VISUAL --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- VISUAL --} | ]]) feed('<Esc>') @@ -196,13 +193,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| ^here | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| | ]]) feed('a') @@ -211,14 +208,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two h^ere | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- INSERT --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Esc>/e') screen:expect([[ @@ -226,13 +223,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h{2:e}re | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| /e^ | ]]) feed('<Esc>v') @@ -241,14 +238,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| ^here | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- VISUAL --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- VISUAL --} | ]]) feed('<Esc>') @@ -259,13 +256,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| ^here | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| | ]]) feed('a') @@ -274,14 +271,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h^ere | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- INSERT --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Esc>/e') screen:expect([[ @@ -289,13 +286,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h{2:e}re | three three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| /e^ | ]]) feed('<Esc>v') @@ -304,14 +301,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two ^here | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- VISUAL --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- VISUAL --} | ]]) feed('<Esc>') @@ -323,14 +320,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two |hidden| h^ere | three three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- INSERT --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Down>') screen:expect([[ @@ -338,14 +335,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two here | three |hidden|^ three | - {0:~ }| - {1:[No Name] [+] }| - {3:-- INSERT --} | + {1:~ }| + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Esc>') @@ -355,13 +352,13 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two here | three |hidden^| three | - {0:~ }| - {1:[No Name] [+] }| + {1:~ }| + {3:[No Name] [+] }| | ]]) feed('o') @@ -370,14 +367,14 @@ describe('Conceal', function() two here | three three | Second window | - {0:~ }| + {1:~ }| {2:[No Name] [+] }| one one one one one | two here | three three | ^ | - {1:[No Name] [+] }| - {3:-- INSERT --} | + {3:[No Name] [+] }| + {5:-- INSERT --} | ]]) feed('<Esc>') end) @@ -433,15 +430,73 @@ describe('Conceal', function() ]]) end) - -- oldtest: Test_conceal_resize_term() - it('resize editor', function() - local screen = Screen.new(75, 6) + -- oldtest: Test_conceal_wrapped_cursorline_wincolor() + it('CursorLine highlight on wrapped lines', function() + local screen = Screen.new(40, 4) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + [1] = { background = Screen.colors.Green }, -- CursorLine (low-priority) + [2] = { foreground = Screen.colors.Red }, -- CursorLine (high-priority) + }) + screen:attach() + exec([[ + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline + normal! g$ + hi! CursorLine guibg=Green + ]]) + screen:expect([[ + {1:one one one one one one one on^e }| + {1: one one one }| + {0:~ }| + | + ]]) + command('hi! CursorLine guibg=NONE guifg=Red') + screen:expect([[ + {2:one one one one one one one on^e }| + {2: one one one }| + {0:~ }| + | + ]]) + end) + + -- oldtest: Test_conceal_wrapped_cursorline_wincolor_rightleft() + it('CursorLine highlight on wrapped lines with rightleft', function() + local screen = Screen.new(40, 4) screen:set_default_attr_ids({ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Blue }, -- Comment + [1] = { background = Screen.colors.Green }, -- CursorLine (low-priority) + [2] = { foreground = Screen.colors.Red }, -- CursorLine (high-priority) }) screen:attach() exec([[ + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline rightleft + normal! g$ + hi! CursorLine guibg=Green + ]]) + screen:expect([[ + {1: ^eno eno eno eno eno eno eno eno}| + {1: eno eno eno }| + {0: ~}| + | + ]]) + command('hi! CursorLine guibg=NONE guifg=Red') + screen:expect([[ + {2: ^eno eno eno eno eno eno eno eno}| + {2: eno eno eno }| + {0: ~}| + | + ]]) + end) + + -- oldtest: Test_conceal_resize_term() + it('resize editor', function() + local screen = Screen.new(75, 6) + screen:attach() + exec([[ call setline(1, '`one` `two` `three` `four` `five`, the backticks should be concealed') setl cocu=n cole=3 syn region CommentCodeSpan matchgroup=Comment start=/`/ end=/`/ concealends @@ -449,14 +504,14 @@ describe('Conceal', function() ]]) screen:expect([[ one two three four five, the ^backticks should be concealed | - {0:~ }|*4 + {1:~ }|*4 | ]]) screen:try_resize(75, 7) screen:expect([[ one two three four five, the ^backticks should be concealed | - {0:~ }|*5 + {1:~ }|*5 | ]]) end) @@ -464,9 +519,6 @@ describe('Conceal', function() -- oldtest: Test_conceal_linebreak() it('with linebreak', function() local screen = Screen.new(75, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() exec([[ let &wrap = v:true @@ -486,9 +538,9 @@ describe('Conceal', function() ^xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - {0:+ }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | - {0:+ }cccccc | - {0:~ }|*2 + {1:+ }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + {1:+ }cccccc | + {1:~ }|*2 | ]]) end) @@ -570,4 +622,210 @@ describe('Conceal', function() feed('$') expect_pos(9, 26) end) + + local function test_conceal_virtualedit_after_eol(wrap) + local screen = Screen.new(60, 3) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + }) + screen:attach() + api.nvim_set_option_value('wrap', wrap, {}) + exec([[ + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all + normal! $ + ]]) + screen:expect([[ + abcdefghijklmnpo^p | + {0:~ }| + | + ]]) + feed('l') + screen:expect([[ + abcdefghijklmnpop^ | + {0:~ }| + | + ]]) + feed('l') + screen:expect([[ + abcdefghijklmnpop ^ | + {0:~ }| + | + ]]) + feed('l') + screen:expect([[ + abcdefghijklmnpop ^ | + {0:~ }| + | + ]]) + feed('rr') + screen:expect([[ + abcdefghijklmnpop ^r | + {0:~ }| + | + ]]) + end + + -- oldtest: Test_conceal_virtualedit_after_eol() + describe('cursor drawn at correct column with virtualedit', function() + it('with wrapping', function() + test_conceal_virtualedit_after_eol(true) + end) + it('without wrapping', function() + test_conceal_virtualedit_after_eol(false) + end) + end) + + local function test_conceal_virtualedit_after_eol_rightleft(wrap) + local screen = Screen.new(60, 3) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + }) + screen:attach() + api.nvim_set_option_value('wrap', wrap, {}) + exec([[ + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all rightleft + normal! $ + ]]) + screen:expect([[ + ^popnmlkjihgfedcba| + {0: ~}| + | + ]]) + feed('h') + screen:expect([[ + ^ popnmlkjihgfedcba| + {0: ~}| + | + ]]) + feed('h') + screen:expect([[ + ^ popnmlkjihgfedcba| + {0: ~}| + | + ]]) + feed('h') + screen:expect([[ + ^ popnmlkjihgfedcba| + {0: ~}| + | + ]]) + feed('rr') + screen:expect([[ + ^r popnmlkjihgfedcba| + {0: ~}| + | + ]]) + end + + -- oldtest: Test_conceal_virtualedit_after_eol_rightleft() + describe('cursor drawn correctly with virtualedit and rightleft', function() + it('with wrapping', function() + test_conceal_virtualedit_after_eol_rightleft(true) + end) + it('without wrapping', function() + test_conceal_virtualedit_after_eol_rightleft(false) + end) + end) + + local function test_conceal_double_width(wrap) + local screen = Screen.new(60, 4) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { background = Screen.colors.DarkGrey, foreground = Screen.colors.LightGrey }, + [2] = { background = Screen.colors.LightRed }, + }) + screen:attach() + api.nvim_set_option_value('wrap', wrap, {}) + exec([[ + call setline(1, ['aaaaa口=口bbbbb口=口ccccc', 'foobar']) + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n colorcolumn=30 + normal! $ + ]]) + screen:expect([[ + aaaaa{1:β}bbbbb{1:β}cccc^c {2: } | + foobar {2: } | + {0:~ }| + | + ]]) + feed('gM') + screen:expect([[ + aaaaa{1:β}bb^bbb{1:β}ccccc {2: } | + foobar {2: } | + {0:~ }| + | + ]]) + command('set conceallevel=3') + screen:expect([[ + aaaaabb^bbbccccc {2: } | + foobar {2: } | + {0:~ }| + | + ]]) + feed('$') + screen:expect([[ + aaaaabbbbbcccc^c {2: } | + foobar {2: } | + {0:~ }| + | + ]]) + end + + -- oldtest: Test_conceal_double_width() + describe('cursor drawn correctly when double-width chars are concealed', function() + it('with wrapping', function() + test_conceal_double_width(true) + end) + it('without wrapping', function() + test_conceal_double_width(false) + end) + end) + + -- oldtest: Test_conceal_double_width_wrap() + it('line wraps correctly when double-width chars are concealed', function() + local screen = Screen.new(20, 4) + screen:set_default_attr_ids({ + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { background = Screen.colors.DarkGrey, foreground = Screen.colors.LightGrey }, + [2] = { background = Screen.colors.LightRed }, + }) + screen:attach() + exec([[ + call setline(1, 'aaaaaaaaaa口=口bbbbbbbbbb口=口cccccccccc') + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n + normal! $ + ]]) + screen:expect([[ + aaaaaaaaaa{1:β}bbbbb | + bbbbb{1:β}ccccccccc^c | + {0:~ }| + | + ]]) + feed('gM') + screen:expect([[ + aaaaaaaaaa{1:β}bbbbb | + ^bbbbb{1:β}cccccccccc | + {0:~ }| + | + ]]) + command('set conceallevel=3') + screen:expect([[ + aaaaaaaaaabbbbb | + ^bbbbbcccccccccc | + {0:~ }| + | + ]]) + feed('$') + screen:expect([[ + aaaaaaaaaabbbbb | + bbbbbccccccccc^c | + {0:~ }| + | + ]]) + end) end) diff --git a/test/functional/legacy/cpoptions_spec.lua b/test/functional/legacy/cpoptions_spec.lua index 288146199a..56b0e72c72 100644 --- a/test/functional/legacy/cpoptions_spec.lua +++ b/test/functional/legacy/cpoptions_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local feed = n.feed before_each(clear) @@ -15,13 +16,13 @@ describe('cpoptions', function() feed('c2w') screen:expect([[ ^one tw$ three | - ~ |*4 - -- INSERT -- | + {1:~ }|*4 + {5:-- INSERT --} | ]]) feed('vim<Esc>') screen:expect([[ vi^m three | - ~ |*4 + {1:~ }|*4 | ]]) end) diff --git a/test/functional/legacy/crash_spec.lua b/test/functional/legacy/crash_spec.lua index 094bea253e..04f77c7d4f 100644 --- a/test/functional/legacy/crash_spec.lua +++ b/test/functional/legacy/crash_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local clear = n.clear +local command = n.command +local feed = n.feed before_each(clear) diff --git a/test/functional/legacy/debugger_spec.lua b/test/functional/legacy/debugger_spec.lua index 7ed5e84da6..c6f552ab51 100644 --- a/test/functional/legacy/debugger_spec.lua +++ b/test/functional/legacy/debugger_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local write_file = helpers.write_file + +local clear = n.clear +local command = n.command +local feed = n.feed +local write_file = t.write_file before_each(clear) @@ -12,10 +14,6 @@ describe('debugger', function() before_each(function() screen = Screen.new(999, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { reverse = true, bold = true }, - }) screen:attach() end) @@ -33,7 +31,7 @@ describe('debugger', function() screen:expect { grid = [[ ^let g:Xtest_var += 1{MATCH: *}| - {0:~{MATCH: *}}|*8 + {1:~{MATCH: *}}|*8 :source %{MATCH: *}| ]], } @@ -41,8 +39,8 @@ describe('debugger', function() screen:expect { grid = [[ let g:Xtest_var += 1{MATCH: *}| - {0:~{MATCH: *}}| - {1:{MATCH: *}}| + {1:~{MATCH: *}}| + {3:{MATCH: *}}| Breakpoint in "{MATCH:.*}XdebugBreakExpr.vim" line 1{MATCH: *}| Entering Debug mode. Type "cont" to continue.{MATCH: *}| Oldval = "10"{MATCH: *}| @@ -56,7 +54,7 @@ describe('debugger', function() screen:expect { grid = [[ ^let g:Xtest_var += 1{MATCH: *}| - {0:~{MATCH: *}}|*8 + {1:~{MATCH: *}}|*8 {MATCH: *}| ]], } @@ -64,8 +62,8 @@ describe('debugger', function() screen:expect { grid = [[ let g:Xtest_var += 1{MATCH: *}| - {0:~{MATCH: *}}| - {1:{MATCH: *}}| + {1:~{MATCH: *}}| + {3:{MATCH: *}}| Breakpoint in "{MATCH:.*}XdebugBreakExpr.vim" line 1{MATCH: *}| Entering Debug mode. Type "cont" to continue.{MATCH: *}| Oldval = "11"{MATCH: *}| diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua index 1227065af2..f8e761c7f0 100644 --- a/test/functional/legacy/delete_spec.lua +++ b/test/functional/legacy/delete_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, source = helpers.clear, helpers.source -local eq, eval, command = helpers.eq, helpers.eval, helpers.command -local exc_exec = helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, source = n.clear, n.source +local eq, eval, command = t.eq, n.eval, n.command +local exc_exec = n.exc_exec describe('Test for delete()', function() before_each(clear) @@ -48,7 +50,7 @@ describe('Test for delete()', function() it('symlink directory delete', function() command("call mkdir('Xdir1')") - if helpers.is_os('win') then + if t.is_os('win') then command('silent !mklink /j Xlink Xdir1') else command('silent !ln -s Xdir1 Xlink') diff --git a/test/functional/legacy/digraph_spec.lua b/test/functional/legacy/digraph_spec.lua index 015f144b74..ed1071079c 100644 --- a/test/functional/legacy/digraph_spec.lua +++ b/test/functional/legacy/digraph_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed = helpers.feed + +local clear = n.clear +local feed = n.feed before_each(clear) @@ -9,29 +10,24 @@ describe('digraph', function() -- oldtest: Test_entering_digraph() it('characters displayed on the screen', function() local screen = Screen.new(10, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Blue }, -- SpecialKey - [2] = { bold = true }, -- ModeMsg - }) screen:attach() feed('i<C-K>') screen:expect([[ - {1:^?} | - {0:~ }|*4 - {2:-- INSERT --}| + {18:^?} | + {1:~ }|*4 + {5:-- INSERT --}| ]]) feed('1') screen:expect([[ - {1:^1} | - {0:~ }|*4 - {2:-- INSERT --}| + {18:^1} | + {1:~ }|*4 + {5:-- INSERT --}| ]]) feed('2') screen:expect([[ ½^ | - {0:~ }|*4 - {2:-- INSERT --}| + {1:~ }|*4 + {5:-- INSERT --}| ]]) end) end) diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua index 153fad2e22..98b9596847 100644 --- a/test/functional/legacy/display_spec.lua +++ b/test/functional/legacy/display_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) - +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed -local command = helpers.command + +local clear = n.clear +local exec = n.exec +local feed = n.feed +local command = n.command describe('display', function() before_each(clear) @@ -13,9 +13,6 @@ describe('display', function() it('scroll when modified at topline vim-patch:8.2.1488', function() local screen = Screen.new(20, 4) screen:attach() - screen:set_default_attr_ids({ - [1] = { bold = true }, - }) command([[call setline(1, repeat('a', 21))]]) feed('O') @@ -23,7 +20,7 @@ describe('display', function() ^ | aaaaaaaaaaaaaaaaaaaa| a | - {1:-- INSERT --} | + {5:-- INSERT --} | ]]) end) @@ -31,11 +28,6 @@ describe('display', function() it('scrolling when modified at topline in Visual mode vim-patch:8.2.4626', function() local screen = Screen.new(60, 8) screen:attach() - screen:set_default_attr_ids({ - [1] = { bold = true }, -- ModeMsg - [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [3] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, -- SignColumn - }) exec([[ set scrolloff=0 @@ -47,9 +39,9 @@ describe('display', function() ]]) feed('VG7kk') screen:expect([[ - {3: }^f{2:oo} | - {3: }foo |*6 - {1:-- VISUAL LINE --} | + {7: }^f{17:oo} | + {7: }foo |*6 + {5:-- VISUAL LINE --} | ]]) end) @@ -149,7 +141,7 @@ describe('display', function() ]]) feed('736|') screen:expect([[ - <<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:<<<}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*11 ^aaaaaaaaaaaaaaa | | @@ -157,22 +149,22 @@ describe('display', function() -- The correct part of the last line is moved into view. feed('D') screen:expect([[ - <<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:<<<}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a| - bbbbb bbbbb bbbbb bbbbb bbbbb bb@@@| + bbbbb bbbbb bbbbb bbbbb bbbbb bb{1:@@@}| | ]]) -- "w_skipcol" does not change because the topline is still long enough -- to maintain the current skipcol. feed('g04l11gkD') screen:expect([[ - <<<^a | + {1:<<<}^a | bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb| bbbbb ccccc ccccc ccccc ccccc cccc| c ccccc ccccc ddddd ddddd ddddd ddd| dd ddddd ddddd ddddd | - ~ |*8 + {1:~ }|*8 | ]]) -- "w_skipcol" is reset to bring the entire topline into view because @@ -183,7 +175,7 @@ describe('display', function() aa^a | bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb| bbbbb ccccc ccccc ccccc ccccc cccc| - c ccccc ccccc ddddd ddddd ddddd @@@| + c ccccc ccccc ddddd ddddd ddddd {1:@@@}| | ]]) end) @@ -197,7 +189,7 @@ describe('display', function() norm $j ]]) screen:expect([[ - <<<bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| + {1:<<<}bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*5 b^b | | @@ -207,7 +199,7 @@ describe('display', function() exec('set number cpo+=n scrolloff=0') feed('$0') screen:expect([[ - <<<b^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| + {1:<<<}b^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6 | ]]) @@ -215,14 +207,14 @@ describe('display', function() exec('set smoothscroll') feed('$b') screen:expect([[ - 2 b ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| + {8: 2 }b ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6 | ]]) -- Same for "ge". feed('$ge') screen:expect([[ - 2 ^b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| + {8: 2 }^b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6 | ]]) diff --git a/test/functional/legacy/edit_spec.lua b/test/functional/legacy/edit_spec.lua index 0762e5e671..f3d18a2541 100644 --- a/test/functional/legacy/edit_spec.lua +++ b/test/functional/legacy/edit_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local expect = helpers.expect -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local expect = n.expect +local feed = n.feed local sleep = vim.uv.sleep before_each(clear) @@ -30,22 +31,17 @@ describe('edit', function() -- oldtest: Test_edit_insert_reg() it('inserting a register using CTRL-R', function() local screen = Screen.new(10, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Blue }, -- SpecialKey - [2] = { bold = true }, -- ModeMsg - }) screen:attach() feed('a<C-R>') screen:expect([[ - {1:^"} | - {0:~ }|*4 - {2:-- INSERT --}| + {18:^"} | + {1:~ }|*4 + {5:-- INSERT --}| ]]) feed('=') screen:expect([[ - {1:"} | - {0:~ }|*4 + {18:"} | + {1:~ }|*4 =^ | ]]) end) @@ -53,51 +49,42 @@ describe('edit', function() -- oldtest: Test_edit_ctrl_r_failed() it('positioning cursor after CTRL-R expression failed', function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Blue }, -- SpecialKey - [2] = { foreground = Screen.colors.SlateBlue }, - [3] = { bold = true }, -- ModeMsg - [4] = { reverse = true, bold = true }, -- MsgSeparator - [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - [6] = { foreground = Screen.colors.SeaGreen, bold = true }, -- MoreMsg - }) screen:attach() feed('i<C-R>') screen:expect([[ - {1:^"} | - {0:~ }|*4 - {3:-- INSERT --} | + {18:^"} | + {1:~ }|*4 + {5:-- INSERT --} | ]]) - feed('={}') + feed('=0z') screen:expect([[ - {1:"} | - {0:~ }|*4 - ={2:{}}^ | + {18:"} | + {1:~ }|*4 + ={26:0}{9:z}^ | ]]) - -- trying to insert a dictionary produces an error + -- trying to insert a blob produces an error feed('<CR>') screen:expect([[ - {1:"} | - {0:~ }| - {4: }| - ={2:{}} | - {5:E731: Using a Dictionary as a String} | + {18:"} | + {1:~ }| + {3: }| + ={26:0}{9:z} | + {9:E976: Using a Blob as a String} | {6:Press ENTER or type command to continue}^ | ]]) feed(':') screen:expect([[ :^ | - {0:~ }|*4 - {3:-- INSERT --} | + {1:~ }|*4 + {5:-- INSERT --} | ]]) -- ending Insert mode should put the cursor back on the ':' feed('<Esc>') screen:expect([[ ^: | - {0:~ }|*4 + {1:~ }|*4 | ]]) end) diff --git a/test/functional/legacy/erasebackword_spec.lua b/test/functional/legacy/erasebackword_spec.lua index 46057fe599..3042c52784 100644 --- a/test/functional/legacy/erasebackword_spec.lua +++ b/test/functional/legacy/erasebackword_spec.lua @@ -1,7 +1,8 @@ -- Test for CTRL-W in Insert mode -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, expect = helpers.clear, helpers.feed, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, expect = n.clear, n.feed, n.expect describe('CTRL-W in Insert mode', function() setup(clear) diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua index 21d0ce118d..554af9418d 100644 --- a/test/functional/legacy/eval_spec.lua +++ b/test/functional/legacy/eval_spec.lua @@ -1,13 +1,15 @@ -- Test for various eval features. -local helpers = require('test.functional.helpers')(after_each) -local assert_alive = helpers.assert_alive -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, command, expect = helpers.clear, helpers.command, helpers.expect -local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file -local poke_eventloop = helpers.poke_eventloop -local exc_exec = helpers.exc_exec -local dedent = helpers.dedent +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local feed, insert, source = n.feed, n.insert, n.source +local clear, command, expect = n.clear, n.command, n.expect +local eq, eval, write_file = t.eq, n.eval, t.write_file +local poke_eventloop = n.poke_eventloop +local exc_exec = n.exc_exec +local dedent = t.dedent describe('eval', function() setup(function() diff --git a/test/functional/legacy/ex_mode_spec.lua b/test/functional/legacy/ex_mode_spec.lua index ae4c4309d1..574c3e4069 100644 --- a/test/functional/legacy/ex_mode_spec.lua +++ b/test/functional/legacy/ex_mode_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local api = helpers.api -local poke_eventloop = helpers.poke_eventloop + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local api = n.api +local poke_eventloop = n.poke_eventloop before_each(clear) @@ -45,60 +47,55 @@ describe('Ex mode', function() it('substitute confirmation prompt', function() command('set noincsearch nohlsearch inccommand=') local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, reverse = true }, -- MsgSeparator - [1] = { foreground = Screen.colors.Brown }, -- LineNr - [2] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() command([[call setline(1, ['foo foo', 'foo foo', 'foo foo'])]]) command([[set number]]) feed('gQ') screen:expect([[ - {1: 1 }foo foo | - {1: 2 }foo foo | - {1: 3 }foo foo | - {0: }| + {8: 1 }foo foo | + {8: 2 }foo foo | + {8: 3 }foo foo | + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :^ | ]]) feed('%s/foo/bar/gc<CR>') screen:expect([[ - {1: 1 }foo foo | - {0: }| + {8: 1 }foo foo | + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :%s/foo/bar/gc | - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^^ | ]]) feed('N<CR>') screen:expect([[ Entering Ex mode. Type "visual" to go to Normal mode. | :%s/foo/bar/gc | - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^N | - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^^ | ]]) feed('n<CR>') screen:expect([[ - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^N | - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^n | - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^^ | ]]) feed('y<CR>') feed('q<CR>') screen:expect([[ - {1: 1 }foo foo | + {8: 1 }foo foo | ^^^y | - {1: 2 }foo foo | + {8: 2 }foo foo | ^^^q | - {1: 2 }foo foo | + {8: 2 }foo foo | :^ | ]]) @@ -106,35 +103,31 @@ describe('Ex mode', function() feed('<CR>') screen:expect([[ ^^^y | - {1: 2 }foo foo | + {8: 2 }foo foo | ^^^q | - {1: 2 }foo foo | - {1: 3 }foo foo | + {8: 2 }foo foo | + {8: 3 }foo foo | :^ | ]]) feed(':vi<CR>') screen:expect([[ - {1: 1 }foo bar | - {1: 2 }foo foo | - {1: 3 }^foo foo | - {2:~ }|*2 + {8: 1 }foo bar | + {8: 2 }foo foo | + {8: 3 }^foo foo | + {1:~ }|*2 | ]]) end) it('pressing Ctrl-C in :append inside a loop in Ex mode does not hang', function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, reverse = true }, -- MsgSeparator - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() feed('gQ') feed('for i in range(1)<CR>') feed('append<CR>') screen:expect([[ - {0: }| + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :for i in range(1) | | diff --git a/test/functional/legacy/excmd_spec.lua b/test/functional/legacy/excmd_spec.lua index 41f14c4645..de3d498f27 100644 --- a/test/functional/legacy/excmd_spec.lua +++ b/test/functional/legacy/excmd_spec.lua @@ -1,18 +1,20 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local expect_exit = helpers.expect_exit -local feed = helpers.feed -local fn = helpers.fn -local api = helpers.api -local read_file = helpers.read_file -local source = helpers.source -local eq = helpers.eq -local write_file = helpers.write_file -local is_os = helpers.is_os + +local clear = n.clear +local command = n.command +local exec = n.exec +local exec_lua = n.exec_lua +local expect_exit = n.expect_exit +local feed = n.feed +local fn = n.fn +local api = n.api +local read_file = t.read_file +local source = n.source +local eq = t.eq +local write_file = t.write_file +local is_os = t.is_os local function sizeoflong() if not exec_lua('return pcall(require, "ffi")') then @@ -48,12 +50,6 @@ describe(':confirm command dialog', function() local function start_new() clear() screen = Screen.new(75, 20) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine, MsgSeparator - [2] = { reverse = true }, -- StatusLineNC - [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - }) screen:attach() end @@ -76,17 +72,17 @@ describe(':confirm command dialog', function() feed(':confirm qall\n') screen:expect([[ bar2 | - {0:~ }|*5 + {1:~ }|*5 {2:Xbar [+] }| foo2 | - {0:~ }|*4 + {1:~ }|*4 {2:Xfoo [+] }| | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| :confirm qall | - {3:Save changes to "Xbar"?} | - {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + {6:Save changes to "Xbar"?} | + {6:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | ]]) expect_exit(1000, feed, 'A') @@ -106,17 +102,17 @@ describe(':confirm command dialog', function() feed(':confirm qall\n') screen:expect([[ bar3 | - {0:~ }|*5 + {1:~ }|*5 {2:Xbar [+] }| foo3 | - {0:~ }|*4 + {1:~ }|*4 {2:Xfoo [+] }| | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| :confirm qall | - {3:Save changes to "Xbar"?} | - {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + {6:Save changes to "Xbar"?} | + {6:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | ]]) expect_exit(1000, feed, 'D') @@ -136,33 +132,33 @@ describe(':confirm command dialog', function() feed(':confirm qall\n') screen:expect([[ bar4 | - {0:~ }|*5 + {1:~ }|*5 {2:Xbar [+] }| foo4 | - {0:~ }|*4 + {1:~ }|*4 {2:Xfoo [+] }| | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| :confirm qall | - {3:Save changes to "Xbar"?} | - {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + {6:Save changes to "Xbar"?} | + {6:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | ]]) feed('N') screen:expect([[ bar4 | - {0:~ }|*5 + {1:~ }|*5 {2:Xbar [+] }| foo4 | - {0:~ }|*4 + {1:~ }|*4 {2:Xfoo [+] }| | - {1: }| + {3: }| :confirm qall | - {3:Save changes to "Xbar"?} | + {6:Save changes to "Xbar"?} | | - {3:Save changes to "Xfoo"?} | - {3:[Y]es, (N)o, (C)ancel: }^ | + {6:Save changes to "Xfoo"?} | + {6:[Y]es, (N)o, (C)ancel: }^ | ]]) expect_exit(1000, feed, 'Y') @@ -186,39 +182,39 @@ describe(':confirm command dialog', function() feed(':confirm close\n') screen:expect([[ abc | - {0:~ }|*3 - {1:[No Name] [+] }| + {1:~ }|*3 + {3:[No Name] [+] }| | - {1: }| + {3: }| :confirm close | - {3:Save changes to "Untitled"?} | - {3:[Y]es, (N)o, (C)ancel: }^ | + {6:Save changes to "Untitled"?} | + {6:[Y]es, (N)o, (C)ancel: }^ | ]]) feed('C') screen:expect([[ ^abc | - {0:~ }|*3 - {1:[No Name] [+] }| + {1:~ }|*3 + {3:[No Name] [+] }| | - {0:~ }|*2 + {1:~ }|*2 {2:[No Name] }| | ]]) feed(':confirm close\n') screen:expect([[ abc | - {0:~ }|*3 - {1:[No Name] [+] }| + {1:~ }|*3 + {3:[No Name] [+] }| | - {1: }| + {3: }| :confirm close | - {3:Save changes to "Untitled"?} | - {3:[Y]es, (N)o, (C)ancel: }^ | + {6:Save changes to "Untitled"?} | + {6:[Y]es, (N)o, (C)ancel: }^ | ]]) feed('N') screen:expect([[ ^ | - {0:~ }|*8 + {1:~ }|*8 | ]]) end) @@ -237,16 +233,16 @@ describe(':confirm command dialog', function() feed(':confirm q\n') screen:expect([[ foo | - {0:~ }|*3 - {1: }| + {1:~ }|*3 + {3: }| :confirm q | - {3:Save changes to "Untitled"?} | - {3:[Y]es, (N)o, (C)ancel: }^ | + {6:Save changes to "Untitled"?} | + {6:[Y]es, (N)o, (C)ancel: }^ | ]]) feed('C') screen:expect([[ ^abc | - {0:~ }|*6 + {1:~ }|*6 | ]]) @@ -254,16 +250,16 @@ describe(':confirm command dialog', function() feed(':confirm wq\n') screen:expect([[ foo | - {0:~ }|*3 - {1: }| + {1:~ }|*3 + {3: }| "Xfoo" [noeol] 1L, 3B written | - {3:Save changes to "Untitled"?} | - {3:[Y]es, (N)o, (C)ancel: }^ | + {6:Save changes to "Untitled"?} | + {6:[Y]es, (N)o, (C)ancel: }^ | ]]) feed('C') screen:expect([[ ^abc | - {0:~ }|*6 + {1:~ }|*6 "Xfoo" [noeol] 1L, 3B written | ]]) @@ -286,17 +282,17 @@ describe(':confirm command dialog', function() feed(':set ro | confirm w\n') screen:expect([[ foobar | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| :set ro | confirm w | - {3:'readonly' option is set for "Xconfirm_write_ro".} | - {3:Do you wish to write anyway?} | - {3:(Y)es, [N]o: }^ | + {6:'readonly' option is set for "Xconfirm_write_ro".} | + {6:Do you wish to write anyway?} | + {6:(Y)es, [N]o: }^ | ]]) feed('N') screen:expect([[ fooba^r | - {0:~ }|*5 + {1:~ }|*5 | 1,6 All | ]]) @@ -305,35 +301,35 @@ describe(':confirm command dialog', function() feed(':confirm w\n') screen:expect([[ foobar | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| :confirm w | - {3:'readonly' option is set for "Xconfirm_write_ro".} | - {3:Do you wish to write anyway?} | - {3:(Y)es, [N]o: }^ | + {6:'readonly' option is set for "Xconfirm_write_ro".} | + {6:Do you wish to write anyway?} | + {6:(Y)es, [N]o: }^ | ]]) feed('Y') if is_os('win') then screen:expect([[ foobar | - {0:~ }| - {1: }| + {1:~ }| + {3: }| :confirm w | - {3:'readonly' option is set for "Xconfirm_write_ro".} | - {3:Do you wish to write anyway?} | + {6:'readonly' option is set for "Xconfirm_write_ro".} | + {6:Do you wish to write anyway?} | "Xconfirm_write_ro" [unix] 1L, 7B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) else screen:expect([[ foobar | - {0:~ }| - {1: }| + {1:~ }| + {3: }| :confirm w | - {3:'readonly' option is set for "Xconfirm_write_ro".} | - {3:Do you wish to write anyway?} | + {6:'readonly' option is set for "Xconfirm_write_ro".} | + {6:Do you wish to write anyway?} | "Xconfirm_write_ro" 1L, 7B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) end eq('foobar\n', read_file('Xconfirm_write_ro')) @@ -344,36 +340,36 @@ describe(':confirm command dialog', function() feed(':set noro | silent undo | confirm w\n') screen:expect([[ foobar | - {0:~ }| - {1: }| + {1:~ }| + {3: }| :set noro | silent undo | confirm w | - {3:File permissions of "Xconfirm_write_ro" are read-only.} | - {3:It may still be possible to write it.} | - {3:Do you wish to try?} | - {3:(Y)es, [N]o: }^ | + {6:File permissions of "Xconfirm_write_ro" are read-only.} | + {6:It may still be possible to write it.} | + {6:Do you wish to try?} | + {6:(Y)es, [N]o: }^ | ]]) feed('Y') if is_os('win') then screen:expect([[ foobar | - {1: }| + {3: }| :set noro | silent undo | confirm w | - {3:File permissions of "Xconfirm_write_ro" are read-only.} | - {3:It may still be possible to write it.} | - {3:Do you wish to try?} | + {6:File permissions of "Xconfirm_write_ro" are read-only.} | + {6:It may still be possible to write it.} | + {6:Do you wish to try?} | "Xconfirm_write_ro" [unix] 1L, 4B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) else screen:expect([[ foobar | - {1: }| + {3: }| :set noro | silent undo | confirm w | - {3:File permissions of "Xconfirm_write_ro" are read-only.} | - {3:It may still be possible to write it.} | - {3:Do you wish to try?} | + {6:File permissions of "Xconfirm_write_ro" are read-only.} | + {6:It may still be possible to write it.} | + {6:Do you wish to try?} | "Xconfirm_write_ro" 1L, 4B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) end eq('foo\n', read_file('Xconfirm_write_ro')) @@ -399,10 +395,10 @@ describe(':confirm command dialog', function() b | c | d | - {1: }| + {3: }| :confirm 2,3w | - {3:Write partial file?} | - {3:(Y)es, [N]o: }^ | + {6:Write partial file?} | + {6:(Y)es, [N]o: }^ | ]]) feed('N') screen:expect([[ @@ -410,7 +406,7 @@ describe(':confirm command dialog', function() b | c | d | - {0:~ }|*2 + {1:~ }|*2 | 1,1 All | ]]) @@ -423,10 +419,10 @@ describe(':confirm command dialog', function() b | c | d | - {1: }| + {3: }| :confirm 2,3w | - {3:Write partial file?} | - {3:(Y)es, [N]o: }^ | + {6:Write partial file?} | + {6:(Y)es, [N]o: }^ | ]]) feed('Y') if is_os('win') then @@ -434,22 +430,22 @@ describe(':confirm command dialog', function() a | b | c | - {1: }| + {3: }| :confirm 2,3w | - {3:Write partial file?} | + {6:Write partial file?} | "Xwrite_partial" [New][unix] 2L, 4B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) else screen:expect([[ a | b | c | - {1: }| + {3: }| :confirm 2,3w | - {3:Write partial file?} | + {6:Write partial file?} | "Xwrite_partial" [New] 2L, 4B written | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) end eq('b\nc\n', read_file('Xwrite_partial')) diff --git a/test/functional/legacy/filechanged_spec.lua b/test/functional/legacy/filechanged_spec.lua deleted file mode 100644 index 46ecfdcd63..0000000000 --- a/test/functional/legacy/filechanged_spec.lua +++ /dev/null @@ -1,142 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, source = helpers.clear, helpers.source -local call, eq, api = helpers.call, helpers.eq, helpers.api -local is_os = helpers.is_os -local skip = helpers.skip - -local function expected_empty() - eq({}, api.nvim_get_vvar('errors')) -end - -describe('file changed dialog', function() - before_each(function() - clear() - api.nvim_ui_attach(80, 24, {}) - api.nvim_set_option_value('autoread', false, {}) - api.nvim_set_option_value('fsync', true, {}) - end) - - it('works', function() - skip(is_os('win')) - source([[ - func Test_file_changed_dialog() - au! FileChangedShell - - new Xchanged_d - call setline(1, 'reload this') - write - " Need to wait until the timestamp would change by at least a second. - sleep 2 - silent !echo 'extra line' >>Xchanged_d - call nvim_input('L') - checktime - call assert_match('W11:', v:warningmsg) - call assert_equal(2, line('$')) - call assert_equal('reload this', getline(1)) - call assert_equal('extra line', getline(2)) - - " delete buffer, only shows an error, no prompt - silent !rm Xchanged_d - checktime - call assert_match('E211:', v:warningmsg) - call assert_equal(2, line('$')) - call assert_equal('extra line', getline(2)) - let v:warningmsg = 'empty' - - " change buffer, recreate the file and reload - call setline(1, 'buffer is changed') - silent !echo 'new line' >Xchanged_d - call nvim_input('L') - checktime - call assert_match('W12:', v:warningmsg) - call assert_equal(1, line('$')) - call assert_equal('new line', getline(1)) - - " Only mode changed, reload - silent !chmod +x Xchanged_d - call nvim_input('L') - checktime - call assert_match('W16:', v:warningmsg) - call assert_equal(1, line('$')) - call assert_equal('new line', getline(1)) - - " Only time changed, no prompt - sleep 2 - silent !touch Xchanged_d - let v:warningmsg = '' - checktime Xchanged_d - call assert_equal('', v:warningmsg) - call assert_equal(1, line('$')) - call assert_equal('new line', getline(1)) - - " File created after starting to edit it - call delete('Xchanged_d') - new Xchanged_d - call writefile(['one'], 'Xchanged_d') - call nvim_input('L') - checktime Xchanged_d - call assert_equal(['one'], getline(1, '$')) - close! - - bwipe! - call delete('Xchanged_d') - endfunc - ]]) - call('Test_file_changed_dialog') - expected_empty() - end) - - it('works with FileChangedShell', function() - source([[ - func Test_FileChangedShell_edit_dialog() - new Xchanged_r - call setline(1, 'reload this') - set fileformat=unix - silent write " Use :silent to prevent a hit-enter prompt - - " File format changed, reload (content only) via prompt - augroup testreload - au! - au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask' - augroup END - call assert_equal(&fileformat, 'unix') - sleep 10m " make the test less flaky in Nvim - call writefile(["line1\r", "line2\r"], 'Xchanged_r') - let g:reason = '' - call nvim_input('L') " load file content only - checktime - call assert_equal('changed', g:reason) - call assert_equal(&fileformat, 'unix') - call assert_equal("line1\r", getline(1)) - call assert_equal("line2\r", getline(2)) - %s/\r - silent write " Use :silent to prevent a hit-enter prompt - - " File format changed, reload (file and options) via prompt - augroup testreload - au! - au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask' - augroup END - call assert_equal(&fileformat, 'unix') - sleep 10m " make the test less flaky in Nvim - call writefile(["line1\r", "line2\r"], 'Xchanged_r') - let g:reason = '' - call nvim_input('a') " load file content and options - checktime - call assert_equal('changed', g:reason) - call assert_equal(&fileformat, 'dos') - call assert_equal("line1", getline(1)) - call assert_equal("line2", getline(2)) - set fileformat=unix - silent write " Use :silent to prevent a hit-enter prompt - - au! testreload - bwipe! - call delete(undofile('Xchanged_r')) - call delete('Xchanged_r') - endfunc - ]]) - call('Test_FileChangedShell_edit_dialog') - expected_empty() - end) -end) diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua index 01b87ac9a0..21f0b9f001 100644 --- a/test/functional/legacy/fixeol_spec.lua +++ b/test/functional/legacy/fixeol_spec.lua @@ -1,8 +1,9 @@ -- Tests for 'fixeol' -local helpers = require('test.functional.helpers')(after_each) -local feed = helpers.feed -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed = n.feed +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('fixeol', function() local function rmtestfiles() diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua index 570b523d92..ce8c710a46 100644 --- a/test/functional/legacy/fnamemodify_spec.lua +++ b/test/functional/legacy/fnamemodify_spec.lua @@ -1,11 +1,13 @@ -- Test filename modifiers. -local helpers = require('test.functional.helpers')(after_each) -local clear, source = helpers.clear, helpers.source -local call, eq, nvim = helpers.call, helpers.eq, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, source = n.clear, n.source +local call, eq, api = n.call, t.eq, n.api local function expected_empty() - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end describe('filename modifiers', function() diff --git a/test/functional/legacy/fold_spec.lua b/test/functional/legacy/fold_spec.lua index c39aae87d2..4fea1ef113 100644 --- a/test/functional/legacy/fold_spec.lua +++ b/test/functional/legacy/fold_spec.lua @@ -1,25 +1,19 @@ -- Tests for folding. + +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local feed, insert, feed_command, expect_any = - helpers.feed, helpers.insert, helpers.feed_command, helpers.expect_any -local command = helpers.command -local exec = helpers.exec +local feed, insert, feed_command, expect_any = n.feed, n.insert, n.feed_command, n.expect_any +local command = n.command +local exec = n.exec describe('folding', function() local screen before_each(function() - helpers.clear() + n.clear() screen = Screen.new(45, 8) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey }, -- Folded - [3] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey }, -- FoldColumn - [4] = { foreground = Screen.colors.Brown }, -- LineNr - }) screen:attach() end) @@ -67,7 +61,7 @@ describe('folding', function() feed('kYpj') feed_command('call append("$", foldlevel("."))') - helpers.poke_eventloop() + n.poke_eventloop() screen:expect([[ dd {{{ | ee {{{ }}} | @@ -93,7 +87,7 @@ describe('folding', function() feed_command('call append("$", foldlevel(2))') feed('zR') - helpers.poke_eventloop() + n.poke_eventloop() screen:expect([[ aa | bb | @@ -222,15 +216,15 @@ describe('folding', function() command('call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])') screen:expect([[ - {3:+ }{4: 0 }{2:^+-- 2 lines: ·························}| - {3:+ }{4: 1 }{2:+-- 2 lines: ·························}| + {7:+ }{8: 0 }{13:^+-- 2 lines: ·························}| + {7:+ }{8: 1 }{13:+-- 2 lines: ·························}| {1:~ }|*5 | ]]) feed('j') screen:expect([[ - {3:+ }{4: 1 }{2:+-- 2 lines: ·························}| - {3:+ }{4: 0 }{2:^+-- 2 lines: ·························}| + {7:+ }{8: 1 }{13:+-- 2 lines: ·························}| + {7:+ }{8: 0 }{13:^+-- 2 lines: ·························}| {1:~ }|*5 | ]]) @@ -246,7 +240,7 @@ describe('folding', function() screen:expect([[ ^one | - {2:+-- 2 lines: two····························}| + {13:+-- 2 lines: two····························}| four | {1:~ }|*4 | @@ -263,7 +257,7 @@ describe('folding', function() feed('4G') screen:expect([[ one | - {2:+-- 2 lines: two····························}| + {13:+-- 2 lines: two····························}| ^four | {1:~ }|*4 | @@ -280,7 +274,7 @@ describe('folding', function() feed('1G') screen:expect([[ ^one | - {2:+-- 2 lines: two····························}| + {13:+-- 2 lines: two····························}| four | {1:~ }|*4 | @@ -297,7 +291,7 @@ describe('folding', function() feed('k') screen:expect([[ ^one | - {2:+-- 2 lines: two····························}| + {13:+-- 2 lines: two····························}| four | {1:~ }|*4 | diff --git a/test/functional/legacy/function_sort_spec.lua b/test/functional/legacy/function_sort_spec.lua index 36128bb0a2..b55c5437ef 100644 --- a/test/functional/legacy/function_sort_spec.lua +++ b/test/functional/legacy/function_sort_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local neq = helpers.neq -local eval = helpers.eval -local clear = helpers.clear -local source = helpers.source -local exc_exec = helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local neq = t.neq +local eval = n.eval +local clear = n.clear +local source = n.source +local exc_exec = n.exc_exec describe('sort', function() before_each(clear) diff --git a/test/functional/legacy/getcwd_spec.lua b/test/functional/legacy/getcwd_spec.lua index eae13da528..c95a010c5a 100644 --- a/test/functional/legacy/getcwd_spec.lua +++ b/test/functional/legacy/getcwd_spec.lua @@ -1,14 +1,16 @@ -- Tests for getcwd(), haslocaldir(), and :lcd -local helpers = require('test.functional.helpers')(after_each) -local eq, eval, source = helpers.eq, helpers.eval, helpers.source -local call, clear, command = helpers.call, helpers.clear, helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, eval, source = t.eq, n.eval, n.source +local call, clear, command = n.call, n.clear, n.command describe('getcwd', function() before_each(clear) after_each(function() - helpers.rmdir('Xtopdir') + n.rmdir('Xtopdir') end) it('is working', function() diff --git a/test/functional/legacy/gf_spec.lua b/test/functional/legacy/gf_spec.lua index b51f671bee..4c98edf8e0 100644 --- a/test/functional/legacy/gf_spec.lua +++ b/test/functional/legacy/gf_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local pcall_err = t.pcall_err describe('gf', function() before_each(clear) diff --git a/test/functional/legacy/glob2regpat_spec.lua b/test/functional/legacy/glob2regpat_spec.lua index de304f3e4b..6d08a77386 100644 --- a/test/functional/legacy/glob2regpat_spec.lua +++ b/test/functional/legacy/glob2regpat_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq, eval = helpers.eq, helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq, eval = t.eq, n.eval describe('glob2regpat()', function() before_each(clear) diff --git a/test/functional/legacy/global_spec.lua b/test/functional/legacy/global_spec.lua index 2c92b7814a..718fd421b0 100644 --- a/test/functional/legacy/global_spec.lua +++ b/test/functional/legacy/global_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed -local poke_eventloop = helpers.poke_eventloop + +local clear = n.clear +local exec = n.exec +local feed = n.feed +local poke_eventloop = n.poke_eventloop before_each(clear) @@ -11,10 +12,6 @@ describe(':global', function() -- oldtest: Test_interrupt_global() it('can be interrupted using Ctrl-C in cmdline mode vim-patch:9.0.0082', function() local screen = Screen.new(75, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, reverse = true }, -- MsgSeparator - [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() exec([[ @@ -29,7 +26,7 @@ describe(':global', function() screen:expect([[ ^foo | foo |*4 - {1:Interrupted} | + {9:Interrupted} | ]]) -- Also test in Ex mode @@ -37,11 +34,11 @@ describe(':global', function() poke_eventloop() -- Wait for :sleep to start feed('<C-C>') screen:expect([[ - {0: }| + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :g/foo/norm :; | | - {1:Interrupted} | + {9:Interrupted} | :^ | ]]) end) diff --git a/test/functional/legacy/highlight_spec.lua b/test/functional/legacy/highlight_spec.lua index 3d06bf3978..35afd9bb4a 100644 --- a/test/functional/legacy/highlight_spec.lua +++ b/test/functional/legacy/highlight_spec.lua @@ -1,12 +1,14 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local clear, feed = helpers.clear, helpers.feed -local expect = helpers.expect -local eq = helpers.eq -local poke_eventloop = helpers.poke_eventloop -local exc_exec = helpers.exc_exec -local feed_command = helpers.feed_command -local exec = helpers.exec + +local clear, feed = n.clear, n.feed +local expect = n.expect +local eq = t.eq +local poke_eventloop = n.poke_eventloop +local exc_exec = n.exc_exec +local feed_command = n.feed_command +local exec = n.exec before_each(clear) @@ -22,15 +24,15 @@ describe(':highlight', function() -- is discarded resulting in test failure screen:expect([[ :highlight | - SpecialKey xxx ctermfg=4 | - guifg=Blue | - EndOfBuffer xxx links to NonText| + SpecialKey {18:xxx} {18:ctermfg=}4 | + {18:guifg=}Blue | + EndOfBuffer {1:xxx} {18:links to} NonText| | - TermCursor xxx cterm=reverse | - gui=reverse | + TermCursor {2:xxx} {18:cterm=}reverse | + {18:gui=}reverse | TermCursorNC xxx cleared | - NonText xxx ctermfg=12 | - -- More --^ | + NonText {1:xxx} {18:ctermfg=}12 | + {6:-- More --}^ | ]]) feed('q') poke_eventloop() -- wait until we're back to normal @@ -99,11 +101,6 @@ describe('Visual selection highlight', function() -- oldtest: Test_visual_sbr() it("when 'showbreak' is set", function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { bold = true }, -- ModeMsg - }) screen:attach() exec([[ set showbreak=> @@ -112,9 +109,9 @@ describe('Visual selection highlight', function() ]]) feed('v$') screen:expect([[ - {0:>}{1:n, no sea takimata sanctus est Lorem ipsum dolor sit amet.}^ | + {1:>}{17:n, no sea takimata sanctus est Lorem ipsum dolor sit amet.}^ | |*4 - {2:-- VISUAL --} | + {5:-- VISUAL --} | ]]) end) end) diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua index a81044114c..c9c2324c42 100644 --- a/test/functional/legacy/increment_spec.lua +++ b/test/functional/legacy/increment_spec.lua @@ -1,9 +1,11 @@ -- Tests for using Ctrl-A/Ctrl-X on visual selections -local helpers = require('test.functional.helpers')(after_each) -local source, command = helpers.source, helpers.command -local call, clear = helpers.call, helpers.clear -local eq, nvim = helpers.eq, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local source, command = n.source, n.command +local call, clear = n.call, n.clear +local eq, api = t.eq, n.api describe('Ctrl-A/Ctrl-X on visual selections', function() before_each(function() @@ -743,18 +745,18 @@ describe('Ctrl-A/Ctrl-X on visual selections', function() it('works on Test ' .. id, function() command('set nrformats&vi') -- &vi makes Vim compatible call('Test_visual_increment_' .. id) - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end) end it('does not drop leading zeroes', function() command('set nrformats&vi') -- &vi makes Vim compatible call('Test_normal_increment_01') - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end) it('maintains correct column after CTRL-A', function() call('Test_normal_increment_02') - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end) end) diff --git a/test/functional/legacy/insertcount_spec.lua b/test/functional/legacy/insertcount_spec.lua index e53c9dc6ce..53402c2163 100644 --- a/test/functional/legacy/insertcount_spec.lua +++ b/test/functional/legacy/insertcount_spec.lua @@ -1,8 +1,9 @@ -- Tests for repeating insert and replace. -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect = helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect = n.feed_command, n.expect describe('insertcount', function() setup(clear) diff --git a/test/functional/legacy/join_spec.lua b/test/functional/legacy/join_spec.lua index d683d25eb0..397a714b2f 100644 --- a/test/functional/legacy/join_spec.lua +++ b/test/functional/legacy/join_spec.lua @@ -1,8 +1,10 @@ -- Test for joining lines -local helpers = require('test.functional.helpers')(after_each) -local clear, eq = helpers.clear, helpers.eq -local eval, command = helpers.eval, helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq = n.clear, t.eq +local eval, command = n.eval, n.command describe('joining lines', function() before_each(clear) diff --git a/test/functional/legacy/lispwords_spec.lua b/test/functional/legacy/lispwords_spec.lua index efac8775d3..b0130320ed 100644 --- a/test/functional/legacy/lispwords_spec.lua +++ b/test/functional/legacy/lispwords_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local command = helpers.command -local source = helpers.source +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local command = n.command +local source = n.source describe('lispwords', function() before_each(clear) diff --git a/test/functional/legacy/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua index 746e0550a6..db9ec7fc9d 100644 --- a/test/functional/legacy/listchars_spec.lua +++ b/test/functional/legacy/listchars_spec.lua @@ -1,9 +1,10 @@ -- Tests for 'listchars' display with 'list' and :list. -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed, insert, exec = helpers.feed, helpers.insert, helpers.exec -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect + +local feed, insert, exec = n.feed, n.insert, n.exec +local clear, feed_command, expect = n.clear, n.feed_command, n.expect -- luacheck: ignore 621 (Indentation) describe("'listchars'", function() @@ -102,12 +103,6 @@ describe("'listchars'", function() it('"exceeds" character does not appear in foldcolumn vim-patch:8.2.3121', function() local screen = Screen.new(60, 10) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { bold = true, reverse = true }, -- StatusLine - [3] = { reverse = true }, -- StatusLineNC - [4] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, -- FoldColumn, SignColumn - }) screen:attach() exec([[ call setline(1, ['aaa', '', 'a', 'aaaaaa']) @@ -117,83 +112,83 @@ describe("'listchars'", function() ]]) feed('13<C-W>>') screen:expect([[ - {4: }aaa │{4: }a{1:>}│{4: }^aaa | - {4: } │{4: } │{4: } | - {4: }a │{4: }a │{4: }a | - {4: }aaaaaa │{4: }a{1:>}│{4: }aaaaaa | + {7: }aaa │{7: }a{1:>}│{7: }^aaa | + {7: } │{7: } │{7: } | + {7: }a │{7: }a │{7: }a | + {7: }aaaaaa │{7: }a{1:>}│{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] <[+] }{2:[No Name] [+] }| + {2:[No Name] [+] <[+] }{3:[No Name] [+] }| | ]]) feed('<C-W>>') screen:expect([[ - {4: }aaa │{4: }{1:>}│{4: }^aaa | - {4: } │{4: } │{4: } | - {4: }a │{4: }a│{4: }a | - {4: }aaaaaa │{4: }{1:>}│{4: }aaaaaa | + {7: }aaa │{7: }{1:>}│{7: }^aaa | + {7: } │{7: } │{7: } | + {7: }a │{7: }a│{7: }a | + {7: }aaaaaa │{7: }{1:>}│{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] <+] }{2:[No Name] [+] }| + {2:[No Name] [+] <+] }{3:[No Name] [+] }| | ]]) feed('<C-W>>') screen:expect([[ - {4: }aaa │{4: }│{4: }^aaa | - {4: } │{4: }│{4: } | - {4: }a │{4: }│{4: }a | - {4: }aaaaaa │{4: }│{4: }aaaaaa | + {7: }aaa │{7: }│{7: }^aaa | + {7: } │{7: }│{7: } | + {7: }a │{7: }│{7: }a | + {7: }aaaaaa │{7: }│{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] <] }{2:[No Name] [+] }| + {2:[No Name] [+] <] }{3:[No Name] [+] }| | ]]) feed('<C-W>>') screen:expect([[ - {4: }aaa │{4: }│{4: }^aaa | - {4: } │{4: }│{4: } | - {4: }a │{4: }│{4: }a | - {4: }aaaaaa │{4: }│{4: }aaaaaa | + {7: }aaa │{7: }│{7: }^aaa | + {7: } │{7: }│{7: } | + {7: }a │{7: }│{7: }a | + {7: }aaaaaa │{7: }│{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] < }{2:[No Name] [+] }| + {2:[No Name] [+] < }{3:[No Name] [+] }| | ]]) feed('<C-W>>') screen:expect([[ - {4: }aaa │{4: }│{4: }^aaa | - {4: } │{4: }│{4: } | - {4: }a │{4: }│{4: }a | - {4: }aaaaaa │{4: }│{4: }aaaaaa | + {7: }aaa │{7: }│{7: }^aaa | + {7: } │{7: }│{7: } | + {7: }a │{7: }│{7: }a | + {7: }aaaaaa │{7: }│{7: }aaaaaa | {1:~ }│{1:~}│{1:~ }|*4 - {3:[No Name] [+] < }{2:[No Name] [+] }| + {2:[No Name] [+] < }{3:[No Name] [+] }| | ]]) feed('<C-W>h') feed_command('set nowrap foldcolumn=4') screen:expect([[ - {4: }aaa │{4: }^aaa │{4: }aaa | - {4: } │{4: } │{4: } | - {4: }a │{4: }a │{4: }a | - {4: }aaaaaa │{4: }aaaaaa │{4: }aaaaaa | + {7: }aaa │{7: }^aaa │{7: }aaa | + {7: } │{7: } │{7: } | + {7: }a │{7: }a │{7: }a | + {7: }aaaaaa │{7: }aaaaaa │{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] }{2:[No Name] [+] }{3:[No Name] [+] }| + {2:[No Name] [+] }{3:[No Name] [+] }{2:[No Name] [+] }| :set nowrap foldcolumn=4 | ]]) feed('15<C-W><lt>') screen:expect([[ - {4: }aaa │{4: }│{4: }aaa | - {4: } │{4: }│{4: } | - {4: }a │{4: }│{4: }a | - {4: }aaaaaa │{4: ^ }│{4: }aaaaaa | + {7: }aaa │{7: }│{7: }aaa | + {7: } │{7: }│{7: } | + {7: }a │{7: }│{7: }a | + {7: }aaaaaa │{7: ^ }│{7: }aaaaaa | {1:~ }│{1:~ }│{1:~ }|*4 - {3:[No Name] [+] }{2:<[+] }{3:[No Name] [+] }| + {2:[No Name] [+] }{3:<[+] }{2:[No Name] [+] }| :set nowrap foldcolumn=4 | ]]) feed('4<C-W><lt>') screen:expect([[ - {4: }aaa │{4: }│{4: }aaa | - {4: } │{4: }│{4: } | - {4: }a │{4: }│{4: }a | - {4: }aaaaaa │{4:^ }│{4: }aaaaaa | + {7: }aaa │{7: }│{7: }aaa | + {7: } │{7: }│{7: } | + {7: }a │{7: }│{7: }a | + {7: }aaaaaa │{7:^ }│{7: }aaaaaa | {1:~ }│{1:~}│{1:~ }|*4 - {3:[No Name] [+] }{2:< }{3:[No Name] [+] }| + {2:[No Name] [+] }{3:< }{2:[No Name] [+] }| :set nowrap foldcolumn=4 | ]]) end) diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua index 50628e5ef9..da641c3b6f 100644 --- a/test/functional/legacy/listlbr_spec.lua +++ b/test/functional/legacy/listlbr_spec.lua @@ -1,9 +1,10 @@ -- Test for linebreak and list option (non-utf8) -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect + +local feed, insert, source = n.feed, n.insert, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('listlbr', function() before_each(clear) @@ -204,11 +205,6 @@ describe('listlbr', function() -- oldtest: Test_linebreak_reset_restore() it('cursor position is drawn correctly after operator', function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() -- f_wincol() calls validate_cursor() @@ -220,61 +216,61 @@ describe('listlbr', function() feed('$v$') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - bbbbbbbbbb {1:c}^ | - {0:~ }|*3 + bbbbbbbbbb {17:c}^ | + {1:~ }|*3 2 | ]]) feed('zo') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbb ^c | - {0:~ }|*3 - {2:E490: No fold found} | + {1:~ }|*3 + {9:E490: No fold found} | ]]) feed('$v$') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - bbbbbbbbbb {1:c}^ | - {0:~ }|*3 - {2:E490: No fold found} 2 | + bbbbbbbbbb {17:c}^ | + {1:~ }|*3 + {9:E490: No fold found} 2 | ]]) feed('gq') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbb ^c | - {0:~ }|*3 - {2:E490: No fold found} | + {1:~ }|*3 + {9:E490: No fold found} | ]]) feed('$<C-V>$') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - bbbbbbbbbb {1:c}^ | - {0:~ }|*3 - {2:E490: No fold found} 1x2 | + bbbbbbbbbb {17:c}^ | + {1:~ }|*3 + {9:E490: No fold found} 1x2 | ]]) feed('I') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbb ^c | - {0:~ }|*3 - {2:E490: No fold found} | + {1:~ }|*3 + {9:E490: No fold found} | ]]) feed('<Esc>$v$') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - bbbbbbbbbb {1:c}^ | - {0:~ }|*3 - {2:E490: No fold found} 2 | + bbbbbbbbbb {17:c}^ | + {1:~ }|*3 + {9:E490: No fold found} 2 | ]]) feed('s') screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbb ^ | - {0:~ }|*3 - {2:E490: No fold found} | + {1:~ }|*3 + {9:E490: No fold found} | ]]) end) end) diff --git a/test/functional/legacy/listlbr_utf8_spec.lua b/test/functional/legacy/listlbr_utf8_spec.lua index 8e5d9b88bc..74cc594cc1 100644 --- a/test/functional/legacy/listlbr_utf8_spec.lua +++ b/test/functional/legacy/listlbr_utf8_spec.lua @@ -1,11 +1,12 @@ -- Test for linebreak and list option in utf-8 mode -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local source = helpers.source -local feed = helpers.feed -local exec = helpers.exec -local clear, expect = helpers.clear, helpers.expect + +local source = n.source +local feed = n.feed +local exec = n.exec +local clear, expect = n.clear, n.expect describe('linebreak', function() before_each(clear) @@ -214,11 +215,6 @@ describe('linebreak', function() -- oldtest: Test_visual_ends_before_showbreak() it("Visual area is correct when it ends before multibyte 'showbreak'", function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { bold = true }, -- ModeMsg - }) screen:attach() exec([[ let &wrap = v:true @@ -229,10 +225,10 @@ describe('linebreak', function() ]]) screen:expect([[ xxxxx | - {0:↪ }{1:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy}^ {1: }| - {0:↪ }zzzz | - {0:~ }|*4 - {2:-- VISUAL --} | + {1:↪ }{17:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy}^ {17: }| + {1:↪ }zzzz | + {1:~ }|*4 + {5:-- VISUAL --} | ]]) end) end) diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua index 9eddec40f7..3fc324f66a 100644 --- a/test/functional/legacy/mapping_spec.lua +++ b/test/functional/legacy/mapping_spec.lua @@ -1,9 +1,13 @@ -- Test for mappings and abbreviations -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local expect, poke_eventloop = helpers.expect, helpers.poke_eventloop -local command, eq, eval, api = helpers.command, helpers.eq, helpers.eval, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') + +local clear, feed, insert = n.clear, n.feed, n.insert +local expect, poke_eventloop = n.expect, n.poke_eventloop +local command, eq, eval, api = n.command, t.eq, n.eval, n.api +local exec = n.exec local sleep = vim.uv.sleep describe('mapping', function() @@ -23,6 +27,7 @@ describe('mapping', function() vim ]]) end) + -- oldtest: Test_map_ctrl_c_insert() it('Ctrl-c works in Insert mode', function() -- Mapping of ctrl-c in insert mode command('set cpo-=< cpo-=k') @@ -41,6 +46,7 @@ describe('mapping', function() ]]) end) + -- oldtest: Test_map_ctrl_c_visual() it('Ctrl-c works in Visual mode', function() command([[vnoremap <c-c> :<C-u>$put ='vmap works'<cr>]]) feed('GV') @@ -83,6 +89,7 @@ describe('mapping', function() +]]) end) + -- oldtest: Test_map_feedkeys() it('feedkeys', function() insert([[ a b c d @@ -100,6 +107,7 @@ describe('mapping', function() ]]) end) + -- oldtest: Test_map_cursor() it('i_CTRL-G_U', function() -- <c-g>U<cursor> works only within a single line command('imapclear') @@ -128,7 +136,8 @@ describe('mapping', function() ]]) end) - it('dragging starts Select mode even if coming from mapping vim-patch:8.2.4806', function() + -- oldtest: Test_mouse_drag_mapped_start_select() + it('dragging starts Select mode even if coming from mapping', function() command('set mouse=a') command('set selectmode=mouse') @@ -141,7 +150,8 @@ describe('mapping', function() eq('s', eval('mode()')) end) - it('<LeftDrag> mapping in Insert mode works correctly vim-patch:8.2.4692', function() + -- oldtest: Test_mouse_drag_insert_map() + it('<LeftDrag> mapping in Insert mode works correctly', function() command('set mouse=a') command('inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>') @@ -165,7 +175,8 @@ describe('mapping', function() eq('n', eval('mode()')) end) - it('timeout works after an <Nop> mapping is triggered on timeout vim-patch:8.1.0052', function() + -- oldtest: Test_map_after_timed_out_nop() + it('timeout works after an <Nop> mapping is triggered on timeout', function() command('set timeout timeoutlen=400') command('inoremap ab TEST') command('inoremap a <Nop>') @@ -181,4 +192,62 @@ describe('mapping', function() feed('b') expect('TEST') end) + + -- oldtest: Test_showcmd_part_map() + it("'showcmd' with a partial mapping", function() + local screen = Screen.new(60, 6) + screen:attach() + exec([[ + set notimeout showcmd + nnoremap ,a <Ignore> + nnoremap ;a <Ignore> + nnoremap Àa <Ignore> + nnoremap Ëa <Ignore> + nnoremap βa <Ignore> + nnoremap ωa <Ignore> + nnoremap …a <Ignore> + nnoremap <C-W>a <Ignore> + ]]) + + for _, c in ipairs({ ',', ';', 'À', 'Ë', 'β', 'ω', '…' }) do + feed(c) + screen:expect(([[ + ^ | + {1:~ }|*4 + %s | + ]]):format(c)) + feed('a') + screen:expect([[ + ^ | + {1:~ }|*4 + | + ]]) + end + + feed('\23') + screen:expect([[ + ^ | + {1:~ }|*4 + ^W | + ]]) + feed('a') + screen:expect([[ + ^ | + {1:~ }|*4 + | + ]]) + + feed('<C-W>') + screen:expect([[ + ^ | + {1:~ }|*4 + ^W | + ]]) + feed('a') + screen:expect([[ + ^ | + {1:~ }|*4 + | + ]]) + end) end) diff --git a/test/functional/legacy/marks_spec.lua b/test/functional/legacy/marks_spec.lua index 470ea49652..fd968eb355 100644 --- a/test/functional/legacy/marks_spec.lua +++ b/test/functional/legacy/marks_spec.lua @@ -1,6 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect +local n = require('test.functional.testnvim')() + +local feed, insert, source = n.feed, n.insert, n.source +local clear, feed_command, expect = n.clear, n.feed_command, n.expect describe('marks', function() before_each(function() diff --git a/test/functional/legacy/match_spec.lua b/test/functional/legacy/match_spec.lua index ab791f03e5..0fc8708244 100644 --- a/test/functional/legacy/match_spec.lua +++ b/test/functional/legacy/match_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local exec = n.exec +local feed = n.feed before_each(clear) @@ -10,28 +11,24 @@ describe('matchaddpos()', function() -- oldtest: Test_matchaddpos_dump() it('can add more than 8 match positions vim-patch:9.0.0620', function() local screen = Screen.new(60, 14) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Yellow }, -- Search - }) screen:attach() exec([[ call setline(1, ['1234567890123']->repeat(14)) call matchaddpos('Search', range(1, 12)->map({i, v -> [v, v]})) ]]) screen:expect([[ - {1:^1}234567890123 | - 1{1:2}34567890123 | - 12{1:3}4567890123 | - 123{1:4}567890123 | - 1234{1:5}67890123 | - 12345{1:6}7890123 | - 123456{1:7}890123 | - 1234567{1:8}90123 | - 12345678{1:9}0123 | - 123456789{1:0}123 | - 1234567890{1:1}23 | - 12345678901{1:2}3 | + {10:^1}234567890123 | + 1{10:2}34567890123 | + 12{10:3}4567890123 | + 123{10:4}567890123 | + 1234{10:5}67890123 | + 12345{10:6}7890123 | + 123456{10:7}890123 | + 1234567{10:8}90123 | + 12345678{10:9}0123 | + 123456789{10:0}123 | + 1234567890{10:1}23 | + 12345678901{10:2}3 | 1234567890123 | | ]]) @@ -42,10 +39,6 @@ describe('match highlighting', function() -- oldtest: Test_match_in_linebreak() it('does not continue in linebreak vim-patch:8.2.3698', function() local screen = Screen.new(75, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() exec([=[ set breakindent linebreak breakat+=] @@ -53,20 +46,15 @@ describe('match highlighting', function() call matchaddpos('ErrorMsg', [[1, 51]]) ]=]) screen:expect([[ - ^xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{1:]} | + ^xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{9:]} | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | - {0:~ }|*7 + {1:~ }|*7 | ]]) end) it('is shown with incsearch vim-patch:8.2.3940', function() local screen = Screen.new(75, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Yellow }, -- Search - [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() exec([[ set incsearch @@ -76,16 +64,16 @@ describe('match highlighting', function() screen:expect([[ ^0 | 1 | - {2:2} | + {9:2} | 3 | 4 | | ]]) feed(':s/0') screen:expect([[ - {1:0} | + {10:0} | 1 | - {2:2} | + {9:2} | 3 | 4 | :s/0^ | @@ -94,10 +82,6 @@ describe('match highlighting', function() it('on a Tab vim-patch:8.2.4062', function() local screen = Screen.new(75, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() exec([[ set linebreak @@ -105,8 +89,8 @@ describe('match highlighting', function() call matchadd('ErrorMsg', '\t') ]]) screen:expect([[ - {1: ^ }ix | - {0:~ }|*8 + {9: ^ }ix | + {1:~ }|*8 | ]]) end) diff --git a/test/functional/legacy/matchparen_spec.lua b/test/functional/legacy/matchparen_spec.lua index b03107deb0..3841761515 100644 --- a/test/functional/legacy/matchparen_spec.lua +++ b/test/functional/legacy/matchparen_spec.lua @@ -1,9 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) - +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local exec = n.exec +local feed = n.feed describe('matchparen', function() before_each(clear) @@ -12,11 +12,6 @@ describe('matchparen', function() it('redraws properly after scrolling with scrolloff=1', function() local screen = Screen.new(30, 7) screen:attach() - screen:set_default_attr_ids({ - [1] = { bold = true }, - [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, - }) - exec([[ source $VIMRUNTIME/plugin/matchparen.vim set scrolloff=1 @@ -26,13 +21,13 @@ describe('matchparen', function() feed('V<c-d><c-d>') screen:expect([[ - {2:{} | - {2:}} | - {2:{} | - {2:f} | + {17:{} | + {17:}} | + {17:{} | + {17:f} | ^g | } | - {1:-- VISUAL LINE --} | + {5:-- VISUAL LINE --} | ]]) end) @@ -61,13 +56,15 @@ describe('matchparen', function() set hidden call setline(1, ['()']) normal 0 + + func OtherBuffer() + enew + exe "normal iaa\<Esc>0" + endfunc ]]) screen:expect(screen1) - exec([[ - enew - exe "normal iaa\<Esc>0" - ]]) + exec('call OtherBuffer()') screen:expect(screen2) feed('<C-^>') @@ -77,17 +74,43 @@ describe('matchparen', function() screen:expect(screen2) end) + -- oldtest: Test_matchparen_win_execute() + it('matchparen highlight when switching buffer in win_execute()', function() + local screen = Screen.new(20, 5) + screen:set_default_attr_ids({ + [1] = { background = Screen.colors.Cyan }, + [2] = { reverse = true, bold = true }, + [3] = { reverse = true }, + }) + screen:attach() + + exec([[ + source $VIMRUNTIME/plugin/matchparen.vim + let s:win = win_getid() + call setline(1, '{}') + split + + func SwitchBuf() + call win_execute(s:win, 'enew | buffer #') + endfunc + ]]) + screen:expect([[ + {1:^{}} | + {2:[No Name] [+] }| + {} | + {3:[No Name] [+] }| + | + ]]) + + -- Switching buffer away and back shouldn't change matchparen highlight. + exec('call SwitchBuf()') + screen:expect_unchanged() + end) + -- oldtest: Test_matchparen_pum_clear() it('is cleared when completion popup is shown', function() local screen = Screen.new(30, 9) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Plum1 }, - [2] = { background = Screen.colors.Grey }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen }, - }) exec([[ source $VIMRUNTIME/plugin/matchparen.vim @@ -103,11 +126,11 @@ describe('matchparen', function() aaa | aaaa | (aaa^) | - {1: aa }{0: }| - {2: aaa }{0: }| - {1: aaaa }{0: }| - {0:~ }| - {3:-- }{4:match 2 of 3} | + {4: aa }{1: }| + {12: aaa }{1: }| + {4: aaaa }{1: }| + {1:~ }| + {5:-- }{6:match 2 of 3} | ]], } end) diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua index a05e9fdf57..87890d4c25 100644 --- a/test/functional/legacy/memory_usage_spec.lua +++ b/test/functional/legacy/memory_usage_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eval = helpers.eval -local eq = helpers.eq -local feed_command = helpers.feed_command -local retry = helpers.retry -local ok = helpers.ok -local source = helpers.source -local poke_eventloop = helpers.poke_eventloop -local load_adjust = helpers.load_adjust -local write_file = helpers.write_file -local is_os = helpers.is_os -local is_ci = helpers.is_ci -local is_asan = helpers.is_asan +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eval = n.eval +local eq = t.eq +local feed_command = n.feed_command +local retry = t.retry +local ok = t.ok +local source = n.source +local poke_eventloop = n.poke_eventloop +local load_adjust = n.load_adjust +local write_file = t.write_file +local is_os = t.is_os +local is_ci = t.is_ci +local is_asan = n.is_asan clear() if is_asan() then @@ -59,7 +61,7 @@ local monitor_memory_usage = { end table.remove(self.hist, 1) self.last = self.hist[#self.hist] - eq(#result, 1) + eq(1, #result) end) end, dump = function(self) diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index a87398b158..2f3693b5ad 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local feed = helpers.feed -local api = helpers.api -local nvim_dir = helpers.nvim_dir -local assert_alive = helpers.assert_alive + +local clear = n.clear +local command = n.command +local exec = n.exec +local feed = n.feed +local api = n.api +local nvim_dir = n.nvim_dir +local assert_alive = n.assert_alive before_each(clear) @@ -16,12 +17,6 @@ describe('messages', function() -- oldtest: Test_warning_scroll() it('a warning causes scrolling if and only if it has a stacktrace', function() screen = Screen.new(75, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - [2] = { bold = true, reverse = true }, -- MsgSeparator - [3] = { foreground = Screen.colors.Red }, -- WarningMsg - }) screen:attach() -- When the warning comes from a script, messages are scrolled so that the @@ -35,14 +30,14 @@ describe('messages', function() screen:expect({ grid = [[ | - {0:~ }|*4 - {3:W10: Warning: Changing a readonly file}^ | + {1:~ }|*4 + {19:W10: Warning: Changing a readonly file}^ | ]], timeout = 500, }) screen:expect([[ ^ | - {0:~ }|*4 + {1:~ }|*4 Already at oldest change | ]]) end) @@ -50,10 +45,6 @@ describe('messages', function() -- oldtest: Test_message_not_cleared_after_mode() it('clearing mode does not remove message', function() screen = Screen.new(60, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() exec([[ nmap <silent> gx :call DebugSilent('normal')<CR> @@ -71,7 +62,7 @@ describe('messages', function() ^one | NoSuchFile | three | - {0:~ }|*6 + {1:~ }|*6 from DebugSilent normal | ]]) @@ -81,7 +72,7 @@ describe('messages', function() ^one | NoSuchFile | three | - {0:~ }|*6 + {1:~ }|*6 from DebugSilent visual | ]]) @@ -92,9 +83,9 @@ describe('messages', function() one | NoSuchFil^e | three | - {0:~ }|*5 + {1:~ }|*5 from DebugSilent visual | - {1:E447: Can't find file "NoSuchFile" in path} | + {9:E447: Can't find file "NoSuchFile" in path} | ]]) end) @@ -403,10 +394,6 @@ describe('messages', function() -- oldtest: Test_echo_verbose_system() it('verbose message before echo command', function() screen = Screen.new(60, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - }) screen:attach() command('cd ' .. nvim_dir) @@ -426,7 +413,7 @@ describe('messages', function() 4: foo | 5: foo | 6: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) feed('<Space>') screen:expect([[ @@ -439,7 +426,7 @@ describe('messages', function() 13: foo | 14: foo | 15: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) feed('b') screen:expect([[ @@ -452,7 +439,7 @@ describe('messages', function() 4: foo | 5: foo | 6: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) -- do the same with 'cmdheight' set to 2 @@ -460,7 +447,7 @@ describe('messages', function() command('set ch=2') screen:expect([[ ^ | - {0:~ }|*7 + {1:~ }|*7 |*2 ]]) feed([[:4 verbose echo system('foo')<CR>]]) @@ -474,7 +461,7 @@ describe('messages', function() 4: foo | 5: foo | 6: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) feed('<Space>') screen:expect([[ @@ -487,7 +474,7 @@ describe('messages', function() 13: foo | 14: foo | 15: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) feed('b') screen:expect([[ @@ -500,37 +487,32 @@ describe('messages', function() 4: foo | 5: foo | 6: foo | - {1:-- More --}^ | + {6:-- More --}^ | ]]) end) -- oldtest: Test_quit_long_message() it('with control characters can be quit vim-patch:8.2.1844', function() screen = Screen.new(40, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - [2] = { foreground = Screen.colors.Blue }, -- SpecialKey - }) screen:attach() feed([[:echom range(9999)->join("\x01")<CR>]]) screen:expect([[ - 0{2:^A}1{2:^A}2{2:^A}3{2:^A}4{2:^A}5{2:^A}6{2:^A}7{2:^A}8{2:^A}9{2:^A}10{2:^A}11{2:^A}12| - {2:^A}13{2:^A}14{2:^A}15{2:^A}16{2:^A}17{2:^A}18{2:^A}19{2:^A}20{2:^A}21{2:^A}22| - {2:^A}23{2:^A}24{2:^A}25{2:^A}26{2:^A}27{2:^A}28{2:^A}29{2:^A}30{2:^A}31{2:^A}32| - {2:^A}33{2:^A}34{2:^A}35{2:^A}36{2:^A}37{2:^A}38{2:^A}39{2:^A}40{2:^A}41{2:^A}42| - {2:^A}43{2:^A}44{2:^A}45{2:^A}46{2:^A}47{2:^A}48{2:^A}49{2:^A}50{2:^A}51{2:^A}52| - {2:^A}53{2:^A}54{2:^A}55{2:^A}56{2:^A}57{2:^A}58{2:^A}59{2:^A}60{2:^A}61{2:^A}62| - {2:^A}63{2:^A}64{2:^A}65{2:^A}66{2:^A}67{2:^A}68{2:^A}69{2:^A}70{2:^A}71{2:^A}72| - {2:^A}73{2:^A}74{2:^A}75{2:^A}76{2:^A}77{2:^A}78{2:^A}79{2:^A}80{2:^A}81{2:^A}82| - {2:^A}83{2:^A}84{2:^A}85{2:^A}86{2:^A}87{2:^A}88{2:^A}89{2:^A}90{2:^A}91{2:^A}92| - {1:-- More --}^ | + 0{18:^A}1{18:^A}2{18:^A}3{18:^A}4{18:^A}5{18:^A}6{18:^A}7{18:^A}8{18:^A}9{18:^A}10{18:^A}11{18:^A}12| + {18:^A}13{18:^A}14{18:^A}15{18:^A}16{18:^A}17{18:^A}18{18:^A}19{18:^A}20{18:^A}21{18:^A}22| + {18:^A}23{18:^A}24{18:^A}25{18:^A}26{18:^A}27{18:^A}28{18:^A}29{18:^A}30{18:^A}31{18:^A}32| + {18:^A}33{18:^A}34{18:^A}35{18:^A}36{18:^A}37{18:^A}38{18:^A}39{18:^A}40{18:^A}41{18:^A}42| + {18:^A}43{18:^A}44{18:^A}45{18:^A}46{18:^A}47{18:^A}48{18:^A}49{18:^A}50{18:^A}51{18:^A}52| + {18:^A}53{18:^A}54{18:^A}55{18:^A}56{18:^A}57{18:^A}58{18:^A}59{18:^A}60{18:^A}61{18:^A}62| + {18:^A}63{18:^A}64{18:^A}65{18:^A}66{18:^A}67{18:^A}68{18:^A}69{18:^A}70{18:^A}71{18:^A}72| + {18:^A}73{18:^A}74{18:^A}75{18:^A}76{18:^A}77{18:^A}78{18:^A}79{18:^A}80{18:^A}81{18:^A}82| + {18:^A}83{18:^A}84{18:^A}85{18:^A}86{18:^A}87{18:^A}88{18:^A}89{18:^A}90{18:^A}91{18:^A}92| + {6:-- More --}^ | ]]) feed('q') screen:expect([[ ^ | - {0:~ }|*8 + {1:~ }|*8 | ]]) end) @@ -539,11 +521,6 @@ describe('messages', function() describe('mode is cleared when', function() before_each(function() screen = Screen.new(40, 6) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { bold = true }, -- ModeMsg - [3] = { bold = true, reverse = true }, -- StatusLine - }) screen:attach() end) @@ -561,7 +538,7 @@ describe('messages', function() ^ | {1:~ }|*3 {3: }| - {2:-- INSERT --} | + {5:-- INSERT --} | ]]) feed('<C-C>') screen:expect([[ @@ -583,7 +560,7 @@ describe('messages', function() ^ | {1:~ }|*3 {3:[No Name] }| - {2:-- INSERT --} | + {5:-- INSERT --} | ]]) feed('<Esc>') screen:expect([[ @@ -600,7 +577,7 @@ describe('messages', function() screen:expect([[ ^ | {1:~ }|*4 - {2:-- (insert) --} | + {5:-- (insert) --} | ]]) feed('<C-C>') screen:expect([[ @@ -614,11 +591,6 @@ describe('messages', function() -- oldtest: Test_ask_yesno() it('y/n prompt works', function() screen = Screen.new(75, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - [2] = { bold = true, reverse = true }, -- MsgSeparator - }) screen:attach() command('set noincsearch nohlsearch inccommand=') command('call setline(1, range(1, 2))') @@ -627,57 +599,51 @@ describe('messages', function() screen:expect([[ 1 | 2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}^ | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}^ | ]]) feed('n') screen:expect([[ ^1 | 2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}n | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}n | ]]) feed(':2,1s/^/Esc/\n') screen:expect([[ 1 | 2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}^ | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}^ | ]]) feed('<Esc>') screen:expect([[ ^1 | 2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}n | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}n | ]]) feed(':2,1s/^/y/\n') screen:expect([[ 1 | 2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}^ | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}^ | ]]) feed('y') screen:expect([[ y1 | ^y2 | - {0:~ }|*3 - {1:Backwards range given, OK to swap (y/n)?}y | + {1:~ }|*3 + {6:Backwards range given, OK to swap (y/n)?}y | ]]) end) -- oldtest: Test_fileinfo_tabpage_cmdheight() it("fileinfo works when 'cmdheight' has just decreased", function() screen = Screen.new(40, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true }, -- TabLineSel - [2] = { underline = true, background = Screen.colors.LightGrey }, -- TabLine - [3] = { reverse = true }, -- TabLineFill - }) screen:attach() exec([[ @@ -688,17 +654,17 @@ describe('messages', function() set cmdheight=2 ]]) screen:expect([[ - {2: [No Name] }{1: [No Name] }{3: }{2:X}| + {24: [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {0:~ }|*2 + {1:~ }|*2 |*2 ]]) feed(':tabprev | edit Xfileinfo.txt<CR>') screen:expect([[ - {1: Xfileinfo.txt }{2: [No Name] }{3: }{2:X}| + {5: Xfileinfo.txt }{24: [No Name] }{2: }{24:X}| ^ | - {0:~ }|*3 + {1:~ }|*3 "Xfileinfo.txt" [New] | ]]) assert_alive() @@ -707,9 +673,6 @@ describe('messages', function() -- oldtest: Test_fileinfo_after_echo() it('fileinfo does not overwrite echo message vim-patch:8.2.4156', function() screen = Screen.new(40, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() exec([[ @@ -730,7 +693,7 @@ describe('messages', function() feed('0$') screen:expect([[ ^hi | - {0:~ }|*4 + {1:~ }|*4 'b' written | ]]) os.remove('b.txt') diff --git a/test/functional/legacy/mksession_spec.lua b/test/functional/legacy/mksession_spec.lua index 689d918cd9..28d4637954 100644 --- a/test/functional/legacy/mksession_spec.lua +++ b/test/functional/legacy/mksession_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local fn = helpers.fn -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local fn = n.fn +local eq = t.eq describe('mksession', function() before_each(clear) diff --git a/test/functional/legacy/move_spec.lua b/test/functional/legacy/move_spec.lua index 1500d48ad9..c2be8bb3eb 100644 --- a/test/functional/legacy/move_spec.lua +++ b/test/functional/legacy/move_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed = helpers.feed -local fn = helpers.fn + +local clear = n.clear +local feed = n.feed +local fn = n.fn before_each(clear) @@ -10,9 +11,6 @@ describe(':move', function() -- oldtest: Test_move_undo() it('redraws correctly when undone', function() local screen = Screen.new(60, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - }) screen:attach() fn.setline(1, { 'First', 'Second', 'Third', 'Fourth' }) @@ -22,7 +20,7 @@ describe(':move', function() ^First | Third | Fourth | - {0:~ }|*5 + {1:~ }|*5 :move +1 | ]]) @@ -34,7 +32,7 @@ describe(':move', function() Second | Third | Fourth | - {0:~ }|*5 + {1:~ }|*5 | ]]) end) diff --git a/test/functional/legacy/nested_function_spec.lua b/test/functional/legacy/nested_function_spec.lua index 7a2ba1ecf2..5e981b5862 100644 --- a/test/functional/legacy/nested_function_spec.lua +++ b/test/functional/legacy/nested_function_spec.lua @@ -1,8 +1,9 @@ -- Tests for nested function. -local helpers = require('test.functional.helpers')(after_each) -local clear, insert = helpers.clear, helpers.insert -local command, expect, source = helpers.command, helpers.expect, helpers.source +local n = require('test.functional.testnvim')() + +local clear, insert = n.clear, n.insert +local command, expect, source = n.command, n.expect, n.source describe('test_nested_function', function() setup(clear) diff --git a/test/functional/legacy/normal_spec.lua b/test/functional/legacy/normal_spec.lua index 1dddeed033..5158ca3009 100644 --- a/test/functional/legacy/normal_spec.lua +++ b/test/functional/legacy/normal_spec.lua @@ -1,35 +1,106 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -before_each(clear) +local clear = n.clear +local exec = n.exec +local feed = n.feed +local api = n.api +local eq = t.eq +local fn = n.fn describe('normal', function() + local screen + + before_each(function() + clear() + screen = Screen.new(40, 19) + screen:attach() + end) + -- oldtest: Test_normal_j_below_botline() - it( - [["j" does not skip lines when scrolling below botline and 'foldmethod' is not "manual"]], - function() - local screen = Screen.new(40, 19) - screen:attach() - screen:set_default_attr_ids({ { foreground = Screen.colors.Brown } }) - exec([[ + it([[no skipped lines with "j" scrolling below botline and 'foldmethod' not "manual"]], function() + exec([[ set number foldmethod=diff scrolloff=0 call setline(1, map(range(1, 9), 'repeat(v:val, 200)')) norm Lj ]]) - screen:expect([[ - {1: 2 }222222222222222222222222222222222222| - {1: }222222222222222222222222222222222222|*4 - {1: }22222222222222222222 | - {1: 3 }333333333333333333333333333333333333| - {1: }333333333333333333333333333333333333|*4 - {1: }33333333333333333333 | - {1: 4 }^444444444444444444444444444444444444| - {1: }444444444444444444444444444444444444|*4 - {1: }44444444444444444444 | + screen:expect([[ + {8: 2 }222222222222222222222222222222222222| + {8: }222222222222222222222222222222222222|*4 + {8: }22222222222222222222 | + {8: 3 }333333333333333333333333333333333333| + {8: }333333333333333333333333333333333333|*4 + {8: }33333333333333333333 | + {8: 4 }^444444444444444444444444444444444444| + {8: }444444444444444444444444444444444444|*4 + {8: }44444444444444444444 | | ]]) - end - ) + end) + + -- oldtest: Test_single_line_scroll() + it('(Half)-page scroll up or down reveals virtual lines #19605, #27967', function() + fn.setline(1, 'foobar one two three') + exec('set smoothscroll') + local ns = api.nvim_create_namespace('') + api.nvim_buf_set_extmark(0, ns, 0, 0, { + virt_lines = { { { '---', 'IncSearch' } } }, + virt_lines_above = true, + }) + -- Nvim: not actually necessary to scroll down to hide the virtual line. + -- Check topfill instead of skipcol and show the screen state. + feed('<C-E>') + eq(0, fn.winsaveview().topfill) + local s1 = [[ + ^foobar one two three | + {1:~ }|*17 + | + ]] + screen:expect(s1) + feed('<C-B>') + eq(1, fn.winsaveview().topfill) + local s2 = [[ + {2:---} | + ^foobar one two three | + {1:~ }|*16 + | + ]] + screen:expect(s2) + feed('<C-E>') + eq(0, fn.winsaveview().topfill) + screen:expect(s1) + feed('<C-U>') + eq(1, fn.winsaveview().topfill) + screen:expect(s2) + + -- Nvim: also test virt_lines below the last line + feed('yy100pG<C-L>') + api.nvim_buf_set_extmark(0, ns, 100, 0, { virt_lines = { { { '---', 'IncSearch' } } } }) + screen:expect({ + grid = [[ + foobar one two three |*17 + ^foobar one two three | + | + ]], + }) + feed('<C-F>') + screen:expect({ + grid = [[ + ^foobar one two three | + {2:---} | + {1:~ }|*16 + | + ]], + }) + feed('ggG<C-D>') + screen:expect({ + grid = [[ + foobar one two three |*16 + ^foobar one two three | + {2:---} | + | + ]], + }) + end) end) diff --git a/test/functional/legacy/number_spec.lua b/test/functional/legacy/number_spec.lua index c112532eed..0ebd731f65 100644 --- a/test/functional/legacy/number_spec.lua +++ b/test/functional/legacy/number_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local exec = n.exec +local feed = n.feed describe("'number' and 'relativenumber'", function() before_each(clear) @@ -214,10 +215,6 @@ describe("'number' and 'relativenumber'", function() -- oldtest: Test_relativenumber_callback() it('relative line numbers are updated if cursor is moved from timer', function() local screen = Screen.new(50, 8) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, -- LineNr - [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText - }) screen:attach() exec([[ call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) @@ -232,22 +229,22 @@ describe("'number' and 'relativenumber'", function() ]]) screen:expect({ grid = [[ - {1: 3 }aaaaa | - {1: 2 }bbbbb | - {1: 1 }ccccc | - {1: 0 }^ddddd | - {2:~ }|*3 + {8: 3 }aaaaa | + {8: 2 }bbbbb | + {8: 1 }ccccc | + {8: 0 }^ddddd | + {1:~ }|*3 | ]], timeout = 100, }) screen:expect({ grid = [[ - {1: 0 }^aaaaa | - {1: 1 }bbbbb | - {1: 2 }ccccc | - {1: 3 }ddddd | - {2:~ }|*3 + {8: 0 }^aaaaa | + {8: 1 }bbbbb | + {8: 2 }ccccc | + {8: 3 }ddddd | + {1:~ }|*3 | ]], }) @@ -256,10 +253,6 @@ describe("'number' and 'relativenumber'", function() -- oldtest: Test_number_insert_delete_lines() it('line numbers are updated when deleting/inserting lines', function() local screen = Screen.new(50, 8) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, -- LineNr - [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText - }) screen:attach() exec([[ call setline(1, range(1, 7)) @@ -267,37 +260,37 @@ describe("'number' and 'relativenumber'", function() call cursor(2, 1) ]]) local snapshot1 = [[ - {1: 1 }1 | - {1: 2 }^2 | - {1: 3 }3 | - {1: 4 }4 | - {1: 5 }5 | - {1: 6 }6 | - {1: 7 }7 | + {8: 1 }1 | + {8: 2 }^2 | + {8: 3 }3 | + {8: 4 }4 | + {8: 5 }5 | + {8: 6 }6 | + {8: 7 }7 | | ]] screen:expect(snapshot1) feed('dd') screen:expect([[ - {1: 1 }1 | - {1: 2 }^3 | - {1: 3 }4 | - {1: 4 }5 | - {1: 5 }6 | - {1: 6 }7 | - {2:~ }| + {8: 1 }1 | + {8: 2 }^3 | + {8: 3 }4 | + {8: 4 }5 | + {8: 5 }6 | + {8: 6 }7 | + {1:~ }| | ]]) feed('P') screen:expect(snapshot1) feed('2dd') screen:expect([[ - {1: 1 }1 | - {1: 2 }^4 | - {1: 3 }5 | - {1: 4 }6 | - {1: 5 }7 | - {2:~ }|*2 + {8: 1 }1 | + {8: 2 }^4 | + {8: 3 }5 | + {8: 4 }6 | + {8: 5 }7 | + {1:~ }|*2 | ]]) feed('P') diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua index 2f20b6bd51..e9a3b73cf7 100644 --- a/test/functional/legacy/options_spec.lua +++ b/test/functional/legacy/options_spec.lua @@ -1,11 +1,13 @@ -- See also: test/old/testdir/test_options.vim -local helpers = require('test.functional.helpers')(after_each) -local command, clear = helpers.command, helpers.clear -local source, expect = helpers.source, helpers.expect -local exc_exec = helpers.exc_exec -local matches = helpers.matches +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local command, clear = n.command, n.clear +local source, expect = n.source, n.expect +local exc_exec = n.exc_exec +local matches = t.matches + describe('options', function() setup(clear) @@ -66,11 +68,11 @@ describe('set', function() command('verbose set scroll?') screen:expect([[ | - ~ |*11 - | + {1:~ }|*11 + {3: }| scroll=7 | Last set from changed window size | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) end) diff --git a/test/functional/legacy/prompt_buffer_spec.lua b/test/functional/legacy/prompt_buffer_spec.lua index e4810feedb..72ec420b15 100644 --- a/test/functional/legacy/prompt_buffer_spec.lua +++ b/test/functional/legacy/prompt_buffer_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local source = helpers.source -local clear = helpers.clear -local command = helpers.command -local expect = helpers.expect -local poke_eventloop = helpers.poke_eventloop -local api = helpers.api -local eq = helpers.eq -local neq = helpers.neq + +local feed = n.feed +local source = n.source +local clear = n.clear +local command = n.command +local expect = n.expect +local poke_eventloop = n.poke_eventloop +local api = n.api +local eq = t.eq +local neq = t.neq describe('prompt buffer', function() local screen @@ -58,11 +60,11 @@ describe('prompt buffer', function() ]]) screen:expect([[ cmd: ^ | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) end @@ -79,15 +81,15 @@ describe('prompt buffer', function() Command: "hello" | Result: "hello" | cmd: ^ | - [Prompt] | + {3:[Prompt] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('exit\n') screen:expect([[ ^other buffer | - ~ |*8 + {1:~ }|*8 | ]]) end) @@ -98,43 +100,43 @@ describe('prompt buffer', function() feed('hello<BS><BS>') screen:expect([[ cmd: hel^ | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<Left><Left><Left><BS>-') screen:expect([[ cmd: -^hel | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<C-O>lz') screen:expect([[ cmd: -hz^el | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<End>x') screen:expect([[ cmd: -hzelx^ | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<C-U>exit\n') screen:expect([[ ^other buffer | - ~ |*8 + {1:~ }|*8 | ]]) end) @@ -143,32 +145,30 @@ describe('prompt buffer', function() it('switch windows', function() source_script() feed('<C-O>:call SwitchWindows()<CR>') - screen:expect { - grid = [[ + screen:expect([[ cmd: | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {2:[Prompt] [+] }| ^other buffer | - ~ |*3 + {1:~ }|*3 | - ]], - } + ]]) feed('<C-O>:call SwitchWindows()<CR>') screen:expect([[ cmd: ^ | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 - -- INSERT -- | + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<Esc>') screen:expect([[ cmd:^ | - ~ |*3 - [Prompt] [+] | + {1:~ }|*3 + {3:[Prompt] [+] }| other buffer | - ~ |*3 + {1:~ }|*3 | ]]) end) diff --git a/test/functional/legacy/put_spec.lua b/test/functional/legacy/put_spec.lua index c78946d690..587424da10 100644 --- a/test/functional/legacy/put_spec.lua +++ b/test/functional/legacy/put_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local api = helpers.api -local source = helpers.source -local eq = helpers.eq + +local clear = n.clear +local exec_lua = n.exec_lua +local api = n.api +local source = n.source +local eq = t.eq local function sizeoflong() if not exec_lua('return pcall(require, "ffi")') then @@ -66,8 +68,8 @@ describe('put', function() three more text │ three more text | ^four more text │ four more text | │ | - ~ │~ |*2 - [No Name] [+] [No Name] [+] | + {1:~ }│{1:~ }|*2 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) end) diff --git a/test/functional/legacy/qf_title_spec.lua b/test/functional/legacy/qf_title_spec.lua index 9f97eb27b2..26b096d633 100644 --- a/test/functional/legacy/qf_title_spec.lua +++ b/test/functional/legacy/qf_title_spec.lua @@ -1,8 +1,9 @@ -- Tests for quickfix window's title -local helpers = require('test.functional.helpers')(after_each) -local insert, source = helpers.insert, helpers.source -local clear, expect = helpers.clear, helpers.expect +local n = require('test.functional.testnvim')() + +local insert, source = n.insert, n.source +local clear, expect = n.clear, n.expect describe('qf_title', function() setup(clear) diff --git a/test/functional/legacy/scroll_opt_spec.lua b/test/functional/legacy/scroll_opt_spec.lua index 8d22c299d6..97578067d5 100644 --- a/test/functional/legacy/scroll_opt_spec.lua +++ b/test/functional/legacy/scroll_opt_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed -local assert_alive = helpers.assert_alive + +local clear = n.clear +local exec = n.exec +local feed = n.feed +local assert_alive = n.assert_alive before_each(clear) @@ -23,9 +24,9 @@ describe('smoothscroll', function() set number ]]) feed('<C-Y>') - screen:expect({ any = ' 1 ^one' }) + screen:expect({ any = '{8: 1 }^one' }) feed('<C-E><C-E><C-E>') - screen:expect({ any = ' 2 ^two' }) + screen:expect({ any = '{8: 2 }^two' }) end) -- oldtest: Test_smoothscroll_CtrlE_CtrlY() @@ -43,28 +44,28 @@ describe('smoothscroll', function() long word long word long word | ^line | line |*2 - ~ |*2 + {1:~ }|*2 | ]] local s2 = [[ - <<<d word word word word word word word | + {1:<<<}d word word word word word word word | word word word word | line three | long word long word long word long word | long word long word long word | ^line | line |*2 - ~ |*3 + {1:~ }|*3 | ]] local s3 = [[ - <<<d word word word | + {1:<<<}d word word word | line three | long word long word long word long word | long word long word long word | ^line | line |*2 - ~ |*4 + {1:~ }|*4 | ]] local s4 = [[ @@ -73,28 +74,28 @@ describe('smoothscroll', function() long word long word long word | line |*2 ^line | - ~ |*5 + {1:~ }|*5 | ]] local s5 = [[ - <<<d word word word | + {1:<<<}d word word word | line three | long word long word long word long word | long word long word long word | line |*2 ^line | - ~ |*4 + {1:~ }|*4 | ]] local s6 = [[ - <<<d word word word word word word word | + {1:<<<}d word word word word word word word | word word word word | line three | long word long word long word long word | long word long word long word | line |*2 ^line | - ~ |*3 + {1:~ }|*3 | ]] local s7 = [[ @@ -105,7 +106,7 @@ describe('smoothscroll', function() long word long word long word | line |*2 ^line | - ~ |*2 + {1:~ }|*2 | ]] local s8 = [[ @@ -117,7 +118,7 @@ describe('smoothscroll', function() long word long word long word | line |*2 ^line | - ~ | + {1:~ }| | ]] feed('<C-E>') @@ -160,7 +161,7 @@ describe('smoothscroll', function() ϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛ^ϛϛϛϛϛ| ϛϛϛϛϛ | 222222222222222222222222222222222222 | - ~ |*2 + {1:~ }|*2 | ]]) end) @@ -181,134 +182,136 @@ describe('smoothscroll', function() endfunc ]]) screen:expect([[ - 1 one word word word word word word wo| + {8: 1 }one word word word word word word wo| rd word word word word word word word wo| rd word word word word word | - 2 two long word long word long word lo| + {8: 2 }two long word long word long word lo| ng word long word long word long word | - 3 ^line | - 4 line | - 5 line | - ~ |*3 + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*3 | ]]) feed('<C-E>') screen:expect([[ - <<<word word word word word word word wo| + {1:<<<}word word word word word word word wo| rd word word word word word | - 2 two long word long word long word lo| + {8: 2 }two long word long word long word lo| ng word long word long word long word | - 3 ^line | - 4 line | - 5 line | - ~ |*4 + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*4 | ]]) feed('<C-E>') screen:expect([[ - <<<word word word word word | - 2 two long word long word long word lo| + {1:<<<}word word word word word | + {8: 2 }two long word long word long word lo| ng word long word long word long word | - 3 ^line | - 4 line | - 5 line | - ~ |*5 + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*5 | ]]) exec('set cpo-=n') screen:expect([[ - <<< d word word word word word word | - 2 two long word long word long word lo| - ng word long word long word long wor| - d | - 3 ^line | - 4 line | - 5 line | - ~ |*4 + {1:<<<}{8: }d word word word word word word | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long wor| + {8: }d | + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*4 | ]]) feed('<C-Y>') screen:expect([[ - <<< rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word lo| - ng word long word long word long wor| - d | - 3 ^line | - 4 line | - 5 line | - ~ |*3 + {1:<<<}{8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long wor| + {8: }d | + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*3 | ]]) feed('<C-Y>') screen:expect([[ - 1 one word word word word word word wo| - rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word lo| - ng word long word long word long wor| - d | - 3 ^line | - 4 line | - 5 line | - ~ |*2 + {8: 1 }one word word word word word word wo| + {8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long wor| + {8: }d | + {8: 3 }^line | + {8: 4 }line | + {8: 5 }line | + {1:~ }|*2 | ]]) exec('botright split') feed('gg') screen:expect([[ - 1 one word word word word word word wo| - rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word@@@| - [No Name] [+] | - 1 ^one word word word word word word wo| - rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word lo| - ng word long word long word long @@@| - [No Name] [+] | + {8: 1 }one word word word word word word wo| + {8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word{1:@@@}| + {2:[No Name] [+] }| + {8: 1 }^one word word word word word word wo| + {8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long {1:@@@}| + {3:[No Name] [+] }| | ]]) + feed('<C-E>') screen:expect([[ - 1 one word word word word word word wo| - rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word@@@| - [No Name] [+] | - <<< rd word word word word word word wor| - d word word word word word word^ | - 2 two long word long word long word lo| - ng word long word long word long wor| - d | - [No Name] [+] | + {8: 1 }one word word word word word word wo| + {8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word{1:@@@}| + {2:[No Name] [+] }| + {1:<<<}{8: }rd word word word word word word wor| + {8: }d word word word word word word^ | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long wor| + {8: }d | + {3:[No Name] [+] }| | ]]) + feed('<C-E>') screen:expect([[ - 1 one word word word word word word wo| - rd word word word word word word wor| - d word word word word word word | - 2 two long word long word long word@@@| - [No Name] [+] | - <<< d word word word word word word^ | - 2 two long word long word long word lo| - ng word long word long word long wor| - d | - 3 line | - [No Name] [+] | + {8: 1 }one word word word word word word wo| + {8: }rd word word word word word word wor| + {8: }d word word word word word word | + {8: 2 }two long word long word long word{1:@@@}| + {2:[No Name] [+] }| + {1:<<<}{8: }d word word word word word word^ | + {8: 2 }two long word long word long word lo| + {8: }ng word long word long word long wor| + {8: }d | + {8: 3 }line | + {3:[No Name] [+] }| | ]]) exec('close') exec('call DoRel()') screen:expect([[ - 2<<<^ong text very long text very long te| - xt very long text very long text ver| - y long text very long text very long| - text very long text very long text | - 1 three | - ~ |*6 + {8:2}{1:<<<}^ong text very long text very long te| + {8: }xt very long text very long text ver| + {8: }y long text very long text very long| + {8: } text very long text very long text | + {8: 1 }three | + {1:~ }|*6 --No lines in buffer-- | ]]) end) @@ -323,22 +326,22 @@ describe('smoothscroll', function() exe "normal 2Gzt\<C-E>" ]]) screen:expect([[ - <<<t very long text very long text very | + {1:<<<}t very long text very long text very | ^long text very long text very long text | very long text very long text very long | - text very long text- | + text very long text{1:-} | three | - ~ |*2 + {1:~ }|*2 | ]]) exec('set listchars+=precedes:#') screen:expect([[ - #ext very long text very long text very | + {1:#}ext very long text very long text very | ^long text very long text very long text | very long text very long text very long | - text very long text- | + text very long text{1:-} | three | - ~ |*2 + {1:~ }|*2 | ]]) end) @@ -356,13 +359,14 @@ describe('smoothscroll', function() set smoothscroll diffthis ]]) + screen:expect([[ - - ^just some text here | - ~ |*2 - [No Name] [+] | - - just some text here | - ~ | - [No Name] [+] | + {7:- }^just some text here | + {1:~ }|*2 + {3:[No Name] [+] }| + {7:- }just some text here | + {1:~ }| + {2:[No Name] [+] }| | ]]) feed('<C-Y>') @@ -380,7 +384,7 @@ describe('smoothscroll', function() :3 ]]) screen:expect([[ - <<<h some text with some text | + {1:<<<}h some text with some text | Line with some text with some text with | some text with some text with some text | with some text with some text | @@ -401,7 +405,7 @@ describe('smoothscroll', function() -- moving cursor up right after the <<< marker - no need to show whole line feed('2gj3l2k') screen:expect([[ - <<<^h some text with some text | + {1:<<<}^h some text with some text | Line with some text with some text with | some text with some text with some text | with some text with some text | @@ -419,7 +423,7 @@ describe('smoothscroll', function() Line with some text with some text with | some text with some text with some text | with some text with some text | - @ | + {1:@ }| | ]]) end) @@ -443,7 +447,7 @@ describe('smoothscroll', function() ]]) feed('<C-E>') screen:expect([[ - <<<th lot^s of text with lots of text wit| + {1:<<<}th lot^s of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text with lots of te| @@ -452,7 +456,7 @@ describe('smoothscroll', function() ]]) feed('5<C-E>') screen:expect([[ - <<< lots ^of text with lots of text with | + {1:<<<} lots ^of text with lots of text with | lots of text with lots of text with lots| of text with lots of text with lots of | text with lots of text with lots of text| @@ -462,7 +466,7 @@ describe('smoothscroll', function() -- scrolling down, cursor moves screen line up feed('5<C-Y>') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text with lots of te| @@ -482,7 +486,7 @@ describe('smoothscroll', function() exec('set scrolloff=1') feed('10|<C-E>') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of^ text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text with lots of te| @@ -492,7 +496,7 @@ describe('smoothscroll', function() -- 'scrolloff' set to 1, scrolling down, cursor moves screen line up feed('<C-E>gjgj<C-Y>') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text wi^th lots of text with lots of te| @@ -503,7 +507,7 @@ describe('smoothscroll', function() exec('set scrolloff=2') feed('10|<C-E>') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of tex^t with lots of text with lots o| f text with lots of text with lots of te| @@ -518,7 +522,7 @@ describe('smoothscroll', function() exec('set scrolloff=0') feed('0j') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text end | @@ -529,20 +533,20 @@ describe('smoothscroll', function() feed('zt') screen:expect([[ ^four | - ~ |*4 + {1:~ }|*4 | ]]) feed('zz') screen:expect([[ - <<<of text with lots of text with lots o| + {1:<<<}of text with lots of text with lots o| f text with lots of text end | ^four | - ~ |*2 + {1:~ }|*2 | ]]) feed('zb') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text end | @@ -567,7 +571,7 @@ describe('smoothscroll', function() -- screen. feed('3Gzt<C-E>j') screen:expect([[ - <<<th lots of text with lots of text wit| + {1:<<<}th lots of text with lots of text wit| h lots of text with lots of text with lo| ts of text with lots of text with lots o| f text with lots of text end | @@ -588,16 +592,16 @@ describe('smoothscroll', function() lots of text with lots of text with lot| s of text with lots of text with lots of| text | - ~ | + {1:~ }| | ]] screen:expect(s1) feed('<C-E>') screen:expect([[ - <<<ts of text with lots of text with lot| + {1:<<<}ts of text with lots of text with lot| ^s of text with lots of text with lots of| text | - ~ |*2 + {1:~ }|*2 | ]]) feed('0') @@ -612,20 +616,20 @@ describe('smoothscroll', function() exec('set smoothscroll scrolloff=0 showbreak=+++\\ ') local s1 = [[ ^with lots of text in one line with lots | - +++ of text in one line with lots of tex| - +++ t in one line with lots of text in o| - +++ ne line with lots of text in one lin| - +++ e with lots of text in one line | + {1:+++ }of text in one line with lots of tex| + {1:+++ }t in one line with lots of text in o| + {1:+++ }ne line with lots of text in one lin| + {1:+++ }e with lots of text in one line | | ]] screen:expect(s1) feed('<C-E>') screen:expect([[ - +++ ^of text in one line with lots of tex| - +++ t in one line with lots of text in o| - +++ ne line with lots of text in one lin| - +++ e with lots of text in one line | - ~ | + {1:+++ }^of text in one line with lots of tex| + {1:+++ }t in one line with lots of text in o| + {1:+++ }ne line with lots of text in one lin| + {1:+++ }e with lots of text in one line | + {1:~ }| | ]]) feed('0') @@ -642,13 +646,13 @@ describe('smoothscroll', function() screen:expect([[ ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| 口口口口口口口口口口 | - ~ |*3 + {1:~ }|*3 | ]]) feed('<C-E>') screen:expect([[ - <<< 口口口口口口口^口 | - ~ |*4 + {1:<<<} 口口口口口口口^口 | + {1:~ }|*4 | ]]) end) @@ -656,10 +660,6 @@ describe('smoothscroll', function() -- oldtest: Test_smoothscroll_zero_width() it('does not divide by zero with a narrow window', function() screen:try_resize(12, 2) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, - }) exec([[ call setline(1, ['a'->repeat(100)]) set wrap smoothscroll number laststatus=0 @@ -669,12 +669,12 @@ describe('smoothscroll', function() wincmd v ]]) screen:expect([[ - {1: 1^ }│{1: }│{1: }│{1: }│{1: }| + {8: 1^ }│{8: }│{8: }│{8: }│{8: }| | ]]) feed('llllllllll<C-W>o') screen:expect([[ - {2:<<<}{1: }aa^aaaaaa| + {1:<<<}{8: }aa^aaaaaa| | ]]) end) @@ -694,7 +694,7 @@ describe('smoothscroll', function() ]=]) feed('<C-E>gjgk') screen:expect([[ - <<<lots of text in one line^ | + {1:<<<}lots of text in one line^ | line two | line three | line four | @@ -717,7 +717,7 @@ describe('smoothscroll', function() call search('xxx') ]=]) screen:expect([[ - <<<_____________________________________| + {1:<<<}_____________________________________| ________________________________________| ______________________________________^xx| x______________________________________x| @@ -741,10 +741,10 @@ describe('smoothscroll', function() | ]]) exec("call setline(92, 'a'->repeat(100))") - feed('<C-B>G') + feed('<C-L><C-B>G') -- cursor is not placed below window screen:expect([[ - <<<aaaaaaaaaaaaaaaaa | + {1:<<<}aaaaaaaaaaaaaaaaa | |*7 ^ | | @@ -754,12 +754,6 @@ describe('smoothscroll', function() -- oldtest: Test_smoothscroll_incsearch() it('does not reset skipcol when doing incremental search on the same word', function() screen:try_resize(40, 8) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, - [3] = { background = Screen.colors.Yellow1 }, - [4] = { reverse = true }, - }) exec([[ set smoothscroll number scrolloff=0 incsearch call setline(1, repeat([''], 20)) @@ -768,46 +762,46 @@ describe('smoothscroll', function() ]]) feed('/b') screen:expect([[ - {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | - {1: 12 } | - {1: 13 } | - {1: 14 }{4:b}{3:bbb} | - {1: 15 } | - {1: 16 } | - {1: 17 } | + {1:<<<}{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {8: 12 } | + {8: 13 } | + {8: 14 }{2:b}{10:bbb} | + {8: 15 } | + {8: 16 } | + {8: 17 } | /b^ | ]]) feed('b') screen:expect([[ - {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | - {1: 12 } | - {1: 13 } | - {1: 14 }{4:bb}{3:bb} | - {1: 15 } | - {1: 16 } | - {1: 17 } | + {1:<<<}{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {8: 12 } | + {8: 13 } | + {8: 14 }{2:bb}{10:bb} | + {8: 15 } | + {8: 16 } | + {8: 17 } | /bb^ | ]]) feed('b') screen:expect([[ - {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | - {1: 12 } | - {1: 13 } | - {1: 14 }{4:bbb}b | - {1: 15 } | - {1: 16 } | - {1: 17 } | + {1:<<<}{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {8: 12 } | + {8: 13 } | + {8: 14 }{2:bbb}b | + {8: 15 } | + {8: 16 } | + {8: 17 } | /bbb^ | ]]) feed('b') screen:expect([[ - {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | - {1: 12 } | - {1: 13 } | - {1: 14 }{4:bbbb} | - {1: 15 } | - {1: 16 } | - {1: 17 } | + {1:<<<}{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {8: 12 } | + {8: 13 } | + {8: 14 }{2:bbbb} | + {8: 15 } | + {8: 16 } | + {8: 17 } | /bbbb^ | ]]) end) @@ -815,10 +809,6 @@ describe('smoothscroll', function() -- oldtest: Test_smoothscroll_multi_skipcol() it('scrolling multiple lines and stopping at non-zero skipcol', function() screen:try_resize(40, 10) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue, bold = true }, - [1] = { background = Screen.colors.Grey90 }, - }) exec([[ setlocal cursorline scrolloff=0 smoothscroll call setline(1, repeat([''], 8)) @@ -829,7 +819,7 @@ describe('smoothscroll', function() redraw ]]) screen:expect([[ - {1:^ }| + {21:^ }| | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaa | @@ -841,22 +831,22 @@ describe('smoothscroll', function() ]]) feed('3<C-E>') screen:expect([[ - {0:<<<}{1:aaaaaa^a }| + {1:<<<}{21:aaaaaa^a }| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| aaaaaaaaaa | |*2 bbb | ccc | - {0:~ }|*2 + {1:~ }|*2 | ]]) feed('2<C-E>') screen:expect([[ - {0:<<<}{1:aaaaaa^a }| + {1:<<<}{21:aaaaaa^a }| |*2 bbb | ccc | - {0:~ }|*4 + {1:~ }|*4 | ]]) end) @@ -864,12 +854,6 @@ describe('smoothscroll', function() -- oldtest: Test_smoothscroll_zero_width_scroll_cursor_bot() it('does not divide by zero in zero-width window', function() screen:try_resize(40, 19) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, -- LineNr - [2] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [3] = { bold = true, reverse = true }, -- StatusLine - [4] = { reverse = true }, -- StatusLineNC - }) exec([[ silent normal yy silent normal 19p @@ -882,10 +866,10 @@ describe('smoothscroll', function() silent normal 20G ]]) screen:expect([[ - {1: }│ | - {2:@}│ |*15 - {2:^@}│ | - {3:< }{4:[No Name] [+] }| + {8: }│ | + {1:@}│ |*15 + {1:^@}│ | + {3:< }{2:[No Name] [+] }| | ]]) end) @@ -901,15 +885,15 @@ describe('smoothscroll', function() ]]) screen:expect([[ | - [No Name] | + {2:[No Name] }| line1 | line2 | ^line3line3line3line3line3line3line3line3| line3line3line3line3line3line3line3line3| line3line3line3line3 | line4 | - ~ |*2 - [No Name] [+] | + {1:~ }|*2 + {3:[No Name] [+] }| | ]]) end) @@ -929,6 +913,119 @@ describe('smoothscroll', function() assert_alive() end) + -- oldtest: Test_smoothscroll_insert_bottom() + it('works in Insert mode at bottom of window', function() + screen:try_resize(40, 9) + exec([[ + call setline(1, repeat([repeat('A very long line ...', 10)], 5)) + set wrap smoothscroll scrolloff=0 + ]]) + feed('Go123456789<CR>') + screen:expect([[ + {1:<<<}ery long line ...A very long line ...| + A very long line ...A very long line ...|*5 + 123456789 | + ^ | + {5:-- INSERT --} | + ]]) + end) + + -- oldtest: Test_smoothscroll_in_qf_window() + it('works in quickfix window when changing quickfix list', function() + screen:try_resize(60, 20) + exec([[ + set nocompatible display=lastline + copen 5 + setlocal number smoothscroll + let g:l = [{'text': 'foo'}] + repeat([{'text': join(range(30))}], 10) + call setqflist(g:l, 'r') + normal! G + wincmd t + let g:l1 = [{'text': join(range(1000))}] + ]]) + screen:expect([[ + ^ | + {1:~ }|*11 + {3:[No Name] }| + {1:<<<}{8: }21 22 23 24 25 26 27 28 29 | + {8: 10 }|| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | + {8: }21 22 23 24 25 26 27 28 29 | + {8: 11 }|| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | + {8: }21 22 23 24 25 26 27 28 29 | + {2:[Quickfix List] }| + | + ]]) + + feed([[:call setqflist([], 'r')<CR>]]) + local screen_empty = [[ + ^ | + {1:~ }|*11 + {3:[No Name] }| + {8: 1 } | + {1:~ }|*4 + {2:[Quickfix List] }| + :call setqflist([], 'r') | + ]] + screen:expect(screen_empty) + + feed([[:call setqflist(g:l, 'r')<CR>]]) + local screen_l_top = [[ + ^ | + {1:~ }|*11 + {3:[No Name] }| + {8: 1 }{10:|| foo }| + {8: 2 }|| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | + {8: }21 22 23 24 25 26 27 28 29 | + {8: 3 }|| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | + {8: }21 22 23 24 25 26 27 28 29 | + {2:[Quickfix List] }| + :call setqflist(g:l, 'r') | + ]] + screen:expect(screen_l_top) + + feed([[:call setqflist(g:l1, 'r')<CR>]]) + local screen_l1_top = [[ + ^ | + {1:~ }|*11 + {3:[No Name] }| + {8: 1 }{10:|| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 }| + {8: }{10:21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39}| + {8: }{10: 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 5}| + {8: }{10:8 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 }| + {8: }{10:77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95}| + {2:[Quickfix List] }| + :call setqflist(g:l1, 'r') | + ]] + screen:expect(screen_l1_top) + + feed('<C-W>b$<C-W>t') + local screen_l1_bot = [[ + ^ | + {1:~ }|*11 + {3:[No Name] }| + {1:<<<}{8: }{10: 937 938 939 940 941 942 943 944 945 946 947 948 949 950}| + {8: }{10: 951 952 953 954 955 956 957 958 959 960 961 962 963 964}| + {8: }{10: 965 966 967 968 969 970 971 972 973 974 975 976 977 978}| + {8: }{10: 979 980 981 982 983 984 985 986 987 988 989 990 991 992}| + {8: }{10: 993 994 995 996 997 998 999 }| + {2:[Quickfix List] }| + :call setqflist(g:l1, 'r') | + ]] + screen:expect(screen_l1_bot) + + feed([[:call setqflist([], 'r')<CR>]]) + screen:expect(screen_empty) + + feed([[:call setqflist(g:l1, 'r')<CR>]]) + screen:expect(screen_l1_top) + + feed('<C-W>b$<C-W>t') + screen:expect(screen_l1_bot) + + feed([[:call setqflist(g:l, 'r')<CR>]]) + screen:expect(screen_l_top) + end) + it('works with virt_lines above and below', function() screen:try_resize(55, 7) exec([=[ @@ -952,7 +1049,7 @@ describe('smoothscroll', function() ]]) feed('<C-E>') screen:expect([[ - <<<e text with some text with some text with some text | + {1:<<<}e text with some text with some text with some text | virt_below1 | virt_above1 | ^Line with some text with some text with some text with | @@ -977,7 +1074,7 @@ describe('smoothscroll', function() some text with some text with some text with some text | virt_below2 | virt_above2 | - Line with some text with some text with some text wi@@@| + Line with some text with some text with some text wi{1:@@@}| | ]]) feed('<C-E>') @@ -992,124 +1089,199 @@ describe('smoothscroll', function() ]]) feed('<C-E>') screen:expect([[ - <<<e text with some text with some text with some tex^t | + {1:<<<}e text with some text with some text with some tex^t | virt_below2 | virt_above2 | Line with some text with some text with some text with | some text with some text with some text with some text | - ~ | + {1:~ }| | ]]) end) - it('works in Insert mode at bottom of window', function() - screen:try_resize(40, 9) - exec([[ - call setline(1, repeat([repeat('A very long line ...', 10)], 5)) - set wrap smoothscroll scrolloff=0 - ]]) - feed('Go123456789<CR>') - screen:expect([[ - <<<ery long line ...A very long line ...| - A very long line ...A very long line ...|*5 - 123456789 | - ^ | - -- INSERT -- | - ]]) - end) - it('<<< marker shows with tabline, winbar and splits', function() screen:try_resize(40, 12) + screen:set_default_attr_ids({ + [1] = { foreground = Screen.colors.Blue1, bold = true }, + [2] = { reverse = true }, + [3] = { bold = true, reverse = true }, + [4] = { background = Screen.colors.LightMagenta }, + [5] = { bold = true }, + [31] = { foreground = Screen.colors.Fuchsia, bold = true }, + }) exec([[ call setline(1, ['Line' .. (' with some text'->repeat(7))]->repeat(7)) set smoothscroll scrolloff=0 norm sj ]]) screen:expect([[ - <<<e text with some text with some text | + {1:<<<}e text with some text with some text | with some text with some text | Line with some text with some text with | some text with some text with some text | with some text with some text | - [No Name] [+] | - <<<e text with some text with some text | + {2:[No Name] [+] }| + {1:<<<}e text with some text with some text | ^with some text with some text | Line with some text with some text with | - some text with some text with some te@@@| - [No Name] [+] | + some text with some text with some te{1:@@@}| + {3:[No Name] [+] }| | ]]) exec('set showtabline=2') feed('<C-E>') screen:expect([[ - 2+ [No Name] | - <<<e text with some text with some text | + {5: }{31:2}{5:+ [No Name] }{2: }| + {1:<<<}e text with some text with some text | with some text with some text | Line with some text with some text with | some text with some text with some text | with some text with some text | - [No Name] [+] | - <<<e text with some text with some text | + {2:[No Name] [+] }| + {1:<<<}e text with some text with some text | ^with some text with some text | - Line with some text with some text wi@@@| - [No Name] [+] | + Line with some text with some text wi{1:@@@}| + {3:[No Name] [+] }| | ]]) exec('set winbar=winbar') feed('<C-w>k<C-E>') screen:expect([[ - 2+ [No Name] | - winbar | - <<<e text with some text with some text | + {5: }{31:2}{5:+ [No Name] }{2: }| + {5:winbar }| + {1:<<<}e text with some text with some text | ^with some text with some text | Line with some text with some text with | - some text with some text with some te@@@| - [No Name] [+] | - winbar | - <<<e text with some text with some text | + some text with some text with some te{1:@@@}| + {3:[No Name] [+] }| + {5:winbar }| + {1:<<<}e text with some text with some text | with some text with some text | - [No Name] [+] | + {2:[No Name] [+] }| | ]]) end) it('works with very long line', function() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Brown }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, - }) exec([[ edit test/functional/fixtures/bigfile_oneline.txt setlocal smoothscroll number ]]) screen:expect([[ - {1: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;| - {1: }; 0001;<control>;Cc;0;BN;;;;;N;START| - {1: } OF HEADING;;;; 0002;<control>;Cc;0;| - {1: }BN;;;;;N;START OF TEXT;;;; 0003;<con| - {1: }trol>;Cc;0;BN;;;;;N;END OF TEXT;;;; | - {1: }0004;<control>;Cc;0;BN;;;;;N;END OF | - {1: }TRANSMISSION;;;; 0005;<control>;Cc;0| - {1: };BN;;;;;N;ENQUIRY;;;; 0006;<control>| - {1: };Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;| - {1: }<control>;Cc;0;BN;;;;;N;BELL;;;; 000| - {1: }8;<control>;Cc;0;BN;;;;;N;BACKSPACE;| + {8: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;| + {8: }; 0001;<control>;Cc;0;BN;;;;;N;START| + {8: } OF HEADING;;;; 0002;<control>;Cc;0;| + {8: }BN;;;;;N;START OF TEXT;;;; 0003;<con| + {8: }trol>;Cc;0;BN;;;;;N;END OF TEXT;;;; | + {8: }0004;<control>;Cc;0;BN;;;;;N;END OF | + {8: }TRANSMISSION;;;; 0005;<control>;Cc;0| + {8: };BN;;;;;N;ENQUIRY;;;; 0006;<control>| + {8: };Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; 0007;| + {8: }<control>;Cc;0;BN;;;;;N;BELL;;;; 000| + {8: }8;<control>;Cc;0;BN;;;;;N;BACKSPACE;| | ]]) feed('j') screen:expect([[ - {2:<<<}{1: }CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo| - {1: };0;L;243AB;;;;N;;;;; 2F920;CJK COMPA| - {1: }TIBILITY IDEOGRAPH-2F920;Lo;0;L;7228| - {1: };;;;N;;;;; 2F921;CJK COMPATIBILITY I| - {1: }DEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;;| - {1: } 2F922;CJK COMPATIBILITY IDEOGRAPH-2| - {1: }F922;Lo;0;L;7250;;;;N;;;;; | - {1: 2 }^2F923;CJK COMPATIBILITY IDEOGRAPH-2F| - {1: }923;Lo;0;L;24608;;;;N;;;;; | - {1: 3 }2F924;CJK COMPATIBILITY IDEOGRAPH-2F| - {1: }924;Lo;0;L;7280;;;;N;;;;; | + {1:<<<}{8: }CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo| + {8: };0;L;243AB;;;;N;;;;; 2F920;CJK COMPA| + {8: }TIBILITY IDEOGRAPH-2F920;Lo;0;L;7228| + {8: };;;;N;;;;; 2F921;CJK COMPATIBILITY I| + {8: }DEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;;| + {8: } 2F922;CJK COMPATIBILITY IDEOGRAPH-2| + {8: }F922;Lo;0;L;7250;;;;N;;;;; | + {8: 2 }^2F923;CJK COMPATIBILITY IDEOGRAPH-2F| + {8: }923;Lo;0;L;24608;;;;N;;;;; | + {8: 3 }2F924;CJK COMPATIBILITY IDEOGRAPH-2F| + {8: }924;Lo;0;L;7280;;;;N;;;;; | | ]]) end) + + it('works with very long line and scrolloff', function() + screen:try_resize(40, 8) + exec([[ + set smoothscroll scrolloff=3 + call setline(1, ['one', 'two long '->repeat(100), 'three', 'four', 'five', 'six']) + ]]) + --FIXME: incorrect screen due to reset_skipcol()/curs_columns() shenanigans + feed(':norm j721|<CR>') + screen:expect([[ + two long two long two long two long two | + long two long two long two long two long| + two long two long two long two long two| + ^ long two long two long two long two lon| + g two long two long two long two long tw| + o long two long two long two long two lo| + ng two long two long two long two long t| + :norm j721| | + ]]) + feed('gj') + screen:expect([[ + {1:<<<}two long two long two long two long t| + wo long two long two long two long two l| + ong two long two long two long two long | + two long two long two long two long two | + ^long two long two long two long two long| + two long two long two long two long two| + long two long two long two long two lon| + :norm j721| | + ]]) + feed('gj') + screen:expect([[ + {1:<<<}long two long two long two long two l| + ong two long two long two long two long | + two long two long two long two long two | + long two long two long two long two long| + ^ two long two long two long two long two| + long two long two long two long two lon| + g two long two long | + :norm j721| | + ]]) + feed('gj') + screen:expect([[ + {1:<<<}long two long two long two long two l| + ong two long two long two long two long | + two long two long two long two long two | + long two long two long two long two long| + two long two long two long two long two| + ^ long two long two long two long two lon| + g two long two long | + :norm j721| | + ]]) + feed('gj') + screen:expect([[ + {1:<<<}long two long two long two long two l| + ong two long two long two long two long | + two long two long two long two long two | + long two long two long two long two long| + two long two long two long two long two| + long two long two long two long two lon| + ^g two long two long | + :norm j721| | + ]]) + feed('gj') + screen:expect([[ + {1:<<<} long two long two long two long two | + long two long two long two long two long| + two long two long two long two long two| + long two long two long two long two lon| + g two long two long | + ^three | + four | + :norm j721| | + ]]) + feed('gk') + --FIXME: incorrect screen due to reset_skipcol()/curs_columns() shenanigans + screen:expect([[ + two long two long two long two long two | + long two long two long two long two long| + two long two long two long two long two| + long two long two long two long two lon| + g two long two long two long two long tw| + o long two long two long two long two lo| + ^ng two long two long two long two long t| + :norm j721| | + ]]) + end) end) diff --git a/test/functional/legacy/search_mbyte_spec.lua b/test/functional/legacy/search_mbyte_spec.lua index ef7e41aa30..6457567176 100644 --- a/test/functional/legacy/search_mbyte_spec.lua +++ b/test/functional/legacy/search_mbyte_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local poke_eventloop = helpers.poke_eventloop -local clear = helpers.clear -local insert = helpers.insert -local expect = helpers.expect -local command = helpers.command +local poke_eventloop = n.poke_eventloop +local clear = n.clear +local insert = n.insert +local expect = n.expect +local command = n.command describe('search_mbyte', function() before_each(clear) diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua index 2fda341123..d421a96579 100644 --- a/test/functional/legacy/search_spec.lua +++ b/test/functional/legacy/search_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local fn = helpers.fn -local poke_eventloop = helpers.poke_eventloop -local exec = helpers.exec + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local fn = n.fn +local poke_eventloop = n.poke_eventloop +local exec = n.exec describe('search cmdline', function() local screen @@ -745,11 +747,6 @@ describe('Search highlight', function() -- oldtest: Test_hlsearch_dump() it('beyond line end vim-patch:8.2.2542', function() local screen = Screen.new(50, 6) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { background = Screen.colors.Yellow }, -- Search - [3] = { background = Screen.colors.Grey90 }, -- CursorLine - }) screen:attach() exec([[ set hlsearch noincsearch cursorline @@ -759,8 +756,8 @@ describe('Search highlight', function() ]]) feed([[/\_.*<CR>]]) screen:expect([[ - {2:xxx } |*2 - {2:^xxx }{3: }| + {10:xxx } |*2 + {10:^xxx }{21: }| {1:~ }|*2 /\_.* | ]]) diff --git a/test/functional/legacy/search_stat_spec.lua b/test/functional/legacy/search_stat_spec.lua index 378060d316..7779b8bef1 100644 --- a/test/functional/legacy/search_stat_spec.lua +++ b/test/functional/legacy/search_stat_spec.lua @@ -1,6 +1,7 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, exec, command = helpers.clear, helpers.feed, helpers.exec, helpers.command + +local clear, feed, exec, command = n.clear, n.feed, n.exec, n.command describe('search stat', function() local screen diff --git a/test/functional/legacy/signs_spec.lua b/test/functional/legacy/signs_spec.lua index 0e65edbcf8..614673ee3c 100644 --- a/test/functional/legacy/signs_spec.lua +++ b/test/functional/legacy/signs_spec.lua @@ -1,7 +1,8 @@ -- Tests for signs -local helpers = require('test.functional.helpers')(after_each) -local clear, command, expect = helpers.clear, helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, command, expect = n.clear, n.command, n.expect describe('signs', function() setup(clear) diff --git a/test/functional/legacy/source_spec.lua b/test/functional/legacy/source_spec.lua index 7a19541a77..a910dc3d43 100644 --- a/test/functional/legacy/source_spec.lua +++ b/test/functional/legacy/source_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed = helpers.feed -local write_file = helpers.write_file + +local clear = n.clear +local feed = n.feed +local write_file = t.write_file before_each(clear) @@ -16,16 +18,12 @@ describe(':source!', function() ]] ) local screen = Screen.new(75, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) screen:attach() feed(':source! Xscript.vim\n') screen:expect([[ ^ | - {0:~ }|*4 - {1:E22: Scripts nested too deep} | + {1:~ }|*4 + {9:E22: Scripts nested too deep} | ]]) os.remove('Xscript.vim') end) diff --git a/test/functional/legacy/statusline_spec.lua b/test/functional/legacy/statusline_spec.lua index 567e829879..148166fdc3 100644 --- a/test/functional/legacy/statusline_spec.lua +++ b/test/functional/legacy/statusline_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local exec = n.exec +local feed = n.feed before_each(clear) @@ -15,11 +16,6 @@ describe('statusline', function() end) it('is updated in cmdline mode when using window-local statusline vim-patch:8.2.2737', function() - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { bold = true, reverse = true }, -- StatusLine - [3] = { reverse = true }, -- StatusLineNC - }) exec([[ setlocal statusline=-%{mode()}- split @@ -28,30 +24,25 @@ describe('statusline', function() screen:expect([[ ^ | {1:~ }| - {2:+n+ }| + {3:+n+ }| | {1:~ }| - {3:-n- }| + {2:-n- }| | ]]) feed(':') screen:expect([[ | {1:~ }| - {2:+c+ }| + {3:+c+ }| | {1:~ }| - {3:-c- }| + {2:-c- }| :^ | ]]) end) it('truncated item does not cause off-by-one highlight vim-patch:8.2.4929', function() - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { foreground = Screen.colors.Blue }, -- User1 - [3] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- User2 - }) exec([[ set laststatus=2 hi! link User1 Directory @@ -61,20 +52,13 @@ describe('statusline', function() screen:expect([[ ^ | {1:~ }|*4 - {3:<F}{2:GHI }| + {9:<F}{18:GHI }| | ]]) end) -- oldtest: Test_statusline_showcmd() it('showcmdloc=statusline works', function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { bold = true }, -- MoreMsg - [3] = { bold = true, reverse = true }, -- StatusLine - [5] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, -- Folded - }) exec([[ func MyStatusLine() return '%S' @@ -92,9 +76,9 @@ describe('statusline', function() feed('g') screen:expect([[ - {5:+-- 2 lines: a···································}| + {13:+-- 2 lines: a···································}| ^c | - {0:~ }|*3 + {1:~ }|*3 {3:g }| | ]]) @@ -105,19 +89,19 @@ describe('statusline', function() ^a | b | c | - {0:~ }|*2 + {1:~ }|*2 {3: }| | ]]) feed('<C-V>Gl') screen:expect([[ - {1:a} | - {1:b} | - {1:c}^ | - {0:~ }|*2 + {17:a} | + {17:b} | + {17:c}^ | + {1:~ }|*2 {3:3x2 }| - {2:-- VISUAL BLOCK --} | + {5:-- VISUAL BLOCK --} | ]]) feed('<Esc>1234') @@ -125,7 +109,7 @@ describe('statusline', function() a | b | ^c | - {0:~ }|*2 + {1:~ }|*2 {3:1234 }| | ]]) @@ -137,7 +121,7 @@ describe('statusline', function() a | b | ^c | - {0:~ }|*2 + {1:~ }|*2 {3:[No Name] [+] 1234 }| : | ]]) diff --git a/test/functional/legacy/substitute_spec.lua b/test/functional/legacy/substitute_spec.lua index b462c10202..647d62782c 100644 --- a/test/functional/legacy/substitute_spec.lua +++ b/test/functional/legacy/substitute_spec.lua @@ -2,12 +2,14 @@ -- Test for submatch() on substitute(). -- Test for *:s%* on :substitute. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed, insert = helpers.feed, helpers.insert -local exec = helpers.exec -local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect -local eq, eval = helpers.eq, helpers.eval + +local feed, insert = n.feed, n.insert +local exec = n.exec +local clear, feed_command, expect = n.clear, n.feed_command, n.expect +local eq, eval = t.eq, n.eval describe('substitute()', function() before_each(clear) @@ -209,11 +211,6 @@ describe(':substitute', function() it('first char is highlighted with confirmation dialog and empty match', function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { reverse = true }, -- IncSearch - [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - }) screen:attach() exec([[ set nohlsearch noincsearch @@ -221,11 +218,11 @@ describe(':substitute', function() ]]) feed(':%s/^/ /c<CR>') screen:expect([[ - {1:o}ne | + {2:o}ne | two | three | - {0:~ }|*4 - {2:replace with (y/n/a/q/l/^E/^Y)?}^ | + {1:~ }|*4 + {6:replace with (y/n/a/q/l/^E/^Y)?}^ | ]]) end) end) diff --git a/test/functional/legacy/syn_attr_spec.lua b/test/functional/legacy/syn_attr_spec.lua index ec47bdf9af..155eb9ce11 100644 --- a/test/functional/legacy/syn_attr_spec.lua +++ b/test/functional/legacy/syn_attr_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval -- oldtest: Test_missing_attr() describe('synIDattr()', function() diff --git a/test/functional/legacy/tabline_spec.lua b/test/functional/legacy/tabline_spec.lua index 683c7d9bd7..4ce32f2fdd 100644 --- a/test/functional/legacy/tabline_spec.lua +++ b/test/functional/legacy/tabline_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local exec = n.exec +local feed = n.feed before_each(clear) @@ -16,14 +17,6 @@ describe('tabline', function() -- oldtest: Test_tabline_showcmd() it('showcmdloc=tabline works', function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - [2] = { bold = true }, -- MoreMsg, TabLineSel - [3] = { reverse = true }, -- TabLineFill - [4] = { background = Screen.colors.LightGrey, underline = true }, -- TabLine - [5] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, -- Folded - }) exec([[ func MyTabLine() return '%S' @@ -41,41 +34,41 @@ describe('tabline', function() feed('g') screen:expect([[ - {3:g }| - {5:+-- 2 lines: a···································}| + {2:g }| + {13:+-- 2 lines: a···································}| ^c | - {0:~ }|*3 + {1:~ }|*3 | ]]) -- typing "gg" should open the fold feed('g') screen:expect([[ - {3: }| + {2: }| ^a | b | c | - {0:~ }|*2 + {1:~ }|*2 | ]]) feed('<C-V>Gl') screen:expect([[ - {3:3x2 }| - {1:a} | - {1:b} | - {1:c}^ | - {0:~ }|*2 - {2:-- VISUAL BLOCK --} | + {2:3x2 }| + {17:a} | + {17:b} | + {17:c}^ | + {1:~ }|*2 + {5:-- VISUAL BLOCK --} | ]]) feed('<Esc>1234') screen:expect([[ - {3:1234 }| + {2:1234 }| a | b | ^c | - {0:~ }|*2 + {1:~ }|*2 | ]]) @@ -83,11 +76,11 @@ describe('tabline', function() feed(':<CR>') feed('1234') screen:expect([[ - {2: + [No Name] }{3: }{4:1234}{3: }| + {5: + [No Name] }{2: }{24:1234}{2: }| a | b | ^c | - {0:~ }|*2 + {1:~ }|*2 : | ]]) end) diff --git a/test/functional/legacy/tagcase_spec.lua b/test/functional/legacy/tagcase_spec.lua index f84fc673cf..e5bdd4658a 100644 --- a/test/functional/legacy/tagcase_spec.lua +++ b/test/functional/legacy/tagcase_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local exc_exec = helpers.exc_exec -local expect = helpers.expect -local insert = helpers.insert -local source = helpers.source -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local exc_exec = n.exc_exec +local expect = n.expect +local insert = n.insert +local source = n.source +local write_file = t.write_file describe("'tagcase' option", function() setup(function() diff --git a/test/functional/legacy/textobjects_spec.lua b/test/functional/legacy/textobjects_spec.lua index 96f655cc41..9ed8716bff 100644 --- a/test/functional/legacy/textobjects_spec.lua +++ b/test/functional/legacy/textobjects_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local call = helpers.call -local clear = helpers.clear -local command = helpers.command -local expect = helpers.expect -local source = helpers.source +local n = require('test.functional.testnvim')() + +local call = n.call +local clear = n.clear +local command = n.command +local expect = n.expect +local source = n.source describe('Text object', function() before_each(function() diff --git a/test/functional/legacy/undolevels_spec.lua b/test/functional/legacy/undolevels_spec.lua index e8badc6864..8453921669 100644 --- a/test/functional/legacy/undolevels_spec.lua +++ b/test/functional/legacy/undolevels_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local source, clear = helpers.source, helpers.clear -local eq, nvim = helpers.eq, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local source, clear = n.source, n.clear +local eq, api = t.eq, n.api describe('undolevel', function() setup(clear) @@ -57,6 +59,6 @@ describe('undolevel', function() call Test_global_local_undolevels() ]]) - eq({}, nvim.nvim_get_vvar('errors')) + eq({}, api.nvim_get_vvar('errors')) end) end) diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua index 67a4bec4c5..cdb0c2ca58 100644 --- a/test/functional/legacy/utf8_spec.lua +++ b/test/functional/legacy/utf8_spec.lua @@ -1,11 +1,13 @@ -- Tests for Unicode manipulations -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, expect = helpers.command, helpers.expect -local eq, eval = helpers.eq, helpers.eval -local source = helpers.source -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed, insert = n.clear, n.feed, n.insert +local command, expect = n.command, n.expect +local eq, eval = t.eq, n.eval +local source = n.source +local poke_eventloop = n.poke_eventloop describe('utf8', function() before_each(clear) diff --git a/test/functional/legacy/vimscript_spec.lua b/test/functional/legacy/vimscript_spec.lua index 8b0a920a3e..66054810a6 100644 --- a/test/functional/legacy/vimscript_spec.lua +++ b/test/functional/legacy/vimscript_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed -local api = helpers.api + +local clear = n.clear +local exec = n.exec +local feed = n.feed +local api = n.api before_each(clear) diff --git a/test/functional/legacy/visual_spec.lua b/test/functional/legacy/visual_spec.lua index 151e5874e1..ab2213b2fc 100644 --- a/test/functional/legacy/visual_spec.lua +++ b/test/functional/legacy/visual_spec.lua @@ -1,9 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) - +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed = helpers.feed -local exec = helpers.exec + +local clear = n.clear +local feed = n.feed +local exec = n.exec before_each(clear) @@ -12,11 +12,6 @@ describe('Visual highlight', function() before_each(function() screen = Screen.new(50, 6) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText - [1] = { bold = true }, -- ModeMsg - [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual - }) screen:attach() end) @@ -30,20 +25,20 @@ describe('Visual highlight', function() feed('<C-V>gg$') screen:expect([[ - {2:aaaaaa}^ | - {2:bbbb } | - {2:cc } | - {0:~ }|*2 - {1:-- VISUAL BLOCK --} | + {17:aaaaaa}^ | + {17:bbbb } | + {17:cc } | + {1:~ }|*2 + {5:-- VISUAL BLOCK --} | ]]) feed('<Esc>gg<C-V>G$') screen:expect([[ - {2:aaaaaa } | - {2:bbbb } | - {2:cc}^ {2: } | - {0:~ }|*2 - {1:-- VISUAL BLOCK --} | + {17:aaaaaa } | + {17:bbbb } | + {17:cc}^ {17: } | + {1:~ }|*2 + {5:-- VISUAL BLOCK --} | ]]) end) @@ -57,9 +52,9 @@ describe('Visual highlight', function() screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a| - {0:+}{2:aaaa}aaaaaa | - {0:~ }|*3 - {1:-- VISUAL --} | + {1:+}{17:aaaa}aaaaaa | + {1:~ }|*3 + {5:-- VISUAL --} | ]]) end) end) diff --git a/test/functional/legacy/window_cmd_spec.lua b/test/functional/legacy/window_cmd_spec.lua index 7fe4ec8eb6..332240d04a 100644 --- a/test/functional/legacy/window_cmd_spec.lua +++ b/test/functional/legacy/window_cmd_spec.lua @@ -1,18 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local command = helpers.command -local feed = helpers.feed + +local clear = n.clear +local exec = n.exec +local exec_lua = n.exec_lua +local command = n.command +local feed = n.feed -- oldtest: Test_window_cmd_ls0_split_scrolling() it('scrolling with laststatus=0 and :botright split', function() clear('--cmd', 'set ruler') local screen = Screen.new(40, 10) - screen:set_default_attr_ids({ - [1] = { reverse = true }, -- StatusLineNC - }) screen:attach() exec([[ set laststatus=0 @@ -25,7 +23,7 @@ it('scrolling with laststatus=0 and :botright split', function() 98 | 99 | 100 | - {1:[No Name] [+] 100,1 Bot}| + {2:[No Name] [+] 100,1 Bot}| 97 | 98 | 99 | @@ -65,10 +63,10 @@ describe('splitkeep', function() 99 | ^100 | 101 | - [No Name] [+] | + {3:[No Name] [+] }| 5 | 6 | - [No Name] [+] | + {2:[No Name] [+] }| | ]]) @@ -77,10 +75,10 @@ describe('splitkeep', function() 100 | ^101 | 102 | - [No Name] [+] | + {3:[No Name] [+] }| 5 | 6 | - [No Name] [+] | + {2:[No Name] [+] }| | ]]) @@ -90,10 +88,10 @@ describe('splitkeep', function() 198 | 199 | ^200 | - [No Name] [+] | + {3:[No Name] [+] }| 5 | 6 | - [No Name] [+] | + {2:[No Name] [+] }| | ]]) end) @@ -135,13 +133,13 @@ describe('splitkeep', function() 3 | 4 | 5 | - [No Name] [+] | + {2:[No Name] [+] }| ^7 | 8 | 9 | 10 | 11 | - [No Name] [+] | + {3:[No Name] [+] }| | ]]) feed(':quit<CR>Ht') @@ -152,13 +150,13 @@ describe('splitkeep', function() 3 | 4 | 5 | - [No Name] [+] | + {3:[No Name] [+] }| 7 | 8 | 9 | 10 | 11 | - [No Name] [+] | + {2:[No Name] [+] }| :quit | ]]) feed(':set sb<CR>:quit<CR>Gj') @@ -168,14 +166,14 @@ describe('splitkeep', function() 3 | 4 | ^5 | - [No Name] [+] | + {3:[No Name] [+] }| 7 | 8 | 9 | 10 | 11 | 12 | - [No Name] [+] | + {2:[No Name] [+] }| :quit | ]]) feed(':quit<CR>Gt') @@ -185,14 +183,14 @@ describe('splitkeep', function() 3 | 4 | 5 | - [No Name] [+] | + {2:[No Name] [+] }| 7 | 8 | 9 | 10 | 11 | ^12 | - [No Name] [+] | + {3:[No Name] [+] }| :quit | ]]) end) @@ -213,70 +211,70 @@ describe('splitkeep', function() ]]) feed('L:wincmd s<CR>') screen:expect([[ - 1 +-- 7 lines: int FuncName() {···················| - 8 after fold | - 9 +-- 7 lines: int FuncName() {···················| - 16 after fold | - 17 +-- 7 lines: int FuncName() {···················| - 24 ^after fold | - [No Name] [+] | - 32 after fold | - 33 +-- 7 lines: int FuncName() {···················| - 40 after fold | - 41 +-- 7 lines: int FuncName() {···················| - 48 after fold | - [No Name] [+] | + {8: 1 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 8 }after fold | + {8: 9 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 16 }after fold | + {8: 17 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 24 }^after fold | + {3:[No Name] [+] }| + {8: 32 }after fold | + {8: 33 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 40 }after fold | + {8: 41 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 48 }after fold | + {2:[No Name] [+] }| :wincmd s | ]]) feed(':quit<CR>') screen:expect([[ - 1 +-- 7 lines: int FuncName() {···················| - 8 after fold | - 9 +-- 7 lines: int FuncName() {···················| - 16 after fold | - 17 +-- 7 lines: int FuncName() {···················| - 24 after fold | - 25 +-- 7 lines: int FuncName() {···················| - 32 after fold | - 33 +-- 7 lines: int FuncName() {···················| - 40 after fold | - 41 +-- 7 lines: int FuncName() {···················| - 48 after fold | - 49 ^+-- 7 lines: int FuncName() {···················| + {8: 1 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 8 }after fold | + {8: 9 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 16 }after fold | + {8: 17 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 24 }after fold | + {8: 25 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 32 }after fold | + {8: 33 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 40 }after fold | + {8: 41 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 48 }after fold | + {8: 49 }{13:^+-- 7 lines: int FuncName() {···················}| :quit | ]]) feed('H:below split<CR>') screen:expect([[ - 1 +-- 7 lines: int FuncName() {···················| - 8 after fold | - 9 +-- 7 lines: int FuncName() {···················| - 16 after fold | - 17 +-- 7 lines: int FuncName() {···················| - [No Name] [+] | - 25 ^+-- 7 lines: int FuncName() {···················| - 32 after fold | - 33 +-- 7 lines: int FuncName() {···················| - 40 after fold | - 41 +-- 7 lines: int FuncName() {···················| - 48 after fold | - [No Name] [+] | + {8: 1 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 8 }after fold | + {8: 9 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 16 }after fold | + {8: 17 }{13:+-- 7 lines: int FuncName() {···················}| + {2:[No Name] [+] }| + {8: 25 }{13:^+-- 7 lines: int FuncName() {···················}| + {8: 32 }after fold | + {8: 33 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 40 }after fold | + {8: 41 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 48 }after fold | + {3:[No Name] [+] }| :below split | ]]) feed(':wincmd k<CR>:quit<CR>') screen:expect([[ - 1 +-- 7 lines: int FuncName() {···················| - 8 after fold | - 9 +-- 7 lines: int FuncName() {···················| - 16 after fold | - 17 +-- 7 lines: int FuncName() {···················| - 24 after fold | - 25 ^+-- 7 lines: int FuncName() {···················| - 32 after fold | - 33 +-- 7 lines: int FuncName() {···················| - 40 after fold | - 41 +-- 7 lines: int FuncName() {···················| - 48 after fold | - 49 +-- 7 lines: int FuncName() {···················| + {8: 1 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 8 }after fold | + {8: 9 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 16 }after fold | + {8: 17 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 24 }after fold | + {8: 25 }{13:^+-- 7 lines: int FuncName() {···················}| + {8: 32 }after fold | + {8: 33 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 40 }after fold | + {8: 41 }{13:+-- 7 lines: int FuncName() {···················}| + {8: 48 }after fold | + {8: 49 }{13:+-- 7 lines: int FuncName() {···················}| :quit | ]]) end) @@ -296,13 +294,13 @@ describe('splitkeep', function() a | b | c | - ~ |*4 - [No Name] | + {1:~ }|*4 + {2:[No Name] }| ^a | b | c | - ~ | - [No Name] | + {1:~ }| + {3:[No Name] }| | ]]) end) @@ -317,16 +315,16 @@ describe('splitkeep', function() wincmd s ]]) screen:expect([[ - <<<e line with lots of text in one line | + {1:<<<}e line with lots of text in one line | with lots of text in one line with lots | of text in one line | - ~ | - [No Name] [+] | - <<<e line with lots of text in one line | + {1:~ }| + {2:[No Name] [+] }| + {1:<<<}e line with lots of text in one line | ^with lots of text in one line with lots | of text in one line | - ~ |*2 - [No Name] [+] | + {1:~ }|*2 + {3:[No Name] [+] }| | ]]) end) diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua index 82021dd98d..85f2a1623c 100644 --- a/test/functional/legacy/wordcount_spec.lua +++ b/test/functional/legacy/wordcount_spec.lua @@ -1,10 +1,12 @@ -- Test for wordcount() function -local helpers = require('test.functional.helpers')(after_each) -local feed, insert, source = helpers.feed, helpers.insert, helpers.source -local clear, command = helpers.clear, helpers.command -local eq, eval = helpers.eq, helpers.eval -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local feed, insert, source = n.feed, n.insert, n.source +local clear, command = n.clear, n.command +local eq, eval = t.eq, n.eval +local poke_eventloop = n.poke_eventloop describe('wordcount', function() before_each(clear) diff --git a/test/functional/legacy/writefile_spec.lua b/test/functional/legacy/writefile_spec.lua index 4d54e07d6a..a5a2c3c682 100644 --- a/test/functional/legacy/writefile_spec.lua +++ b/test/functional/legacy/writefile_spec.lua @@ -1,7 +1,8 @@ -- Tests for writefile() -local helpers = require('test.functional.helpers')(after_each) -local clear, command, expect = helpers.clear, helpers.command, helpers.expect +local n = require('test.functional.testnvim')() + +local clear, command, expect = n.clear, n.command, n.expect describe('writefile', function() setup(clear) diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua index acd56a0ddb..56969150bd 100644 --- a/test/functional/lua/api_spec.lua +++ b/test/functional/lua/api_spec.lua @@ -1,15 +1,16 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) - -local exc_exec = helpers.exc_exec -local remove_trace = helpers.remove_trace -local fn = helpers.fn -local clear = helpers.clear -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exc_exec = n.exc_exec +local remove_trace = t.remove_trace +local fn = n.fn +local clear = n.clear +local eval = n.eval local NIL = vim.NIL -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local pcall_err = helpers.pcall_err +local eq = t.eq +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err before_each(clear) diff --git a/test/functional/lua/base64_spec.lua b/test/functional/lua/base64_spec.lua index 21fd536a98..529f5f56e8 100644 --- a/test/functional/lua/base64_spec.lua +++ b/test/functional/lua/base64_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local pcall_err = helpers.pcall_err -local matches = helpers.matches +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local pcall_err = t.pcall_err +local matches = t.matches describe('vim.base64', function() before_each(clear) @@ -42,6 +44,7 @@ describe('vim.base64', function() ̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕ Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮ ]], + 'Hello\0world', } for _, v in ipairs(values) do diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index 714e1b951f..d4af7e4732 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -1,17 +1,19 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) - -local command = helpers.command -local api = helpers.api -local fn = helpers.fn -local clear = helpers.clear -local eq = helpers.eq -local fail = helpers.fail -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local expect_events = helpers.expect_events -local write_file = helpers.write_file -local dedent = helpers.dedent +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') + +local command = n.command +local api = n.api +local fn = n.fn +local clear = n.clear +local eq = t.eq +local fail = t.fail +local exec_lua = n.exec_lua +local feed = n.feed +local expect_events = t.expect_events +local write_file = t.write_file +local dedent = t.dedent local origlines = { 'original line 1', @@ -291,11 +293,11 @@ describe('lua buffer event callbacks: on_lines', function() exec_lua(code) command('q!') - helpers.assert_alive() + n.assert_alive() exec_lua(code) command('bd!') - helpers.assert_alive() + n.assert_alive() end) it('#12718 lnume', function() @@ -312,31 +314,71 @@ describe('lua buffer event callbacks: on_lines', function() feed('G0') feed('p') -- Is the last arg old_byte_size correct? Doesn't matter for this PR - eq(api.nvim_get_var('linesev'), { 'lines', 1, 4, 2, 3, 5, 4 }) + eq({ 'lines', 1, 4, 2, 3, 5, 4 }, api.nvim_get_var('linesev')) feed('2G0') feed('p') - eq(api.nvim_get_var('linesev'), { 'lines', 1, 5, 1, 4, 4, 8 }) + eq({ 'lines', 1, 5, 1, 4, 4, 8 }, api.nvim_get_var('linesev')) feed('1G0') feed('P') - eq(api.nvim_get_var('linesev'), { 'lines', 1, 6, 0, 3, 3, 9 }) + eq({ 'lines', 1, 6, 0, 3, 3, 9 }, api.nvim_get_var('linesev')) end) - it( - 'calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729', - function() - exec_lua([[ + it('nvim_buf_call() from callback does not cause wrong Normal mode CTRL-A #16729', function() + exec_lua([[ vim.api.nvim_buf_attach(0, false, { on_lines = function(...) vim.api.nvim_buf_call(0, function() end) end, }) ]]) - feed('itest123<Esc><C-A>') - eq('test124', api.nvim_get_current_line()) - end - ) + feed('itest123<Esc><C-A>') + eq('test124', api.nvim_get_current_line()) + end) + + it('setting extmark in on_lines callback works', function() + local screen = Screen.new(40, 6) + screen:attach() + + api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa', 'bbb', 'ccc' }) + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.api.nvim_buf_attach(0, false, { + on_lines = function(_, _, _, row, _, end_row) + vim.api.nvim_buf_clear_namespace(0, ns, row, end_row) + for i = row, end_row - 1 do + local id = vim.api.nvim_buf_set_extmark(0, ns, i, 0, { + virt_text = {{ 'NEW' .. tostring(i), 'WarningMsg' }}, + }) + end + end, + }) + ]]) + + feed('o') + screen:expect({ + grid = [[ + aaa | + ^ {19:NEW1} | + bbb | + ccc | + {1:~ }| + {5:-- INSERT --} | + ]], + }) + feed('<CR>') + screen:expect({ + grid = [[ + aaa | + {19:NEW1} | + ^ {19:NEW2} | + bbb | + ccc | + {5:-- INSERT --} | + ]], + }) + end) end) describe('lua: nvim_buf_attach on_bytes', function() @@ -426,14 +468,14 @@ describe('lua: nvim_buf_attach on_bytes', function() it('opening lines', function() local check_events = setup_eventcheck(verify, origlines) - -- api.nvim_set_option_value('autoindent', true, {}) + api.nvim_set_option_value('autoindent', false, {}) feed 'Go' check_events { { 'test1', 'bytes', 1, 3, 7, 0, 114, 0, 0, 0, 1, 0, 1 }, } feed '<cr>' check_events { - { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 }, + { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 }, } end) @@ -447,7 +489,7 @@ describe('lua: nvim_buf_attach on_bytes', function() feed '<cr>' check_events { { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 }, - { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 }, + { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 4, 5 }, } end) @@ -477,7 +519,7 @@ describe('lua: nvim_buf_attach on_bytes', function() api.nvim_set_option_value('filetype', 'c', {}) feed 'A<CR>' check_events { - { 'test1', 'bytes', 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 }, + { 'test1', 'bytes', 1, 3, 0, 10, 10, 0, 0, 0, 1, 3, 4 }, } feed '<ESC>' @@ -493,7 +535,7 @@ describe('lua: nvim_buf_attach on_bytes', function() feed '<CR>' check_events { { 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 }, - { 'test1', 'bytes', 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 }, + { 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 0, 0, 1, 3, 4 }, } end) @@ -541,7 +583,7 @@ describe('lua: nvim_buf_attach on_bytes', function() feed 'cc' check_events { - { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 }, + { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 15, 15, 0, 0, 0 }, } feed '<ESC>' @@ -924,7 +966,7 @@ describe('lua: nvim_buf_attach on_bytes', function() command('e! Xtest-undofile') command('set undodir=. | set undofile') - local ns = helpers.request('nvim_create_namespace', 'ns1') + local ns = n.request('nvim_create_namespace', 'ns1') api.nvim_buf_set_extmark(0, ns, 0, 0, {}) eq({ '12345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true)) @@ -1225,6 +1267,25 @@ describe('lua: nvim_buf_attach on_bytes', function() } end) + it('prompt buffer', function() + local check_events = setup_eventcheck(verify, {}) + api.nvim_set_option_value('buftype', 'prompt', {}) + feed('i') + check_events { + { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2 }, + } + feed('<CR>') + check_events { + { 'test1', 'bytes', 1, 4, 1, 0, 3, 0, 0, 0, 1, 0, 1 }, + { 'test1', 'bytes', 1, 5, 1, 0, 3, 0, 0, 0, 0, 2, 2 }, + } + feed('<CR>') + check_events { + { 'test1', 'bytes', 1, 6, 2, 0, 6, 0, 0, 0, 1, 0, 1 }, + { 'test1', 'bytes', 1, 7, 2, 0, 6, 0, 0, 0, 0, 2, 2 }, + } + end) + local function test_lockmarks(mode) local description = (mode ~= '') and mode or '(baseline)' it('test_lockmarks ' .. description .. ' %delete _', function() diff --git a/test/functional/lua/command_line_completion_spec.lua b/test/functional/lua/command_line_completion_spec.lua index b88a38082f..2ba432133b 100644 --- a/test/functional/lua/command_line_completion_spec.lua +++ b/test/functional/lua/command_line_completion_spec.lua @@ -1,8 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua local get_completions = function(input, env) return exec_lua('return {vim._expand_pat(...)}', input, env) diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index b8d0638ce5..57b084d3d6 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -1,24 +1,25 @@ -- Test suite for checking :lua* commands -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq +local eq = t.eq local NIL = vim.NIL -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local matches = helpers.matches -local api = helpers.api -local exec_lua = helpers.exec_lua -local exec_capture = helpers.exec_capture -local fn = helpers.fn -local source = helpers.source -local dedent = helpers.dedent -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err -local write_file = helpers.write_file -local remove_trace = helpers.remove_trace +local eval = n.eval +local feed = n.feed +local clear = n.clear +local matches = t.matches +local api = n.api +local exec_lua = n.exec_lua +local exec_capture = n.exec_capture +local fn = n.fn +local source = n.source +local dedent = t.dedent +local command = n.command +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err +local write_file = t.write_file +local remove_trace = t.remove_trace before_each(clear) diff --git a/test/functional/lua/comment_spec.lua b/test/functional/lua/comment_spec.lua new file mode 100644 index 0000000000..bbf061a2ab --- /dev/null +++ b/test/functional/lua/comment_spec.lua @@ -0,0 +1,651 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local api = n.api +local clear = n.clear +local eq = t.eq +local exec_capture = n.exec_capture +local exec_lua = n.exec_lua +local feed = n.feed + +-- Reference text +-- aa +-- aa +-- aa +-- +-- aa +-- aa +-- aa +local example_lines = { 'aa', ' aa', ' aa', '', ' aa', ' aa', 'aa' } + +local set_commentstring = function(commentstring) + api.nvim_set_option_value('commentstring', commentstring, { buf = 0 }) +end + +local get_lines = function(from, to) + from, to = from or 0, to or -1 + return api.nvim_buf_get_lines(0, from, to, false) +end + +local set_lines = function(lines, from, to) + from, to = from or 0, to or -1 + api.nvim_buf_set_lines(0, from, to, false, lines) +end + +local set_cursor = function(row, col) + api.nvim_win_set_cursor(0, { row, col }) +end + +local get_cursor = function() + return api.nvim_win_get_cursor(0) +end + +local setup_treesitter = function() + -- NOTE: This leverages bundled Vimscript and Lua tree-sitter parsers + api.nvim_set_option_value('filetype', 'vim', { buf = 0 }) + exec_lua('vim.treesitter.start()') +end + +before_each(function() + clear({ args_rm = { '--cmd' }, args = { '--clean' } }) +end) + +describe('commenting', function() + before_each(function() + set_lines(example_lines) + set_commentstring('# %s') + end) + + describe('toggle_lines()', function() + local toggle_lines = function(...) + exec_lua('require("vim._comment").toggle_lines(...)', ...) + end + + it('works', function() + toggle_lines(3, 5) + eq(get_lines(2, 5), { ' # aa', ' #', ' # aa' }) + + toggle_lines(3, 5) + eq(get_lines(2, 5), { ' aa', '', ' aa' }) + end) + + it("works with different 'commentstring' options", function() + local validate = function(lines_before, lines_after, lines_again) + set_lines(lines_before) + toggle_lines(1, #lines_before) + eq(get_lines(), lines_after) + toggle_lines(1, #lines_before) + eq(get_lines(), lines_again or lines_before) + end + + -- Single whitespace inside comment parts (main case) + set_commentstring('# %s #') + -- - General case + validate( + { 'aa', ' aa', 'aa ', ' aa ' }, + { '# aa #', '# aa #', '# aa #', '# aa #' } + ) + -- - Tabs + validate( + { 'aa', '\taa', 'aa\t', '\taa\t' }, + { '# aa #', '# \taa #', '# aa\t #', '# \taa\t #' } + ) + -- - With indent + validate({ ' aa', ' aa' }, { ' # aa #', ' # aa #' }) + -- - With blank/empty lines + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa #', ' ##', ' ##', ' ##' }, + { ' aa', '', '', '' } + ) + + set_commentstring('# %s') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '# aa', '# aa', '# aa ', '# aa ' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '# aa', '# \taa', '# aa\t', '# \taa\t' }) + validate({ ' aa', ' aa' }, { ' # aa', ' # aa' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + set_commentstring('%s #') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa #', ' aa #', 'aa #', ' aa #' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa #', '\taa #', 'aa\t #', '\taa\t #' }) + validate({ ' aa', ' aa' }, { ' aa #', ' aa #' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' aa #', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + -- No whitespace in parts + set_commentstring('#%s#') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '#aa#', '# aa#', '#aa #', '# aa #' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '#aa#', '#\taa#', '#aa\t#', '#\taa\t#' }) + validate({ ' aa', ' aa' }, { ' #aa#', ' # aa#' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' #aa#', ' ##', ' ##', ' ##' }, + { ' aa', '', '', '' } + ) + + set_commentstring('#%s') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '#aa', '# aa', '#aa ', '# aa ' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '#aa', '#\taa', '#aa\t', '#\taa\t' }) + validate({ ' aa', ' aa' }, { ' #aa', ' # aa' }) + validate({ ' aa', '', ' ', '\t' }, { ' #aa', ' #', ' #', ' #' }, { ' aa', '', '', '' }) + + set_commentstring('%s#') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa#', ' aa#', 'aa #', ' aa #' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa#', '\taa#', 'aa\t#', '\taa\t#' }) + validate({ ' aa', ' aa' }, { ' aa#', ' aa#' }) + validate({ ' aa', '', ' ', '\t' }, { ' aa#', ' #', ' #', ' #' }, { ' aa', '', '', '' }) + + -- Extra whitespace inside comment parts + set_commentstring('# %s #') + validate( + { 'aa', ' aa', 'aa ', ' aa ' }, + { '# aa #', '# aa #', '# aa #', '# aa #' } + ) + validate( + { 'aa', '\taa', 'aa\t', '\taa\t' }, + { '# aa #', '# \taa #', '# aa\t #', '# \taa\t #' } + ) + validate({ ' aa', ' aa' }, { ' # aa #', ' # aa #' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa #', ' ##', ' ##', ' ##' }, + { ' aa', '', '', '' } + ) + + set_commentstring('# %s') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '# aa', '# aa', '# aa ', '# aa ' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '# aa', '# \taa', '# aa\t', '# \taa\t' }) + validate({ ' aa', ' aa' }, { ' # aa', ' # aa' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + set_commentstring('%s #') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa #', ' aa #', 'aa #', ' aa #' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa #', '\taa #', 'aa\t #', '\taa\t #' }) + validate({ ' aa', ' aa' }, { ' aa #', ' aa #' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' aa #', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + -- Whitespace outside of comment parts + set_commentstring(' # %s # ') + validate( + { 'aa', ' aa', 'aa ', ' aa ' }, + { ' # aa # ', ' # aa # ', ' # aa # ', ' # aa # ' } + ) + validate( + { 'aa', '\taa', 'aa\t', '\taa\t' }, + { ' # aa # ', ' # \taa # ', ' # aa\t # ', ' # \taa\t # ' } + ) + validate({ ' aa', ' aa' }, { ' # aa # ', ' # aa # ' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa # ', ' ##', ' ##', ' ##' }, + { ' aa', '', '', '' } + ) + + set_commentstring(' # %s ') + validate( + { 'aa', ' aa', 'aa ', ' aa ' }, + { ' # aa ', ' # aa ', ' # aa ', ' # aa ' } + ) + validate( + { 'aa', '\taa', 'aa\t', '\taa\t' }, + { ' # aa ', ' # \taa ', ' # aa\t ', ' # \taa\t ' } + ) + validate({ ' aa', ' aa' }, { ' # aa ', ' # aa ' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' # aa ', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + set_commentstring(' %s # ') + validate( + { 'aa', ' aa', 'aa ', ' aa ' }, + { ' aa # ', ' aa # ', ' aa # ', ' aa # ' } + ) + validate( + { 'aa', '\taa', 'aa\t', '\taa\t' }, + { ' aa # ', ' \taa # ', ' aa\t # ', ' \taa\t # ' } + ) + validate({ ' aa', ' aa' }, { ' aa # ', ' aa # ' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' aa # ', ' #', ' #', ' #' }, + { ' aa', '', '', '' } + ) + + -- LaTeX + set_commentstring('% %s') + validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '% aa', '% aa', '% aa ', '% aa ' }) + validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '% aa', '% \taa', '% aa\t', '% \taa\t' }) + validate({ ' aa', ' aa' }, { ' % aa', ' % aa' }) + validate( + { ' aa', '', ' ', '\t' }, + { ' % aa', ' %', ' %', ' %' }, + { ' aa', '', '', '' } + ) + end) + + it('respects tree-sitter injections', function() + setup_treesitter() + + local lines = { + 'set background=dark', + 'lua << EOF', + 'print(1)', + 'vim.api.nvim_exec2([[', + ' set background=light', + ']])', + 'EOF', + } + + -- Single line comments + local validate = function(line, ref_output) + set_lines(lines) + toggle_lines(line, line) + eq(get_lines(line - 1, line)[1], ref_output) + end + + validate(1, '"set background=dark') + validate(2, '"lua << EOF') + validate(3, '-- print(1)') + validate(4, '-- vim.api.nvim_exec2([[') + validate(5, ' "set background=light') + validate(6, '-- ]])') + validate(7, '"EOF') + + -- Multiline comments should be computed based on first line 'commentstring' + set_lines(lines) + toggle_lines(1, 3) + local out_lines = get_lines() + eq(out_lines[1], '"set background=dark') + eq(out_lines[2], '"lua << EOF') + eq(out_lines[3], '"print(1)') + end) + + it('correctly computes indent', function() + toggle_lines(2, 4) + eq(get_lines(1, 4), { ' # aa', ' # aa', ' #' }) + end) + + it('correctly detects comment/uncomment', function() + local validate = function(from, to, ref_lines) + set_lines({ '', 'aa', '# aa', '# aa', 'aa', '' }) + toggle_lines(from, to) + eq(get_lines(), ref_lines) + end + + -- It should uncomment only if all non-blank lines are comments + validate(3, 4, { '', 'aa', 'aa', 'aa', 'aa', '' }) + validate(2, 4, { '', '# aa', '# # aa', '# # aa', 'aa', '' }) + validate(3, 5, { '', 'aa', '# # aa', '# # aa', '# aa', '' }) + validate(1, 6, { '#', '# aa', '# # aa', '# # aa', '# aa', '#' }) + + -- Blank lines should be ignored when making a decision + set_lines({ '# aa', '', ' ', '\t', '# aa' }) + toggle_lines(1, 5) + eq(get_lines(), { 'aa', '', ' ', '\t', 'aa' }) + end) + + it('correctly matches comment parts during checking and uncommenting', function() + local validate = function(from, to, ref_lines) + set_lines({ '/*aa*/', '/* aa */', '/* aa */' }) + toggle_lines(from, to) + eq(get_lines(), ref_lines) + end + + -- Should first try to match 'commentstring' parts exactly with their + -- whitespace, with fallback on trimmed parts + set_commentstring('/*%s*/') + validate(1, 3, { 'aa', ' aa ', ' aa ' }) + validate(2, 3, { '/*aa*/', ' aa ', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) + + set_commentstring('/* %s */') + validate(1, 3, { 'aa', 'aa', ' aa ' }) + validate(2, 3, { '/*aa*/', 'aa', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) + + set_commentstring('/* %s */') + validate(1, 3, { 'aa', ' aa ', 'aa' }) + validate(2, 3, { '/*aa*/', ' aa ', 'aa' }) + validate(3, 3, { '/*aa*/', '/* aa */', 'aa' }) + + set_commentstring(' /*%s*/ ') + validate(1, 3, { 'aa', ' aa ', ' aa ' }) + validate(2, 3, { '/*aa*/', ' aa ', ' aa ' }) + validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' }) + end) + + it('uncomments on inconsistent indent levels', function() + set_lines({ '# aa', ' # aa', ' # aa' }) + toggle_lines(1, 3) + eq(get_lines(), { 'aa', ' aa', ' aa' }) + end) + + it('respects tabs', function() + api.nvim_set_option_value('expandtab', false, { buf = 0 }) + set_lines({ '\t\taa', '\t\taa' }) + + toggle_lines(1, 2) + eq(get_lines(), { '\t\t# aa', '\t\t# aa' }) + + toggle_lines(1, 2) + eq(get_lines(), { '\t\taa', '\t\taa' }) + end) + + it('works with trailing whitespace', function() + -- Without right-hand side + set_commentstring('# %s') + set_lines({ ' aa', ' aa ', ' ' }) + toggle_lines(1, 3) + eq(get_lines(), { ' # aa', ' # aa ', ' #' }) + toggle_lines(1, 3) + eq(get_lines(), { ' aa', ' aa ', '' }) + + -- With right-hand side + set_commentstring('%s #') + set_lines({ ' aa', ' aa ', ' ' }) + toggle_lines(1, 3) + eq(get_lines(), { ' aa #', ' aa #', ' #' }) + toggle_lines(1, 3) + eq(get_lines(), { ' aa', ' aa ', '' }) + + -- Trailing whitespace after right side should be preserved for non-blanks + set_commentstring('%s #') + set_lines({ ' aa # ', ' aa #\t', ' # ', ' #\t' }) + toggle_lines(1, 4) + eq(get_lines(), { ' aa ', ' aa\t', '', '' }) + end) + end) + + describe('Operator', function() + it('works in Normal mode', function() + set_cursor(2, 2) + feed('gc', 'ap') + eq(get_lines(), { '# aa', '# aa', '# aa', '#', ' aa', ' aa', 'aa' }) + -- Cursor moves to start line + eq(get_cursor(), { 1, 0 }) + + -- Supports `v:count` + set_lines(example_lines) + set_cursor(2, 0) + feed('2gc', 'ap') + eq(get_lines(), { '# aa', '# aa', '# aa', '#', '# aa', '# aa', '# aa' }) + end) + + it('allows dot-repeat in Normal mode', function() + local doubly_commented = { '# # aa', '# # aa', '# # aa', '# #', '# aa', '# aa', '# aa' } + + set_lines(example_lines) + set_cursor(2, 2) + feed('gc', 'ap') + feed('.') + eq(get_lines(), doubly_commented) + + -- Not immediate dot-repeat + set_lines(example_lines) + set_cursor(2, 2) + feed('gc', 'ap') + set_cursor(7, 0) + feed('.') + eq(get_lines(), doubly_commented) + end) + + it('works in Visual mode', function() + set_cursor(2, 2) + feed('v', 'ap', 'gc') + eq(get_lines(), { '# aa', '# aa', '# aa', '#', ' aa', ' aa', 'aa' }) + + -- Cursor moves to start line + eq(get_cursor(), { 1, 0 }) + end) + + it('allows dot-repeat after initial Visual mode', function() + -- local example_lines = { 'aa', ' aa', ' aa', '', ' aa', ' aa', 'aa' } + + set_lines(example_lines) + set_cursor(2, 2) + feed('vip', 'gc') + eq(get_lines(), { '# aa', '# aa', '# aa', '', ' aa', ' aa', 'aa' }) + eq(get_cursor(), { 1, 0 }) + + -- Dot-repeat after first application in Visual mode should apply to the same + -- relative region + feed('.') + eq(get_lines(), example_lines) + + set_cursor(3, 0) + feed('.') + eq(get_lines(), { 'aa', ' aa', ' # aa', ' #', ' # aa', ' aa', 'aa' }) + end) + + it("respects 'commentstring'", function() + set_commentstring('/*%s*/') + set_cursor(2, 2) + feed('gc', 'ap') + eq(get_lines(), { '/*aa*/', '/* aa*/', '/* aa*/', '/**/', ' aa', ' aa', 'aa' }) + end) + + it("works with empty 'commentstring'", function() + set_commentstring('') + set_cursor(2, 2) + feed('gc', 'ap') + eq(get_lines(), example_lines) + eq(exec_capture('1messages'), [[Option 'commentstring' is empty.]]) + end) + + it('respects tree-sitter injections', function() + setup_treesitter() + + local lines = { + 'set background=dark', + 'lua << EOF', + 'print(1)', + 'vim.api.nvim_exec2([[', + ' set background=light', + ']])', + 'EOF', + } + + -- Single line comments + local validate = function(line, ref_output) + set_lines(lines) + set_cursor(line, 0) + feed('gc_') + eq(get_lines(line - 1, line)[1], ref_output) + end + + validate(1, '"set background=dark') + validate(2, '"lua << EOF') + validate(3, '-- print(1)') + validate(4, '-- vim.api.nvim_exec2([[') + validate(5, ' "set background=light') + validate(6, '-- ]])') + validate(7, '"EOF') + + -- Has proper dot-repeat which recomputes 'commentstring' + set_lines(lines) + + set_cursor(1, 0) + feed('gc_') + eq(get_lines()[1], '"set background=dark') + + set_cursor(3, 0) + feed('.') + eq(get_lines()[3], '-- print(1)') + + -- Multiline comments should be computed based on cursor position + -- which in case of Visual selection means its left part + set_lines(lines) + set_cursor(1, 0) + feed('v2j', 'gc') + local out_lines = get_lines() + eq(out_lines[1], '"set background=dark') + eq(out_lines[2], '"lua << EOF') + eq(out_lines[3], '"print(1)') + end) + + it("recomputes local 'commentstring' based on cursor position", function() + setup_treesitter() + local lines = { + ' print(1)', + 'lua << EOF', + ' print(1)', + 'EOF', + } + set_lines(lines) + + set_cursor(1, 1) + feed('gc_') + eq(get_lines()[1], ' "print(1)') + + set_lines(lines) + set_cursor(3, 2) + feed('.') + eq(get_lines()[3], ' -- print(1)') + end) + + it('preserves marks', function() + set_cursor(2, 0) + -- Set '`<' and '`>' marks + feed('VV') + feed('gc', 'ip') + eq(api.nvim_buf_get_mark(0, '<'), { 2, 0 }) + eq(api.nvim_buf_get_mark(0, '>'), { 2, 2147483647 }) + end) + end) + + describe('Current line', function() + it('works', function() + set_lines(example_lines) + set_cursor(1, 1) + feed('gcc') + eq(get_lines(0, 2), { '# aa', ' aa' }) + + -- Does not comment empty line + set_lines(example_lines) + set_cursor(4, 0) + feed('gcc') + eq(get_lines(2, 5), { ' aa', '', ' aa' }) + + -- Supports `v:count` + set_lines(example_lines) + set_cursor(2, 0) + feed('2gcc') + eq(get_lines(0, 3), { 'aa', ' # aa', ' # aa' }) + end) + + it('allows dot-repeat', function() + set_lines(example_lines) + set_cursor(1, 1) + feed('gcc') + feed('.') + eq(get_lines(), example_lines) + + -- Not immediate dot-repeat + set_lines(example_lines) + set_cursor(1, 1) + feed('gcc') + set_cursor(7, 0) + feed('.') + eq(get_lines(6, 7), { '# aa' }) + end) + + it('respects tree-sitter injections', function() + setup_treesitter() + + local lines = { + 'set background=dark', + 'lua << EOF', + 'print(1)', + 'EOF', + } + set_lines(lines) + + set_cursor(1, 0) + feed('gcc') + eq(get_lines(), { '"set background=dark', 'lua << EOF', 'print(1)', 'EOF' }) + + -- Should work with dot-repeat + set_cursor(3, 0) + feed('.') + eq(get_lines(), { '"set background=dark', 'lua << EOF', '-- print(1)', 'EOF' }) + end) + end) + + describe('Textobject', function() + it('works', function() + set_lines({ 'aa', '# aa', '# aa', 'aa' }) + set_cursor(2, 0) + feed('d', 'gc') + eq(get_lines(), { 'aa', 'aa' }) + end) + + it('allows dot-repeat', function() + set_lines({ 'aa', '# aa', '# aa', 'aa', '# aa' }) + set_cursor(2, 0) + feed('d', 'gc') + set_cursor(3, 0) + feed('.') + eq(get_lines(), { 'aa', 'aa' }) + end) + + it('does nothing when not inside textobject', function() + -- Builtin operators + feed('d', 'gc') + eq(get_lines(), example_lines) + + -- Comment operator + local validate_no_action = function(line, col) + set_lines(example_lines) + set_cursor(line, col) + feed('gc', 'gc') + eq(get_lines(), example_lines) + end + + validate_no_action(1, 1) + validate_no_action(2, 2) + + -- Doesn't work (but should) because both `[` and `]` are set to (1, 0) + -- (instead of more reasonable (1, -1) or (0, 2147483647)). + -- validate_no_action(1, 0) + end) + + it('respects tree-sitter injections', function() + setup_treesitter() + local lines = { + '"set background=dark', + '"set termguicolors', + 'lua << EOF', + '-- print(1)', + '-- print(2)', + 'EOF', + } + set_lines(lines) + + set_cursor(1, 0) + feed('dgc') + eq(get_lines(), { 'lua << EOF', '-- print(1)', '-- print(2)', 'EOF' }) + + -- Should work with dot-repeat + set_cursor(2, 0) + feed('.') + eq(get_lines(), { 'lua << EOF', 'EOF' }) + end) + end) +end) diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 5802925339..05082bc132 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local NIL = vim.NIL -local command = helpers.command -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local matches = helpers.matches -local api = helpers.api -local pcall_err = helpers.pcall_err +local command = n.command +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local matches = t.matches +local api = n.api +local pcall_err = t.pcall_err +local fn = n.fn describe('vim.diagnostic', function() before_each(function() @@ -16,12 +18,12 @@ describe('vim.diagnostic', function() exec_lua [[ require('vim.diagnostic') - function make_diagnostic(msg, x1, y1, x2, y2, severity, source, code) + function make_diagnostic(msg, lnum, col, end_lnum, end_col, severity, source, code) return { - lnum = x1, - col = y1, - end_lnum = x2, - end_col = y2, + lnum = lnum, + col = col, + end_lnum = end_lnum, + end_col = end_col, message = msg, severity = severity, source = source, @@ -29,20 +31,20 @@ describe('vim.diagnostic', function() } end - function make_error(msg, x1, y1, x2, y2, source, code) - return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.ERROR, source, code) + function make_error(msg, lnum, col, end_lnum, end_col, source, code) + return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.ERROR, source, code) end - function make_warning(msg, x1, y1, x2, y2, source, code) - return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.WARN, source, code) + function make_warning(msg, lnum, col, end_lnum, end_col, source, code) + return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.WARN, source, code) end - function make_info(msg, x1, y1, x2, y2, source, code) - return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.INFO, source, code) + function make_info(msg, lnum, col, end_lnum, end_col, source, code) + return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.INFO, source, code) end - function make_hint(msg, x1, y1, x2, y2, source, code) - return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.HINT, source, code) + function make_hint(msg, lnum, col, end_lnum, end_col, source, code) + return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.HINT, source, code) end function count_diagnostics(bufnr, severity, namespace) @@ -109,7 +111,7 @@ describe('vim.diagnostic', function() 'DiagnosticVirtualTextOk', 'DiagnosticVirtualTextWarn', 'DiagnosticWarn', - }, exec_lua([[return vim.fn.getcompletion('Diagnostic', 'highlight')]])) + }, fn.getcompletion('Diagnostic', 'highlight')) end) it('retrieves diagnostics from all buffers and namespaces', function() @@ -205,7 +207,7 @@ describe('vim.diagnostic', function() diag[1].col = 10000 return vim.diagnostic.get()[1].col == 10000 ]] - eq(result, false) + eq(false, result) end) it('resolves buffer number 0 to the current buffer', function() @@ -328,7 +330,7 @@ describe('vim.diagnostic', function() eq( { 1, 1, 2, 0, 2 }, exec_lua [[ - vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns) + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) return { count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns), count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns), @@ -343,7 +345,7 @@ describe('vim.diagnostic', function() eq( all_highlights, exec_lua([[ - vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns) + vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) return { count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns), count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns), @@ -370,7 +372,7 @@ describe('vim.diagnostic', function() vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags) vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags) - vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns) + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) return { count_extmarks(diagnostic_bufnr, diagnostic_ns), @@ -382,8 +384,8 @@ describe('vim.diagnostic', function() eq( { 4, 0 }, exec_lua [[ - vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns) - vim.diagnostic.disable(diagnostic_bufnr, other_ns) + vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = other_ns }) return { count_extmarks(diagnostic_bufnr, diagnostic_ns), @@ -477,7 +479,32 @@ describe('vim.diagnostic', function() end) describe('enable() and disable()', function() - it('works without arguments', function() + it('validation', function() + matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({})]])) + matches( + 'filter: expected table, got string', + pcall_err(exec_lua, [[vim.diagnostic.enable(false, '')]]) + ) + matches( + 'Invalid buffer id: 42', + pcall_err(exec_lua, [[vim.diagnostic.enable(true, { bufnr = 42 })]]) + ) + matches( + 'expected boolean, got number', + pcall_err(exec_lua, [[vim.diagnostic.enable(42, {})]]) + ) + matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({}, 42)]])) + + -- Deprecated signature. + matches('Invalid buffer id: 42', pcall_err(exec_lua, [[vim.diagnostic.enable(42)]])) + -- Deprecated signature. + matches( + 'namespace does not exist or is anonymous', + pcall_err(exec_lua, [[vim.diagnostic.enable(nil, 42)]]) + ) + end) + + it('without arguments', function() local result = exec_lua [[ vim.api.nvim_win_set_buf(0, diagnostic_bufnr) @@ -499,7 +526,7 @@ describe('vim.diagnostic', function() table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) - vim.diagnostic.disable() + vim.diagnostic.enable(false) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) @@ -531,7 +558,7 @@ describe('vim.diagnostic', function() eq(4, result[4]) end) - it('works with only a buffer argument', function() + it('with buffer argument', function() local result = exec_lua [[ local other_bufnr = vim.api.nvim_create_buf(true, false) @@ -560,19 +587,19 @@ describe('vim.diagnostic', function() count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.disable(diagnostic_bufnr) + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.enable(diagnostic_bufnr) + vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.disable(other_bufnr) + vim.diagnostic.enable(false, { bufnr = other_bufnr }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + @@ -587,7 +614,7 @@ describe('vim.diagnostic', function() eq(3, result[4]) end) - it('works with only a namespace argument', function() + it('with a namespace argument', function() local result = exec_lua [[ vim.api.nvim_win_set_buf(0, diagnostic_bufnr) @@ -609,17 +636,17 @@ describe('vim.diagnostic', function() table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) - vim.diagnostic.disable(nil, diagnostic_ns) + vim.diagnostic.enable(false, { ns_id = diagnostic_ns }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) - vim.diagnostic.enable(nil, diagnostic_ns) + vim.diagnostic.enable(true, { ns_id = diagnostic_ns }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) - vim.diagnostic.disable(nil, other_ns) + vim.diagnostic.enable(false, { ns_id = other_ns }) table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns)) @@ -633,8 +660,11 @@ describe('vim.diagnostic', function() eq(2, result[4]) end) - it('works with both a buffer and a namespace argument', function() - local result = exec_lua [[ + --- @return table + local function test_enable(legacy) + local result = exec_lua( + [[ + local legacy = ... local other_bufnr = vim.api.nvim_create_buf(true, false) vim.api.nvim_win_set_buf(0, diagnostic_bufnr) @@ -662,34 +692,68 @@ describe('vim.diagnostic', function() count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns) + if legacy then + vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns) + else + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) + end table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.disable(diagnostic_bufnr, other_ns) + if legacy then + vim.diagnostic.disable(diagnostic_bufnr, other_ns) + else + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = other_ns }) + end table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns) + if legacy then + vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns) + else + vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) + end table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) - -- Should have no effect - vim.diagnostic.disable(other_bufnr, other_ns) + if legacy then + -- Should have no effect + vim.diagnostic.disable(other_bufnr, other_ns) + else + -- Should have no effect + vim.diagnostic.enable(false, { bufnr = other_bufnr, ns_id = other_ns }) + end table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns) + count_extmarks(other_bufnr, diagnostic_ns)) return result - ]] + ]], + legacy + ) + + return result + end + it('with both buffer and namespace arguments', function() + local result = test_enable(false) + eq(4, result[1]) + eq(2, result[2]) + eq(1, result[3]) + eq(3, result[4]) + eq(3, result[5]) + end) + + it('with both buffer and namespace arguments (deprecated signature)', function() + -- Exercise the legacy/deprecated signature. + local result = test_enable(true) eq(4, result[1]) eq(2, result[2]) eq(1, result[3]) @@ -870,15 +934,112 @@ describe('vim.diagnostic', function() eq( { 4, 0 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 3, 9001, 3, 9001), - make_error('Diagnostic #2', 4, -1, 4, -1), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {1, 1}) - vim.diagnostic.goto_next { float = false } - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 3, 9001, 3, 9001), + make_error('Diagnostic #2', 4, -1, 4, -1), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 1}) + vim.diagnostic.goto_next { float = false } + return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } + ]] + ) + end) + + it('jumps to diagnostic with highest severity', function() + exec_lua([[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_info('Info', 1, 0, 1, 1), + make_error('Error', 2, 0, 2, 1), + make_warning('Warning', 3, 0, 3, 1), + make_error('Error', 4, 0, 4, 1), + }) + + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 0}) + ]]) + + eq( + { 3, 0 }, + exec_lua([[ + vim.diagnostic.goto_next({_highest = true}) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 5, 0 }, + exec_lua([[ + vim.diagnostic.goto_next({_highest = true}) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + exec_lua([[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_info('Info', 1, 0, 1, 1), + make_hint('Hint', 2, 0, 2, 1), + make_warning('Warning', 3, 0, 3, 1), + make_hint('Hint', 4, 0, 4, 1), + make_warning('Warning', 5, 0, 5, 1), + }) + + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 0}) + ]]) + + eq( + { 4, 0 }, + exec_lua([[ + vim.diagnostic.goto_next({_highest = true}) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 6, 0 }, + exec_lua([[ + vim.diagnostic.goto_next({_highest = true}) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + end) + + it('jumps to next diagnostic if severity is non-nil', function() + exec_lua([[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_info('Info', 1, 0, 1, 1), + make_error('Error', 2, 0, 2, 1), + make_warning('Warning', 3, 0, 3, 1), + make_error('Error', 4, 0, 4, 1), + }) + + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 0}) + ]]) + + eq( + { 2, 0 }, + exec_lua([[ + vim.diagnostic.goto_next() + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 3, 0 }, + exec_lua([[ + vim.diagnostic.goto_next() + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 4, 0 }, + exec_lua([[ + vim.diagnostic.goto_next() + return vim.api.nvim_win_get_cursor(0) + ]]) ) end) end) @@ -940,6 +1101,29 @@ describe('vim.diagnostic', function() ]] ) end) + + it('works on blank line #28397', function() + eq( + { 0, 2 }, + exec_lua [[ + local test_bufnr = vim.api.nvim_create_buf(true, false) + vim.api.nvim_buf_set_lines(test_bufnr, 0, -1, false, { + 'first line', + '', + '', + 'end line', + }) + vim.diagnostic.set(diagnostic_ns, test_bufnr, { + make_info('Diagnostic #1', 0, 2, 0, 2), + make_info('Diagnostic #2', 2, 0, 2, 0), + make_info('Diagnostic #3', 2, 0, 2, 0), + }) + vim.api.nvim_win_set_buf(0, test_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 0}) + return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns} + ]] + ) + end) end) describe('get()', function() @@ -1013,13 +1197,13 @@ describe('vim.diagnostic', function() it('allows filtering by line', function() eq( - 1, + 2, exec_lua [[ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { make_error("Error 1", 1, 1, 1, 5), make_warning("Warning on Server 1", 1, 1, 2, 3), make_info("Ignored information", 1, 1, 2, 3), - make_error("Error On Other Line", 2, 1, 1, 5), + make_error("Error On Other Line", 3, 1, 3, 5), }) return #vim.diagnostic.get(diagnostic_bufnr, {lnum = 2}) @@ -1129,13 +1313,16 @@ describe('vim.diagnostic', function() it('allows filtering by line', function() eq( - exec_lua [[return { [vim.diagnostic.severity.ERROR] = 1 }]], + exec_lua [[return { + [vim.diagnostic.severity.WARN] = 1, + [vim.diagnostic.severity.INFO] = 1, + }]], exec_lua [[ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { make_error("Error 1", 1, 1, 1, 5), make_warning("Warning on Server 1", 1, 1, 2, 3), make_info("Ignored information", 1, 1, 2, 3), - make_error("Error On Other Line", 2, 1, 1, 5), + make_error("Error On Other Line", 3, 1, 3, 5), }) return vim.diagnostic.count(diagnostic_bufnr, {lnum = 2}) @@ -1554,7 +1741,7 @@ describe('vim.diagnostic', function() end) describe('set()', function() - it('validates its arguments', function() + it('validation', function() matches( 'expected a list of diagnostics', pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]]) @@ -1741,7 +1928,7 @@ describe('vim.diagnostic', function() eq( 0, exec_lua [[ - vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns) + vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { make_error('Diagnostic From Server 1:1', 1, 1, 1, 1), }) @@ -1752,7 +1939,7 @@ describe('vim.diagnostic', function() eq( 2, exec_lua [[ - vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns) + vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }) return count_extmarks(diagnostic_bufnr, diagnostic_ns) ]] ) @@ -1825,20 +2012,12 @@ describe('vim.diagnostic', function() it('respects legacy signs placed with :sign define or sign_define #26618', function() -- Legacy signs for diagnostics were deprecated in 0.10 and will be removed in 0.12 - eq(0, helpers.fn.has('nvim-0.12')) + eq(0, n.fn.has('nvim-0.12')) - helpers.command( - 'sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg' - ) - helpers.command( - 'sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg' - ) - helpers.command( - 'sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined' - ) - helpers.command( - 'sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined' - ) + n.command('sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg') + n.command('sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg') + n.command('sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined') + n.command('sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined') local result = exec_lua [[ vim.diagnostic.config({ @@ -2451,6 +2630,47 @@ describe('vim.diagnostic', function() ]] ) end) + + it('works for multi-line diagnostics #21949', function() + -- open float failed non diagnostic lnum + eq( + vim.NIL, + exec_lua [[ + local diagnostics = { + make_error("Error in two lines lnum is 1 and end_lnum is 2", 1, 1, 2, 3), + } + local winids = {} + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + local _, winnr = vim.diagnostic.open_float(0, { header = false }) + return winnr + ]] + ) + + -- can open a float window on lnum 1 + eq( + { '1. Error in two lines lnum is 1 and end_lnum is 2' }, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {2, 0}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) + + -- can open a float window on end_lnum 2 + eq( + { '1. Error in two lines lnum is 1 and end_lnum is 2' }, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {3, 0}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) + end) end) describe('setloclist()', function() @@ -2718,7 +2938,41 @@ describe('vim.diagnostic', function() ) end) - it('checks if diagnostics are disabled in a buffer', function() + it('is_enabled', function() + eq( + { false, false, false, false, false }, + exec_lua [[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + }) + vim.api.nvim_set_current_buf(diagnostic_bufnr) + vim.diagnostic.enable(false) + return { + vim.diagnostic.is_enabled(), + vim.diagnostic.is_enabled{ bufnr = 0 }, + vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr }, + vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }, + vim.diagnostic.is_enabled{ bufnr = 0, ns_id = diagnostic_ns }, + } + ]] + ) + + eq( + { true, true, true, true, true }, + exec_lua [[ + vim.diagnostic.enable() + return { + vim.diagnostic.is_enabled(), + vim.diagnostic.is_enabled{ bufnr = 0 }, + vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr }, + vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr, ns_id = diagnostic_ns }, + vim.diagnostic.is_enabled{ bufnr = 0, ns_id = diagnostic_ns }, + } + ]] + ) + end) + + it('is_disabled (deprecated)', function() eq( { true, true, true, true }, exec_lua [[ diff --git a/test/functional/lua/ffi_spec.lua b/test/functional/lua/ffi_spec.lua index c9e8e9d4ca..85ca264107 100644 --- a/test/functional/lua/ffi_spec.lua +++ b/test/functional/lua/ffi_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local clear = helpers.clear +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local exec_lua = n.exec_lua +local clear = n.clear before_each(clear) @@ -13,15 +15,19 @@ describe('ffi.cdef', function() eq( 12, - exec_lua [[ + exec_lua [=[ local ffi = require('ffi') - ffi.cdef('int curwin_col_off(void);') + ffi.cdef [[ + typedef struct window_S win_T; + int win_col_off(win_T *wp); + extern win_T *curwin; + ]] vim.cmd('set number numberwidth=4 signcolumn=yes:4') - return ffi.C.curwin_col_off() - ]] + return ffi.C.win_col_off(ffi.C.curwin) + ]=] ) eq( @@ -30,7 +36,6 @@ describe('ffi.cdef', function() local ffi = require('ffi') ffi.cdef[[ - typedef struct window_S win_T; typedef struct {} stl_hlrec_t; typedef struct {} StlClickRecord; typedef struct {} statuscol_T; diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua index 8b0e0a8beb..7db04e6f6b 100644 --- a/test/functional/lua/filetype_spec.lua +++ b/test/functional/lua/filetype_spec.lua @@ -1,10 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local api = helpers.api -local clear = helpers.clear -local pathroot = helpers.pathroot -local command = helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exec_lua = n.exec_lua +local eq = t.eq +local api = n.api +local clear = n.clear +local pathroot = n.pathroot +local command = n.command +local mkdir = t.mkdir +local rmdir = n.rmdir +local write_file = t.write_file +local uv = vim.uv local root = pathroot() @@ -161,10 +167,30 @@ describe('vim.filetype', function() end) describe('filetype.lua', function() + before_each(function() + mkdir('Xfiletype') + end) + + after_each(function() + rmdir('Xfiletype') + end) + it('does not override user autocommands that set filetype #20333', function() clear({ args = { '--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md' }, }) eq('notmarkdown', api.nvim_get_option_value('filetype', {})) end) + + it('uses unexpanded path for matching when editing a symlink #27914', function() + mkdir('Xfiletype/.config') + mkdir('Xfiletype/actual') + write_file('Xfiletype/actual/config', '') + uv.fs_symlink(assert(uv.fs_realpath('Xfiletype/actual')), 'Xfiletype/.config/git') + finally(function() + uv.fs_unlink('Xfiletype/.config/git') + end) + clear({ args = { '--clean', 'Xfiletype/.config/git/config' } }) + eq('gitconfig', api.nvim_get_option_value('filetype', {})) + end) end) diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua index 6821fe3c5e..aba02ab01b 100644 --- a/test/functional/lua/fs_spec.lua +++ b/test/functional/lua/fs_spec.lua @@ -1,16 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local mkdir_p = helpers.mkdir_p -local rmdir = helpers.rmdir -local nvim_dir = helpers.nvim_dir -local test_build_dir = helpers.paths.test_build_dir -local test_source_path = helpers.paths.test_source_path -local nvim_prog = helpers.nvim_prog -local is_os = helpers.is_os -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local mkdir_p = n.mkdir_p +local rmdir = n.rmdir +local nvim_dir = n.nvim_dir +local command = n.command +local api = n.api +local test_build_dir = t.paths.test_build_dir +local test_source_path = t.paths.test_source_path +local nvim_prog = n.nvim_prog +local is_os = t.is_os +local mkdir = t.mkdir local nvim_prog_basename = is_os('win') and 'nvim.exe' or 'nvim' @@ -36,6 +39,7 @@ local test_basename_dirname_eq = { 'c:/users/foo', 'c:/users/foo/bar.lua', 'c:/users/foo/bar/../', + '~/foo/bar\\baz', } local tests_windows_paths = { @@ -54,7 +58,7 @@ describe('vim.fs', function() it('works', function() local test_dir = nvim_dir .. '/test' mkdir_p(test_dir) - local dirs = {} + local dirs = {} --- @type string[] for dir in vim.fs.parents(test_dir .. '/foo.txt') do dirs[#dirs + 1] = dir if dir == test_build_dir then @@ -70,25 +74,26 @@ describe('vim.fs', function() it('works', function() eq(test_build_dir, vim.fs.dirname(nvim_dir)) - local function test_paths(paths) + ---@param paths string[] + ---@param is_win? boolean + local function test_paths(paths, is_win) + local gsub = is_win and [[:gsub('\\', '/')]] or '' + local code = string.format( + [[ + local path = ... + return vim.fn.fnamemodify(path,':h')%s + ]], + gsub + ) + for _, path in ipairs(paths) do - eq( - exec_lua( - [[ - local path = ... - return vim.fn.fnamemodify(path,':h'):gsub('\\', '/') - ]], - path - ), - vim.fs.dirname(path), - path - ) + eq(exec_lua(code, path), vim.fs.dirname(path), path) end end test_paths(test_basename_dirname_eq) if is_os('win') then - test_paths(tests_windows_paths) + test_paths(tests_windows_paths, true) end end) end) @@ -97,25 +102,26 @@ describe('vim.fs', function() it('works', function() eq(nvim_prog_basename, vim.fs.basename(nvim_prog)) - local function test_paths(paths) + ---@param paths string[] + ---@param is_win? boolean + local function test_paths(paths, is_win) + local gsub = is_win and [[:gsub('\\', '/')]] or '' + local code = string.format( + [[ + local path = ... + return vim.fn.fnamemodify(path,':t')%s + ]], + gsub + ) + for _, path in ipairs(paths) do - eq( - exec_lua( - [[ - local path = ... - return vim.fn.fnamemodify(path,':t'):gsub('\\', '/') - ]], - path - ), - vim.fs.basename(path), - path - ) + eq(exec_lua(code, path), vim.fs.basename(path), path) end end test_paths(test_basename_dirname_eq) if is_os('win') then - test_paths(tests_windows_paths) + test_paths(tests_windows_paths, true) end end) end) @@ -274,6 +280,57 @@ describe('vim.fs', function() end) end) + describe('root()', function() + before_each(function() + command('edit test/functional/fixtures/tty-test.c') + end) + + it('works with a single marker', function() + eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]])) + end) + + it('works with multiple markers', function() + local bufnr = api.nvim_get_current_buf() + eq( + vim.fs.joinpath(test_source_path, 'test/functional/fixtures'), + exec_lua([[return vim.fs.root(..., {'CMakeLists.txt', '.git'})]], bufnr) + ) + end) + + it('works with a function', function() + ---@type string + local result = exec_lua([[ + return vim.fs.root(0, function(name, path) + return name:match('%.txt$') + end) + ]]) + eq(vim.fs.joinpath(test_source_path, 'test/functional/fixtures'), result) + end) + + it('works with a filename argument', function() + eq(test_source_path, exec_lua([[return vim.fs.root(..., '.git')]], nvim_prog)) + end) + + it('works with a relative path', function() + eq( + test_source_path, + exec_lua([[return vim.fs.root(..., '.git')]], vim.fs.basename(nvim_prog)) + ) + end) + + it('uses cwd for unnamed buffers', function() + command('new') + eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]])) + end) + + it("uses cwd for buffers with non-empty 'buftype'", function() + command('new') + command('set buftype=nofile') + command('file lua://') + eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]])) + end) + end) + describe('joinpath()', function() it('works', function() eq('foo/bar/baz', vim.fs.joinpath('foo', 'bar', 'baz')) @@ -282,9 +339,6 @@ describe('vim.fs', function() end) describe('normalize()', function() - it('works with backward slashes', function() - eq('C:/Users/jdoe', vim.fs.normalize('C:\\Users\\jdoe')) - end) it('removes trailing /', function() eq('/home/user', vim.fs.normalize('/home/user/')) end) @@ -292,7 +346,7 @@ describe('vim.fs', function() eq('/', vim.fs.normalize('/')) end) it('works with ~', function() - eq(vim.fs.normalize(vim.uv.os_homedir()) .. '/src/foo', vim.fs.normalize('~/src/foo')) + eq(vim.fs.normalize(assert(vim.uv.os_homedir())) .. '/src/foo', vim.fs.normalize('~/src/foo')) end) it('works with environment variables', function() local xdg_config_home = test_build_dir .. '/.config' @@ -307,10 +361,113 @@ describe('vim.fs', function() ) ) end) - if is_os('win') then - it('Last slash is not truncated from root drive', function() - eq('C:/', vim.fs.normalize('C:/')) + + -- Opts required for testing posix paths and win paths + local posix_opts = is_os('win') and { win = false } or {} + local win_opts = is_os('win') and {} or { win = true } + + it('preserves leading double slashes in POSIX paths', function() + eq('//foo', vim.fs.normalize('//foo', posix_opts)) + eq('//foo/bar', vim.fs.normalize('//foo//bar////', posix_opts)) + eq('/foo', vim.fs.normalize('///foo', posix_opts)) + eq('//', vim.fs.normalize('//', posix_opts)) + eq('/', vim.fs.normalize('///', posix_opts)) + eq('/foo/bar', vim.fs.normalize('/foo//bar////', posix_opts)) + end) + + it('allows backslashes on unix-based os', function() + eq('/home/user/hello\\world', vim.fs.normalize('/home/user/hello\\world', posix_opts)) + end) + + it('preserves / after drive letters', function() + eq('C:/', vim.fs.normalize([[C:\]], win_opts)) + end) + + it('works with UNC and DOS device paths', function() + eq('//server/share/foo/bar', vim.fs.normalize([[\\server\\share\\\foo\bar\\\]], win_opts)) + eq('//system07/C$/', vim.fs.normalize([[\\system07\C$\\\\]], win_opts)) + eq('//./C:/foo/bar', vim.fs.normalize([[\\.\\C:\foo\\\\bar]], win_opts)) + eq('//?/C:/foo/bar', vim.fs.normalize([[\\?\C:\\\foo\bar\\\\]], win_opts)) + eq( + '//?/UNC/server/share/foo/bar', + vim.fs.normalize([[\\?\UNC\server\\\share\\\\foo\\\bar]], win_opts) + ) + eq('//./BootPartition/foo/bar', vim.fs.normalize([[\\.\BootPartition\\foo\bar]], win_opts)) + eq( + '//./Volume{12345678-1234-1234-1234-1234567890AB}/foo/bar', + vim.fs.normalize([[\\.\Volume{12345678-1234-1234-1234-1234567890AB}\\\foo\bar\\]], win_opts) + ) + end) + + it('handles invalid UNC and DOS device paths', function() + eq('//server/share', vim.fs.normalize([[\\server\share]], win_opts)) + eq('//server/', vim.fs.normalize([[\\server\]], win_opts)) + eq('//./UNC/server/share', vim.fs.normalize([[\\.\UNC\server\share]], win_opts)) + eq('//?/UNC/server/', vim.fs.normalize([[\\?\UNC\server\]], win_opts)) + eq('//?/UNC/server/..', vim.fs.normalize([[\\?\UNC\server\..]], win_opts)) + eq('//./', vim.fs.normalize([[\\.\]], win_opts)) + eq('//./foo', vim.fs.normalize([[\\.\foo]], win_opts)) + eq('//./BootPartition', vim.fs.normalize([[\\.\BootPartition]], win_opts)) + end) + + it('converts backward slashes', function() + eq('C:/Users/jdoe', vim.fs.normalize([[C:\Users\jdoe]], win_opts)) + end) + + describe('. and .. component resolving', function() + it('works', function() + -- Windows paths + eq('C:/Users', vim.fs.normalize([[C:\Users\jdoe\Downloads\.\..\..\]], win_opts)) + eq('C:/Users/jdoe', vim.fs.normalize([[C:\Users\jdoe\Downloads\.\..\.\.\]], win_opts)) + eq('C:/', vim.fs.normalize('C:/Users/jdoe/Downloads/./../../../', win_opts)) + eq('C:foo', vim.fs.normalize([[C:foo\bar\.\..\.]], win_opts)) + -- POSIX paths + eq('/home', vim.fs.normalize('/home/jdoe/Downloads/./../..', posix_opts)) + eq('/home/jdoe', vim.fs.normalize('/home/jdoe/Downloads/./../././', posix_opts)) + eq('/', vim.fs.normalize('/home/jdoe/Downloads/./../../../', posix_opts)) + -- OS-agnostic relative paths + eq('foo/bar/baz', vim.fs.normalize('foo/bar/foobar/../baz/./')) + eq('foo/bar', vim.fs.normalize('foo/bar/foobar/../baz/./../../bar/./.')) end) - end + + it('works when relative path reaches current directory', function() + eq('C:', vim.fs.normalize('C:foo/bar/../../.', win_opts)) + + eq('.', vim.fs.normalize('.')) + eq('.', vim.fs.normalize('././././')) + eq('.', vim.fs.normalize('foo/bar/../../.')) + end) + + it('works when relative path goes outside current directory', function() + eq('../../foo/bar', vim.fs.normalize('../../foo/bar')) + eq('../foo', vim.fs.normalize('foo/bar/../../../foo')) + + eq('C:../foo', vim.fs.normalize('C:../foo', win_opts)) + eq('C:../../foo/bar', vim.fs.normalize('C:foo/../../../foo/bar', win_opts)) + end) + + it('.. in root directory resolves to itself', function() + eq('C:/', vim.fs.normalize('C:/../../', win_opts)) + eq('C:/foo', vim.fs.normalize('C:/foo/../../foo', win_opts)) + + eq('//server/share/', vim.fs.normalize([[\\server\share\..\..]], win_opts)) + eq('//server/share/foo', vim.fs.normalize([[\\server\\share\foo\..\..\foo]], win_opts)) + + eq('//./C:/', vim.fs.normalize([[\\.\C:\..\..]], win_opts)) + eq('//?/C:/foo', vim.fs.normalize([[\\?\C:\..\..\foo]], win_opts)) + + eq('//./UNC/server/share/', vim.fs.normalize([[\\.\UNC\\server\share\..\..\]], win_opts)) + eq( + '//?/UNC/server/share/foo', + vim.fs.normalize([[\\?\UNC\server\\share\..\..\foo]], win_opts) + ) + + eq('//?/BootPartition/', vim.fs.normalize([[\\?\BootPartition\..\..]], win_opts)) + eq('//./BootPartition/foo', vim.fs.normalize([[\\.\BootPartition\..\..\foo]], win_opts)) + + eq('/', vim.fs.normalize('/../../', posix_opts)) + eq('/foo', vim.fs.normalize('/foo/../../foo', posix_opts)) + end) + end) end) end) diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index 1eac037575..56cd4c9bb5 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local exec_lua = n.exec_lua describe('glob', function() - before_each(helpers.clear) - after_each(helpers.clear) + before_each(n.clear) + after_each(n.clear) local match = function(...) return exec_lua( diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua index 197f3139f3..c9f2d0a47f 100644 --- a/test/functional/lua/highlight_spec.lua +++ b/test/functional/lua/highlight_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local neq = helpers.neq -local eval = helpers.eval -local command = helpers.command -local clear = helpers.clear -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exec_lua = n.exec_lua +local eq = t.eq +local neq = t.neq +local eval = n.eval +local command = n.command +local clear = n.clear +local api = n.api describe('vim.highlight.on_yank', function() before_each(function() @@ -19,7 +21,7 @@ describe('vim.highlight.on_yank', function() vim.cmd('bwipeout!') ]]) vim.uv.sleep(10) - helpers.feed('<cr>') -- avoid hang if error message exists + n.feed('<cr>') -- avoid hang if error message exists eq('', eval('v:errmsg')) end) @@ -41,9 +43,9 @@ describe('vim.highlight.on_yank', function() vim.api.nvim_buf_set_mark(0,"]",1,1,{}) vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) - neq({}, api.nvim_win_get_ns(0)) + neq({}, api.nvim__win_get_ns(0)) command('wincmd w') - eq({}, api.nvim_win_get_ns(0)) + eq({}, api.nvim__win_get_ns(0)) end) it('removes old highlight if new one is created before old one times out', function() @@ -53,7 +55,7 @@ describe('vim.highlight.on_yank', function() vim.api.nvim_buf_set_mark(0,"]",1,1,{}) vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) - neq({}, api.nvim_win_get_ns(0)) + neq({}, api.nvim__win_get_ns(0)) command('wincmd w') exec_lua([[ vim.api.nvim_buf_set_mark(0,"[",1,1,{}) @@ -61,6 +63,6 @@ describe('vim.highlight.on_yank', function() vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) command('wincmd w') - eq({}, api.nvim_win_get_ns(0)) + eq({}, api.nvim__win_get_ns(0)) end) end) diff --git a/test/functional/lua/inspector_spec.lua b/test/functional/lua/inspector_spec.lua index ad8b5a45a8..8fadba6ee8 100644 --- a/test/functional/lua/inspector_spec.lua +++ b/test/functional/lua/inspector_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local eval = helpers.eval -local clear = helpers.clear +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exec_lua = n.exec_lua +local eq = t.eq +local eval = n.eval +local clear = n.clear describe('vim.inspect_pos', function() before_each(function() diff --git a/test/functional/lua/iter_spec.lua b/test/functional/lua/iter_spec.lua index 8d6cf1264b..79e92e6a7d 100644 --- a/test/functional/lua/iter_spec.lua +++ b/test/functional/lua/iter_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local matches = helpers.matches -local pcall_err = helpers.pcall_err +local t = require('test.testutil') + +local eq = t.eq +local matches = t.matches +local pcall_err = t.pcall_err describe('vim.iter', function() it('new() on iterable class instance', function() @@ -18,12 +19,12 @@ describe('vim.iter', function() return v % 2 ~= 0 end - local t = { 1, 2, 3, 4, 5 } - eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable()) + local q = { 1, 2, 3, 4, 5 } + eq({ 1, 3, 5 }, vim.iter(q):filter(odd):totable()) eq( { 2, 4 }, vim - .iter(t) + .iter(q) :filter(function(v) return not odd(v) end) @@ -32,7 +33,7 @@ describe('vim.iter', function() eq( {}, vim - .iter(t) + .iter(q) :filter(function(v) return v > 5 end) @@ -40,7 +41,7 @@ describe('vim.iter', function() ) do - local it = vim.iter(ipairs(t)) + local it = vim.iter(ipairs(q)) it:filter(function(i, v) return i > 1 and v < 5 end) @@ -60,11 +61,11 @@ describe('vim.iter', function() end) it('map()', function() - local t = { 1, 2, 3, 4, 5 } + local q = { 1, 2, 3, 4, 5 } eq( { 2, 4, 6, 8, 10 }, vim - .iter(t) + .iter(q) :map(function(v) return 2 * v end) @@ -96,10 +97,10 @@ describe('vim.iter', function() end) it('for loops', function() - local t = { 1, 2, 3, 4, 5 } + local q = { 1, 2, 3, 4, 5 } local acc = 0 for v in - vim.iter(t):map(function(v) + vim.iter(q):map(function(v) return v * 3 end) do @@ -116,6 +117,9 @@ describe('vim.iter', function() eq({ { 1, 1 }, { 2, 4 }, { 3, 9 } }, it:totable()) end + -- Holes in array-like tables are removed + eq({ 1, 2, 3 }, vim.iter({ 1, nil, 2, nil, 3 }):totable()) + do local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber) eq({ 1, 4, 17, 2, 9, 3 }, it:totable()) @@ -141,18 +145,18 @@ describe('vim.iter', function() eq({ 3, 2, 1 }, vim.iter({ 1, 2, 3 }):rev():totable()) local it = vim.iter(string.gmatch('abc', '%w')) - matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it)) + matches('rev%(%) requires an array%-like table', pcall_err(it.rev, it)) end) it('skip()', function() do - local t = { 4, 3, 2, 1 } - eq(t, vim.iter(t):skip(0):totable()) - eq({ 3, 2, 1 }, vim.iter(t):skip(1):totable()) - eq({ 2, 1 }, vim.iter(t):skip(2):totable()) - eq({ 1 }, vim.iter(t):skip(#t - 1):totable()) - eq({}, vim.iter(t):skip(#t):totable()) - eq({}, vim.iter(t):skip(#t + 1):totable()) + local q = { 4, 3, 2, 1 } + eq(q, vim.iter(q):skip(0):totable()) + eq({ 3, 2, 1 }, vim.iter(q):skip(1):totable()) + eq({ 2, 1 }, vim.iter(q):skip(2):totable()) + eq({ 1 }, vim.iter(q):skip(#q - 1):totable()) + eq({}, vim.iter(q):skip(#q):totable()) + eq({}, vim.iter(q):skip(#q + 1):totable()) end do @@ -168,44 +172,44 @@ describe('vim.iter', function() end end) - it('skipback()', function() + it('rskip()', function() do - local t = { 4, 3, 2, 1 } - eq(t, vim.iter(t):skipback(0):totable()) - eq({ 4, 3, 2 }, vim.iter(t):skipback(1):totable()) - eq({ 4, 3 }, vim.iter(t):skipback(2):totable()) - eq({ 4 }, vim.iter(t):skipback(#t - 1):totable()) - eq({}, vim.iter(t):skipback(#t):totable()) - eq({}, vim.iter(t):skipback(#t + 1):totable()) + local q = { 4, 3, 2, 1 } + eq(q, vim.iter(q):rskip(0):totable()) + eq({ 4, 3, 2 }, vim.iter(q):rskip(1):totable()) + eq({ 4, 3 }, vim.iter(q):rskip(2):totable()) + eq({ 4 }, vim.iter(q):rskip(#q - 1):totable()) + eq({}, vim.iter(q):rskip(#q):totable()) + eq({}, vim.iter(q):rskip(#q + 1):totable()) end local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0)) + matches('rskip%(%) requires an array%-like table', pcall_err(it.rskip, it, 0)) end) it('slice()', function() - local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } - eq({ 3, 4, 5, 6, 7 }, vim.iter(t):slice(3, 7):totable()) - eq({}, vim.iter(t):slice(6, 5):totable()) - eq({}, vim.iter(t):slice(0, 0):totable()) - eq({ 1 }, vim.iter(t):slice(1, 1):totable()) - eq({ 1, 2 }, vim.iter(t):slice(1, 2):totable()) - eq({ 10 }, vim.iter(t):slice(10, 10):totable()) - eq({ 8, 9, 10 }, vim.iter(t):slice(8, 11):totable()) + local q = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } + eq({ 3, 4, 5, 6, 7 }, vim.iter(q):slice(3, 7):totable()) + eq({}, vim.iter(q):slice(6, 5):totable()) + eq({}, vim.iter(q):slice(0, 0):totable()) + eq({ 1 }, vim.iter(q):slice(1, 1):totable()) + eq({ 1, 2 }, vim.iter(q):slice(1, 2):totable()) + eq({ 10 }, vim.iter(q):slice(10, 10):totable()) + eq({ 8, 9, 10 }, vim.iter(q):slice(8, 11):totable()) local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('slice%(%) requires a list%-like table', pcall_err(it.slice, it, 1, 3)) + matches('slice%(%) requires an array%-like table', pcall_err(it.slice, it, 1, 3)) end) it('nth()', function() do - local t = { 4, 3, 2, 1 } - eq(nil, vim.iter(t):nth(0)) - eq(4, vim.iter(t):nth(1)) - eq(3, vim.iter(t):nth(2)) - eq(2, vim.iter(t):nth(3)) - eq(1, vim.iter(t):nth(4)) - eq(nil, vim.iter(t):nth(5)) + local q = { 4, 3, 2, 1 } + eq(nil, vim.iter(q):nth(0)) + eq(4, vim.iter(q):nth(1)) + eq(3, vim.iter(q):nth(2)) + eq(2, vim.iter(q):nth(3)) + eq(1, vim.iter(q):nth(4)) + eq(nil, vim.iter(q):nth(5)) end do @@ -221,35 +225,41 @@ describe('vim.iter', function() end end) - it('nthback()', function() + it('nth(-x) advances in reverse order starting from end', function() do - local t = { 4, 3, 2, 1 } - eq(nil, vim.iter(t):nthback(0)) - eq(1, vim.iter(t):nthback(1)) - eq(2, vim.iter(t):nthback(2)) - eq(3, vim.iter(t):nthback(3)) - eq(4, vim.iter(t):nthback(4)) - eq(nil, vim.iter(t):nthback(5)) + local q = { 4, 3, 2, 1 } + eq(nil, vim.iter(q):nth(0)) + eq(1, vim.iter(q):nth(-1)) + eq(2, vim.iter(q):nth(-2)) + eq(3, vim.iter(q):nth(-3)) + eq(4, vim.iter(q):nth(-4)) + eq(nil, vim.iter(q):nth(-5)) end local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1)) + matches('rskip%(%) requires an array%-like table', pcall_err(it.nth, it, -1)) end) it('take()', function() do - local t = { 4, 3, 2, 1 } - eq({}, vim.iter(t):take(0):totable()) - eq({ 4 }, vim.iter(t):take(1):totable()) - eq({ 4, 3 }, vim.iter(t):take(2):totable()) - eq({ 4, 3, 2 }, vim.iter(t):take(3):totable()) - eq({ 4, 3, 2, 1 }, vim.iter(t):take(4):totable()) - eq({ 4, 3, 2, 1 }, vim.iter(t):take(5):totable()) + local q = { 4, 3, 2, 1 } + eq({}, vim.iter(q):take(0):totable()) + eq({ 4 }, vim.iter(q):take(1):totable()) + eq({ 4, 3 }, vim.iter(q):take(2):totable()) + eq({ 4, 3, 2 }, vim.iter(q):take(3):totable()) + eq({ 4, 3, 2, 1 }, vim.iter(q):take(4):totable()) + eq({ 4, 3, 2, 1 }, vim.iter(q):take(5):totable()) + end + + do + local q = { 4, 3, 2, 1 } + eq({ 1, 2, 3 }, vim.iter(q):rev():take(3):totable()) + eq({ 2, 3, 4 }, vim.iter(q):take(3):rev():totable()) end do - local t = { 4, 3, 2, 1 } - local it = vim.iter(t) + local q = { 4, 3, 2, 1 } + local it = vim.iter(q) eq({ 4, 3 }, it:take(2):totable()) -- tail is already set from the previous take() eq({ 4, 3 }, it:take(3):totable()) @@ -269,13 +279,13 @@ describe('vim.iter', function() end do - local t = { 4, 8, 9, 10 } - eq(true, vim.iter(t):any(odd)) + local q = { 4, 8, 9, 10 } + eq(true, vim.iter(q):any(odd)) end do - local t = { 4, 8, 10 } - eq(false, vim.iter(t):any(odd)) + local q = { 4, 8, 10 } + eq(false, vim.iter(q):any(odd)) end do @@ -300,13 +310,13 @@ describe('vim.iter', function() end do - local t = { 3, 5, 7, 9 } - eq(true, vim.iter(t):all(odd)) + local q = { 3, 5, 7, 9 } + eq(true, vim.iter(q):all(odd)) end do - local t = { 3, 5, 7, 10 } - eq(false, vim.iter(t):all(odd)) + local q = { 3, 5, 7, 10 } + eq(false, vim.iter(q):all(odd)) end do @@ -349,23 +359,23 @@ describe('vim.iter', function() do local it = vim.iter(vim.gsplit('hi', '')) - matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it)) + matches('peek%(%) requires an array%-like table', pcall_err(it.peek, it)) end end) it('find()', function() - local t = { 3, 6, 9, 12 } - eq(12, vim.iter(t):find(12)) - eq(nil, vim.iter(t):find(15)) + local q = { 3, 6, 9, 12 } + eq(12, vim.iter(q):find(12)) + eq(nil, vim.iter(q):find(15)) eq( 12, - vim.iter(t):find(function(v) + vim.iter(q):find(function(v) return v % 4 == 0 end) ) do - local it = vim.iter(t) + local it = vim.iter(q) local pred = function(v) return v % 3 == 0 end @@ -389,16 +399,16 @@ describe('vim.iter', function() end) it('rfind()', function() - local t = { 1, 2, 3, 2, 1 } + local q = { 1, 2, 3, 2, 1 } do - local it = vim.iter(t) + local it = vim.iter(q) eq(1, it:rfind(1)) eq(1, it:rfind(1)) eq(nil, it:rfind(1)) end do - local it = vim.iter(t):enumerate() + local it = vim.iter(q):enumerate() local pred = function(i) return i % 2 ~= 0 end @@ -410,52 +420,52 @@ describe('vim.iter', function() do local it = vim.iter(vim.gsplit('AbCdE', '')) - matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E')) + matches('rfind%(%) requires an array%-like table', pcall_err(it.rfind, it, 'E')) end end) - it('nextback()', function() + it('pop()', function() do local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:nextback()) - eq(3, it:nextback()) - eq(2, it:nextback()) - eq(1, it:nextback()) - eq(nil, it:nextback()) - eq(nil, it:nextback()) + eq(4, it:pop()) + eq(3, it:pop()) + eq(2, it:pop()) + eq(1, it:pop()) + eq(nil, it:pop()) + eq(nil, it:pop()) end do local it = vim.iter(vim.gsplit('hi', '')) - matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it)) + matches('pop%(%) requires an array%-like table', pcall_err(it.pop, it)) end end) - it('peekback()', function() + it('rpeek()', function() do local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:peekback()) - eq(4, it:peekback()) - eq(4, it:nextback()) + eq(4, it:rpeek()) + eq(4, it:rpeek()) + eq(4, it:pop()) end do local it = vim.iter(vim.gsplit('hi', '')) - matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it)) + matches('rpeek%(%) requires an array%-like table', pcall_err(it.rpeek, it)) end end) it('fold()', function() - local t = { 1, 2, 3, 4, 5 } + local q = { 1, 2, 3, 4, 5 } eq( 115, - vim.iter(t):fold(100, function(acc, v) + vim.iter(q):fold(100, function(acc, v) return acc + v end) ) eq( { 5, 4, 3, 2, 1 }, - vim.iter(t):fold({}, function(acc, v) + vim.iter(q):fold({}, function(acc, v) table.insert(acc, 1, v) return acc end) @@ -463,30 +473,32 @@ describe('vim.iter', function() end) it('flatten()', function() - local t = { { 1, { 2 } }, { { { { 3 } } }, { 4 } }, { 5 } } + local q = { { 1, { 2 } }, { { { { 3 } } }, { 4 } }, { 5 } } - eq(t, vim.iter(t):flatten(-1):totable()) - eq(t, vim.iter(t):flatten(0):totable()) - eq({ 1, { 2 }, { { { 3 } } }, { 4 }, 5 }, vim.iter(t):flatten():totable()) - eq({ 1, 2, { { 3 } }, 4, 5 }, vim.iter(t):flatten(2):totable()) - eq({ 1, 2, { 3 }, 4, 5 }, vim.iter(t):flatten(3):totable()) - eq({ 1, 2, 3, 4, 5 }, vim.iter(t):flatten(4):totable()) + eq(q, vim.iter(q):flatten(-1):totable()) + eq(q, vim.iter(q):flatten(0):totable()) + eq({ 1, { 2 }, { { { 3 } } }, { 4 }, 5 }, vim.iter(q):flatten():totable()) + eq({ 1, 2, { { 3 } }, 4, 5 }, vim.iter(q):flatten(2):totable()) + eq({ 1, 2, { 3 }, 4, 5 }, vim.iter(q):flatten(3):totable()) + eq({ 1, 2, 3, 4, 5 }, vim.iter(q):flatten(4):totable()) local m = { a = 1, b = { 2, 3 }, d = { 4 } } local it = vim.iter(m) - local flat_err = 'flatten%(%) requires a list%-like table' + local flat_err = 'flatten%(%) requires an array%-like table' matches(flat_err, pcall_err(it.flatten, it)) -- cases from the documentation local simple_example = { 1, { 2 }, { { 3 } } } eq({ 1, 2, { 3 } }, vim.iter(simple_example):flatten():totable()) - local not_list_like = vim.iter({ [2] = 2 }) - matches(flat_err, pcall_err(not_list_like.flatten, not_list_like)) + local not_list_like = { [2] = 2 } + eq({ 2 }, vim.iter(not_list_like):flatten():totable()) + + local also_not_list_like = { nil, 2 } + eq({ 2 }, vim.iter(also_not_list_like):flatten():totable()) - local also_not_list_like = vim.iter({ nil, 2 }) - matches(flat_err, pcall_err(not_list_like.flatten, also_not_list_like)) + eq({ 1, 2, 3 }, vim.iter({ nil, { 1, nil, 2 }, 3 }):flatten():totable()) local nested_non_lists = vim.iter({ 1, { { a = 2 } }, { { nil } }, { 3 } }) eq({ 1, { a = 2 }, { nil }, 3 }, nested_non_lists:flatten():totable()) @@ -501,11 +513,11 @@ describe('vim.iter', function() end end) - local t = it:fold({}, function(t, k, v) - t[k] = v - return t + local q = it:fold({}, function(q, k, v) + q[k] = v + return q end) - eq({ A = 2, C = 6 }, t) + eq({ A = 2, C = 6 }, q) end) it('handles table values mid-pipeline', function() diff --git a/test/functional/lua/json_spec.lua b/test/functional/lua/json_spec.lua index d348e2de3c..a6e814d739 100644 --- a/test/functional/lua/json_spec.lua +++ b/test/functional/lua/json_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local pcall_err = t.pcall_err describe('vim.json.decode()', function() before_each(function() @@ -30,6 +32,18 @@ describe('vim.json.decode()', function() baz = vim.NIL, foo = { a = 'b' }, }, exec_lua([[return vim.json.decode(..., {})]], jsonstr)) + eq( + { + arr = { 1, 2, vim.NIL }, + bar = { 3, 7 }, + baz = vim.NIL, + foo = { a = 'b' }, + }, + exec_lua( + [[return vim.json.decode(..., { luanil = { array = false, object = false } })]], + jsonstr + ) + ) eq({ arr = { 1, 2, vim.NIL }, bar = { 3, 7 }, diff --git a/test/functional/lua/loader_spec.lua b/test/functional/lua/loader_spec.lua index 4e42a18405..f13e6664c5 100644 --- a/test/functional/lua/loader_spec.lua +++ b/test/functional/lua/loader_spec.lua @@ -1,10 +1,11 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local exec_lua = helpers.exec_lua -local command = helpers.command -local clear = helpers.clear -local eq = helpers.eq +local exec_lua = n.exec_lua +local command = n.command +local clear = n.clear +local eq = t.eq describe('vim.loader', function() before_each(clear) @@ -35,7 +36,7 @@ describe('vim.loader', function() vim.loader.enable() ]] - local tmp = helpers.tmpname() + local tmp = t.tmpname() command('edit ' .. tmp) eq( @@ -73,15 +74,15 @@ describe('vim.loader', function() vim.loader.enable() ]] - local tmp1, tmp2 = (function(t) - assert(os.remove(t)) - assert(helpers.mkdir(t)) - assert(helpers.mkdir(t .. '/%')) - return t .. '/%/x', t .. '/%%x' - end)(helpers.tmpname()) + local tmp = t.tmpname() + assert(os.remove(tmp)) + assert(t.mkdir(tmp)) + assert(t.mkdir(tmp .. '/%')) + local tmp1 = tmp .. '/%/x' + local tmp2 = tmp .. '/%%x' - helpers.write_file(tmp1, 'return 1', true) - helpers.write_file(tmp2, 'return 2', true) + t.write_file(tmp1, 'return 1', true) + t.write_file(tmp2, 'return 2', true) vim.uv.fs_utime(tmp1, 0, 0) vim.uv.fs_utime(tmp2, 0, 0) eq(1, exec_lua('return loadfile(...)()', tmp1)) diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua index 71eaf29009..566a171a84 100644 --- a/test/functional/lua/loop_spec.lua +++ b/test/functional/lua/loop_spec.lua @@ -1,16 +1,18 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local fn = helpers.fn -local api = helpers.api -local clear = helpers.clear + +local fn = n.fn +local api = n.api +local clear = n.clear local sleep = vim.uv.sleep -local feed = helpers.feed -local eq = helpers.eq -local eval = helpers.eval -local matches = helpers.matches -local exec_lua = helpers.exec_lua -local retry = helpers.retry +local feed = n.feed +local eq = t.eq +local eval = n.eval +local matches = t.matches +local exec_lua = n.exec_lua +local retry = t.retry before_each(clear) @@ -131,6 +133,20 @@ describe('vim.uv', function() {5:-- INSERT --} | ]]) eq({ blocking = false, mode = 'n' }, exec_lua('return _G.mode')) + + exec_lua([[ + local timer = vim.uv.new_timer() + timer:start(20, 0, function () + _G.is_fast = vim.in_fast_event() + timer:close() + _G.value = vim.fn.has("nvim-0.5") + _G.unvalue = vim.fn.has("python3") + end) + ]]) + + screen:expect({ any = [[{3:Vim:E5560: Vimscript function must not be called i}]] }) + feed('<cr>') + eq({ 1, nil }, exec_lua('return {_G.value, _G.unvalue}')) end) it("is equal to require('luv')", function() diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua index b28cfa4dd2..3f62cd8325 100644 --- a/test/functional/lua/luaeval_spec.lua +++ b/test/functional/lua/luaeval_spec.lua @@ -1,19 +1,20 @@ -- Test suite for testing luaeval() function -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local pcall_err = helpers.pcall_err -local exc_exec = helpers.exc_exec -local remove_trace = helpers.remove_trace -local exec_lua = helpers.exec_lua -local command = helpers.command -local api = helpers.api -local fn = helpers.fn -local clear = helpers.clear -local eval = helpers.eval -local feed = helpers.feed +local pcall_err = t.pcall_err +local exc_exec = n.exc_exec +local remove_trace = t.remove_trace +local exec_lua = n.exec_lua +local command = n.command +local api = n.api +local fn = n.fn +local clear = n.clear +local eval = n.eval +local feed = n.feed local NIL = vim.NIL -local eq = helpers.eq +local eq = t.eq before_each(clear) @@ -38,8 +39,8 @@ describe('luaeval()', function() describe('second argument', function() it('is successfully received', function() - local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}} - eq(t, fn.luaeval("_A", t)) + local q = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}} + eq(q, fn.luaeval("_A", q)) -- Not tested: nil, funcrefs, returned object identity: behaviour will -- most likely change. end) diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua index 0b6a6d60bd..efd69d4607 100644 --- a/test/functional/lua/mpack_spec.lua +++ b/test/functional/lua/mpack_spec.lua @@ -1,9 +1,10 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua describe('lua vim.mpack', function() before_each(clear) @@ -22,7 +23,7 @@ describe('lua vim.mpack', function() { { {}, 'foo', {} }, true, false }, exec_lua [[ local var = vim.mpack.decode(vim.mpack.encode({{}, "foo", vim.empty_dict()})) - return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])} + return {var, vim.islist(var[1]), vim.islist(var[3])} ]] ) end) diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua index ecbdde3bfd..849978f080 100644 --- a/test/functional/lua/overrides_spec.lua +++ b/test/functional/lua/overrides_spec.lua @@ -1,19 +1,20 @@ -- Test for Vim overrides of lua built-ins -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq +local eq = t.eq local NIL = vim.NIL -local feed = helpers.feed -local clear = helpers.clear -local fn = helpers.fn -local api = helpers.api -local command = helpers.command -local write_file = helpers.write_file -local exec_capture = helpers.exec_capture -local exec_lua = helpers.exec_lua -local pcall_err = helpers.pcall_err -local is_os = helpers.is_os +local feed = n.feed +local clear = n.clear +local fn = n.fn +local api = n.api +local command = n.command +local write_file = t.write_file +local exec_capture = n.exec_capture +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err +local is_os = t.is_os local fname = 'Xtest-functional-lua-overrides-luafile' @@ -195,7 +196,7 @@ describe('print', function() end) describe('debug.debug', function() - local screen + local screen --- @type test.functional.ui.screen before_each(function() screen = Screen.new() diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua index 6f36ccfb9e..4adce42c3e 100644 --- a/test/functional/lua/runtime_spec.lua +++ b/test/functional/lua/runtime_spec.lua @@ -1,17 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local exec = helpers.exec -local fn = helpers.fn -local mkdir_p = helpers.mkdir_p -local rmdir = helpers.rmdir -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local exec = n.exec +local fn = n.fn +local mkdir_p = n.mkdir_p +local rmdir = n.rmdir +local write_file = t.write_file describe('runtime:', function() local plug_dir = 'Test_Plugin' - local sep = helpers.get_pathsep() + local sep = n.get_pathsep() local init = 'dummy_init.lua' setup(function() diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua index 7aed711b23..c58fd689b7 100644 --- a/test/functional/lua/secure_spec.lua +++ b/test/functional/lua/secure_spec.lua @@ -1,18 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local clear = helpers.clear -local command = helpers.command -local pathsep = helpers.get_pathsep() -local is_os = helpers.is_os -local api = helpers.api -local exec_lua = helpers.exec_lua -local feed_command = helpers.feed_command -local feed = helpers.feed -local fn = helpers.fn -local pcall_err = helpers.pcall_err -local matches = helpers.matches +local eq = t.eq +local clear = n.clear +local command = n.command +local pathsep = n.get_pathsep() +local is_os = t.is_os +local api = n.api +local exec_lua = n.exec_lua +local feed_command = n.feed_command +local feed = n.feed +local fn = n.fn +local stdpath = fn.stdpath +local pcall_err = t.pcall_err +local matches = t.matches +local read_file = t.read_file describe('vim.secure', function() describe('read()', function() @@ -20,8 +23,8 @@ describe('vim.secure', function() setup(function() clear { env = { XDG_STATE_HOME = xstate } } - helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) - helpers.write_file( + n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + t.write_file( 'Xfile', [[ let g:foobar = 42 @@ -31,7 +34,7 @@ describe('vim.secure', function() teardown(function() os.remove('Xfile') - helpers.rmdir(xstate) + n.rmdir(xstate) end) it('works', function() @@ -71,11 +74,11 @@ describe('vim.secure', function() ]], } - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust)) eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]])) - os.remove(fn.stdpath('state') .. pathsep .. 'trust') + os.remove(stdpath('state') .. pathsep .. 'trust') feed_command([[lua vim.secure.read('Xfile')]]) screen:expect { @@ -100,12 +103,12 @@ describe('vim.secure', function() ]], } - local hash = fn.sha256(helpers.read_file('Xfile')) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local hash = fn.sha256(read_file('Xfile')) + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust)) eq(vim.NIL, exec_lua([[vim.secure.read('Xfile')]])) - os.remove(fn.stdpath('state') .. pathsep .. 'trust') + os.remove(stdpath('state') .. pathsep .. 'trust') feed_command([[lua vim.secure.read('Xfile')]]) screen:expect { @@ -131,7 +134,7 @@ describe('vim.secure', function() } -- Trust database is not updated - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(nil, trust) feed_command([[lua vim.secure.read('Xfile')]]) @@ -165,7 +168,7 @@ describe('vim.secure', function() } -- Trust database is not updated - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(nil, trust) -- Cannot write file @@ -179,15 +182,15 @@ describe('vim.secure', function() setup(function() clear { env = { XDG_STATE_HOME = xstate } } - helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) + n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim')) end) teardown(function() - helpers.rmdir(xstate) + n.rmdir(xstate) end) before_each(function() - helpers.write_file('test_file', 'test') + t.write_file('test_file', 'test') end) after_each(function() @@ -210,70 +213,70 @@ describe('vim.secure', function() it('trust then deny then remove a file using bufnr', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(read_file('test_file')) local full_path = cwd .. pathsep .. 'test_file' command('edit test_file') eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, full_path), vim.trim(trust)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]])) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', full_path), vim.trim(trust)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]])) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq('', vim.trim(trust)) end) it('deny then trust then remove a file using bufnr', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(read_file('test_file')) local full_path = cwd .. pathsep .. 'test_file' command('edit test_file') eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]])) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', full_path), vim.trim(trust)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, full_path), vim.trim(trust)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]])) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq('', vim.trim(trust)) end) it('trust using bufnr then deny then remove a file using path', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(read_file('test_file')) local full_path = cwd .. pathsep .. 'test_file' command('edit test_file') eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, full_path), vim.trim(trust)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]]) ) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', full_path), vim.trim(trust)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]]) ) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq('', vim.trim(trust)) end) it('deny then trust then remove a file using bufnr', function() local cwd = fn.getcwd() - local hash = fn.sha256(helpers.read_file('test_file')) + local hash = fn.sha256(read_file('test_file')) local full_path = cwd .. pathsep .. 'test_file' command('edit test_file') @@ -281,18 +284,18 @@ describe('vim.secure', function() { true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]]) ) - local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + local trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('! %s', full_path), vim.trim(trust)) eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq(string.format('%s %s', hash, full_path), vim.trim(trust)) eq( { true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]]) ) - trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust') + trust = read_file(stdpath('state') .. pathsep .. 'trust') eq('', vim.trim(trust)) end) diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua index e981bc6261..413aa93994 100644 --- a/test/functional/lua/snippet_spec.lua +++ b/test/functional/lua/snippet_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) - -local buf_lines = helpers.buf_lines -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local fn = helpers.fn -local matches = helpers.matches -local pcall_err = helpers.pcall_err -local poke_eventloop = helpers.poke_eventloop -local retry = helpers.retry +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local buf_lines = n.buf_lines +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua +local feed = n.feed +local api = n.api +local fn = n.fn +local matches = t.matches +local pcall_err = t.pcall_err +local poke_eventloop = n.poke_eventloop +local retry = t.retry describe('vim.snippet', function() before_each(function() @@ -95,9 +97,9 @@ describe('vim.snippet', function() it('does not jump outside snippet range', function() test_expand_success({ 'function $1($2)', ' $0', 'end' }, { 'function ()', ' ', 'end' }) - eq(false, exec_lua('return vim.snippet.jumpable(-1)')) + eq(false, exec_lua('return vim.snippet.active({ direction = -1 })')) feed('<Tab><Tab>i') - eq(false, exec_lua('return vim.snippet.jumpable(1)')) + eq(false, exec_lua('return vim.snippet.active( { direction = 1 })')) end) it('navigates backwards', function() @@ -230,7 +232,7 @@ describe('vim.snippet', function() end) it('updates snippet state when built-in completion menu is visible', function() - test_expand_success({ '$1 = function($2)\n$3\nend' }, { ' = function()', '', 'end' }) + test_expand_success({ '$1 = function($2)\nend' }, { ' = function()', 'end' }) -- Show the completion menu. feed('<C-n>') -- Make sure no item is selected. @@ -238,6 +240,50 @@ describe('vim.snippet', function() -- Jump forward (the 2nd tabstop). exec_lua('vim.snippet.jump(1)') feed('foo') - eq({ ' = function(foo)', '', 'end' }, buf_lines(0)) + eq({ ' = function(foo)', 'end' }, buf_lines(0)) + end) + + it('correctly indents with newlines', function() + local curbuf = api.nvim_get_current_buf() + test_expand_success( + { 'function($2)\n\t$3\nend' }, + { 'function()', ' ', 'end' }, + [[ + vim.opt.sw = 2 + vim.opt.expandtab = true + ]] + ) + api.nvim_buf_set_lines(curbuf, 0, -1, false, {}) + test_expand_success( + { 'function($2)\n$3\nend' }, + { 'function()', '', 'end' }, + [[ + vim.opt.sw = 2 + vim.opt.expandtab = true + ]] + ) + api.nvim_buf_set_lines(curbuf, 0, -1, false, {}) + test_expand_success( + { 'func main() {\n\t$1\n}' }, + { 'func main() {', '\t', '}' }, + [[ + vim.opt.sw = 4 + vim.opt.ts = 4 + vim.opt.expandtab = false + ]] + ) + api.nvim_buf_set_lines(curbuf, 0, -1, false, {}) + test_expand_success( + { '${1:name} :: ${2}\n${1:name} ${3}= ${0:undefined}' }, + { + 'name :: ', + 'name = undefined', + }, + [[ + vim.opt.sw = 4 + vim.opt.ts = 4 + vim.opt.expandtab = false + ]] + ) end) end) diff --git a/test/functional/lua/spell_spec.lua b/test/functional/lua/spell_spec.lua index e82dd7b4a0..af7d08b390 100644 --- a/test/functional/lua/spell_spec.lua +++ b/test/functional/lua/spell_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local pcall_err = t.pcall_err describe('vim.spell', function() before_each(function() diff --git a/test/functional/lua/system_spec.lua b/test/functional/lua/system_spec.lua index cb561f0771..e72a009d2e 100644 --- a/test/functional/lua/system_spec.lua +++ b/test/functional/lua/system_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq local function system_sync(cmd, opts) return exec_lua( diff --git a/test/functional/lua/text_spec.lua b/test/functional/lua/text_spec.lua index e31aa63768..9e77953c8c 100644 --- a/test/functional/lua/text_spec.lua +++ b/test/functional/lua/text_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq describe('vim.text', function() before_each(clear) diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua index c1981e19d4..780057b580 100644 --- a/test/functional/lua/thread_spec.lua +++ b/test/functional/lua/thread_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local feed = helpers.feed -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local next_msg = helpers.next_msg + +local assert_alive = n.assert_alive +local clear = n.clear +local feed = n.feed +local eq = t.eq +local exec_lua = n.exec_lua +local next_msg = n.next_msg local NIL = vim.NIL -local pcall_err = helpers.pcall_err +local pcall_err = t.pcall_err describe('thread', function() local screen @@ -166,7 +168,7 @@ describe('thread', function() ]] local msg = next_msg() - eq(msg[1], 'notification') + eq('notification', msg[1]) assert(tonumber(msg[2]) >= 72961) end) @@ -327,7 +329,7 @@ describe('threadpool', function() ]] local msg = next_msg() - eq(msg[1], 'notification') + eq('notification', msg[1]) assert(tonumber(msg[2]) >= 72961) end) diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua index 3e46018682..1e80c88403 100644 --- a/test/functional/lua/ui_event_spec.lua +++ b/test/functional/lua/ui_event_spec.lua @@ -1,10 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local clear = helpers.clear -local feed = helpers.feed -local fn = helpers.fn + +local eq = t.eq +local exec_lua = n.exec_lua +local clear = n.clear +local feed = n.feed +local fn = n.fn +local assert_log = t.assert_log +local check_close = n.check_close + +local testlog = 'Xtest_lua_ui_event_log' describe('vim.ui_attach', function() local screen @@ -108,7 +114,7 @@ describe('vim.ui_attach', function() it('does not crash on exit', function() fn.system({ - helpers.nvim_prog, + n.nvim_prog, '-u', 'NONE', '-i', @@ -120,7 +126,7 @@ describe('vim.ui_attach', function() '--cmd', 'quitall!', }) - eq(0, helpers.eval('v:shell_error')) + eq(0, n.eval('v:shell_error')) end) it('can receive accurate message kinds even if they are history', function() @@ -149,4 +155,56 @@ describe('vim.ui_attach', function() }, }, actual, vim.inspect(actual)) end) + + it('ui_refresh() activates correct capabilities without remote UI', function() + screen:detach() + exec_lua('vim.ui_attach(ns, { ext_cmdline = true }, on_event)') + eq(1, n.api.nvim_get_option_value('cmdheight', {})) + exec_lua('vim.ui_detach(ns)') + exec_lua('vim.ui_attach(ns, { ext_messages = true }, on_event)') + n.api.nvim_set_option_value('cmdheight', 1, {}) + screen:attach() + eq(1, n.api.nvim_get_option_value('cmdheight', {})) + end) + + it("ui_refresh() sets 'cmdheight' for all open tabpages with ext_messages", function() + exec_lua('vim.cmd.tabnew()') + exec_lua('vim.ui_attach(ns, { ext_messages = true }, on_event)') + exec_lua('vim.cmd.tabnext()') + eq(0, n.api.nvim_get_option_value('cmdheight', {})) + end) + + it('avoids recursive flushing and invalid memory access with :redraw', function() + exec_lua([[ + _G.cmdline = 0 + vim.ui_attach(ns, { ext_messages = true }, function(ev) + vim.cmd.redraw() + _G.cmdline = _G.cmdline + (ev == 'cmdline_show' and 1 or 0) + end + )]]) + feed(':') + eq(1, exec_lua('return _G.cmdline')) + n.assert_alive() + feed('version<CR><CR>v<Esc>') + n.assert_alive() + end) +end) + +describe('vim.ui_attach', function() + after_each(function() + check_close() + os.remove(testlog) + end) + + it('error in callback is logged', function() + clear({ env = { NVIM_LOG_FILE = testlog } }) + local screen = Screen.new() + screen:attach() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('testspace') + vim.ui_attach(ns, { ext_popupmenu = true }, function() error(42) end) + ]]) + feed('ifoo<CR>foobar<CR>fo<C-X><C-N>') + assert_log('Error executing UI event callback: Error executing lua: .*: 42', testlog, 100) + end) end) diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua index e769843b19..d69e893c96 100644 --- a/test/functional/lua/ui_spec.lua +++ b/test/functional/lua/ui_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local matches = helpers.matches -local exec_lua = helpers.exec_lua -local clear = helpers.clear -local feed = helpers.feed -local eval = helpers.eval -local is_ci = helpers.is_ci -local is_os = helpers.is_os -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local ok = t.ok +local exec_lua = n.exec_lua +local clear = n.clear +local feed = n.feed +local eval = n.eval +local is_ci = t.is_ci +local is_os = t.is_os +local poke_eventloop = n.poke_eventloop describe('vim.ui', function() before_each(function() @@ -138,13 +140,12 @@ describe('vim.ui', function() describe('open()', function() it('validation', function() if is_os('win') or not is_ci('github') then - exec_lua [[vim.system = function() return { wait=function() return { code=3} end } end]] + exec_lua [[vim.system = function() return { wait=function() return { code=3 } end } end]] end if not is_os('bsd') then - matches( - 'vim.ui.open: command failed %(%d%): { "[^"]+", .*"non%-existent%-file" }', - exec_lua [[local _, err = vim.ui.open('non-existent-file') ; return err]] - ) + local rv = + exec_lua [[local cmd = vim.ui.open('non-existent-file'); return cmd:wait(100).code]] + ok(type(rv) == 'number' and rv ~= 0, 'nonzero exit code', rv) end exec_lua [[ @@ -152,7 +153,7 @@ describe('vim.ui', function() vim.fn.executable = function() return 0 end ]] eq( - 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)', + 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)', exec_lua [[local _, err = vim.ui.open('foo') ; return err]] ) end) diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua index dacaf95867..553afb35d3 100644 --- a/test/functional/lua/uri_spec.lua +++ b/test/functional/lua/uri_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local is_os = helpers.is_os -local skip = helpers.skip -local write_file = require('test.helpers').write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local is_os = t.is_os +local skip = t.skip +local write_file = t.write_file describe('URI methods', function() before_each(function() @@ -206,7 +208,7 @@ describe('URI methods', function() it('Windows paths should not be treated as uris', function() skip(not is_os('win'), 'Not applicable on non-Windows') - local file = helpers.tmpname() + local file = t.tmpname() write_file(file, 'Test content') local test_case = string.format( [[ diff --git a/test/functional/lua/version_spec.lua b/test/functional/lua/version_spec.lua index 3bc9e26d41..4ce8fb8dfe 100644 --- a/test/functional/lua/version_spec.lua +++ b/test/functional/lua/version_spec.lua @@ -1,10 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local ok = helpers.ok -local exec_lua = helpers.exec_lua -local matches = helpers.matches -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local ok = t.ok +local exec_lua = n.exec_lua +local matches = t.matches +local pcall_err = t.pcall_err +local fn = n.fn local function v(ver) return vim.version._version(ver) @@ -17,7 +20,7 @@ describe('version', function() end) it('version() returns Nvim version', function() - local expected = exec_lua('return vim.fn.api_info().version') + local expected = fn.api_info().version local actual = exec_lua('return vim.version()') eq(expected.major, actual.major) eq(expected.minor, actual.minor) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index a262d239e8..c8f94c6ffa 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1,32 +1,33 @@ -- Test suite for testing interactions with API bindings -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local nvim_prog = helpers.nvim_prog -local fn = helpers.fn -local api = helpers.api -local command = helpers.command -local dedent = helpers.dedent -local insert = helpers.insert -local clear = helpers.clear -local eq = helpers.eq -local ok = helpers.ok +local nvim_prog = n.nvim_prog +local fn = n.fn +local api = n.api +local command = n.command +local dedent = t.dedent +local insert = n.insert +local clear = n.clear +local eq = t.eq +local ok = t.ok local pesc = vim.pesc -local eval = helpers.eval -local feed = helpers.feed -local pcall_err = helpers.pcall_err -local exec_lua = helpers.exec_lua -local matches = helpers.matches -local exec = helpers.exec +local eval = n.eval +local feed = n.feed +local pcall_err = t.pcall_err +local exec_lua = n.exec_lua +local matches = t.matches +local exec = n.exec local NIL = vim.NIL -local retry = helpers.retry -local next_msg = helpers.next_msg -local remove_trace = helpers.remove_trace -local mkdir_p = helpers.mkdir_p -local rmdir = helpers.rmdir -local write_file = helpers.write_file -local poke_eventloop = helpers.poke_eventloop -local assert_alive = helpers.assert_alive +local retry = t.retry +local next_msg = n.next_msg +local remove_trace = t.remove_trace +local mkdir_p = n.mkdir_p +local rmdir = n.rmdir +local write_file = t.write_file +local poke_eventloop = n.poke_eventloop +local assert_alive = n.assert_alive describe('lua stdlib', function() before_each(clear) @@ -128,63 +129,62 @@ describe('lua stdlib', function() eq(1, fn.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")')) end) - local function test_vim_deprecate(current_version) + --- @param prerel string | nil + local function test_vim_deprecate(prerel) -- vim.deprecate(name, alternative, version, plugin, backtrace) -- See MAINTAIN.md for the soft/hard deprecation policy - describe(('vim.deprecate [current_version = %s]'):format(current_version), function() - before_each(function() - -- mock vim.version() behavior, should be pinned for consistent testing - exec_lua( - [[ - local current_version_mock = vim.version.parse(...) - getmetatable(vim.version).__call = function() - return current_version_mock - end - ]], - current_version - ) - end) + describe(('vim.deprecate prerel=%s,'):format(prerel or 'nil'), function() + local curver = exec_lua('return vim.version()') --[[@as {major:number, minor:number}]] + -- "0.10" or "0.10-dev+xxx" + local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '') + -- "0.10" or "0.11" + local nextver = ('%s.%s'):format(curver.major, curver.minor + (prerel and 0 or 1)) + local was_removed = prerel and 'was removed' or 'will be removed' - it('when plugin = nil', function() + it('plugin=nil, same message skipped', function() eq( - dedent [[ - foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated - This feature will be removed in Nvim version 0.10]], - exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10') + dedent( + [[ + foo.bar() is deprecated. Run ":checkhealth vim.deprecated" for more information]] + ):format(curstr), + exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', curstr) ) - -- Same message, skipped. - eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10')) + -- Same message as above; skipped this time. + eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', curstr)) + end) - -- Don't show error if not hard-deprecated (only soft-deprecated) + it('plugin=nil, no error if soft-deprecated', function() eq( vim.NIL, - exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.12.0') + exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.99.0') ) + end) - -- Show error if hard-deprecated + it('plugin=nil, show error if hard-deprecated', function() eq( - dedent [[ - foo.hard_dep() is deprecated, use vim.new_api() instead. :help deprecated - This feature will be removed in Nvim version 0.11]], - exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', '0.11') + dedent( + [[ + foo.hard_dep() is deprecated. Run ":checkhealth vim.deprecated" for more information]] + ):format(was_removed, nextver), + exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', nextver) ) + end) - -- To be deleted in the next major version (1.0) + it('plugin=nil, to be deleted in the next major version (1.0)', function() eq( dedent [[ - foo.baz() is deprecated. :help deprecated - This feature will be removed in Nvim version 1.0]], + foo.baz() is deprecated. Run ":checkhealth vim.deprecated" for more information]], exec_lua [[ return vim.deprecate('foo.baz()', nil, '1.0') ]] ) end) - it('when plugin is specified', function() + it('plugin specified', function() -- When `plugin` is specified, don't show ":help deprecated". #22235 eq( dedent [[ foo.bar() is deprecated, use zub.wooo{ok=yay} instead. - This feature will be removed in my-plugin.nvim version 0.3.0]], + Feature will be removed in my-plugin.nvim 0.3.0]], exec_lua( 'return vim.deprecate(...)', 'foo.bar()', @@ -199,7 +199,7 @@ describe('lua stdlib', function() eq( dedent [[ foo.bar() is deprecated, use zub.wooo{ok=yay} instead. - This feature will be removed in my-plugin.nvim version 0.11.0]], + Feature will be removed in my-plugin.nvim 0.11.0]], exec_lua( 'return vim.deprecate(...)', 'foo.bar()', @@ -213,8 +213,8 @@ describe('lua stdlib', function() end) end - test_vim_deprecate('0.10') - test_vim_deprecate('0.10-dev+g0000000') + test_vim_deprecate() + test_vim_deprecate('-dev+g0000000') it('vim.startswith', function() eq(true, fn.luaeval('vim.startswith("123", "1")')) @@ -592,8 +592,8 @@ describe('lua stdlib', function() { 'x*yz*oo*l', '*', true, false, { 'x', 'yz', 'oo', 'l' } }, } - for _, t in ipairs(tests) do - eq(t[5], vim.split(t[1], t[2], { plain = t[3], trimempty = t[4] }), t[1]) + for _, q in ipairs(tests) do + eq(q[5], vim.split(q[1], q[2], { plain = q[3], trimempty = q[4] }), q[1]) end -- Test old signature @@ -603,8 +603,8 @@ describe('lua stdlib', function() { 'abc', '.-' }, } - for _, t in ipairs(loops) do - matches('Infinite loop detected', pcall_err(vim.split, t[1], t[2])) + for _, q in ipairs(loops) do + matches('Infinite loop detected', pcall_err(vim.split, q[1], q[2])) end -- Validates args. @@ -626,8 +626,8 @@ describe('lua stdlib', function() { 'r\n', 'r' }, } - for _, t in ipairs(trims) do - assert(t[2], trim(t[1])) + for _, q in ipairs(trims) do + assert(q[2], trim(q[1])) end -- Validates args. @@ -636,8 +636,8 @@ describe('lua stdlib', function() it('vim.inspect', function() -- just make sure it basically works, it has its own test suite - local inspect = function(t, opts) - return exec_lua('return vim.inspect(...)', t, opts) + local inspect = function(q, opts) + return exec_lua('return vim.inspect(...)', q, opts) end eq('2', inspect(2)) @@ -670,21 +670,21 @@ describe('lua stdlib', function() local a = {} local b = vim.deepcopy(a) - return vim.tbl_islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b) + return vim.islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b) ]])) ok(exec_lua([[ local a = vim.empty_dict() local b = vim.deepcopy(a) - return not vim.tbl_islist(b) and vim.tbl_count(b) == 0 + return not vim.islist(b) and vim.tbl_count(b) == 0 ]])) ok(exec_lua([[ local a = {x = vim.empty_dict(), y = {}} local b = vim.deepcopy(a) - return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y) + return not vim.islist(b.x) and vim.islist(b.y) and vim.tbl_count(b) == 2 and tostring(a) ~= tostring(b) ]])) @@ -822,30 +822,30 @@ describe('lua stdlib', function() ) end) - it('vim.tbl_isarray', function() - eq(true, exec_lua('return vim.tbl_isarray({})')) - eq(false, exec_lua('return vim.tbl_isarray(vim.empty_dict())')) - eq(true, exec_lua("return vim.tbl_isarray({'a', 'b', 'c'})")) - eq(false, exec_lua("return vim.tbl_isarray({'a', '32', a='hello', b='baz'})")) - eq(false, exec_lua("return vim.tbl_isarray({1, a='hello', b='baz'})")) - eq(false, exec_lua("return vim.tbl_isarray({a='hello', b='baz', 1})")) - eq(false, exec_lua("return vim.tbl_isarray({1, 2, nil, a='hello'})")) - eq(true, exec_lua('return vim.tbl_isarray({1, 2, nil, 4})')) - eq(true, exec_lua('return vim.tbl_isarray({nil, 2, 3, 4})')) - eq(false, exec_lua('return vim.tbl_isarray({1, [1.5]=2, [3]=3})')) + it('vim.isarray', function() + eq(true, exec_lua('return vim.isarray({})')) + eq(false, exec_lua('return vim.isarray(vim.empty_dict())')) + eq(true, exec_lua("return vim.isarray({'a', 'b', 'c'})")) + eq(false, exec_lua("return vim.isarray({'a', '32', a='hello', b='baz'})")) + eq(false, exec_lua("return vim.isarray({1, a='hello', b='baz'})")) + eq(false, exec_lua("return vim.isarray({a='hello', b='baz', 1})")) + eq(false, exec_lua("return vim.isarray({1, 2, nil, a='hello'})")) + eq(true, exec_lua('return vim.isarray({1, 2, nil, 4})')) + eq(true, exec_lua('return vim.isarray({nil, 2, 3, 4})')) + eq(false, exec_lua('return vim.isarray({1, [1.5]=2, [3]=3})')) end) - it('vim.tbl_islist', function() - eq(true, exec_lua('return vim.tbl_islist({})')) - eq(false, exec_lua('return vim.tbl_islist(vim.empty_dict())')) - eq(true, exec_lua("return vim.tbl_islist({'a', 'b', 'c'})")) - eq(false, exec_lua("return vim.tbl_islist({'a', '32', a='hello', b='baz'})")) - eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})")) - eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})")) - eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})")) - eq(false, exec_lua('return vim.tbl_islist({1, 2, nil, 4})')) - eq(false, exec_lua('return vim.tbl_islist({nil, 2, 3, 4})')) - eq(false, exec_lua('return vim.tbl_islist({1, [1.5]=2, [3]=3})')) + it('vim.islist', function() + eq(true, exec_lua('return vim.islist({})')) + eq(false, exec_lua('return vim.islist(vim.empty_dict())')) + eq(true, exec_lua("return vim.islist({'a', 'b', 'c'})")) + eq(false, exec_lua("return vim.islist({'a', '32', a='hello', b='baz'})")) + eq(false, exec_lua("return vim.islist({1, a='hello', b='baz'})")) + eq(false, exec_lua("return vim.islist({a='hello', b='baz', 1})")) + eq(false, exec_lua("return vim.islist({1, 2, nil, a='hello'})")) + eq(false, exec_lua('return vim.islist({1, 2, nil, 4})')) + eq(false, exec_lua('return vim.islist({nil, 2, 3, 4})')) + eq(false, exec_lua('return vim.islist({1, [1.5]=2, [3]=3})')) end) it('vim.tbl_isempty', function() @@ -918,7 +918,7 @@ describe('lua stdlib', function() local b = {} local c = vim.tbl_extend("keep", a, b) - return not vim.tbl_islist(c) and vim.tbl_count(c) == 0 + return not vim.islist(c) and vim.tbl_count(c) == 0 ]])) ok(exec_lua([[ @@ -926,7 +926,7 @@ describe('lua stdlib', function() local b = vim.empty_dict() local c = vim.tbl_extend("keep", a, b) - return vim.tbl_islist(c) and vim.tbl_count(c) == 0 + return vim.islist(c) and vim.tbl_count(c) == 0 ]])) ok(exec_lua([[ @@ -1026,7 +1026,7 @@ describe('lua stdlib', function() local count = 0 for _ in pairs(c) do count = count + 1 end - return not vim.tbl_islist(c) and count == 0 + return not vim.islist(c) and count == 0 ]])) ok(exec_lua([[ @@ -1037,7 +1037,7 @@ describe('lua stdlib', function() local count = 0 for _ in pairs(c) do count = count + 1 end - return vim.tbl_islist(c) and count == 0 + return vim.islist(c) and count == 0 ]])) eq( @@ -1282,7 +1282,7 @@ describe('lua stdlib', function() vim.rpcrequest(chan, 'nvim_exec', 'let xx = {}\nlet yy = []', false) local dict = vim.rpcrequest(chan, 'nvim_eval', 'xx') local list = vim.rpcrequest(chan, 'nvim_eval', 'yy') - return {dict, list, vim.tbl_islist(dict), vim.tbl_islist(list)} + return {dict, list, vim.islist(dict), vim.islist(list)} ]]) ) @@ -1355,7 +1355,7 @@ describe('lua stdlib', function() vim.api.nvim_set_var('dicty', vim.empty_dict()) local listy = vim.fn.eval("listy") local dicty = vim.fn.eval("dicty") - return {vim.tbl_islist(listy), vim.tbl_islist(dicty), next(listy) == nil, next(dicty) == nil} + return {vim.islist(listy), vim.islist(dicty), next(listy) == nil, next(dicty) == nil} ]]) ) @@ -1569,7 +1569,7 @@ describe('lua stdlib', function() eq(NIL, exec_lua([[return vim.g.Unknown_script_func]])) -- Check if autoload works properly - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() local xconfig = 'Xhome' .. pathsep .. 'Xconfig' local xdata = 'Xhome' .. pathsep .. 'Xdata' local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep) @@ -2016,7 +2016,7 @@ describe('lua stdlib', function() vim.opt.scrolloff = 10 return vim.o.scrolloff ]] - eq(scrolloff, 10) + eq(10, scrolloff) end) pending('should handle STUPID window things', function() @@ -2037,7 +2037,7 @@ describe('lua stdlib', function() vim.opt.wildignore = { 'hello', 'world' } return vim.o.wildignore ]] - eq(wildignore, 'hello,world') + eq('hello,world', wildignore) end) it('should allow setting tables with shortnames', function() @@ -2045,7 +2045,7 @@ describe('lua stdlib', function() vim.opt.wig = { 'hello', 'world' } return vim.o.wildignore ]] - eq(wildignore, 'hello,world') + eq('hello,world', wildignore) end) it('should error when you attempt to set string values to numeric options', function() @@ -2451,13 +2451,13 @@ describe('lua stdlib', function() vim.opt.wildignore = 'foo' return vim.o.wildignore ]] - eq(wildignore, 'foo') + eq('foo', wildignore) wildignore = exec_lua [[ vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } return vim.o.wildignore ]] - eq(wildignore, 'foo,bar,baz') + eq('foo,bar,baz', wildignore) end) it('should handle adding duplicates', function() @@ -2465,19 +2465,19 @@ describe('lua stdlib', function() vim.opt.wildignore = 'foo' return vim.o.wildignore ]] - eq(wildignore, 'foo') + eq('foo', wildignore) wildignore = exec_lua [[ vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } return vim.o.wildignore ]] - eq(wildignore, 'foo,bar,baz') + eq('foo,bar,baz', wildignore) wildignore = exec_lua [[ vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } return vim.o.wildignore ]] - eq(wildignore, 'foo,bar,baz') + eq('foo,bar,baz', wildignore) end) it('should allow adding multiple times', function() @@ -2486,7 +2486,7 @@ describe('lua stdlib', function() vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz' return vim.o.wildignore ]] - eq(wildignore, 'foo,bar,baz') + eq('foo,bar,baz', wildignore) end) it('should remove values when you use minus', function() @@ -2494,19 +2494,19 @@ describe('lua stdlib', function() vim.opt.wildignore = 'foo' return vim.o.wildignore ]] - eq(wildignore, 'foo') + eq('foo', wildignore) wildignore = exec_lua [[ vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' } return vim.o.wildignore ]] - eq(wildignore, 'foo,bar,baz') + eq('foo,bar,baz', wildignore) wildignore = exec_lua [[ vim.opt.wildignore = vim.opt.wildignore - 'bar' return vim.o.wildignore ]] - eq(wildignore, 'foo,baz') + eq('foo,baz', wildignore) end) it('should prepend values when using ^', function() @@ -2521,7 +2521,7 @@ describe('lua stdlib', function() vim.opt.wildignore = vim.opt.wildignore ^ 'super_first' return vim.o.wildignore ]] - eq(wildignore, 'super_first,first,foo') + eq('super_first,first,foo', wildignore) end) it('should not remove duplicates from wildmode: #14708', function() @@ -2530,7 +2530,7 @@ describe('lua stdlib', function() return vim.o.wildmode ]] - eq(wildmode, 'full,list,full') + eq('full,list,full', wildmode) end) describe('option types', function() @@ -2738,7 +2738,7 @@ describe('lua stdlib', function() return vim.go.whichwrap ]] - eq(ww, 'b,s') + eq('b,s', ww) eq( 'b,s,<,>,[,]', exec_lua [[ @@ -3007,25 +3007,65 @@ describe('lua stdlib', function() end) describe('vim.on_key', function() - it('tracks keystrokes', function() + it('tracks Unicode input', function() insert([[hello world ]]) exec_lua [[ keys = {} + typed = {} - vim.on_key(function(buf) + vim.on_key(function(buf, typed_buf) if buf:byte() == 27 then buf = "<ESC>" end + if typed_buf:byte() == 27 then + typed_buf = "<ESC>" + end table.insert(keys, buf) + table.insert(typed, typed_buf) end) ]] - insert([[next 🤦 lines å ]]) + insert([[next 🤦 lines å …]]) -- It has escape in the keys pressed - eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(keys, '')]]) + eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(keys, '')]]) + eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(typed, '')]]) + end) + + it('tracks input with modifiers', function() + exec_lua [[ + keys = {} + typed = {} + + vim.on_key(function(buf, typed_buf) + table.insert(keys, vim.fn.keytrans(buf)) + table.insert(typed, vim.fn.keytrans(typed_buf)) + end) + ]] + + feed([[i<C-V><C-;><C-V><C-…><Esc>]]) + + eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(keys, '')]]) + eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(typed, '')]]) + end) + + it('works with character find and Select mode', function() + insert('12345') + + exec_lua [[ + typed = {} + + vim.cmd('snoremap # @') + + vim.on_key(function(buf, typed_buf) + table.insert(typed, vim.fn.keytrans(typed_buf)) + end) + ]] + + feed('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^') + eq('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^', exec_lua [[return table.concat(typed, '')]]) end) it('allows removing on_key listeners', function() @@ -3087,23 +3127,29 @@ describe('lua stdlib', function() eq('inext l', exec_lua [[ return table.concat(keys, '') ]]) end) - it('processes mapped keys, not unmapped keys', function() + it('argument 1 is keys after mapping, argument 2 is typed keys', function() exec_lua [[ keys = {} + typed = {} vim.cmd("inoremap hello world") - vim.on_key(function(buf) + vim.on_key(function(buf, typed_buf) if buf:byte() == 27 then buf = "<ESC>" end + if typed_buf:byte() == 27 then + typed_buf = "<ESC>" + end table.insert(keys, buf) + table.insert(typed, typed_buf) end) ]] insert('hello') eq('iworld<ESC>', exec_lua [[return table.concat(keys, '')]]) + eq('ihello<ESC>', exec_lua [[return table.concat(typed, '')]]) end) it('can call vim.fn functions on Ctrl-C #17273', function() @@ -3664,6 +3710,20 @@ describe('lua stdlib', function() ]] ) end) + + it('layout in current tabpage does not affect windows in others', function() + command('tab split') + local t2_move_win = api.nvim_get_current_win() + command('vsplit') + local t2_other_win = api.nvim_get_current_win() + command('tabprevious') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + command('vsplit') + + -- Without vim-patch:8.2.3862, this gives E36, despite just the 1st tabpage being full. + exec_lua('vim.api.nvim_win_call(..., function() vim.cmd.wincmd "J" end)', t2_move_win) + eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2)) + end) end) describe('vim.iconv', function() @@ -4011,7 +4071,7 @@ describe('vim.keymap', function() feed('asdf\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) + eq('\nNo mapping found', n.exec_capture('nmap asdf')) end) it('works with buffer-local mappings', function() @@ -4035,7 +4095,7 @@ describe('vim.keymap', function() feed('asdf\n') eq(1, exec_lua [[return GlobalCount]]) - eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) + eq('\nNo mapping found', n.exec_capture('nmap asdf')) end) it('does not mutate the opts parameter', function() diff --git a/test/functional/lua/watch_spec.lua b/test/functional/lua/watch_spec.lua index 115fee8091..bd8faadf5b 100644 --- a/test/functional/lua/watch_spec.lua +++ b/test/functional/lua/watch_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local clear = helpers.clear -local is_ci = helpers.is_ci -local is_os = helpers.is_os -local skip = helpers.skip +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local exec_lua = n.exec_lua +local clear = n.clear +local is_ci = t.is_ci +local is_os = t.is_os +local skip = t.skip -- Create a file via a rename to avoid multiple -- events which can happen with some backends on some platforms local function touch(path) - local tmp = helpers.tmpname() + local tmp = t.tmpname() io.open(tmp, 'w'):close() assert(vim.uv.fs_rename(tmp, path)) end @@ -22,15 +24,13 @@ describe('vim._watch', function() local function run(watchfunc) it('detects file changes (watchfunc=' .. watchfunc .. '())', function() if watchfunc == 'fswatch' then - skip(is_os('mac'), 'flaky test on mac') - skip( - not is_ci() and helpers.fn.executable('fswatch') == 0, - 'fswatch not installed and not on CI' - ) skip(is_os('win'), 'not supported on windows') + skip(is_os('mac'), 'flaky test on mac') + skip(not is_ci() and n.fn.executable('fswatch') == 0, 'fswatch not installed and not on CI') end if watchfunc == 'watch' then + skip(is_os('mac'), 'flaky test on mac') skip(is_os('bsd'), 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38') else skip( @@ -39,7 +39,7 @@ describe('vim._watch', function() ) end - local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX') + local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname()) .. '/nvim_XXXXXXXXXX') local expected_events = 0 diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua index c21309c2e4..d5589c1f13 100644 --- a/test/functional/lua/xdiff_spec.lua +++ b/test/functional/lua/xdiff_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local pcall_err = t.pcall_err describe('xdiff bindings', function() before_each(function() diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua index 11f71912a9..c490ab67a9 100644 --- a/test/functional/options/autochdir_spec.lua +++ b/test/functional/options/autochdir_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local fn = helpers.fn -local command = helpers.command -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local fn = n.fn +local command = n.command +local mkdir = t.mkdir describe("'autochdir'", function() it('given on the shell gets processed properly', function() @@ -16,7 +18,7 @@ describe("'autochdir'", function() -- With 'autochdir' on, we should get the directory of tty-test.c. clear('--cmd', 'set autochdir', targetdir .. '/tty-test.c') - eq(helpers.is_os('win') and expected:gsub('/', '\\') or expected, fn.getcwd()) + eq(t.is_os('win') and expected:gsub('/', '\\') or expected, fn.getcwd()) end) it('is not overwritten by getwinvar() call #17609', function() @@ -38,7 +40,7 @@ describe("'autochdir'", function() eq(dir_a, fn.getcwd()) fn.getwinvar(2, 'foo') eq(dir_a, fn.getcwd()) - helpers.rmdir(dir_a) - helpers.rmdir(dir_b) + n.rmdir(dir_a) + n.rmdir(dir_b) end) end) diff --git a/test/functional/options/chars_spec.lua b/test/functional/options/chars_spec.lua index e9c20b5da9..8e63e07e09 100644 --- a/test/functional/options/chars_spec.lua +++ b/test/functional/options/chars_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, command = helpers.clear, helpers.command -local pcall_err = helpers.pcall_err -local eval = helpers.eval -local eq = helpers.eq -local insert = helpers.insert -local feed = helpers.feed -local api = helpers.api + +local clear, command = n.clear, n.command +local pcall_err = t.pcall_err +local eval = n.eval +local eq = t.eq +local insert = n.insert +local feed = n.feed +local api = n.api describe("'fillchars'", function() local screen @@ -22,7 +24,7 @@ describe("'fillchars'", function() eq('', eval('&fillchars')) screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 | ]]) end) @@ -30,13 +32,14 @@ describe("'fillchars'", function() it('supports whitespace', function() screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 | ]]) command('set fillchars=eob:\\ ') screen:expect([[ ^ | - |*4 + {1: }|*3 + | ]]) end) @@ -44,7 +47,7 @@ describe("'fillchars'", function() command('set fillchars=eob:ñ') screen:expect([[ ^ | - ñ |*3 + {1:ñ }|*3 | ]]) end) @@ -53,7 +56,7 @@ describe("'fillchars'", function() command('set fillchars=eob:å̲') screen:expect([[ ^ | - å̲ |*3 + {1:å̲ }|*3 | ]]) end) @@ -112,8 +115,8 @@ describe("'fillchars'", function() command('vsplit') command('set fillchars=fold:x') screen:expect([[ - ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: fooxxxxxxx| - ~ │~ |*3 + {13:^+-- 2 lines: fooxxxxxxxx}│{13:+-- 2 lines: fooxxxxxxx}| + {1:~ }│{1:~ }|*3 | ]]) end) @@ -126,8 +129,8 @@ describe("'fillchars'", function() command('vsplit') command('setl fillchars=fold:x') screen:expect([[ - ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: foo·······| - ~ │~ |*3 + {13:^+-- 2 lines: fooxxxxxxxx}│{13:+-- 2 lines: foo·······}| + {1:~ }│{1:~ }|*3 | ]]) end) @@ -141,8 +144,8 @@ describe("'fillchars'", function() command('vsplit') command('set fillchars&') screen:expect([[ - ^+-- 2 lines: foo········│+-- 2 lines: fooxxxxxxx| - ~ │~ |*3 + {13:^+-- 2 lines: foo········}│{13:+-- 2 lines: fooxxxxxxx}| + {1:~ }│{1:~ }|*3 | ]]) end) @@ -163,8 +166,8 @@ describe("'listchars'", function() command('vsplit') command('set listchars=tab:<->') screen:expect([[ - <------><------>^<------> │<------><------><------>| - ~ │~ |*3 + {1:<------><------>^<------>} │{1:<------><------><------>}| + {1:~ }│{1:~ }|*3 | ]]) end) @@ -176,8 +179,8 @@ describe("'listchars'", function() command('vsplit') command('setl listchars<') screen:expect([[ - > > ^> │<------><------><------>| - ~ │~ |*3 + {1:> > ^> } │{1:<------><------><------>}| + {1:~ }│{1:~ }|*3 | ]]) end) @@ -189,8 +192,8 @@ describe("'listchars'", function() command('vsplit') command('set listchars=tab:>-,eol:$') screen:expect([[ - >------->-------^>-------$│<------><------><------>| - ~ │~ |*3 + {1:>------->-------^>-------$}│{1:<------><------><------>}| + {1:~ }│{1:~ }|*3 | ]]) end) diff --git a/test/functional/options/cursorbind_spec.lua b/test/functional/options/cursorbind_spec.lua index cafdc83de2..19551b928f 100644 --- a/test/functional/options/cursorbind_spec.lua +++ b/test/functional/options/cursorbind_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local exec = helpers.exec -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local exec = n.exec +local feed = n.feed before_each(clear) diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index d27fa375ee..f61139d92d 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -1,26 +1,27 @@ -local helpers = require('test.functional.helpers')(after_each) - +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local assert_log = helpers.assert_log -local api = helpers.api -local command = helpers.command -local clear = helpers.clear -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local eval = helpers.eval -local eq = helpers.eq -local ok = helpers.ok -local fn = helpers.fn -local insert = helpers.insert -local neq = helpers.neq -local mkdir = helpers.mkdir -local rmdir = helpers.rmdir -local alter_slashes = helpers.alter_slashes +local assert_alive = n.assert_alive +local assert_log = t.assert_log +local api = n.api +local command = n.command +local clear = n.clear +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local eval = n.eval +local eq = t.eq +local ok = t.ok +local fn = n.fn +local insert = n.insert +local neq = t.neq +local mkdir = t.mkdir +local rmdir = n.rmdir +local alter_slashes = n.alter_slashes local tbl_contains = vim.tbl_contains -local expect_exit = helpers.expect_exit -local is_os = helpers.is_os +local expect_exit = n.expect_exit +local check_close = n.check_close +local is_os = t.is_os local testlog = 'Xtest-defaults-log' @@ -32,7 +33,7 @@ describe('startup defaults', function() command('filetype') screen:expect([[ ^ | - ~ |*2 + {1:~ }|*2 ]] .. expected) end @@ -132,9 +133,9 @@ describe('startup defaults', function() command('vsp') screen:expect([[ 1 │1 | - ^+-- 2 lines: 2··········│+-- 2 lines: 2·········| + {13:^+-- 2 lines: 2··········}│{13:+-- 2 lines: 2·········}| 4 │4 | - ~ │~ | + {1:~ }│{1:~ }| | ]]) @@ -142,9 +143,9 @@ describe('startup defaults', function() command('set ambiwidth=double') screen:expect([[ 1 |1 | - ^+-- 2 lines: 2----------|+-- 2 lines: 2---------| + {13:^+-- 2 lines: 2----------}|{13:+-- 2 lines: 2---------}| 4 |4 | - ~ |~ | + {1:~ }|{1:~ }| | ]]) @@ -152,9 +153,9 @@ describe('startup defaults', function() fn.setcellwidths({ { 0x2502, 0x2502, 1 } }) screen:expect([[ 1 │1 | - ^+-- 2 lines: 2----------│+-- 2 lines: 2---------| + {13:^+-- 2 lines: 2----------}│{13:+-- 2 lines: 2---------}| 4 │4 | - ~ │~ | + {1:~ }│{1:~ }| | ]]) @@ -162,9 +163,9 @@ describe('startup defaults', function() fn.setcellwidths({ { 0x2502, 0x2502, 2 } }) screen:expect([[ 1 |1 | - ^+-- 2 lines: 2----------|+-- 2 lines: 2---------| + {13:^+-- 2 lines: 2----------}|{13:+-- 2 lines: 2---------}| 4 |4 | - ~ |~ | + {1:~ }|{1:~ }| | ]]) @@ -172,9 +173,9 @@ describe('startup defaults', function() command('set ambiwidth=single') screen:expect([[ 1 |1 | - ^+-- 2 lines: 2··········|+-- 2 lines: 2·········| + {13:^+-- 2 lines: 2··········}|{13:+-- 2 lines: 2·········}| 4 |4 | - ~ |~ | + {1:~ }|{1:~ }| | ]]) end) @@ -274,6 +275,7 @@ describe('XDG defaults', function() -- Do not put before_each() here for the same reasons. after_each(function() + check_close() os.remove(testlog) end) @@ -378,7 +380,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -393,12 +395,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -413,7 +415,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048) @@ -449,7 +451,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -464,12 +466,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -484,7 +486,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048) @@ -865,6 +867,11 @@ describe('XDG defaults', function() end) describe('stdpath()', function() + after_each(function() + check_close() + os.remove(testlog) + end) + -- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions -- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same. local function maybe_data(name) @@ -890,7 +897,7 @@ describe('stdpath()', function() it('reacts to $NVIM_APPNAME', function() local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106) - clear({ env = { NVIM_APPNAME = appname } }) + clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } }) eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t')) eq(appname, fn.fnamemodify(fn.stdpath('cache'), ':t')) eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('log'), ':t')) @@ -928,6 +935,9 @@ describe('stdpath()', function() -- Valid appnames: test_appname('a/b', 0) test_appname('a/b\\c', 0) + if not is_os('win') then + assert_log('Failed to start server: no such file or directory:', testlog) + end end) describe('returns a String', function() @@ -1220,6 +1230,8 @@ describe('stdpath()', function() end) describe('errors', function() + before_each(clear) + it('on unknown strings', function() eq('Vim(call):E6100: "capybara" is not a valid stdpath', exc_exec('call stdpath("capybara")')) eq('Vim(call):E6100: "" is not a valid stdpath', exc_exec('call stdpath("")')) @@ -1235,7 +1247,8 @@ end) describe('autocommands', function() it('closes terminal with default shell on success', function() - api.nvim_set_option_value('shell', helpers.testprg('shell-test'), {}) + clear() + api.nvim_set_option_value('shell', n.testprg('shell-test'), {}) command('set shellcmdflag=EXIT shellredir= shellpipe= shellquote= shellxquote=') -- Should not block other events @@ -1243,11 +1256,11 @@ describe('autocommands', function() command('au BufEnter * let g:n = g:n + 1') command('terminal') - eq(eval('get(g:, "n", 0)'), 1) + eq(1, eval('get(g:, "n", 0)')) - helpers.retry(nil, 1000, function() - neq(api.nvim_get_option_value('buftype', { buf = 0 }), 'terminal') - eq(eval('get(g:, "n", 0)'), 2) + t.retry(nil, 1000, function() + neq('terminal', api.nvim_get_option_value('buftype', { buf = 0 })) + eq(2, eval('get(g:, "n", 0)')) end) end) end) diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua index 7be58888bc..f76525699f 100644 --- a/test/functional/options/keymap_spec.lua +++ b/test/functional/options/keymap_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq -local expect, command, eval = helpers.expect, helpers.command, helpers.eval -local insert, call = helpers.insert, helpers.call -local exec_capture, dedent = helpers.exec_capture, helpers.dedent +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed, eq = n.clear, n.feed, t.eq +local expect, command, eval = n.expect, n.command, n.eval +local insert, call = n.insert, n.call +local exec_capture, dedent = n.exec_capture, t.dedent -- First test it's implemented using the :lmap and :lnoremap commands, then -- check those mappings behave as expected. diff --git a/test/functional/options/modified_spec.lua b/test/functional/options/modified_spec.lua new file mode 100644 index 0000000000..956deb70ff --- /dev/null +++ b/test/functional/options/modified_spec.lua @@ -0,0 +1,20 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local api = n.api + +describe("'modified'", function() + before_each(function() + clear() + end) + + it("can be unset after changing 'fileformat'", function() + for _, ff in ipairs({ 'unix', 'dos', 'mac' }) do + api.nvim_set_option_value('fileformat', ff, {}) + api.nvim_set_option_value('modified', false, {}) + eq(false, api.nvim_get_option_value('modified', {}), 'fileformat=' .. ff) + end + end) +end) diff --git a/test/functional/options/mousescroll_spec.lua b/test/functional/options/mousescroll_spec.lua index 96af8987b8..2ccf934fd4 100644 --- a/test/functional/options/mousescroll_spec.lua +++ b/test/functional/options/mousescroll_spec.lua @@ -1,21 +1,23 @@ -local helpers = require('test.functional.helpers')(after_each) -local command = helpers.command -local clear = helpers.clear -local eval = helpers.eval -local eq = helpers.eq -local exc_exec = helpers.exc_exec -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local command = n.command +local clear = n.clear +local eval = n.eval +local eq = t.eq +local exc_exec = n.exc_exec +local feed = n.feed local scroll = function(direction) - return helpers.request('nvim_input_mouse', 'wheel', direction, '', 0, 2, 2) + return n.request('nvim_input_mouse', 'wheel', direction, '', 0, 2, 2) end local screenrow = function() - return helpers.call('screenrow') + return n.call('screenrow') end local screencol = function() - return helpers.call('screencol') + return n.call('screencol') end describe("'mousescroll'", function() diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua index 0614bcf814..3ac6f3f121 100644 --- a/test/functional/options/num_options_spec.lua +++ b/test/functional/options/num_options_spec.lua @@ -1,8 +1,9 @@ -- Tests for :setlocal and :setglobal -local helpers = require('test.functional.helpers')(after_each) -local clear, feed_command, eval, eq, api = - helpers.clear, helpers.feed_command, helpers.eval, helpers.eq, helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, feed_command, eval, eq, api = n.clear, n.feed_command, n.eval, t.eq, n.api local function should_fail(opt, value, errmsg) feed_command('setglobal ' .. opt .. '=' .. value) @@ -12,7 +13,7 @@ local function should_fail(opt, value, errmsg) eq(errmsg, eval('v:errmsg'):match('E%d*')) feed_command('let v:errmsg = ""') local status, err = pcall(api.nvim_set_option_value, opt, value, {}) - eq(status, false) + eq(false, status) eq(errmsg, err:match('E%d*')) eq('', eval('v:errmsg')) end diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua index 6bc00ca1c5..dcbf9d15e0 100644 --- a/test/functional/options/shortmess_spec.lua +++ b/test/functional/options/shortmess_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed describe("'shortmess'", function() local screen @@ -22,7 +24,7 @@ describe("'shortmess'", function() feed(':edit foo<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 "foo" [New] | ]]) eq(1, eval('bufnr("%")')) @@ -31,7 +33,7 @@ describe("'shortmess'", function() feed(':edit bar<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 :edit bar | ]]) eq(2, eval('bufnr("%")')) @@ -43,21 +45,21 @@ describe("'shortmess'", function() feed(':edit foo<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 "foo" [New] | ]]) eq(1, eval('bufnr("%")')) feed(':edit bar<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 "bar" [New] | ]]) eq(2, eval('bufnr("%")')) feed(':bprevious<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 "foo" [New] --No lines in buffer-- | ]]) eq(1, eval('bufnr("%")')) @@ -66,14 +68,14 @@ describe("'shortmess'", function() feed(':bnext<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 :bnext | ]]) eq(2, eval('bufnr("%")')) feed(':bprevious<CR>') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 :bprevious | ]]) eq(1, eval('bufnr("%")')) diff --git a/test/functional/options/tabstop_spec.lua b/test/functional/options/tabstop_spec.lua index 9070db8257..4ddbb13a0e 100644 --- a/test/functional/options/tabstop_spec.lua +++ b/test/functional/options/tabstop_spec.lua @@ -1,8 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local feed = helpers.feed +local assert_alive = n.assert_alive +local clear = n.clear +local feed = n.feed describe("'tabstop' option", function() before_each(function() diff --git a/test/functional/options/winfixbuf_spec.lua b/test/functional/options/winfixbuf_spec.lua new file mode 100644 index 0000000000..124f194b5a --- /dev/null +++ b/test/functional/options/winfixbuf_spec.lua @@ -0,0 +1,55 @@ +local n = require('test.functional.testnvim')() + +local clear = n.clear +local exec_lua = n.exec_lua + +describe("Nvim API calls with 'winfixbuf'", function() + before_each(function() + clear() + end) + + it("Calling vim.api.nvim_win_set_buf with 'winfixbuf'", function() + local results = exec_lua([[ + local function _setup_two_buffers() + local buffer = vim.api.nvim_create_buf(true, true) + + vim.api.nvim_create_buf(true, true) -- Make another buffer + + local current_window = 0 + vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window}) + + return buffer + end + + local other_buffer = _setup_two_buffers() + local current_window = 0 + local results, _ = pcall(vim.api.nvim_win_set_buf, current_window, other_buffer) + + return results + ]]) + + assert(results == false) + end) + + it("Calling vim.api.nvim_set_current_buf with 'winfixbuf'", function() + local results = exec_lua([[ + local function _setup_two_buffers() + local buffer = vim.api.nvim_create_buf(true, true) + + vim.api.nvim_create_buf(true, true) -- Make another buffer + + local current_window = 0 + vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window}) + + return buffer + end + + local other_buffer = _setup_two_buffers() + local results, _ = pcall(vim.api.nvim_set_current_buf, other_buffer) + + return results + ]]) + + assert(results == false) + end) +end) diff --git a/test/functional/plugin/ccomplete_spec.lua b/test/functional/plugin/ccomplete_spec.lua index 903f16fc73..4c4c5e9444 100644 --- a/test/functional/plugin/ccomplete_spec.lua +++ b/test/functional/plugin/ccomplete_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local write_file = helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed +local write_file = t.write_file describe('ccomplete#Complete', function() setup(function() diff --git a/test/functional/plugin/cfilter_spec.lua b/test/functional/plugin/cfilter_spec.lua index 37261d59df..220404a934 100644 --- a/test/functional/plugin/cfilter_spec.lua +++ b/test/functional/plugin/cfilter_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local fn = n.fn describe('cfilter.lua', function() before_each(function() diff --git a/test/functional/plugin/editorconfig_spec.lua b/test/functional/plugin/editorconfig_spec.lua index 115c28fbf6..839a723405 100644 --- a/test/functional/plugin/editorconfig_spec.lua +++ b/test/functional/plugin/editorconfig_spec.lua @@ -1,14 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local pathsep = helpers.get_pathsep() -local fn = helpers.fn -local api = helpers.api -local exec_lua = helpers.exec_lua +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local command = n.command +local eq = t.eq +local pathsep = n.get_pathsep() +local fn = n.fn +local api = n.api +local exec_lua = n.exec_lua local testdir = 'Xtest-editorconfig' +--- @param name string +--- @param expected table<string,any> local function test_case(name, expected) local filename = testdir .. pathsep .. name command('edit ' .. filename) @@ -18,8 +22,8 @@ local function test_case(name, expected) end setup(function() - helpers.mkdir_p(testdir) - helpers.write_file( + n.mkdir_p(testdir) + t.write_file( testdir .. pathsep .. '.editorconfig', [[ root = true @@ -94,7 +98,7 @@ setup(function() end) teardown(function() - helpers.rmdir(testdir) + n.rmdir(testdir) end) describe('editorconfig', function() @@ -176,18 +180,18 @@ But not this one -- luacheck: pop local trimmed = untrimmed:gsub('%s+\n', '\n') - helpers.write_file(filename, untrimmed) + t.write_file(filename, untrimmed) command('edit ' .. filename) command('write') command('bdelete') - eq(trimmed, helpers.read_file(filename)) + eq(trimmed, t.read_file(filename)) filename = testdir .. pathsep .. 'no_trim.txt' - helpers.write_file(filename, untrimmed) + t.write_file(filename, untrimmed) command('edit ' .. filename) command('write') command('bdelete') - eq(untrimmed, helpers.read_file(filename)) + eq(untrimmed, t.read_file(filename)) end) it('sets textwidth', function() diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index 8564ec7c9b..9c7c953fb0 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -1,14 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -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.fn.getcompletion -local insert = helpers.insert -local source = helpers.source -local exec_lua = helpers.exec_lua +local clear = n.clear +local curbuf_contents = n.curbuf_contents +local command = n.command +local eq, matches = t.eq, t.matches +local getcompletion = n.fn.getcompletion +local insert = n.insert +local exec_lua = n.exec_lua +local source = n.source +local assert_alive = n.assert_alive +local fn = n.fn +local api = n.api describe(':checkhealth', function() it('detects invalid $VIMRUNTIME', function() @@ -19,6 +23,7 @@ describe(':checkhealth', function() eq(false, status) eq('Invalid $VIMRUNTIME: bogus', string.match(err, 'Invalid.*')) end) + it("detects invalid 'runtimepath'", function() clear() command('set runtimepath=bogus') @@ -26,19 +31,29 @@ describe(':checkhealth', function() eq(false, status) eq("Invalid 'runtimepath'", string.match(err, 'Invalid.*')) end) + it('detects invalid $VIM', function() clear() -- Do this after startup, otherwise it just breaks $VIMRUNTIME. command("let $VIM='zub'") - command('checkhealth nvim') + command('checkhealth vim.health') matches('ERROR $VIM .* zub', curbuf_contents()) end) + it('completions can be listed via getcompletion()', function() clear() - eq('nvim', getcompletion('nvim', 'checkhealth')[1]) - eq('provider.clipboard', getcompletion('prov', 'checkhealth')[1]) + eq('vim.deprecated', getcompletion('vim', 'checkhealth')[1]) + eq('vim.provider', getcompletion('vim.prov', 'checkhealth')[1]) eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1]) - neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health + end) + + it('completion checks for vim.health._complete() return type #28456', function() + clear() + exec_lua([[vim.health._complete = function() return 1 end]]) + eq({}, getcompletion('', 'checkhealth')) + exec_lua([[vim.health._complete = function() return { 1 } end]]) + eq({}, getcompletion('', 'checkhealth')) + assert_alive() end) end) @@ -52,7 +67,7 @@ describe('health.vim', function() describe(':checkhealth', function() it('functions report_*() render correctly', function() command('checkhealth full_render') - helpers.expect([[ + n.expect([[ ============================================================================== test_plug.full_render: require("test_plug.full_render.health").check() @@ -75,7 +90,7 @@ describe('health.vim', function() it('concatenates multiple reports', function() command('checkhealth success1 success2 test_plug') - helpers.expect([[ + n.expect([[ ============================================================================== test_plug: require("test_plug.health").check() @@ -105,7 +120,7 @@ describe('health.vim', function() it('lua plugins submodules', function() command('checkhealth test_plug.submodule') - helpers.expect([[ + n.expect([[ ============================================================================== test_plug.submodule: require("test_plug.submodule.health").check() @@ -120,7 +135,7 @@ describe('health.vim', function() it('... including empty reports', function() command('checkhealth test_plug.submodule_empty') - helpers.expect([[ + n.expect([[ ============================================================================== test_plug.submodule_empty: require("test_plug.submodule_empty.health").check() @@ -158,28 +173,10 @@ describe('health.vim', function() } end) - it('fold healthchecks', function() - local screen = Screen.new(50, 7) - screen:attach() - command('checkhealth foo success1') - command('set nowrap laststatus=0') - screen:expect { - grid = [[ - ^ | - ──────────────────────────────────────────────────| - +WE 4 lines: foo: ·······························| - ──────────────────────────────────────────────────| - +-- 8 lines: test_plug.success1: require("test_pl| - ~ | - | - ]], - } - end) - it('gracefully handles invalid healthcheck', function() command('checkhealth non_existent_healthcheck') -- luacheck: ignore 613 - helpers.expect([[ + n.expect([[ ============================================================================== non_existent_healthcheck: @@ -191,7 +188,7 @@ describe('health.vim', function() it('does not use vim.health as a healtcheck', function() -- vim.health is not a healthcheck command('checkhealth vim') - helpers.expect([[ + n.expect([[ ERROR: No healthchecks found.]]) end) end) @@ -218,6 +215,12 @@ describe(':checkhealth window', function() it('opens directly if no buffer created', function() local screen = Screen.new(50, 12) + screen:set_default_attr_ids { + [1] = { foreground = Screen.colors.Blue, bold = true }, + [14] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray }, + [31] = { foreground = tonumber('0x6a0dad') }, + [32] = { foreground = Screen.colors.PaleGreen2 }, + } screen:attach({ ext_multigrid = true }) command('checkhealth success1') screen:expect { @@ -227,16 +230,16 @@ describe(':checkhealth window', function() [3:--------------------------------------------------]| ## grid 2 ^ | - ──────────────────────────────────────────────────| - ──────────────────────────── | - test_plug.success1: require("test_plug.success1. | - health").check() | + {14:──────────────────────────────────────────────────}| + {14:────────────────────────────} | + {31:test_plug.success1: require("test_plug.success1. }| + {31:health").check()} | | - report 1 | - - OK everything is fine | + {31:report 1} | + - {32:OK} everything is fine | | - report 2 | - - OK nothing to see here | + {31:report 2} | + - {32:OK} nothing to see here | ## grid 3 | ]], @@ -245,6 +248,12 @@ describe(':checkhealth window', function() local function test_health_vsplit(left, emptybuf, mods) local screen = Screen.new(50, 20) + screen:set_default_attr_ids { + [1] = { foreground = Screen.colors.Blue, bold = true }, + [14] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray }, + [31] = { foreground = tonumber('0x6a0dad') }, + [32] = { foreground = Screen.colors.PaleGreen2 }, + } screen:attach({ ext_multigrid = true }) if not emptybuf then insert('hello') @@ -257,24 +266,24 @@ describe(':checkhealth window', function() [3:--------------------------------------------------]| ## grid 2 %s | - ~ |*18 + {1:~ }|*18 ## grid 3 | ## grid 4 ^ | - ─────────────────────────|*3 - ─── | - test_plug.success1: | - require("test_plug. | - success1.health").check()| + {14:─────────────────────────}|*3 + {14:───} | + {31:test_plug.success1: }| + {31:require("test_plug. }| + {31:success1.health").check()}| | - report 1 | - - OK everything is fine | + {31:report 1} | + - {32:OK} everything is fine | | - report 2 | - - OK nothing to see here | + {31:report 2} | + - {32:OK} nothing to see here | | - ~ |*4 + {1:~ }|*4 ]]):format( left and '[4:-------------------------]│[2:------------------------]|*19' or '[2:------------------------]│[4:-------------------------]|*19', @@ -304,6 +313,7 @@ describe(':checkhealth window', function() local function test_health_split(top, emptybuf, mods) local screen = Screen.new(50, 25) screen:attach({ ext_multigrid = true }) + screen._default_attr_ids = nil if not emptybuf then insert('hello') end @@ -368,7 +378,7 @@ describe(':checkhealth window', function() it('opens in tab', function() -- create an empty buffer called "my_buff" - exec_lua 'vim.api.nvim_create_buf(false, true)' + api.nvim_create_buf(false, true) command('file my_buff') command('checkhealth success1') -- define a function that collects all buffers in each tab @@ -387,7 +397,7 @@ describe(':checkhealth window', function() return buffs endfunction ]]) - local buffers_per_tab = exec_lua('return vim.fn.CollectBuffersPerTab()') + local buffers_per_tab = 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 29daf7a066..cd20e95dd1 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local exec_lua = helpers.exec_lua -local eq = helpers.eq +local exec_lua = n.exec_lua +local eq = t.eq describe('vim.lsp.codelens', function() before_each(function() - helpers.clear() + n.clear() exec_lua('require("vim.lsp")') end) - after_each(helpers.clear) + after_each(n.clear) it('on_codelens_stores_and_displays_lenses', function() local fake_uri = 'file:///fake/uri' diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 655eb76be6..2798d57381 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -1,7 +1,9 @@ ---@diagnostic disable: no-unknown -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local exec_lua = n.exec_lua --- Convert completion results. --- @@ -41,7 +43,7 @@ local function complete(line, candidates, lnum) end describe('vim.lsp._completion', function() - before_each(helpers.clear) + before_each(n.clear) -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion it('prefers textEdit over label as word', function() diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua index 705c182df7..c5e14ffdc2 100644 --- a/test/functional/plugin/lsp/diagnostic_spec.lua +++ b/test/functional/plugin/lsp/diagnostic_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local lsp_helpers = require('test.functional.plugin.lsp.helpers') +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local neq = require('test.helpers').neq +local t_lsp = require('test.functional.plugin.lsp.testutil') -local create_server_definition = lsp_helpers.create_server_definition +local clear = n.clear +local exec_lua = n.exec_lua +local eq = t.eq +local neq = t.neq + +local create_server_definition = t_lsp.create_server_definition describe('vim.lsp.diagnostic', function() local fake_uri @@ -257,7 +259,7 @@ describe('vim.lsp.diagnostic', function() }, {client_id=client_id}) return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2")) ]] - eq(bufnr, -1) + eq(-1, bufnr) -- Create buffer on diagnostics bufnr = exec_lua [[ @@ -269,8 +271,8 @@ describe('vim.lsp.diagnostic', function() }, {client_id=client_id}) return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2")) ]] - neq(bufnr, -1) - eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 1) + neq(-1, bufnr) + eq(1, exec_lua([[return #vim.diagnostic.get(...)]], bufnr)) -- Clear diagnostics after buffer was created bufnr = exec_lua [[ @@ -280,8 +282,8 @@ describe('vim.lsp.diagnostic', function() }, {client_id=client_id}) return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2")) ]] - neq(bufnr, -1) - eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 0) + neq(-1, bufnr) + eq(0, exec_lua([[return #vim.diagnostic.get(...)]], bufnr)) end) end) diff --git a/test/functional/plugin/lsp/handler_spec.lua b/test/functional/plugin/lsp/handler_spec.lua index 56e29e7337..013a5fb5e7 100644 --- a/test/functional/plugin/lsp/handler_spec.lua +++ b/test/functional/plugin/lsp/handler_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local pcall_err = helpers.pcall_err -local matches = helpers.matches +local eq = t.eq +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err +local matches = t.matches describe('lsp-handlers', function() describe('vim.lsp._with_extend', function() diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua index bd1842ceb5..238b90b57d 100644 --- a/test/functional/plugin/lsp/incremental_sync_spec.lua +++ b/test/functional/plugin/lsp/incremental_sync_spec.lua @@ -1,11 +1,12 @@ -- Test suite for testing interactions with the incremental sync algorithms powering the LSP client -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local api = helpers.api -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local feed = helpers.feed +local api = n.api +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua +local feed = n.feed before_each(function() clear() diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua index 192797b312..d3b5ae0e4e 100644 --- a/test/functional/plugin/lsp/inlay_hint_spec.lua +++ b/test/functional/plugin/lsp/inlay_hint_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local lsp_helpers = require('test.functional.plugin.lsp.helpers') +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local t_lsp = require('test.functional.plugin.lsp.testutil') -local eq = helpers.eq -local dedent = helpers.dedent -local exec_lua = helpers.exec_lua -local insert = helpers.insert +local eq = t.eq +local dedent = t.dedent +local exec_lua = n.exec_lua +local insert = n.insert +local api = n.api -local clear_notrace = lsp_helpers.clear_notrace -local create_server_definition = lsp_helpers.create_server_definition +local clear_notrace = t_lsp.clear_notrace +local create_server_definition = t_lsp.create_server_definition local text = dedent([[ auto add(int a, int b) { return a + b; } @@ -41,12 +43,12 @@ local grid_without_inlay_hints = [[ ]] local grid_with_inlay_hints = [[ - auto add(int a, int b)-> int { return a + b; } | + auto add(int a, int b){1:-> int} { return a + b; } | | int main() { | int x = 1; | int y = 2; | - return add(a: x,b: y); | + return add({1:a:} x,{1:b:} y); | } | ^} | | @@ -68,8 +70,8 @@ before_each(function() inlayHintProvider = true, }, handlers = { - ['textDocument/inlayHint'] = function() - return vim.json.decode(response) + ['textDocument/inlayHint'] = function(_, _, callback) + callback(nil, vim.json.decode(response)) end, } }) @@ -83,12 +85,12 @@ before_each(function() ) insert(text) - exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]]) + exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]]) screen:expect({ grid = grid_with_inlay_hints }) end) after_each(function() - exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) end) describe('vim.lsp.inlay_hint', function() @@ -104,13 +106,13 @@ describe('vim.lsp.inlay_hint', function() inlayHintProvider = true, }, handlers = { - ['textDocument/inlayHint'] = function() - return {} + ['textDocument/inlayHint'] = function(_, _, callback) + callback(nil, {}) end, } }) client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd }) - vim.lsp.inlay_hint.enable(bufnr) + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) ]]) exec_lua([[ vim.lsp.stop_client(client2) ]]) @@ -118,18 +120,66 @@ describe('vim.lsp.inlay_hint', function() end) describe('enable()', function() - it('clears/applies inlay hints when passed false/true/nil', function() - exec_lua([[vim.lsp.inlay_hint.enable(bufnr, false)]]) - screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) + it('validation', function() + t.matches( + 'enable: expected boolean, got table', + t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable({}, { bufnr = bufnr })]]) + ) + t.matches( + 'enable: expected boolean, got number', + t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable(42)]]) + ) + t.matches( + 'filter: expected table, got number', + t.pcall_err(exec_lua, [[vim.lsp.inlay_hint.enable(true, 42)]]) + ) + end) + + describe('clears/applies inlay hints when passed false/true/nil', function() + before_each(function() + exec_lua([[ + bufnr2 = vim.api.nvim_create_buf(true, false) + vim.lsp.buf_attach_client(bufnr2, client_id) + vim.api.nvim_win_set_buf(0, bufnr2) + ]]) + insert(text) + exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr2 })]]) + exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]]) + screen:expect({ grid = grid_with_inlay_hints }) + end) + + it('for one single buffer', function() + exec_lua([[ + vim.lsp.inlay_hint.enable(false, { bufnr = bufnr }) + vim.api.nvim_win_set_buf(0, bufnr2) + ]]) + screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]]) + screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) - exec_lua([[vim.lsp.inlay_hint.enable(bufnr, true)]]) - screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]]) + screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) - exec_lua([[vim.lsp.inlay_hint.enable(bufnr, not vim.lsp.inlay_hint.is_enabled(bufnr))]]) - screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) + exec_lua( + [[vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr })]] + ) + screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) - exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]]) - screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + exec_lua([[vim.lsp.inlay_hint.enable(true, { bufnr = bufnr })]]) + screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + end) + + it('for all buffers', function() + exec_lua([[vim.lsp.inlay_hint.enable(false)]]) + screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) + exec_lua([[vim.api.nvim_win_set_buf(0, bufnr2)]]) + screen:expect({ grid = grid_without_inlay_hints, unchanged = true }) + + exec_lua([[vim.lsp.inlay_hint.enable(true)]]) + screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + exec_lua([[vim.api.nvim_win_set_buf(0, bufnr)]]) + screen:expect({ grid = grid_with_inlay_hints, unchanged = true }) + end) end) end) @@ -156,25 +206,25 @@ describe('vim.lsp.inlay_hint', function() inlayHintProvider = true, }, handlers = { - ['textDocument/inlayHint'] = function() - return { expected2 } + ['textDocument/inlayHint'] = function(_, _, callback) + callback(nil, { expected2 }) end, } }) client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd }) - vim.lsp.inlay_hint.enable(bufnr) + vim.lsp.inlay_hint.enable(true, { bufnr = bufnr }) ]], expected2 ) --- @type vim.lsp.inlay_hint.get.ret local res = exec_lua([[return vim.lsp.inlay_hint.get()]]) - eq(res, { + eq({ { bufnr = 1, client_id = 1, inlay_hint = expected[1] }, { bufnr = 1, client_id = 1, inlay_hint = expected[2] }, { bufnr = 1, client_id = 1, inlay_hint = expected[3] }, { bufnr = 1, client_id = 2, inlay_hint = expected2 }, - }) + }, res) --- @type vim.lsp.inlay_hint.get.ret res = exec_lua([[return vim.lsp.inlay_hint.get({ @@ -183,9 +233,9 @@ describe('vim.lsp.inlay_hint', function() ["end"] = { line = 2, character = 10 }, }, })]]) - eq(res, { + eq({ { bufnr = 1, client_id = 2, inlay_hint = expected2 }, - }) + }, res) --- @type vim.lsp.inlay_hint.get.ret res = exec_lua([[return vim.lsp.inlay_hint.get({ @@ -195,16 +245,16 @@ describe('vim.lsp.inlay_hint', function() ["end"] = { line = 5, character = 17 }, }, })]]) - eq(res, { + eq({ { bufnr = 1, client_id = 1, inlay_hint = expected[2] }, { bufnr = 1, client_id = 1, inlay_hint = expected[3] }, - }) + }, res) --- @type vim.lsp.inlay_hint.get.ret res = exec_lua([[return vim.lsp.inlay_hint.get({ bufnr = vim.api.nvim_get_current_buf() + 1, })]]) - eq(res, {}) + eq({}, res) end) end) end) diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua index 77e39c81c8..7908c5d2e7 100644 --- a/test/functional/plugin/lsp/semantic_tokens_spec.lua +++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua @@ -1,25 +1,27 @@ -local helpers = require('test.functional.helpers')(after_each) -local lsp_helpers = require('test.functional.plugin.lsp.helpers') +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local t_lsp = require('test.functional.plugin.lsp.testutil') -local command = helpers.command -local dedent = helpers.dedent -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local feed_command = helpers.feed_command -local insert = helpers.insert -local matches = helpers.matches +local command = n.command +local dedent = t.dedent +local eq = t.eq +local exec_lua = n.exec_lua +local feed = n.feed +local feed_command = n.feed_command +local insert = n.insert +local matches = t.matches +local api = n.api -local clear_notrace = lsp_helpers.clear_notrace -local create_server_definition = lsp_helpers.create_server_definition +local clear_notrace = t_lsp.clear_notrace +local create_server_definition = t_lsp.create_server_definition before_each(function() clear_notrace() end) after_each(function() - exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) end) describe('semantic token highlighting', function() @@ -37,6 +39,8 @@ describe('semantic token highlighting', function() [7] = { bold = true, foreground = Screen.colors.DarkCyan }, [8] = { bold = true, foreground = Screen.colors.SlateBlue }, [9] = { bold = true, foreground = tonumber('0x6a0dad') }, + [10] = { bold = true, foreground = Screen.colors.Brown }, + [11] = { foreground = Screen.colors.Magenta1 }, } command([[ hi link @lsp.type.namespace Type ]]) command([[ hi link @lsp.type.function Special ]]) @@ -91,11 +95,11 @@ describe('semantic token highlighting', function() }, }, handlers = { - ['textDocument/semanticTokens/full'] = function() - return vim.fn.json_decode(response) + ['textDocument/semanticTokens/full'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(response)) end, - ['textDocument/semanticTokens/full/delta'] = function() - return vim.fn.json_decode(edit_response) + ['textDocument/semanticTokens/full/delta'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(edit_response)) end, } }) @@ -269,6 +273,63 @@ describe('semantic token highlighting', function() end ) + it('highlights start and stop when using "0" for current buffer', 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) + + exec_lua([[ + vim.notify = function() end + vim.lsp.semantic_tokens.stop(0, client_id) + ]]) + + screen:expect { + grid = [[ + #include <iostream> | + | + int main() | + { | + int x; | + #ifdef __cplusplus | + std::cout << x << "\n"; | + #else | + printf("%d\n", x); | + #endif | + } | + ^} | + {1:~ }|*3 + | + ]], + } + + exec_lua([[ + vim.lsp.semantic_tokens.start(0, client_id) + ]]) + + screen:expect { + grid = [[ + #include <iostream> | + | + int {8:main}() | + { | + int {7:x}; | + #ifdef {5:__cplusplus} | + {4:std}::{2:cout} << {2:x} << "\n"; | + {6:#else} | + {6: printf("%d\n", x);} | + {6:#endif} | + } | + ^} | + {1:~ }|*3 + | + ]], + } + end) + it('buffer is re-highlighted when force refreshed', function() exec_lua([[ bufnr = vim.api.nvim_get_current_buf() @@ -499,11 +560,11 @@ describe('semantic token highlighting', function() }, }, handlers = { - ['textDocument/semanticTokens/full'] = function() - return nil + ['textDocument/semanticTokens/full'] = function(_, _, callback) + callback(nil, nil) end, ['textDocument/semanticTokens/full/delta'] = function() - return nil + callback(nil, nil) end, } }) @@ -547,11 +608,11 @@ describe('semantic token highlighting', function() }, }, handlers = { - ['textDocument/semanticTokens/full'] = function() - return vim.fn.json_decode(response) + ['textDocument/semanticTokens/full'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(response)) end, - ['textDocument/semanticTokens/full/delta'] = function() - return vim.fn.json_decode(edit_response) + ['textDocument/semanticTokens/full/delta'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(edit_response)) end, } }) @@ -837,11 +898,13 @@ b = "as"]], { it = 'rust-analyzer', text = [[pub fn main() { - break rust; - /// what? + println!("Hello world!"); + break rust; + /// what? } ]], - response = [[{"data": [0, 0, 3, 1, 0, 0, 4, 2, 1, 0, 0, 3, 4, 14, 524290, 0, 4, 1, 45, 0, 0, 1, 1, 45, 0, 0, 2, 1, 26, 0, 1, 4, 5, 1, 8192, 0, 6, 4, 52, 0, 0, 4, 1, 48, 0, 1, 4, 9, 0, 1, 1, 0, 1, 26, 0], "resultId": "1"}]], + response = [[{"data": [0, 0, 3, 1, 0, 0, 4, 2, 1, 0, 0, 3, 4, 14, 524290, 0, 4, 1, 45, 0, 0, 1, 1, 45, 0, 0, 2, 1, 26, 0, 1, 4, 8, 17, 0, 0, 8, 1, 45, 0, 0, 1, 14, 2, 0, 0, 14, 1, 45, 0, 0, 1, 1, 48, 0, 1, 4, 5, 1, 8192, 0, 6, 4, 52, 0, 0, 4, 1, 48, 0, 1, 4, 9, 0, 1, 1, 0, 1, 26, 0 ], "resultId": "1"}]], + legend = [[{ "tokenTypes": [ "comment", "keyword", "string", "number", "regexp", "operator", "namespace", "type", "struct", "class", "interface", "enum", "enumMember", "typeParameter", "function", "method", "property", "macro", "variable", @@ -904,6 +967,46 @@ b = "as"]], }, { line = 1, + modifiers = {}, + start_col = 4, + end_col = 12, + type = 'macro', -- println! + marked = true, + }, + { + line = 1, + modifiers = {}, + start_col = 12, + end_col = 13, + type = 'parenthesis', + marked = true, + }, + { + line = 1, + modifiers = {}, + start_col = 13, + end_col = 27, + type = 'string', -- "Hello world!" + marked = true, + }, + { + line = 1, + modifiers = {}, + start_col = 27, + end_col = 28, + type = 'parenthesis', + marked = true, + }, + { + line = 1, + modifiers = {}, + start_col = 28, + end_col = 29, + type = 'semicolon', + marked = true, + }, + { + line = 2, modifiers = { controlFlow = true }, start_col = 4, end_col = 9, -- break @@ -911,31 +1014,31 @@ b = "as"]], marked = true, }, { - line = 1, + line = 2, modifiers = {}, start_col = 10, - end_col = 13, -- rust + end_col = 14, -- rust type = 'unresolvedReference', marked = true, }, { - line = 1, + line = 2, modifiers = {}, - start_col = 13, - end_col = 13, + start_col = 14, + end_col = 15, type = 'semicolon', marked = true, }, { - line = 2, + line = 3, modifiers = { documentation = true }, start_col = 4, - end_col = 11, + end_col = 13, type = 'comment', -- /// what? marked = true, }, { - line = 3, + line = 4, modifiers = {}, start_col = 0, end_col = 1, @@ -946,12 +1049,13 @@ b = "as"]], expected_screen = function() screen:expect { grid = [[ - pub fn {8:main}() { | - break rust; | - //{6:/ what?} | + {10:pub} {10:fn} {8:main}() { | + {5:println!}({11:"Hello world!"}); | + {10:break} rust; | + {6:/// what?} | } | ^ | - {1:~ }|*10 + {1:~ }|*9 | ]], } @@ -971,8 +1075,8 @@ b = "as"]], }, }, handlers = { - ['textDocument/semanticTokens/full'] = function() - return vim.fn.json_decode(resp) + ['textDocument/semanticTokens/full'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(resp)) end, } }) @@ -1357,11 +1461,11 @@ int main() }, }, handlers = { - ['textDocument/semanticTokens/full'] = function() - return vim.fn.json_decode(resp1) + ['textDocument/semanticTokens/full'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(resp1)) end, - ['textDocument/semanticTokens/full/delta'] = function() - return vim.fn.json_decode(resp2) + ['textDocument/semanticTokens/full/delta'] = function(_, _, callback) + callback(nil, vim.fn.json_decode(resp2)) end, } }) diff --git a/test/functional/plugin/lsp/snippet_spec.lua b/test/functional/plugin/lsp/snippet_spec.lua index ba8bc7fe04..e60c36cd23 100644 --- a/test/functional/plugin/lsp/snippet_spec.lua +++ b/test/functional/plugin/lsp/snippet_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local snippet = require('vim.lsp._snippet_grammar') local type = snippet.NodeType -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local eq = t.eq +local exec_lua = n.exec_lua describe('vim.lsp._snippet_grammar', function() - before_each(helpers.clear) - after_each(helpers.clear) + before_each(n.clear) + after_each(n.clear) local parse = function(...) local res = exec_lua('return require("vim.lsp._snippet_grammar").parse(...)', ...) diff --git a/test/functional/plugin/lsp/helpers.lua b/test/functional/plugin/lsp/testutil.lua index 97fa108500..3430a1e1a3 100644 --- a/test/functional/plugin/lsp/helpers.lua +++ b/test/functional/plugin/lsp/testutil.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(nil) +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local exec_lua = helpers.exec_lua -local run = helpers.run -local stop = helpers.stop +local clear = n.clear +local exec_lua = n.exec_lua +local run = n.run +local stop = n.stop +local api = n.api local NIL = vim.NIL local M = {} @@ -38,8 +39,7 @@ M.create_server_definition = [[ }) local handler = handlers[method] if handler then - local response, err = handler(method, params) - callback(err, response) + handler(method, params, callback) elseif method == 'initialize' then callback(nil, { capabilities = opts.capabilities or {} @@ -105,6 +105,11 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings) uri = 'file://' .. vim.uv.cwd(), name = 'test_folder', }}; + before_init = function(params, config) + vim.schedule(function() + vim.rpcrequest(1, "setup") + end) + end, on_init = function(client, result) TEST_RPC_CLIENT = client vim.rpcrequest(1, "init", result) @@ -128,6 +133,18 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings) ) end +--- @class test.lsp.Config +--- @field test_name string +--- @field timeout_ms? integer +--- @field options? table +--- @field settings? table +--- +--- @field on_setup? fun() +--- @field on_init? fun(client: vim.lsp.Client, ...) +--- @field on_handler? fun(...) +--- @field on_exit? fun(code: integer, signal: integer) + +--- @param config test.lsp.Config function M.test_rpc_server(config) if config.test_name then M.clear_notrace() @@ -158,8 +175,15 @@ function M.test_rpc_server(config) end end, }) + --- @type integer, integer local code, signal local function on_request(method, args) + if method == 'setup' then + if config.on_setup then + config.on_setup() + end + return NIL + end if method == 'init' then if config.on_init then config.on_init(client, unpack(args)) @@ -180,14 +204,14 @@ function M.test_rpc_server(config) end end -- TODO specify timeout? - -- run(on_request, on_notify, config.on_setup, 1000) - run(on_request, on_notify, config.on_setup) + -- run(on_request, on_notify, nil, 1000) + run(on_request, on_notify, nil) if config.on_exit then config.on_exit(code, signal) end stop() if config.test_name then - exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) end end diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index bb9cdb8390..6c6dec0667 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local feed = n.feed +local eq = t.eq +local exec_lua = n.exec_lua describe('vim.lsp.util', function() - before_each(helpers.clear) + before_each(n.clear) describe('stylize_markdown', function() local stylize_markdown = function(content, opts) @@ -142,7 +143,7 @@ describe('vim.lsp.util', function() local screen before_each(function() - helpers.clear() + n.clear() screen = Screen.new(80, 80) screen:attach() feed('79i<CR><Esc>') -- fill screen with empty lines diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 4826153edb..c95a96baca 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1,36 +1,38 @@ -local helpers = require('test.functional.helpers')(after_each) -local lsp_helpers = require('test.functional.plugin.lsp.helpers') - -local assert_log = helpers.assert_log -local buf_lines = helpers.buf_lines -local clear = helpers.clear -local command = helpers.command -local dedent = helpers.dedent -local exec_lua = helpers.exec_lua -local eq = helpers.eq -local eval = helpers.eval -local matches = helpers.matches -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local t_lsp = require('test.functional.plugin.lsp.testutil') + +local assert_log = t.assert_log +local buf_lines = n.buf_lines +local clear = n.clear +local command = n.command +local dedent = t.dedent +local exec_lua = n.exec_lua +local eq = t.eq +local eval = n.eval +local matches = t.matches +local pcall_err = t.pcall_err local pesc = vim.pesc -local insert = helpers.insert -local fn = helpers.fn -local retry = helpers.retry -local stop = helpers.stop +local insert = n.insert +local fn = n.fn +local retry = t.retry +local stop = n.stop 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 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 -local fake_lsp_code = lsp_helpers.fake_lsp_code -local fake_lsp_logfile = lsp_helpers.fake_lsp_logfile -local test_rpc_server = lsp_helpers.test_rpc_server +local read_file = t.read_file +local write_file = t.write_file +local is_ci = t.is_ci +local api = n.api +local is_os = t.is_os +local skip = t.skip +local mkdir = t.mkdir +local tmpname = t.tmpname + +local clear_notrace = t_lsp.clear_notrace +local create_server_definition = t_lsp.create_server_definition +local fake_lsp_code = t_lsp.fake_lsp_code +local fake_lsp_logfile = t_lsp.fake_lsp_logfile +local test_rpc_server = t_lsp.test_rpc_server local function get_buf_option(name, bufnr) bufnr = bufnr or 'BUFFER' @@ -83,7 +85,7 @@ describe('LSP', function() end) after_each(function() - exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) -- exec_lua("lsp.stop_all_clients(true)") end) @@ -146,7 +148,7 @@ describe('LSP', function() after_each(function() stop() exec_lua('lsp.stop_client(lsp.get_clients(), true)') - exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })") + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) end) it('should run correctly', function() @@ -249,7 +251,7 @@ describe('LSP', function() if is_ci() then pending('hangs the build on CI #14028, re-enable with freeze timeout #14204') return - elseif helpers.skip_fragile(pending) then + elseif t.skip_fragile(pending) then return end local expected_handlers = { @@ -279,7 +281,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'finish', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_finish', on_setup = function() @@ -312,7 +314,7 @@ describe('LSP', function() end) it('should fire autocommands on attach and detach', function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_init', on_setup = function() @@ -349,7 +351,7 @@ describe('LSP', function() end) it('should set default options on attach', function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'set_defaults_all_capabilities', on_init = function(_client) @@ -397,7 +399,7 @@ describe('LSP', function() end) it('should overwrite options set by ftplugins', function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'set_defaults_all_capabilities', on_init = function(_client) @@ -437,7 +439,7 @@ describe('LSP', function() end) it('should not overwrite user-defined options', function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'set_defaults_all_capabilities', on_init = function(_client) @@ -473,6 +475,12 @@ describe('LSP', function() local server = _create_server() local bufnr = vim.api.nvim_create_buf(false, true) vim.api.nvim_set_current_buf(bufnr) + local detach_called = false + vim.api.nvim_create_autocmd("LspDetach", { + callback = function() + detach_called = true + end + }) local client_id = vim.lsp.start({ name = 'detach-dummy', cmd = server.cmd }) assert(client_id, "lsp.start must return client_id") local client = vim.lsp.get_client_by_id(client_id) @@ -484,11 +492,42 @@ describe('LSP', function() client_id = client_id, num_attached_before = num_attached_before, num_attached_after = num_attached_after, + detach_called = detach_called, } ]]) eq(true, result ~= nil, 'exec_lua must return result') eq(1, result.num_attached_before) eq(0, result.num_attached_after) + eq(true, result.detach_called) + end) + + it('should not re-attach buffer if it was deleted in on_init #28575', function() + clear() + exec_lua(create_server_definition) + exec_lua([[ + local server = _create_server({ + handlers = { + initialize = function(method, params, callback) + vim.schedule(function() + callback(nil, { capabilities = {} }) + end) + end + } + }) + local bufnr = vim.api.nvim_create_buf(false, true) + local on_init_called = false + local client_id = vim.lsp.start({ + name = 'detach-dummy', + cmd = server.cmd, + on_init = function() + vim.api.nvim_buf_delete(bufnr, {}) + on_init_called = true + end + }) + vim.lsp.buf_attach_client(bufnr, client_id) + local ok = vim.wait(1000, function() return on_init_called end) + assert(ok, "on_init was not called") + ]]) end) it('client should return settings via workspace/configuration handler', function() @@ -508,7 +547,7 @@ describe('LSP', function() }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_workspace_configuration', on_init = function(_client) @@ -598,7 +637,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'text_document_sync_save_bool', on_init = function(c) @@ -641,11 +680,11 @@ describe('LSP', function() vim.lsp.stop_client(client_id) return server.messages ]]) - eq(#messages, 4) - eq(messages[1].method, 'initialize') - eq(messages[2].method, 'initialized') - eq(messages[3].method, 'shutdown') - eq(messages[4].method, 'exit') + eq(4, #messages) + eq('initialize', messages[1].method) + eq('initialized', messages[2].method) + eq('shutdown', messages[3].method) + eq('exit', messages[4].method) end) it('BufWritePre sends willSave / willSaveWaitUntil, applies textEdits', function() @@ -660,7 +699,7 @@ describe('LSP', function() } }, handlers = { - ['textDocument/willSaveWaitUntil'] = function() + ['textDocument/willSaveWaitUntil'] = function(_, _, callback) local text_edit = { range = { start = { line = 0, character = 0 }, @@ -668,7 +707,7 @@ describe('LSP', function() }, newText = 'Hello' } - return { text_edit, } + callback(nil, { text_edit, }) end }, }) @@ -692,7 +731,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server({ test_name = 'text_document_save_did_open', on_init = function(c) @@ -732,7 +771,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'text_document_sync_save_includeText', on_init = function(c) @@ -808,14 +847,12 @@ describe('LSP', function() BUFFER = vim.api.nvim_get_current_buf() lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) vim.lsp.handlers['textDocument/typeDefinition'] = function() end + vim.cmd(BUFFER.."bwipeout") ]=]) end, on_init = function(client) client.stop() exec_lua('vim.lsp.buf.type_definition()') - exec_lua [[ - vim.api.nvim_command(BUFFER.."bwipeout") - ]] end, on_exit = function(code, signal) eq(0, code, 'exit code') @@ -859,7 +896,7 @@ describe('LSP', function() local expected_handlers = { { NIL, {}, { method = 'finish', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_forward_request_cancelled', on_init = function(_client) @@ -885,7 +922,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_forward_content_modified', on_init = function(_client) @@ -915,7 +952,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_pending_request_tracked', on_init = function(_client) @@ -949,7 +986,7 @@ describe('LSP', function() local expected_handlers = { { NIL, {}, { method = 'finish', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_cancel_request_tracked', on_init = function(_client) @@ -982,7 +1019,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_tracked_requests_cleared', on_init = function(_client) @@ -1021,7 +1058,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'check_tracked_requests_cleared', on_init = function(_client) @@ -1057,7 +1094,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'finish', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_finish', on_setup = function() @@ -1067,12 +1104,10 @@ describe('LSP', function() "testing"; "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)')) - exec_lua [[ - vim.api.nvim_command(BUFFER.."bwipeout") + assert(TEST_RPC_CLIENT_ID == 1) + assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)) + assert(lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)) + vim.cmd(BUFFER.."bwipeout") ]] end, on_init = function(_client) @@ -1101,7 +1136,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open', on_setup = function() @@ -1147,7 +1182,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open', on_setup = function() @@ -1190,7 +1225,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change', on_setup = function() @@ -1238,7 +1273,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_noeol', on_setup = function() @@ -1305,7 +1340,7 @@ describe('LSP', function() }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'inlay_hint', on_setup = function() @@ -1332,7 +1367,7 @@ describe('LSP', function() on_handler = function(err, result, ctx) if ctx.method == 'start' then exec_lua [[ - vim.lsp.inlay_hint.enable(BUFFER) + vim.lsp.inlay_hint.enable(true, { bufnr = BUFFER }) ]] end if ctx.method == 'textDocument/inlayHint' then @@ -1352,7 +1387,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_incremental', options = { @@ -1403,7 +1438,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_incremental', options = { @@ -1457,7 +1492,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_incremental_editing', on_setup = function() @@ -1485,7 +1520,7 @@ describe('LSP', function() end, on_handler = function(err, result, ctx) if ctx.method == 'start' then - helpers.command('normal! 1Go') + n.command('normal! 1Go') client.notify('finish') end eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') @@ -1502,7 +1537,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_multi', on_setup = function() @@ -1553,7 +1588,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_check_buffer_open_and_change_multi_and_close', on_setup = function() @@ -1607,7 +1642,7 @@ describe('LSP', function() { NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'invalid_header', on_setup = function() end, @@ -1640,7 +1675,7 @@ describe('LSP', function() }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'decode_nil', on_setup = function() @@ -1807,7 +1842,7 @@ describe('LSP', function() 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, {})')) + eq(true, api.nvim_buf_set_mark(1, 'a', 2, 1, {})) exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ 'First line of text', @@ -1815,7 +1850,7 @@ describe('LSP', function() 'Fourth line of text', 'barfoo', }, buf_lines(1)) - local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') + local mark = api.nvim_buf_get_mark(1, 'a') eq({ 2, 1 }, mark) end) @@ -1824,7 +1859,7 @@ describe('LSP', function() 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, {})')) + eq(true, api.nvim_buf_set_mark(1, 'a', 2, 10, {})) exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ 'First line of text', @@ -1832,7 +1867,7 @@ describe('LSP', function() 'Fourth line of text', 'barfoo', }, buf_lines(1)) - local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') + local mark = api.nvim_buf_get_mark(1, 'a') eq({ 2, 9 }, mark) end) @@ -1841,19 +1876,19 @@ describe('LSP', function() 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, {})')) + eq(true, api.nvim_buf_set_mark(1, 'a', 4, 1, {})) exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16') eq({ 'First line of text', 'foobaro', }, buf_lines(1)) - local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")') + local mark = 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() - fn.nvim_win_set_cursor(0, { 2, 6 }) + api.nvim_win_set_cursor(0, { 2, 6 }) local edits = { make_edit(1, 0, 1, 19, 'Second line of text'), } @@ -1865,11 +1900,11 @@ describe('LSP', function() 'Fourth line of text', 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 2, 6 }, fn.nvim_win_get_cursor(0)) + eq({ 2, 6 }, api.nvim_win_get_cursor(0)) end) it('fix the cursor to the valid col if the content was removed', function() - fn.nvim_win_set_cursor(0, { 2, 6 }) + api.nvim_win_set_cursor(0, { 2, 6 }) local edits = { make_edit(1, 0, 1, 6, ''), make_edit(1, 6, 1, 19, ''), @@ -1882,11 +1917,11 @@ describe('LSP', function() 'Fourth line of text', 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 2, 0 }, fn.nvim_win_get_cursor(0)) + eq({ 2, 0 }, api.nvim_win_get_cursor(0)) end) it('fix the cursor to the valid row if the content was removed', function() - fn.nvim_win_set_cursor(0, { 2, 6 }) + api.nvim_win_set_cursor(0, { 2, 6 }) local edits = { make_edit(1, 0, 1, 6, ''), make_edit(0, 18, 5, 0, ''), @@ -1895,11 +1930,11 @@ describe('LSP', function() eq({ 'First line of text', }, buf_lines(1)) - eq({ 1, 17 }, fn.nvim_win_get_cursor(0)) + eq({ 1, 17 }, api.nvim_win_get_cursor(0)) end) it('fix the cursor row', function() - fn.nvim_win_set_cursor(0, { 3, 0 }) + api.nvim_win_set_cursor(0, { 3, 0 }) local edits = { make_edit(1, 0, 2, 0, ''), } @@ -1910,14 +1945,14 @@ describe('LSP', function() 'Fourth line of text', 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 2, 0 }, fn.nvim_win_get_cursor(0)) + eq({ 2, 0 }, api.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, { '' }) + api.nvim_buf_set_lines(1, -1, -1, true, { '' }) - fn.nvim_win_set_cursor(0, { 2, 11 }) + api.nvim_win_set_cursor(0, { 2, 11 }) local edits = { make_edit(1, 7, 1, 11, ''), } @@ -1930,11 +1965,11 @@ describe('LSP', function() 'å å ɧ 汉语 ↥ 🤦 🦄', '', }, buf_lines(1)) - eq({ 2, 7 }, fn.nvim_win_get_cursor(0)) + eq({ 2, 7 }, api.nvim_win_get_cursor(0)) end) it('fix the cursor row and col', function() - fn.nvim_win_set_cursor(0, { 2, 12 }) + api.nvim_win_set_cursor(0, { 2, 12 }) local edits = { make_edit(0, 11, 1, 12, ''), } @@ -1945,7 +1980,7 @@ describe('LSP', function() 'Fourth line of text', 'å å ɧ 汉语 ↥ 🤦 🦄', }, buf_lines(1)) - eq({ 1, 11 }, fn.nvim_win_get_cursor(0)) + eq({ 1, 11 }, api.nvim_win_get_cursor(0)) end) end) @@ -2021,7 +2056,7 @@ describe('LSP', function() end) describe('apply_text_document_edit', function() - local target_bufnr + local target_bufnr --- @type integer local text_document_edit = function(editVersion) return { edits = { @@ -2267,7 +2302,7 @@ describe('LSP', function() }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + eq(true, vim.uv.fs_stat(tmpfile) ~= nil) end) it( 'Supports file creation in folder that needs to be created with CreateFile payload', @@ -2285,7 +2320,7 @@ describe('LSP', function() }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + eq(true, vim.uv.fs_stat(tmpfile) ~= nil) end ) it('createFile does not touch file if it exists and ignoreIfExists is set', function() @@ -2304,7 +2339,7 @@ describe('LSP', function() }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + eq(true, vim.uv.fs_stat(tmpfile) ~= nil) eq('Dummy content', read_file(tmpfile)) end) it('createFile overrides file if overwrite is set', function() @@ -2324,7 +2359,7 @@ describe('LSP', function() }, } exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + eq(true, vim.uv.fs_stat(tmpfile) ~= nil) eq('', read_file(tmpfile)) end) it('DeleteFile delete file and buffer', function() @@ -2348,8 +2383,8 @@ describe('LSP', function() }, } 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)) + eq(false, vim.uv.fs_stat(tmpfile) ~= nil) + eq(false, api.nvim_buf_is_loaded(fn.bufadd(tmpfile))) end) it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function() local tmpfile = tmpname() @@ -2367,12 +2402,12 @@ describe('LSP', function() }, } eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit)) - eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile)) + eq(false, vim.uv.fs_stat(tmpfile) ~= nil) end) end) describe('lsp.util.rename', function() - local pathsep = helpers.get_pathsep() + local pathsep = n.get_pathsep() it('Can rename an existing file', function() local old = tmpname() @@ -2395,9 +2430,9 @@ describe('LSP', function() new ) eq({ 'Test content' }, lines) - local exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', old) + local exists = vim.uv.fs_stat(old) ~= nil eq(false, exists) - exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', new) + exists = vim.uv.fs_stat(new) ~= nil eq(true, exists) os.remove(new) end) @@ -2408,7 +2443,7 @@ describe('LSP', function() os.remove(old_dir) os.remove(new_dir) - helpers.mkdir_p(old_dir) + n.mkdir_p(old_dir) local file = 'file.txt' write_file(old_dir .. pathsep .. file, 'Test content') @@ -2433,9 +2468,9 @@ describe('LSP', function() 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(false, vim.uv.fs_stat(old_dir) ~= nil) + eq(true, vim.uv.fs_stat(new_dir) ~= nil) + eq(true, vim.uv.fs_stat(new_dir .. pathsep .. file) ~= nil) os.remove(new_dir) end) @@ -2444,7 +2479,7 @@ describe('LSP', function() local new = tmpname() os.remove(old) os.remove(new) - helpers.mkdir_p(old) + n.mkdir_p(old) local result = exec_lua( [[ @@ -2499,7 +2534,7 @@ describe('LSP', function() new ) - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq(true, vim.uv.fs_stat(old) ~= nil) eq('New file', read_file(new)) exec_lua( @@ -2513,7 +2548,7 @@ describe('LSP', function() new ) - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) + eq(true, vim.uv.fs_stat(old) ~= nil) eq('New file', read_file(new)) end ) @@ -2543,8 +2578,8 @@ describe('LSP', function() 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(false, vim.uv.fs_stat(old) ~= nil) + eq(true, vim.uv.fs_stat(new) ~= nil) eq(true, undo_kept) end) it('Maintains undo information for unloaded buffer', function() @@ -2570,8 +2605,8 @@ describe('LSP', function() 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(false, vim.uv.fs_stat(old) ~= nil) + eq(true, vim.uv.fs_stat(new) ~= nil) eq(true, undo_kept) end) it('Does not rename file when it conflicts with a buffer without file', function() @@ -2615,8 +2650,8 @@ describe('LSP', function() new ) - eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old)) - eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new)) + eq(false, vim.uv.fs_stat(old) ~= nil) + eq(true, vim.uv.fs_stat(new) ~= nil) eq('Old file', read_file(new)) end) end) @@ -2697,6 +2732,7 @@ describe('LSP', function() eq(expected, actual) end) end) + describe('lsp.util.symbols_to_items', function() describe('convert DocumentSymbol[] to items', function() it('DocumentSymbol has children', function() @@ -2971,7 +3007,7 @@ describe('LSP', function() end) describe('lsp.util.jump_to_location', function() - local target_bufnr + local target_bufnr --- @type integer before_each(function() target_bufnr = exec_lua [[ @@ -2994,10 +3030,10 @@ describe('LSP', function() 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(target_bufnr, fn.bufnr('%')) return { - line = exec_lua [[return vim.fn.line('.')]], - col = exec_lua [[return vim.fn.col('.')]], + line = fn.line('.'), + col = fn.col('.'), } end @@ -3027,25 +3063,25 @@ 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('å', fn.expand('<cword>')) end) it('adds current position to jumplist before jumping', function() - fn.nvim_win_set_buf(0, target_bufnr) - local mark = fn.nvim_buf_get_mark(target_bufnr, "'") + api.nvim_win_set_buf(0, target_bufnr) + local mark = api.nvim_buf_get_mark(target_bufnr, "'") eq({ 1, 0 }, mark) - fn.nvim_win_set_cursor(0, { 2, 3 }) + api.nvim_win_set_cursor(0, { 2, 3 }) jump(location(0, 9, 0, 9)) - mark = fn.nvim_buf_get_mark(target_bufnr, "'") + mark = api.nvim_buf_get_mark(target_bufnr, "'") eq({ 2, 3 }, mark) end) end) describe('lsp.util.show_document', function() - local target_bufnr - local target_bufnr2 + local target_bufnr --- @type integer + local target_bufnr2 --- @type integer before_each(function() target_bufnr = exec_lua([[ @@ -3084,11 +3120,11 @@ describe('LSP', function() ) ) if focus == true or focus == nil then - eq(target_bufnr, exec_lua([[return vim.fn.bufnr('%')]])) + eq(target_bufnr, fn.bufnr('%')) end return { - line = exec_lua([[return vim.fn.line('.')]]), - col = exec_lua([[return vim.fn.col('.')]]), + line = fn.line('.'), + col = fn.col('.'), } end @@ -3132,101 +3168,101 @@ describe('LSP', function() end) it('does not add current position to jumplist if not focus', function() - fn.nvim_win_set_buf(0, target_bufnr) - local mark = fn.nvim_buf_get_mark(target_bufnr, "'") + api.nvim_win_set_buf(0, target_bufnr) + local mark = api.nvim_buf_get_mark(target_bufnr, "'") eq({ 1, 0 }, mark) - fn.nvim_win_set_cursor(0, { 2, 3 }) + api.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 = fn.nvim_buf_get_mark(target_bufnr, "'") + mark = api.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() - fn.nvim_win_set_buf(0, target_bufnr) - local cursor = fn.nvim_win_get_cursor(0) + api.nvim_win_set_buf(0, target_bufnr) + local cursor = api.nvim_win_get_cursor(0) show_document(location(0, 9, 0, 9), false, false) - eq(cursor, fn.nvim_win_get_cursor(0)) + eq(cursor, api.nvim_win_get_cursor(0)) end) it('does not change window if not focus', function() - fn.nvim_win_set_buf(0, target_bufnr) - local win = fn.nvim_get_current_win() + api.nvim_win_set_buf(0, target_bufnr) + local win = api.nvim_get_current_win() -- same document/bufnr show_document(location(0, 9, 0, 9), false, true) - eq(win, fn.nvim_get_current_win()) + eq(win, api.nvim_get_current_win()) -- different document/bufnr, new window/split show_document(location(0, 9, 0, 9, true), false, true) - eq(2, #fn.nvim_list_wins()) - eq(win, fn.nvim_get_current_win()) + eq(2, #api.nvim_list_wins()) + eq(win, api.nvim_get_current_win()) end) it("respects 'reuse_win' parameter", function() - fn.nvim_win_set_buf(0, target_bufnr) + api.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, #fn.nvim_list_wins()) + eq(1, #api.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, #fn.nvim_list_wins()) + eq(2, #api.nvim_list_wins()) end) it('correctly sets the cursor of the split if range is given without focus', function() - fn.nvim_win_set_buf(0, target_bufnr) + api.nvim_win_set_buf(0, target_bufnr) show_document(location(0, 9, 0, 9, true), false, true) - local wins = fn.nvim_list_wins() + local wins = api.nvim_list_wins() eq(2, #wins) table.sort(wins) - eq({ 1, 0 }, fn.nvim_win_get_cursor(wins[1])) - eq({ 1, 9 }, fn.nvim_win_get_cursor(wins[2])) + eq({ 1, 0 }, api.nvim_win_get_cursor(wins[1])) + eq({ 1, 9 }, api.nvim_win_get_cursor(wins[2])) end) it('does not change cursor of the split if not range and not focus', function() - fn.nvim_win_set_buf(0, target_bufnr) - fn.nvim_win_set_cursor(0, { 2, 3 }) + api.nvim_win_set_buf(0, target_bufnr) + api.nvim_win_set_cursor(0, { 2, 3 }) exec_lua([[vim.cmd.new()]]) - fn.nvim_win_set_buf(0, target_bufnr2) - fn.nvim_win_set_cursor(0, { 2, 3 }) + api.nvim_win_set_buf(0, target_bufnr2) + api.nvim_win_set_cursor(0, { 2, 3 }) show_document({ uri = 'file:///fake/uri2' }, false, true) - local wins = fn.nvim_list_wins() + local wins = api.nvim_list_wins() eq(2, #wins) - eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[1])) - eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[2])) + eq({ 2, 3 }, api.nvim_win_get_cursor(wins[1])) + eq({ 2, 3 }, api.nvim_win_get_cursor(wins[2])) end) it('respects existing buffers', function() - fn.nvim_win_set_buf(0, target_bufnr) - local win = fn.nvim_get_current_win() + api.nvim_win_set_buf(0, target_bufnr) + local win = api.nvim_get_current_win() exec_lua([[vim.cmd.new()]]) - fn.nvim_win_set_buf(0, target_bufnr2) - fn.nvim_win_set_cursor(0, { 2, 3 }) - local split = fn.nvim_get_current_win() + api.nvim_win_set_buf(0, target_bufnr2) + api.nvim_win_set_cursor(0, { 2, 3 }) + local split = api.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 }, fn.nvim_win_get_cursor(split)) - eq(2, #fn.nvim_list_wins()) + eq({ 1, 9 }, api.nvim_win_get_cursor(split)) + eq(2, #api.nvim_list_wins()) - fn.nvim_set_current_win(win) + api.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 }, fn.nvim_win_get_cursor(split)) - eq(2, #fn.nvim_list_wins()) + eq({ 1, 9 }, api.nvim_win_get_cursor(split)) + eq(2, #api.nvim_list_wins()) end) end) @@ -3464,6 +3500,442 @@ describe('LSP', function() end) end) + describe('vim.lsp.buf.typehierarchy subtypes', function() + it('does nothing for an empty response', function() + local qflist_count = exec_lua([=[ + require'vim.lsp.handlers'['typeHierarchy/subtypes'](nil, nil, {}) + return #vim.fn.getqflist() + ]=]) + eq(0, qflist_count) + end) + + it('opens the quickfix list with the right subtypes', function() + clear() + exec_lua(create_server_definition) + local qflist = exec_lua([=[ + local clangd_response = { { + data = { + parents = { { + parents = { { + parents = { { + parents = {}, + symbolID = "62B3D268A01B9978" + } }, + symbolID = "DC9B0AD433B43BEC" + } }, + symbolID = "06B5F6A19BA9F6A8" + } }, + symbolID = "EDC336589C09ABB2" + }, + kind = 5, + name = "D2", + range = { + ["end"] = { + character = 8, + line = 9 + }, + start = { + character = 6, + line = 9 + } + }, + selectionRange = { + ["end"] = { + character = 8, + line = 9 + }, + start = { + character = 6, + line = 9 + } + }, + uri = "file:///home/jiangyinzuo/hello.cpp" + }, { + data = { + parents = { { + parents = { { + parents = { { + parents = {}, + symbolID = "62B3D268A01B9978" + } }, + symbolID = "DC9B0AD433B43BEC" + } }, + symbolID = "06B5F6A19BA9F6A8" + } }, + symbolID = "AFFCAED15557EF08" + }, + kind = 5, + name = "D1", + range = { + ["end"] = { + character = 8, + line = 8 + }, + start = { + character = 6, + line = 8 + } + }, + selectionRange = { + ["end"] = { + character = 8, + line = 8 + }, + start = { + character = 6, + line = 8 + } + }, + uri = "file:///home/jiangyinzuo/hello.cpp" + } } + + local server = _create_server({ + capabilities = { + positionEncoding = "utf-8" + }, + }) + local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + local handler = require'vim.lsp.handlers'['typeHierarchy/subtypes'] + handler(nil, clangd_response, { client_id = client_id, bufnr = 1 }) + return vim.fn.getqflist() + ]=]) + + local expected = { + { + bufnr = 2, + col = 7, + end_col = 0, + end_lnum = 0, + lnum = 10, + module = '', + nr = 0, + pattern = '', + text = 'D2', + type = '', + valid = 1, + vcol = 0, + }, + { + bufnr = 2, + col = 7, + end_col = 0, + end_lnum = 0, + lnum = 9, + module = '', + nr = 0, + pattern = '', + text = 'D1', + type = '', + valid = 1, + vcol = 0, + }, + } + + eq(expected, qflist) + end) + + it('opens the quickfix list with the right subtypes and details', function() + clear() + exec_lua(create_server_definition) + local qflist = exec_lua([=[ + local jdtls_response = { + { + data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' }, + detail = '', + kind = 5, + name = 'A', + range = { + ['end'] = { character = 26, line = 3 }, + start = { character = 1, line = 3 }, + }, + selectionRange = { + ['end'] = { character = 8, line = 3 }, + start = { character = 7, line = 3 }, + }, + tags = {}, + uri = 'file:///home/jiangyinzuo/hello-java/Main.java', + }, + { + data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' }, + detail = 'mylist', + kind = 5, + name = 'MyList$Inner', + range = { + ['end'] = { character = 37, line = 3 }, + start = { character = 1, line = 3 }, + }, + selectionRange = { + ['end'] = { character = 19, line = 3 }, + start = { character = 14, line = 3 }, + }, + tags = {}, + uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java', + }, + } + + local server = _create_server({ + capabilities = { + positionEncoding = "utf-8" + }, + }) + local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + local handler = require'vim.lsp.handlers'['typeHierarchy/subtypes'] + handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 }) + return vim.fn.getqflist() + ]=]) + + local expected = { + { + bufnr = 2, + col = 2, + end_col = 0, + end_lnum = 0, + lnum = 4, + module = '', + nr = 0, + pattern = '', + text = 'A', + type = '', + valid = 1, + vcol = 0, + }, + { + bufnr = 3, + col = 2, + end_col = 0, + end_lnum = 0, + lnum = 4, + module = '', + nr = 0, + pattern = '', + text = 'MyList$Inner mylist', + type = '', + valid = 1, + vcol = 0, + }, + } + eq(expected, qflist) + end) + end) + + describe('vim.lsp.buf.typehierarchy supertypes', function() + it('does nothing for an empty response', function() + local qflist_count = exec_lua([=[ + require'vim.lsp.handlers'['typeHierarchy/supertypes'](nil, nil, {}) + return #vim.fn.getqflist() + ]=]) + eq(0, qflist_count) + end) + + it('opens the quickfix list with the right supertypes', function() + clear() + exec_lua(create_server_definition) + local qflist = exec_lua([=[ + local clangd_response = { { + data = { + parents = { { + parents = { { + parents = { { + parents = {}, + symbolID = "62B3D268A01B9978" + } }, + symbolID = "DC9B0AD433B43BEC" + } }, + symbolID = "06B5F6A19BA9F6A8" + } }, + symbolID = "EDC336589C09ABB2" + }, + kind = 5, + name = "D2", + range = { + ["end"] = { + character = 8, + line = 9 + }, + start = { + character = 6, + line = 9 + } + }, + selectionRange = { + ["end"] = { + character = 8, + line = 9 + }, + start = { + character = 6, + line = 9 + } + }, + uri = "file:///home/jiangyinzuo/hello.cpp" + }, { + data = { + parents = { { + parents = { { + parents = { { + parents = {}, + symbolID = "62B3D268A01B9978" + } }, + symbolID = "DC9B0AD433B43BEC" + } }, + symbolID = "06B5F6A19BA9F6A8" + } }, + symbolID = "AFFCAED15557EF08" + }, + kind = 5, + name = "D1", + range = { + ["end"] = { + character = 8, + line = 8 + }, + start = { + character = 6, + line = 8 + } + }, + selectionRange = { + ["end"] = { + character = 8, + line = 8 + }, + start = { + character = 6, + line = 8 + } + }, + uri = "file:///home/jiangyinzuo/hello.cpp" + } } + + local server = _create_server({ + capabilities = { + positionEncoding = "utf-8" + }, + }) + local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + local handler = require'vim.lsp.handlers'['typeHierarchy/supertypes'] + handler(nil, clangd_response, { client_id = client_id, bufnr = 1 }) + return vim.fn.getqflist() + ]=]) + + local expected = { + { + bufnr = 2, + col = 7, + end_col = 0, + end_lnum = 0, + lnum = 10, + module = '', + nr = 0, + pattern = '', + text = 'D2', + type = '', + valid = 1, + vcol = 0, + }, + { + bufnr = 2, + col = 7, + end_col = 0, + end_lnum = 0, + lnum = 9, + module = '', + nr = 0, + pattern = '', + text = 'D1', + type = '', + valid = 1, + vcol = 0, + }, + } + + eq(expected, qflist) + end) + + it('opens the quickfix list with the right supertypes and details', function() + clear() + exec_lua(create_server_definition) + local qflist = exec_lua([=[ + local jdtls_response = { + { + data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' }, + detail = '', + kind = 5, + name = 'A', + range = { + ['end'] = { character = 26, line = 3 }, + start = { character = 1, line = 3 }, + }, + selectionRange = { + ['end'] = { character = 8, line = 3 }, + start = { character = 7, line = 3 }, + }, + tags = {}, + uri = 'file:///home/jiangyinzuo/hello-java/Main.java', + }, + { + data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' }, + detail = 'mylist', + kind = 5, + name = 'MyList$Inner', + range = { + ['end'] = { character = 37, line = 3 }, + start = { character = 1, line = 3 }, + }, + selectionRange = { + ['end'] = { character = 19, line = 3 }, + start = { character = 14, line = 3 }, + }, + tags = {}, + uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java', + }, + } + + local server = _create_server({ + capabilities = { + positionEncoding = "utf-8" + }, + }) + local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + local handler = require'vim.lsp.handlers'['typeHierarchy/supertypes'] + handler(nil, jdtls_response, { client_id = client_id, bufnr = 1 }) + return vim.fn.getqflist() + ]=]) + + local expected = { + { + bufnr = 2, + col = 2, + end_col = 0, + end_lnum = 0, + lnum = 4, + module = '', + nr = 0, + pattern = '', + text = 'A', + type = '', + valid = 1, + vcol = 0, + }, + { + bufnr = 3, + col = 2, + end_col = 0, + end_lnum = 0, + lnum = 4, + module = '', + nr = 0, + pattern = '', + text = 'MyList$Inner mylist', + type = '', + valid = 1, + vcol = 0, + }, + } + eq(expected, qflist) + end) + end) + describe('vim.lsp.buf.rename', function() for _, test in ipairs({ { @@ -3504,7 +3976,7 @@ describe('LSP', function() }, }) do it(test.it, function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = test.name, on_init = function(_client) @@ -3554,7 +4026,7 @@ describe('LSP', function() describe('vim.lsp.buf.code_action', function() it('Calls client side command if available', function() - local client + local client --- @type vim.lsp.Client local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, @@ -3592,7 +4064,7 @@ describe('LSP', function() } end) it('Calls workspace/executeCommand if no client side command', function() - local client + local client --- @type vim.lsp.Client local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, { @@ -3632,7 +4104,7 @@ describe('LSP', function() }) end) it('Filters and automatically applies action if requested', function() - local client + local client --- @type vim.lsp.Client local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, @@ -3701,8 +4173,8 @@ describe('LSP', function() } }, handlers = { - ["textDocument/codeAction"] = function() - return { + ["textDocument/codeAction"] = function(_, _, callback) + callback(nil, { { title = "Code Action 1", command = { @@ -3710,10 +4182,10 @@ describe('LSP', function() command = "command:1", } } - } + }) end, - ["codeAction/resolve"] = function() - return nil, "resolve failed" + ["codeAction/resolve"] = function(_, _, callback) + callback("resolve failed", nil) end, } }) @@ -3732,6 +4204,7 @@ describe('LSP', function() eq('command:1', result[5].params.command) end) end) + describe('vim.lsp.commands', function() it('Accepts only string keys', function() matches( @@ -3746,9 +4219,10 @@ describe('LSP', function() ) end) end) + describe('vim.lsp.codelens', function() it('uses client commands', function() - local client + local client --- @type vim.lsp.Client local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, @@ -3802,7 +4276,7 @@ describe('LSP', function() end) it('releases buffer refresh lock', function() - local client + local client --- @type vim.lsp.Client local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, @@ -3879,11 +4353,97 @@ describe('LSP', function() end, } end) + + it('refresh multiple buffers', function() + local lens_title_per_fake_uri = { + ['file:///fake/uri1'] = 'Lens1', + ['file:///fake/uri2'] = 'Lens2', + } + clear() + exec_lua(create_server_definition) + + -- setup lsp + exec_lua( + [[ + local lens_title_per_fake_uri = ... + local server = _create_server({ + capabilities = { + codeLensProvider = { + resolveProvider = true + }, + }, + handlers = { + ["textDocument/codeLens"] = function(method, params, callback) + local lenses = { + { + range = { + start = { line = 0, character = 0 }, + ['end'] = { line = 0, character = 0 }, + }, + command = { + title = lens_title_per_fake_uri[params.textDocument.uri], + command = 'Dummy', + }, + }, + } + callback(nil, lenses) + end, + } + }) + + CLIENT_ID = vim.lsp.start({ + name = "dummy", + cmd = server.cmd, + }) + ]], + lens_title_per_fake_uri + ) + + -- create buffers and setup handler + exec_lua( + [[ + local lens_title_per_fake_uri = ... + local default_buf = vim.api.nvim_get_current_buf() + for fake_uri, _ in pairs(lens_title_per_fake_uri) do + local bufnr = vim.uri_to_bufnr(fake_uri) + vim.api.nvim_set_current_buf(bufnr) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'Some contents'}) + vim.lsp.buf_attach_client(bufnr, CLIENT_ID) + end + vim.api.nvim_buf_delete(default_buf, {force = true}) + + REQUEST_COUNT = vim.tbl_count(lens_title_per_fake_uri) + RESPONSES = {} + local on_codelens = vim.lsp.codelens.on_codelens + vim.lsp.codelens.on_codelens = function (err, result, ctx, ...) + table.insert(RESPONSES, { err = err, result = result, ctx = ctx }) + return on_codelens(err, result, ctx, ...) + end + ]], + lens_title_per_fake_uri + ) + + -- call codelens refresh + local cmds = exec_lua([[ + RESPONSES = {} + vim.lsp.codelens.refresh() + vim.wait(100, function () return #RESPONSES >= REQUEST_COUNT end) + + local cmds = {} + for _, resp in ipairs(RESPONSES) do + local uri = resp.ctx.params.textDocument.uri + cmds[uri] = resp.result[1].command + end + return cmds + ]]) + eq({ command = 'Dummy', title = 'Lens1' }, cmds['file:///fake/uri1']) + eq({ command = 'Dummy', title = 'Lens2' }, cmds['file:///fake/uri2']) + end) end) describe('vim.lsp.buf.format', function() it('Aborts with notify if no client matches filter', function() - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_init', on_init = function(c) @@ -3912,7 +4472,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_formatting', on_init = function(c) @@ -3945,7 +4505,7 @@ describe('LSP', function() { NIL, {}, { method = 'shutdown', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } }, } - local client + local client --- @type vim.lsp.Client test_rpc_server { test_name = 'basic_formatting', on_init = function(c) @@ -4068,6 +4628,9 @@ describe('LSP', function() end ]]) local fail_msg = '[LSP] Format request failed, no matching language servers.' + --- @param name string + --- @param formatting boolean + --- @param range_formatting boolean local function check_notify(name, formatting, range_formatting) local timeout_msg = '[LSP][' .. name .. '] timeout' exec_lua( @@ -4131,13 +4694,13 @@ describe('LSP', function() }, handlers = { ---@return lsp.Location[] - ['textDocument/definition'] = function() - return { _G.mock_locations[1] } + ['textDocument/definition'] = function(_, _, callback) + callback(nil, { _G.mock_locations[1] }) end, ---@return lsp.WorkspaceSymbol[] - ['workspace/symbol'] = function(_, request) + ['workspace/symbol'] = function(_, request, callback) assert(request.query == 'foobar') - return { + callback(nil, { { name = 'foobar', kind = 13, ---@type lsp.SymbolKind @@ -4148,7 +4711,7 @@ describe('LSP', function() kind = 12, ---@type lsp.SymbolKind location = _G.mock_locations[2], } - } + }) end, }, }) @@ -4221,10 +4784,10 @@ describe('LSP', function() server:shutdown() return vim.json.decode(init) ]] - eq(result.method, 'initialize') + eq('initialize', result.method) end) - it('can connect to lsp server via rpc.domain_socket_connect', function() - local tmpfile + it('can connect to lsp server via pipe or domain_socket', function() + local tmpfile --- @type string if is_os('win') then tmpfile = '\\\\.\\\\pipe\\pipe.test' else @@ -4248,7 +4811,7 @@ describe('LSP', function() client:close() end)) end) - vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) }) + vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.connect(SOCK) }) vim.wait(1000, function() return init ~= nil end) assert(init, "server must receive `initialize` request") server:close() @@ -4257,7 +4820,7 @@ describe('LSP', function() ]], tmpfile ) - eq(result.method, 'initialize') + eq('initialize', result.method) end) end) @@ -4449,18 +5012,26 @@ describe('LSP', function() string.format('sends notifications when files change (watchfunc=%s)', watchfunc), function() if watchfunc == 'fswatch' then + skip(is_os('win'), 'not supported on windows') + skip(is_os('mac'), 'flaky test on mac') 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 - skip( - is_os('bsd'), - 'kqueue only reports events on watched folder itself, not contained files #26110' - ) + if watchfunc == 'watch' then + skip(is_os('mac'), 'flaky test on mac') + skip( + is_os('bsd'), + 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38' + ) + else + skip( + is_os('bsd'), + 'kqueue only reports events on watched folder itself, not contained files #26110' + ) + end local root_dir = tmpname() os.remove(root_dir) @@ -4679,14 +5250,7 @@ describe('LSP', function() ) local function watched_uri(fname) - return exec_lua( - [[ - local root_dir, fname = ... - return vim.uri_from_fname(root_dir .. '/' .. fname) - ]], - root_dir, - fname - ) + return vim.uri_from_fname(root_dir .. '/' .. fname) end eq(4, #result) @@ -4792,13 +5356,7 @@ describe('LSP', function() ) local function watched_uri(fname) - return exec_lua( - [[ - local fname = ... - return vim.uri_from_fname('/dir/' .. fname) - ]], - fname - ) + return vim.uri_from_fname('/dir/' .. fname) end eq(3, #result) @@ -4923,30 +5481,21 @@ describe('LSP', function() root_dir ) - local function watched_uri(fname) - return exec_lua( - [[ - return vim.uri_from_fname(...) - ]], - fname - ) - end - eq(3, #result) eq('workspace/didChangeWatchedFiles', result[3].method) eq({ changes = { { type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]), - uri = watched_uri('file1'), + uri = vim.uri_from_fname('file1'), }, { type = exec_lua([[return vim.lsp.protocol.FileChangeType.Changed]]), - uri = watched_uri('file1'), + uri = vim.uri_from_fname('file1'), }, { type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]), - uri = watched_uri('file2'), + uri = vim.uri_from_fname('file2'), }, }, }, result[3].params) @@ -5009,7 +5558,7 @@ describe('LSP', function() ) end - eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities(). + eq(is_os('mac') or is_os('win'), check_registered(nil)) -- start{_client}() defaults to make_client_capabilities(). eq(false, check_registered(vim.empty_dict())) eq( false, diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua index 5bfa566729..978178191c 100644 --- a/test/functional/plugin/man_spec.lua +++ b/test/functional/plugin/man_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() 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 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 command, feed = n.command, n.feed +local clear = n.clear +local exec_lua = n.exec_lua +local fn = n.fn +local nvim_prog = n.nvim_prog +local matches = t.matches +local write_file = t.write_file +local tmpname = t.tmpname +local eq = t.eq local pesc = vim.pesc -local skip = helpers.skip -local is_ci = helpers.is_ci +local skip = t.skip +local is_ci = t.is_ci -- Collects all names passed to find_path() after attempting ":Man foo". local function get_search_history(name) @@ -44,7 +46,7 @@ describe(':Man', function() end) describe('man.lua: highlight_line()', function() - local screen + local screen --- @type test.functional.ui.screen before_each(function() command('syntax on') @@ -64,7 +66,7 @@ describe(':Man', function() end) it('clears backspaces from text and adds highlights', function() - rawfeed( + feed( [[ 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>]] @@ -90,7 +92,7 @@ describe(':Man', function() end) it('clears escape sequences from text and adds highlights', function() - rawfeed( + feed( [[ 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>]] @@ -116,7 +118,7 @@ describe(':Man', function() end) it('highlights multibyte text', function() - rawfeed( + feed( [[ 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>]] @@ -132,7 +134,7 @@ describe(':Man', function() end) it('highlights underscores based on context', function() - rawfeed( + feed( [[ 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 @@ -150,7 +152,7 @@ describe(':Man', function() end) it('highlights various bullet formats', function() - rawfeed([[ + feed([[ 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>]]) @@ -166,7 +168,7 @@ describe(':Man', function() end) it('handles : characters in input', function() - rawfeed([[ + feed([[ i<C-v><C-[>[40m 0 <C-v><C-[>[41m 1 <C-v><C-[>[42m 2 <C-v><C-[>[43m 3 <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 @@ -190,6 +192,7 @@ describe(':Man', function() '--headless', '+autocmd VimLeave * echo "quit works!!"', '+Man!', + '+tag ls', '+call nvim_input("q")', } matches('quit works!!', fn.system(args, { 'manpage contents' })) diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua index 530afd16e4..ae718ac1bd 100644 --- a/test/functional/plugin/matchparen_spec.lua +++ b/test/functional/plugin/matchparen_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local api = helpers.api -local feed = helpers.feed -local eq = helpers.eq +local clear = n.clear +local command = n.command +local api = n.api +local feed = n.feed +local eq = t.eq describe('matchparen', function() - local screen + local screen --- @type test.functional.ui.screen before_each(function() clear { args = { '-u', 'NORC' } } diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index 8511e6c703..1d5d20ec02 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -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 t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local api = n.api +local eq = t.eq +local nvim_eval = n.eval +local nvim_command = n.command +local exc_exec = n.exc_exec +local ok = t.ok local NIL = vim.NIL describe('autoload/msgpack.vim', function() diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index 1c20548321..1c2bcbd497 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear +local t_shada = require('test.functional.shada.testutil') + +local clear = n.clear 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 + t.eq, n.api, n.eval, n.command, n.exc_exec, n.fn, n.feed +local neq = t.neq +local read_file = t.read_file -local shada_helpers = require('test.functional.shada.helpers') -local get_shada_rw = shada_helpers.get_shada_rw +local get_shada_rw = t_shada.get_shada_rw local function reset(shada_file) clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } } @@ -2612,7 +2614,7 @@ end) describe('plugin/shada.vim', function() local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0) - local eol = helpers.is_os('win') and '\r\n' or '\n' + local eol = t.is_os('win') and '\r\n' or '\n' before_each(function() -- Note: reset() is called explicitly in each test. os.remove(fname) diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua index 2ac0fe1fa3..200a5f34b2 100644 --- a/test/functional/plugin/tohtml_spec.lua +++ b/test/functional/plugin/tohtml_spec.lua @@ -1,13 +1,14 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() 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 clear = n.clear +local exec = n.exec +local exec_lua = n.exec_lua +local eq = t.eq +local fn = n.fn +local api = n.api +local insert = n.insert local function html_syntax_match() local styles = diff --git a/test/functional/plugin/tutor_spec.lua b/test/functional/plugin/tutor_spec.lua index 99538e1db0..9f381d45db 100644 --- a/test/functional/plugin/tutor_spec.lua +++ b/test/functional/plugin/tutor_spec.lua @@ -1,18 +1,20 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local is_os = helpers.is_os + +local clear = n.clear +local command = n.command +local feed = n.feed +local is_os = t.is_os describe(':Tutor', function() - local screen + local screen --- @type test.functional.ui.screen before_each(function() clear({ args = { '--clean' } }) command('set cmdheight=0') command('Tutor') - screen = Screen.new(80, 30) + screen = Screen.new(81, 30) screen:set_default_attr_ids({ [0] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, [1] = { bold = true }, @@ -20,6 +22,7 @@ describe(':Tutor', function() [3] = { foreground = Screen.colors.SlateBlue }, [4] = { bold = true, foreground = Screen.colors.Brown }, [5] = { bold = true, foreground = Screen.colors.Magenta1 }, + [6] = { italic = true }, }) screen:attach() end) @@ -27,71 +30,109 @@ describe(':Tutor', function() it('applies {unix:…,win:…} transform', function() 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. | - {0: } | - {0: }{1:NOTE}: You can also read the output of an external command. For example, | - {0: } | - {0: } :r {4:!}dir | - {0: } | - {0: } reads the output of the ls command and puts it below the cursor. | - {0: } | - {0: }{3:#}{5: Lesson 5 SUMMARY} | - {0: } | - {0: } 1. {2::!command} executes an external command. | - {0: } | - {0: } Some useful examples are: | - {0: } :{4:!}dir - shows a directory listing | - {0: } :{4:!}del FILENAME - removes file FILENAME | - {0: } | - {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | - {0: } name FILENAME. | - {0: } | - {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | - {0: } FILENAME. | - {0: } | - {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | - {0: } below the cursor position. | - {0: } | - {0: } 5. {2::r !dir} reads the output of the dir command and | - {0: } puts it below the cursor position. | - {0: } | + {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. | + {0: } | + {0: }{1:NOTE}: You can also read the output of an external command. For example, | + {0: } | + {0: } :r {4:!}dir | + {0: } | + {0: } reads the output of the ls command and puts it below the cursor. | + {0: } | + {0: }{3:#}{5: Lesson 5 SUMMARY} | + {0: } | + {0: } 1. {2::!command} executes an external command. | + {0: } | + {0: } Some useful examples are: | + {0: } :{4:!}dir - shows a directory listing | + {0: } :{4:!}del FILENAME - removes file FILENAME | + {0: } | + {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | + {0: } name FILENAME. | + {0: } | + {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | + {0: } FILENAME. | + {0: } | + {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | + {0: } below the cursor position. | + {0: } | + {0: } 5. {2::r !dir} reads the output of the dir command and | + {0: } puts it below the cursor position. | + {0: } | ]] 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. | - {0: } | - {0: }{1:NOTE}: You can also read the output of an external command. For example, | - {0: } | - {0: } :r {4:!}ls | - {0: } | - {0: } reads the output of the ls command and puts it below the cursor. | - {0: } | - {0: }{3:#}{5: Lesson 5 SUMMARY} | - {0: } | - {0: } 1. {2::!command} executes an external command. | - {0: } | - {0: } Some useful examples are: | - {0: } :{4:!}ls - shows a directory listing | - {0: } :{4:!}rm FILENAME - removes file FILENAME | - {0: } | - {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | - {0: } name FILENAME. | - {0: } | - {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | - {0: } FILENAME. | - {0: } | - {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | - {0: } below the cursor position. | - {0: } | - {0: } 5. {2::r !ls} reads the output of the ls command and | - {0: } puts it below the cursor position. | - {0: } | + {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. | + {0: } | + {0: }{1:NOTE}: You can also read the output of an external command. For example, | + {0: } | + {0: } :r {4:!}ls | + {0: } | + {0: } reads the output of the ls command and puts it below the cursor. | + {0: } | + {0: }{3:#}{5: Lesson 5 SUMMARY} | + {0: } | + {0: } 1. {2::!command} executes an external command. | + {0: } | + {0: } Some useful examples are: | + {0: } :{4:!}ls - shows a directory listing | + {0: } :{4:!}rm FILENAME - removes file FILENAME | + {0: } | + {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | + {0: } name FILENAME. | + {0: } | + {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | + {0: } FILENAME. | + {0: } | + {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | + {0: } below the cursor position. | + {0: } | + {0: } 5. {2::r !ls} reads the output of the ls command and | + {0: } puts it below the cursor position. | + {0: } | ]] feed(':700<CR>zt') screen:expect(expected) end) + + it('applies hyperlink highlighting', function() + local expected = [[ + {0: }^ | + {0: }{3:#}{5: CONCLUSION} | + {0: } | + {0: }This was intended to give a brief overview of the Neovim editor, just enough to| + {0: }allow you to use it fairly easily. It is far from complete as Neovim has | + {0: }many many more commands. Consult the help often. | + {0: }There are also countless great tutorials and videos to be found online. | + {0: }Here's a bunch of them: | + {0: } | + {0: }- {6:Learn Vim Progressively}: | + {0: } {2:https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/} | + {0: }- {6:Learning Vim in 2014}: | + {0: } {2:https://benmccormick.org/learning-vim-in-2014/} | + {0: }- {6:Vimcasts}: | + {0: } {2:http://vimcasts.org/} | + {0: }- {6:Vim Video-Tutorials by Derek Wyatt}: | + {0: } {2:http://derekwyatt.org/vim/tutorials/} | + {0: }- {6:Learn Vimscript the Hard Way}: | + {0: } {2:https://learnvimscriptthehardway.stevelosh.com/} | + {0: }- {6:7 Habits of Effective Text Editing}: | + {0: } {2:https://www.moolenaar.net/habits.html} | + {0: }- {6:vim-galore}: | + {0: } {2:https://github.com/mhinz/vim-galore} | + {0: } | + {0: }If you prefer a book, {6:Practical Vim} by Drew Neil is recommended often | + {0: }(the sequel, {6:Modern Vim}, includes material specific to Neovim). | + {0: } | + {0: }This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado | + {0: }School of Mines using ideas supplied by Charles Smith, Colorado State | + {0: }University. E-mail: {2:bware@mines.colorado.edu}. | + ]] + + feed(':960<CR>zt') + screen:expect(expected) + end) end) diff --git a/test/functional/plugin/vim_syntax_spec.lua b/test/functional/plugin/vim_syntax_spec.lua index 9396bbce5c..d99a69eab9 100644 --- a/test/functional/plugin/vim_syntax_spec.lua +++ b/test/functional/plugin/vim_syntax_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local api = helpers.api + +local clear = n.clear +local exec = n.exec +local api = n.api describe('Vimscript syntax highlighting', function() - local screen + local screen --- @type test.functional.ui.screen before_each(function() clear() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() exec([[ setfiletype vim syntax on diff --git a/test/functional/preload.lua b/test/functional/preload.lua index 49f1eff0da..e524ab34aa 100644 --- a/test/functional/preload.lua +++ b/test/functional/preload.lua @@ -1,12 +1,10 @@ -- Modules loaded here will NOT be cleared and reloaded by Busted. -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. -local helpers = require('test.functional.helpers')(nil) +local t = require('test.testutil') require('test.functional.ui.screen') -local busted = require('busted') -local is_os = helpers.is_os -if is_os('win') then +if t.is_os('win') then local ffi = require('ffi') ffi.cdef [[ typedef int errno_t; @@ -14,26 +12,3 @@ if is_os('win') then ]] ffi.C._set_fmode(0x8000) end - -local testid = (function() - local id = 0 - return function() - id = id + 1 - return id - end -end)() - --- Global before_each. https://github.com/Olivine-Labs/busted/issues/613 -local function before_each(_element, _parent) - local id = ('T%d'):format(testid()) - _G._nvim_test_id = id - return nil, true -end -busted.subscribe({ 'test', 'start' }, before_each, { - -- Ensure our --helper is handled before --output (see busted/runner.lua). - priority = 1, - -- Don't generate a test-id for skipped tests. /shrug - predicate = function(element, _, status) - return not (element.descriptor == 'pending' or status == 'pending') - end, -}) diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua index 0c4fd7aaa0..9e7df0ba6b 100644 --- a/test/functional/provider/clipboard_spec.lua +++ b/test/functional/provider/clipboard_spec.lua @@ -1,12 +1,13 @@ -- Test clipboard provider support -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local feed_command, expect, eq, eval, source = - helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source -local command = helpers.command -local api = helpers.api + +local clear, feed, insert = n.clear, n.feed, n.insert +local feed_command, expect, eq, eval, source = n.feed_command, n.expect, t.eq, n.eval, n.source +local command = n.command +local api = n.api local function basic_register_test(noblock) insert('some words') diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua index 657f1a0d8a..3945486d98 100644 --- a/test/functional/provider/define_spec.lua +++ b/test/functional/provider/define_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local eval, command = helpers.eval, helpers.command -local eq, run, stop = helpers.eq, helpers.run, helpers.stop -local clear = helpers.clear -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eval, command = n.eval, n.command +local eq, run, stop = t.eq, n.run, n.stop +local clear = n.clear +local api = n.api local function get_prefix(sync) if sync then @@ -28,7 +30,7 @@ local function runx(sync, handler, on_setup) local function setup_cb(...) on_setup(...) -- need to stop on setup callback because there's two session:request - -- calls in `request/helpers.lua`. The second call will always return + -- calls in `request/testnvim.lua`. The second call will always return -- after pending notification/request callbacks are processed stop() end @@ -324,7 +326,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init) end) it('with range', function() - helpers.insert([[ + n.insert([[ foo bar baz diff --git a/test/functional/provider/nodejs_spec.lua b/test/functional/provider/nodejs_spec.lua index 1769239cb0..a67ad36f79 100644 --- a/test/functional/provider/nodejs_spec.lua +++ b/test/functional/provider/nodejs_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, clear = helpers.eq, helpers.clear -local missing_provider = helpers.missing_provider -local command = helpers.command -local write_file = helpers.write_file -local eval = helpers.eval -local retry = helpers.retry +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear = t.eq, n.clear +local missing_provider = n.missing_provider +local command = n.command +local write_file = t.write_file +local eval = n.eval +local retry = t.retry do clear() diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua index e9a031eb07..ea4aaa9ee9 100644 --- a/test/functional/provider/perl_spec.lua +++ b/test/functional/provider/perl_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, clear = helpers.eq, helpers.clear -local missing_provider = helpers.missing_provider -local command = helpers.command -local write_file = helpers.write_file -local eval = helpers.eval -local retry = helpers.retry -local api = helpers.api -local insert = helpers.insert -local expect = helpers.expect -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear = t.eq, n.clear +local missing_provider = n.missing_provider +local command = n.command +local write_file = t.write_file +local eval = n.eval +local retry = t.retry +local api = n.api +local insert = n.insert +local expect = n.expect +local feed = n.feed do clear() diff --git a/test/functional/provider/provider_spec.lua b/test/functional/provider/provider_spec.lua index cccd1a1184..caed30ab0b 100644 --- a/test/functional/provider/provider_spec.lua +++ b/test/functional/provider/provider_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eval = helpers.clear, helpers.eval -local command = helpers.command -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval = n.clear, n.eval +local command = n.command +local eq = t.eq +local pcall_err = t.pcall_err describe('providers', function() before_each(function() diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua index 80b3552e82..71a067d3d2 100644 --- a/test/functional/provider/python3_spec.lua +++ b/test/functional/provider/python3_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_alive = helpers.assert_alive -local eval, command, feed = helpers.eval, helpers.command, helpers.feed -local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert -local expect, write_file = helpers.expect, helpers.write_file -local feed_command = helpers.feed_command -local source = helpers.source -local missing_provider = helpers.missing_provider -local matches = helpers.matches -local pcall_err = helpers.pcall_err -local fn = helpers.fn -local dedent = helpers.dedent +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local eval, command, feed = n.eval, n.command, n.feed +local eq, clear, insert = t.eq, n.clear, n.insert +local expect, write_file = n.expect, t.write_file +local feed_command = n.feed_command +local source = n.source +local missing_provider = n.missing_provider +local matches = t.matches +local pcall_err = t.pcall_err +local fn = n.fn +local dedent = t.dedent do clear() @@ -153,7 +155,7 @@ describe('python3 provider', function() end) it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() source([=[ python3 << EOF import vim diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua index 9b2531a23c..716ef296be 100644 --- a/test/functional/provider/ruby_spec.lua +++ b/test/functional/provider/ruby_spec.lua @@ -1,20 +1,21 @@ -local helpers = require('test.functional.helpers')(after_each) - -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local exc_exec = helpers.exc_exec -local expect = helpers.expect -local feed = helpers.feed -local feed_command = helpers.feed_command -local fn = helpers.fn -local insert = helpers.insert -local api = helpers.api -local missing_provider = helpers.missing_provider -local matches = helpers.matches -local write_file = helpers.write_file -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local clear = n.clear +local command = n.command +local eq = t.eq +local exc_exec = n.exc_exec +local expect = n.expect +local feed = n.feed +local feed_command = n.feed_command +local fn = n.fn +local insert = n.insert +local api = n.api +local missing_provider = n.missing_provider +local matches = t.matches +local write_file = t.write_file +local pcall_err = t.pcall_err do clear() @@ -103,7 +104,7 @@ end) describe('ruby provider', function() it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function() - helpers.add_builddir_to_rtp() + n.add_builddir_to_rtp() command([=[autocmd BufDelete * ruby VIM::evaluate('expand("<afile>")')]=]) feed_command('help help') assert_alive() diff --git a/test/functional/script/luacats_grammar_spec.lua b/test/functional/script/luacats_grammar_spec.lua index c3ac9fe722..6d444e1888 100644 --- a/test/functional/script/luacats_grammar_spec.lua +++ b/test/functional/script/luacats_grammar_spec.lua @@ -1,5 +1,6 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq +local t = require('test.testutil') + +local eq = t.eq local grammar = require('scripts/luacats_grammar') @@ -151,4 +152,11 @@ describe('luacats grammar', function() name = '[1]', type = 'integer', }) + + test('@param type `T` this is a generic type', { + desc = 'this is a generic type', + kind = 'param', + name = 'type', + type = '`T`', + }) end) diff --git a/test/functional/script/luacats_parser_spec.lua b/test/functional/script/luacats_parser_spec.lua index e10aa81003..bc87b38eca 100644 --- a/test/functional/script/luacats_parser_spec.lua +++ b/test/functional/script/luacats_parser_spec.lua @@ -1,5 +1,6 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq +local t = require('test.testutil') + +local eq = t.eq local parser = require('scripts/luacats_parser') diff --git a/test/functional/script/text_utils_spec.lua b/test/functional/script/text_utils_spec.lua index 190c617e1d..176c2ef816 100644 --- a/test/functional/script/text_utils_spec.lua +++ b/test/functional/script/text_utils_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local exec_lua = helpers.exec_lua -local eq = helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exec_lua = n.exec_lua +local eq = t.eq local function md_to_vimdoc(text, start_indent, indent, text_width) return exec_lua( @@ -28,7 +30,7 @@ end describe('md_to_vimdoc', function() before_each(function() - helpers.clear() + n.clear() end) test('can render para after fenced code', { diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua index 9fead98fed..07b0bf4217 100644 --- a/test/functional/shada/buffers_spec.lua +++ b/test/functional/shada/buffers_spec.lua @@ -1,10 +1,12 @@ -- shada buffer list saving/reading support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, fn, eq, api = helpers.command, helpers.fn, helpers.eq, helpers.api -local expect_exit = helpers.expect_exit +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear = shada_helpers.reset, shada_helpers.clear +local nvim_command, fn, eq, api = n.command, n.fn, t.eq, n.api +local expect_exit = n.expect_exit + +local reset, clear = t_shada.reset, t_shada.clear describe('shada support code', function() local testfilename = 'Xtestfile-functional-shada-buffers' diff --git a/test/functional/shada/compatibility_spec.lua b/test/functional/shada/compatibility_spec.lua index bc4e9675c6..98d3884098 100644 --- a/test/functional/shada/compatibility_spec.lua +++ b/test/functional/shada/compatibility_spec.lua @@ -1,18 +1,18 @@ -- ShaDa compatibility support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq -local exc_exec = helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear, get_shada_rw = - shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw -local read_shada_file = shada_helpers.read_shada_file +local nvim_command, fn, eq = n.command, n.fn, t.eq +local exc_exec = n.exc_exec +local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw +local read_shada_file = t_shada.read_shada_file local wshada, sdrcmd, shada_fname = get_shada_rw('Xtest-functional-shada-compatibility.shada') local mock_file_path = '/a/b/' local mock_file_path2 = '/d/e/' -if helpers.is_os('win') then +if t.is_os('win') then mock_file_path = 'C:/a/' mock_file_path2 = 'C:/d/' end diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua index 233f03e5c0..a9084da929 100644 --- a/test/functional/shada/errors_spec.lua +++ b/test/functional/shada/errors_spec.lua @@ -1,10 +1,10 @@ -- ShaDa errors handling support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, eq, exc_exec = helpers.command, helpers.eq, helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear, get_shada_rw = - shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw +local nvim_command, eq, exc_exec = n.command, t.eq, n.exc_exec +local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw local wshada, sdrcmd, shada_fname, clean = get_shada_rw('Xtest-functional-shada-errors.shada') diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua index c8a19bb082..39a5f8df7e 100644 --- a/test/functional/shada/history_spec.lua +++ b/test/functional/shada/history_spec.lua @@ -1,12 +1,13 @@ -- ShaDa history saving/reading support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, fn, api, nvim_feed, eq = - helpers.command, helpers.fn, helpers.api, helpers.feed, helpers.eq -local assert_alive = helpers.assert_alive -local expect_exit = helpers.expect_exit +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear = shada_helpers.reset, shada_helpers.clear +local nvim_command, fn, api, nvim_feed, eq = n.command, n.fn, n.api, n.feed, t.eq +local assert_alive = n.assert_alive +local expect_exit = n.expect_exit + +local reset, clear = t_shada.reset, t_shada.clear describe('ShaDa support code', function() before_each(reset) @@ -115,6 +116,12 @@ describe('ShaDa support code', function() nvim_feed('gg0n') eq({ 0, 2, 3, 0 }, fn.getpos('.')) eq(1, api.nvim_get_vvar('searchforward')) + -- Autocommands shouldn't cause search pattern to change + nvim_command('autocmd User * :') + nvim_command('doautocmd User') + nvim_feed('gg0n') + eq({ 0, 2, 3, 0 }, fn.getpos('.')) + eq(1, api.nvim_get_vvar('searchforward')) end) it('dumps and loads last search pattern with offset and backward direction', function() @@ -129,6 +136,12 @@ describe('ShaDa support code', function() nvim_feed('G$n') eq({ 0, 2, 3, 0 }, fn.getpos('.')) eq(0, api.nvim_get_vvar('searchforward')) + -- Autocommands shouldn't cause search pattern to change + nvim_command('autocmd User * :') + nvim_command('doautocmd User') + nvim_feed('G$n') + eq({ 0, 2, 3, 0 }, fn.getpos('.')) + eq(0, api.nvim_get_vvar('searchforward')) end) it('saves v:hlsearch=1', function() diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua index 3f29a02506..d680f0b83b 100644 --- a/test/functional/shada/marks_spec.lua +++ b/test/functional/shada/marks_spec.lua @@ -1,12 +1,14 @@ -- ShaDa marks saving/reading support -local helpers = require('test.functional.helpers')(after_each) -local api, nvim_command, fn, eq = helpers.api, helpers.command, helpers.fn, helpers.eq -local feed = helpers.feed -local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture -local expect_exit = helpers.expect_exit +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear = shada_helpers.reset, shada_helpers.clear +local api, nvim_command, fn, eq = n.api, n.command, n.fn, t.eq +local feed = n.feed +local exc_exec, exec_capture = n.exc_exec, n.exec_capture +local expect_exit = n.expect_exit + +local reset, clear = t_shada.reset, t_shada.clear local nvim_current_line = function() return api.nvim_win_get_cursor(0)[1] @@ -163,17 +165,17 @@ describe('ShaDa support code', function() eq({ 2, 0 }, api.nvim_win_get_cursor(0)) end) - it('is able to dump and restore jump list with different times (slow!)', function() + it('is able to dump and restore jump list with different times', function() nvim_command('edit ' .. testfilename_2) - nvim_command('sleep 2') + nvim_command('sleep 10m') nvim_command('normal! G') - nvim_command('sleep 2') + nvim_command('sleep 10m') nvim_command('normal! gg') - nvim_command('sleep 2') + nvim_command('sleep 10m') nvim_command('edit ' .. testfilename) - nvim_command('sleep 2') + nvim_command('sleep 10m') nvim_command('normal! G') - nvim_command('sleep 2') + nvim_command('sleep 10m') nvim_command('normal! gg') expect_exit(nvim_command, 'qall') reset() @@ -216,7 +218,7 @@ describe('ShaDa support code', function() -- -c temporary sets lnum to zero to make `+/pat` work, so calling setpcmark() -- during -c used to add item with zero lnum to jump list. it('does not create incorrect file for non-existent buffers when writing from -c', function() - local argv = helpers.new_argv { + local argv = n.new_argv { args_rm = { '-i', '--embed', -- no --embed @@ -235,7 +237,7 @@ describe('ShaDa support code', function() end) it('does not create incorrect file for non-existent buffers opened from -c', function() - local argv = helpers.new_argv { + local argv = n.new_argv { args_rm = { '-i', '--embed', -- no --embed diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua index 1b5c0eab5d..c98678ccbf 100644 --- a/test/functional/shada/merging_spec.lua +++ b/test/functional/shada/merging_spec.lua @@ -1,18 +1,19 @@ -- ShaDa merging data support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq -local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear, get_shada_rw = - shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw -local read_shada_file = shada_helpers.read_shada_file +local nvim_command, fn, eq = n.command, n.fn, t.eq +local exc_exec, exec_capture = n.exc_exec, n.exec_capture +local api = n.api + +local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw +local read_shada_file = t_shada.read_shada_file local wshada, sdrcmd, shada_fname = get_shada_rw('Xtest-functional-shada-merging.shada') local mock_file_path = '/a/b/' -if helpers.is_os('win') then +if t.is_os('win') then mock_file_path = 'C:/a/' end @@ -698,9 +699,9 @@ describe('ShaDa marks support code', function() for _, v in ipairs(read_shada_file(shada_fname)) do if v.type == 7 then local name = ('%c'):format(v.value.n) - local t = found[name] or {} - t[v.value.f] = (t[v.value.f] or 0) + 1 - found[name] = t + local _t = found[name] or {} + _t[v.value.f] = (_t[v.value.f] or 0) + 1 + found[name] = _t end end eq({ ['0'] = { [mock_file_path .. '-'] = 1 }, A = { [mock_file_path .. '?'] = 1 } }, found) @@ -1003,7 +1004,7 @@ describe('ShaDa jumps support code', function() eq(jumps[found].line, v.value.l) end end - eq(found, #jumps) + eq(#jumps, found) end) it('merges JUMPLISTSIZE jumps when writing', function() @@ -1018,14 +1019,14 @@ describe('ShaDa jumps support code', function() eq(0, exc_exec(sdrcmd())) shada = '' for i = 1, 101 do - local t = i * 2 + local _t = i * 2 shada = shada .. ('\008\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format( - t, - t + _t, + _t ) - jumps[(t > #jumps + 1) and (#jumps + 1) or t] = - { file = '' .. mock_file_path .. 'c', line = t } + jumps[(_t > #jumps + 1) and (#jumps + 1) or _t] = + { file = '' .. mock_file_path .. 'c', line = _t } end wshada(shada) eq(0, exc_exec('wshada ' .. shada_fname)) @@ -1041,7 +1042,7 @@ describe('ShaDa jumps support code', function() eq(jumps[found].line, v.value.l) end end - eq(found, 100) + eq(100, found) end) end) @@ -1132,7 +1133,7 @@ describe('ShaDa changes support code', function() eq(changes[found].line, v.value.l or 1) end end - eq(found, #changes) + eq(#changes, found) end) it('merges JUMPLISTSIZE changes when writing', function() @@ -1149,13 +1150,13 @@ describe('ShaDa changes support code', function() eq(0, exc_exec(sdrcmd())) shada = '' for i = 1, 101 do - local t = i * 2 + local _t = i * 2 shada = shada .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format( - t, - t + _t, + _t ) - changes[(t > #changes + 1) and (#changes + 1) or t] = { line = t } + changes[(_t > #changes + 1) and (#changes + 1) or _t] = { line = _t } end wshada(shada) eq(0, exc_exec('wshada ' .. shada_fname)) @@ -1170,7 +1171,7 @@ describe('ShaDa changes support code', function() eq(changes[found].line, v.value.l) end end - eq(found, 100) + eq(100, found) end) it('merges JUMPLISTSIZE changes when writing, with new items between old', function() @@ -1178,11 +1179,11 @@ describe('ShaDa changes support code', function() nvim_command('keepjumps call setline(1, range(202))') local shada = '' for i = 1, 101 do - local t = i * 2 + local _t = i * 2 shada = shada .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format( - t, - t + _t, + _t ) end wshada(shada) @@ -1197,8 +1198,8 @@ describe('ShaDa changes support code', function() changes[i] = { line = i } end for i = 1, 101 do - local t = i * 2 - changes[(t > #changes + 1) and (#changes + 1) or t] = { line = t } + local _t = i * 2 + changes[(_t > #changes + 1) and (#changes + 1) or _t] = { line = _t } end wshada(shada) eq(0, exc_exec('wshada ' .. shada_fname)) @@ -1213,6 +1214,6 @@ describe('ShaDa changes support code', function() eq(changes[found].line, v.value.l) end end - eq(found, 100) + eq(100, found) end) end) diff --git a/test/functional/shada/registers_spec.lua b/test/functional/shada/registers_spec.lua index ef15ab9a05..1e6249807e 100644 --- a/test/functional/shada/registers_spec.lua +++ b/test/functional/shada/registers_spec.lua @@ -1,10 +1,11 @@ -- ShaDa registers saving/reading support -local helpers = require('test.functional.helpers')(after_each) -local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear = shada_helpers.reset, shada_helpers.clear -local expect_exit = helpers.expect_exit +local nvim_command, fn, eq = n.command, n.fn, t.eq +local reset, clear = t_shada.reset, t_shada.clear +local expect_exit = n.expect_exit local setreg = function(name, contents, typ) if type(contents) == 'string' then diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua index 6eb318015d..5debdc6c77 100644 --- a/test/functional/shada/shada_spec.lua +++ b/test/functional/shada/shada_spec.lua @@ -1,18 +1,18 @@ -- Other ShaDa tests -local helpers = require('test.functional.helpers')(after_each) -local api, nvim_command, fn, eq = helpers.api, helpers.command, helpers.fn, helpers.eq -local write_file, spawn, set_session, nvim_prog, exc_exec = - helpers.write_file, helpers.spawn, helpers.set_session, helpers.nvim_prog, helpers.exc_exec -local is_os = helpers.is_os -local skip = helpers.skip - +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') local uv = vim.uv -local paths = helpers.paths +local paths = t.paths + +local api, nvim_command, fn, eq = n.api, n.command, n.fn, t.eq +local write_file, spawn, set_session, nvim_prog, exc_exec = + t.write_file, n.spawn, n.set_session, n.nvim_prog, n.exc_exec +local is_os = t.is_os +local skip = t.skip -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear, get_shada_rw = - shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw -local read_shada_file = shada_helpers.read_shada_file +local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw +local read_shada_file = t_shada.read_shada_file local wshada, _, shada_fname, clean = get_shada_rw('Xtest-functional-shada-shada.shada') diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/testutil.lua index baa27889f3..d9252af5f0 100644 --- a/test/functional/shada/helpers.lua +++ b/test/functional/shada/testutil.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(nil) -local api = helpers.api -local write_file = helpers.write_file -local concat_tables = helpers.concat_tables +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local tmpname = helpers.tmpname() +local api = n.api +local write_file = t.write_file +local concat_tables = t.concat_tables + +local tmpname = t.tmpname() -- o={ -- args=…, @@ -24,7 +26,7 @@ local function reset(o) elseif o.args then args = concat_tables(args, o.args) end - helpers.clear { + n.clear { args_rm = args_rm, args = args, } @@ -32,7 +34,7 @@ local function reset(o) end local clear = function() - helpers.expect_exit(helpers.command, 'qall!') + n.expect_exit(n.command, 'qall!') os.remove(tmpname) end diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua index d70f5deded..2fea7278ef 100644 --- a/test/functional/shada/variables_spec.lua +++ b/test/functional/shada/variables_spec.lua @@ -1,11 +1,11 @@ -- ShaDa variables saving/reading support -local helpers = require('test.functional.helpers')(after_each) -local api, fn, nvim_command, eq, eval = - helpers.api, helpers.fn, helpers.command, helpers.eq, helpers.eval -local expect_exit = helpers.expect_exit +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local t_shada = require('test.functional.shada.testutil') -local shada_helpers = require('test.functional.shada.helpers') -local reset, clear = shada_helpers.reset, shada_helpers.clear +local api, fn, nvim_command, eq, eval = n.api, n.fn, n.command, t.eq, n.eval +local expect_exit = n.expect_exit +local reset, clear = t_shada.reset, t_shada.clear describe('ShaDa support code', function() before_each(reset) diff --git a/test/functional/terminal/altscreen_spec.lua b/test/functional/terminal/altscreen_spec.lua index c3be9ec6ca..12c8615799 100644 --- a/test/functional/terminal/altscreen_spec.lua +++ b/test/functional/terminal/altscreen_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local clear, eq, api = helpers.clear, helpers.eq, helpers.api -local feed = helpers.feed -local feed_data = thelpers.feed_data -local enter_altscreen = thelpers.enter_altscreen -local exit_altscreen = thelpers.exit_altscreen +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -if helpers.skip(helpers.is_os('win')) then +local tt = require('test.functional.terminal.testutil') +local clear, eq, api = n.clear, t.eq, n.api +local feed = n.feed +local feed_data = tt.feed_data +local enter_altscreen = tt.enter_altscreen +local exit_altscreen = tt.exit_altscreen + +if t.skip(t.is_os('win')) then return end @@ -15,7 +17,7 @@ describe(':terminal altscreen', function() before_each(function() clear() - screen = thelpers.screen_setup() + screen = tt.screen_setup() feed_data({ 'line1', 'line2', diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua index 79cc5016da..1f10dda551 100644 --- a/test/functional/terminal/api_spec.lua +++ b/test/functional/terminal/api_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local child_session = require('test.functional.terminal.helpers') -local ok = helpers.ok +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -if helpers.skip(helpers.is_os('win')) then +local tt = require('test.functional.terminal.testutil') +local ok = t.ok + +if t.skip(t.is_os('win')) then return end @@ -11,9 +13,9 @@ describe('api', function() local socket_name = './Xtest_functional_api.sock' before_each(function() - helpers.clear() + n.clear() os.remove(socket_name) - screen = child_session.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -21,7 +23,7 @@ describe('api', function() '--cmd', 'colorscheme vim', '--cmd', - helpers.nvim_set .. ' notermguicolors', + n.nvim_set .. ' notermguicolors', }) end) after_each(function() @@ -39,7 +41,7 @@ describe('api', function() } -- Start the socket from the child nvim. - child_session.feed_data(":echo serverstart('" .. socket_name .. "')\n") + tt.feed_data(":echo serverstart('" .. socket_name .. "')\n") -- Wait for socket creation. screen:expect([[ @@ -49,10 +51,10 @@ describe('api', function() {3:-- TERMINAL --} | ]]) - local socket_session1 = helpers.connect(socket_name) - local socket_session2 = helpers.connect(socket_name) + local socket_session1 = n.connect(socket_name) + local socket_session2 = n.connect(socket_name) - child_session.feed_data('i[tui] insert-mode') + tt.feed_data('i[tui] insert-mode') -- Wait for stdin to be processed. screen:expect([[ [tui] insert-mode{1: } | diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 376b7b849e..96abd9f543 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1,24 +1,27 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local thelpers = require('test.functional.terminal.helpers') -local assert_alive = helpers.assert_alive -local feed, clear = helpers.feed, helpers.clear -local poke_eventloop = helpers.poke_eventloop -local nvim_prog = helpers.nvim_prog -local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source -local pcall_err = helpers.pcall_err -local eq, neq = helpers.eq, helpers.neq -local api = helpers.api -local retry = helpers.retry -local write_file = helpers.write_file -local command = helpers.command -local exc_exec = helpers.exc_exec -local matches = helpers.matches -local exec_lua = helpers.exec_lua +local tt = require('test.functional.terminal.testutil') + +local assert_alive = n.assert_alive +local feed, clear = n.feed, n.clear +local poke_eventloop = n.poke_eventloop +local nvim_prog = n.nvim_prog +local eval, feed_command, source = n.eval, n.feed_command, n.source +local pcall_err = t.pcall_err +local eq, neq = t.eq, t.neq +local api = n.api +local retry = t.retry +local testprg = n.testprg +local write_file = t.write_file +local command = n.command +local exc_exec = n.exc_exec +local matches = t.matches +local exec_lua = n.exec_lua local sleep = vim.uv.sleep -local fn = helpers.fn -local is_os = helpers.is_os -local skip = helpers.skip +local fn = n.fn +local is_os = t.is_os +local skip = t.skip describe(':terminal buffer', function() local screen @@ -26,7 +29,7 @@ describe(':terminal buffer', function() before_each(function() clear() command('set modifiable swapfile undolevels=20') - screen = thelpers.screen_setup() + screen = tt.screen_setup() end) it('terminal-mode forces various options', function() @@ -54,7 +57,7 @@ describe(':terminal buffer', function() eq({ 0, 'both' }, eval('[&l:cursorline, &l:cursorlineopt]')) end) - it('terminal-mode disables cursorline when cursorlineopt is only set to "line', function() + it('terminal-mode disables cursorline when cursorlineopt is only set to "line"', function() feed([[<C-\><C-N>]]) command('setlocal cursorline cursorlineopt=line') feed('i') @@ -205,22 +208,14 @@ describe(':terminal buffer', function() eq(tbuf, eval('bufnr("%")')) end) - it('term_close() use-after-free #4393', function() - feed_command('terminal yes') - feed([[<C-\><C-n>]]) - feed_command('bdelete!') - end) - describe('handles confirmations', function() it('with :confirm', function() - feed_command('terminal') feed('<c-\\><c-n>') feed_command('confirm bdelete') screen:expect { any = 'Close "term://' } end) it('with &confirm', function() - feed_command('terminal') feed('<c-\\><c-n>') feed_command('bdelete') screen:expect { any = 'E89' } @@ -273,7 +268,7 @@ describe(':terminal buffer', function() it('does not segfault when pasting empty register #13955', function() feed('<c-\\><c-n>') feed_command('put a') -- register a is empty - helpers.assert_alive() + n.assert_alive() end) it([[can use temporary normal mode <c-\><c-o>]], function() @@ -317,13 +312,22 @@ describe(':terminal buffer', function() pcall_err(command, 'write test/functional/fixtures/tty-test.c') ) end) +end) + +describe(':terminal buffer', function() + before_each(clear) + + it('term_close() use-after-free #4393', function() + command('terminal yes') + feed('<Ignore>') -- Add input to separate two RPC requests + command('bdelete!') + end) it('emits TermRequest events #26972', function() - command('new') local term = api.nvim_open_term(0, {}) local termbuf = api.nvim_get_current_buf() - -- Test that autocommand buffer is associated with the terminal buffer, not the current buffer + -- Test that <abuf> is the terminal buffer, not the current buffer command('au TermRequest * let g:termbuf = +expand("<abuf>")') command('wincmd p') @@ -337,7 +341,6 @@ describe(':terminal buffer', function() end) it('TermReqeust synchronization #27572', function() - command('new') command('autocmd! nvim_terminal TermRequest') local term = exec_lua([[ _G.input = {} @@ -364,20 +367,13 @@ describe(':terminal buffer', function() '\027[0n', }, exec_lua('return _G.input')) end) -end) - -describe('No heap-buffer-overflow when using', function() - local testfilename = 'Xtestfile-functional-terminal-buffers_spec' - before_each(function() + it('no heap-buffer-overflow when using termopen(echo) #3161', function() + local testfilename = 'Xtestfile-functional-terminal-buffers_spec' write_file(testfilename, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa') - end) - - after_each(function() - os.remove(testfilename) - end) - - it('termopen(echo) #3161', function() + finally(function() + os.remove(testfilename) + end) feed_command('edit ' .. testfilename) -- Move cursor away from the beginning of the line feed('$') @@ -386,15 +382,36 @@ describe('No heap-buffer-overflow when using', function() assert_alive() feed_command('bdelete!') end) -end) -describe('No heap-buffer-overflow when', function() - it('set nowrap and send long line #11548', function() + it('no heap-buffer-overflow when sending long line with nowrap #11548', function() feed_command('set nowrap') feed_command('autocmd TermOpen * startinsert') feed_command('call feedkeys("4000ai\\<esc>:terminal!\\<cr>")') assert_alive() end) + + it('truncates number of composing characters to 5', function() + local chan = api.nvim_open_term(0, {}) + local composing = ('a̳'):sub(2) + api.nvim_chan_send(chan, 'a' .. composing:rep(8)) + retry(nil, nil, function() + eq('a' .. composing:rep(5), api.nvim_get_current_line()) + end) + end) + + it('handles split UTF-8 sequences #16245', function() + local screen = Screen.new(50, 7) + screen:attach() + fn.termopen({ testprg('shell-test'), 'UTF-8' }) + screen:expect([[ + ^å | + ref: å̲ | + 1: å̲ | + 2: å̲ | + 3: å̲ | + |*2 + ]]) + end) end) describe('on_lines does not emit out-of-bounds line indexes when', function() @@ -431,16 +448,6 @@ describe('on_lines does not emit out-of-bounds line indexes when', function() end) end) -it('terminal truncates number of composing characters to 5', function() - clear() - local chan = api.nvim_open_term(0, {}) - local composing = ('a̳'):sub(2) - api.nvim_chan_send(chan, 'a' .. composing:rep(8)) - retry(nil, nil, function() - eq('a' .. composing:rep(5), api.nvim_get_current_line()) - end) -end) - describe('terminal input', function() before_each(function() clear() @@ -468,7 +475,7 @@ end) describe('terminal input', function() it('sends various special keys with modifiers', function() clear() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -477,18 +484,16 @@ describe('terminal input', function() 'colorscheme vim', '--cmd', 'set notermguicolors', - '--cmd', - 'startinsert', + '-c', + 'while 1 | redraw | echo keytrans(getcharstr()) | endwhile', }) - screen:expect { - grid = [[ + screen:expect([[ {1: } | {4:~ }|*3 - {5:[No Name] 0,1 All}| - {3:-- INSERT --} | + {5:[No Name] 0,0-1 All}| + | {3:-- TERMINAL --} | - ]], - } + ]]) for _, key in ipairs({ '<M-Tab>', '<M-CR>', @@ -538,10 +543,14 @@ describe('terminal input', function() '<ScrollWheelLeft>', '<ScrollWheelRight>', }) do - feed('<CR><C-V>' .. key) - retry(nil, nil, function() - eq(key, api.nvim_get_current_line()) - end) + feed(key) + screen:expect(([[ + | + {4:~ }|*3 + {5:[No Name] 0,0-1 All}| + %s{1: }{MATCH: *}| + {3:-- TERMINAL --} | + ]]):format(key)) end end) end) @@ -555,7 +564,7 @@ if is_os('win') then feed_command('set modifiable swapfile undolevels=20') poke_eventloop() local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' } - screen = thelpers.screen_setup(nil, cmd) + screen = tt.screen_setup(nil, cmd) end) it('"put" operator sends data normally', function() diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua index 9615534c87..774ff01291 100644 --- a/test/functional/terminal/channel_spec.lua +++ b/test/functional/terminal/channel_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local command = helpers.command -local pcall_err = helpers.pcall_err -local feed = helpers.feed -local poke_eventloop = helpers.poke_eventloop -local is_os = helpers.is_os -local api = helpers.api -local async_meths = helpers.async_meths -local testprg = helpers.testprg -local assert_alive = helpers.assert_alive + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local command = n.command +local pcall_err = t.pcall_err +local feed = n.feed +local poke_eventloop = n.poke_eventloop +local is_os = t.is_os +local api = n.api +local async_meths = n.async_meths +local testprg = n.testprg +local assert_alive = n.assert_alive describe('terminal channel is closed and later released if', function() local screen @@ -121,6 +123,7 @@ it('chansend sends lines to terminal channel in proper order', function() clear({ args = { '--cmd', 'set laststatus=2' } }) local screen = Screen.new(100, 20) screen:attach() + screen._default_attr_ids = nil local shells = is_os('win') and { 'cmd.exe', 'pwsh.exe -nop', 'powershell.exe -nop' } or { 'sh' } for _, sh in ipairs(shells) do command([[let id = termopen(']] .. sh .. [[')]]) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index 73fd97203e..51c6b12e62 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -1,26 +1,28 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local thelpers = require('test.functional.terminal.helpers') -local feed, clear = helpers.feed, helpers.clear -local testprg, command = helpers.testprg, helpers.command -local eq, eval = helpers.eq, helpers.eval -local matches = helpers.matches -local poke_eventloop = helpers.poke_eventloop -local hide_cursor = thelpers.hide_cursor -local show_cursor = thelpers.show_cursor -local is_os = helpers.is_os -local skip = helpers.skip +local tt = require('test.functional.terminal.testutil') + +local feed, clear = n.feed, n.clear +local testprg, command = n.testprg, n.command +local eq, eval = t.eq, n.eval +local matches = t.matches +local poke_eventloop = n.poke_eventloop +local hide_cursor = tt.hide_cursor +local show_cursor = tt.show_cursor +local is_os = t.is_os +local skip = t.skip describe(':terminal cursor', function() local screen before_each(function() clear() - screen = thelpers.screen_setup() + screen = tt.screen_setup() end) it('moves the screen cursor when focused', function() - thelpers.feed_data('testing cursor') + tt.feed_data('testing cursor') screen:expect([[ tty ready | testing cursor{1: } | @@ -66,7 +68,7 @@ describe(':terminal cursor', function() :set number | ]]) feed('i') - helpers.poke_eventloop() + n.poke_eventloop() screen:expect([[ {7: 1 }tty ready | {7: 2 }rows: 6, cols: 46 | @@ -152,7 +154,7 @@ describe('buffer cursor position is correct in terminal without number column', local screen local function setup_ex_register(str) - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -189,7 +191,7 @@ describe('buffer cursor position is correct in terminal without number column', before_each(clear) - describe('in a line with no multibyte characters or trailing spaces,', function() + describe('in a line with no multibyte chars or trailing spaces,', function() before_each(function() setup_ex_register('aaaaaaaa') end) @@ -252,7 +254,7 @@ describe('buffer cursor position is correct in terminal without number column', end) end) - describe('in a line with single-cell multibyte characters and no trailing spaces,', function() + describe('in a line with single-cell multibyte chars and no trailing spaces,', function() before_each(function() setup_ex_register('µµµµµµµµ') end) @@ -315,81 +317,72 @@ describe('buffer cursor position is correct in terminal without number column', end) end) - describe( - 'in a line with single-cell composed multibyte characters and no trailing spaces,', - function() - if skip(is_os('win'), 'Encoding problem?') then - return - end - - before_each(function() - setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳') - end) + describe('in a line with single-cell composed multibyte chars and no trailing spaces,', function() + before_each(function() + setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳') + end) - it('at the end', function() - feed('<C-R>r') - screen:expect([[ + it('at the end', function() + feed('<C-R>r') + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } | {3:-- TERMINAL --} | ]]) - eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } | | ]]) - eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) - end) + eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) + end) - it('near the end', function() - feed('<C-R>r<C-X><C-X>') - screen:expect([[ + it('near the end', function() + skip(is_os('win')) + feed('<C-R>r<C-X><C-X>') + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ | {3:-- TERMINAL --} | ]]) - eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ | | ]]) - eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) - end) + eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) + end) - it('near the start', function() - feed('<C-R>r<C-B><C-O>') - screen:expect([[ + it('near the start', function() + skip(is_os('win')) + feed('<C-R>r<C-B><C-O>') + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {3:-- TERMINAL --} | ]]) - eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ |*4 Entering Ex mode. Type "visual" to go to Normal mode. | :^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | | ]]) - eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) - end) - end - ) - - describe('in a line with double-cell multibyte characters and no trailing spaces,', function() - if skip(is_os('win'), 'Encoding problem?') then - return - end + eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) + end) + end) + describe('in a line with double-cell multibyte chars and no trailing spaces,', function() before_each(function() setup_ex_register('哦哦哦哦哦哦哦哦') end) @@ -478,7 +471,7 @@ describe('buffer cursor position is correct in terminal with number column', fun local screen local function setup_ex_register(str) - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -522,7 +515,7 @@ describe('buffer cursor position is correct in terminal with number column', fun command('set number') end) - describe('in a line with no multibyte characters or trailing spaces,', function() + describe('in a line with no multibyte chars or trailing spaces,', function() before_each(function() setup_ex_register('aaaaaaaa') end) @@ -603,7 +596,7 @@ describe('buffer cursor position is correct in terminal with number column', fun end) end) - describe('in a line with single-cell multibyte characters and no trailing spaces,', function() + describe('in a line with single-cell multibyte chars and no trailing spaces,', function() before_each(function() setup_ex_register('µµµµµµµµ') end) @@ -684,20 +677,14 @@ describe('buffer cursor position is correct in terminal with number column', fun end) end) - describe( - 'in a line with single-cell composed multibyte characters and no trailing spaces,', - function() - if skip(is_os('win'), 'Encoding problem?') then - return - end - - before_each(function() - setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳') - end) + describe('in a line with single-cell composed multibyte chars and no trailing spaces,', function() + before_each(function() + setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳') + end) - it('at the end', function() - feed('<C-R>r') - screen:expect([[ + it('at the end', function() + feed('<C-R>r') + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -706,9 +693,9 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } | {3:-- TERMINAL --} | ]]) - eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 33 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -717,12 +704,13 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } | | ]]) - eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) - end) + eq({ 6, 29 }, eval('nvim_win_get_cursor(0)')) + end) - it('near the end', function() - feed('<C-R>r<C-X><C-X>') - screen:expect([[ + it('near the end', function() + skip(is_os('win')) + feed('<C-R>r<C-X><C-X>') + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -731,9 +719,9 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ | {3:-- TERMINAL --} | ]]) - eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 25 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -742,12 +730,13 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ | | ]]) - eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) - end) + eq({ 6, 21 }, eval('nvim_win_get_cursor(0)')) + end) - it('near the start', function() - feed('<C-R>r<C-B><C-O>') - screen:expect([[ + it('near the start', function() + skip(is_os('win')) + feed('<C-R>r<C-B><C-O>') + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -756,9 +745,9 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {3:-- TERMINAL --} | ]]) - eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) - feed([[<C-\><C-N>]]) - screen:expect([[ + eq({ 6, 5 }, eval('nvim_win_get_cursor(0)')) + feed([[<C-\><C-N>]]) + screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | @@ -767,16 +756,11 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 6 }:^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | | ]]) - eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) - end) - end - ) - - describe('in a line with double-cell multibyte characters and no trailing spaces,', function() - if skip(is_os('win'), 'Encoding problem?') then - return - end + eq({ 6, 1 }, eval('nvim_win_get_cursor(0)')) + end) + end) + describe('in a line with double-cell multibyte chars and no trailing spaces,', function() before_each(function() setup_ex_register('哦哦哦哦哦哦哦哦') end) diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua index f7ceb0a68b..24c5eb28e5 100644 --- a/test/functional/terminal/edit_spec.lua +++ b/test/functional/terminal/edit_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + local screen = require('test.functional.ui.screen') -local testprg = helpers.testprg -local command = helpers.command -local fn = helpers.fn -local api = helpers.api -local clear = helpers.clear -local eq = helpers.eq -local matches = helpers.matches +local testprg = n.testprg +local command = n.command +local fn = n.fn +local api = n.api +local clear = n.clear +local eq = t.eq +local matches = t.matches local pesc = vim.pesc describe(':edit term://*', function() diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 92d37fc04a..1039572210 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -1,18 +1,20 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local clear, poke_eventloop = helpers.clear, helpers.poke_eventloop -local testprg, source, eq = helpers.testprg, helpers.source, helpers.eq -local feed = helpers.feed -local feed_command, eval = helpers.feed_command, helpers.eval -local fn = helpers.fn -local api = helpers.api -local retry = helpers.retry -local ok = helpers.ok -local command = helpers.command -local skip = helpers.skip -local is_os = helpers.is_os -local is_ci = helpers.is_ci + +local assert_alive = n.assert_alive +local clear, poke_eventloop = n.clear, n.poke_eventloop +local testprg, source, eq = n.testprg, n.source, t.eq +local feed = n.feed +local feed_command, eval = n.feed_command, n.eval +local fn = n.fn +local api = n.api +local retry = t.retry +local ok = t.ok +local command = n.command +local skip = t.skip +local is_os = t.is_os +local is_ci = t.is_ci describe(':terminal', function() local screen @@ -21,6 +23,7 @@ describe(':terminal', function() clear() screen = Screen.new(50, 4) screen:attach({ rgb = false }) + screen._default_attr_ids = nil end) it('does not interrupt Press-ENTER prompt #2748', function() @@ -168,6 +171,7 @@ local function test_terminal_with_fake_shell(backslash) clear() screen = Screen.new(50, 4) screen:attach({ rgb = false }) + screen._default_attr_ids = nil api.nvim_set_option_value('shell', shell_path, {}) api.nvim_set_option_value('shellcmdflag', 'EXE', {}) api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index ec057c6766..4f3d010d02 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local thelpers = require('test.functional.terminal.helpers') -local feed, clear = helpers.feed, helpers.clear -local api = helpers.api -local testprg, command = helpers.testprg, helpers.command -local nvim_prog_abs = helpers.nvim_prog_abs -local eq, eval = helpers.eq, helpers.eval -local fn = helpers.fn -local nvim_set = helpers.nvim_set -local is_os = helpers.is_os -local skip = helpers.skip +local tt = require('test.functional.terminal.testutil') + +local feed, clear = n.feed, n.clear +local api = n.api +local testprg, command = n.testprg, n.command +local nvim_prog_abs = n.nvim_prog_abs +local fn = n.fn +local nvim_set = n.nvim_set +local is_os = t.is_os +local skip = t.skip describe(':terminal highlight', function() local screen @@ -52,9 +53,9 @@ describe(':terminal highlight', function() describe(title, function() before_each(function() set_attrs_fn() - thelpers.feed_data('text') - thelpers.clear_attrs() - thelpers.feed_data('text') + tt.feed_data('text') + tt.clear_attrs() + tt.feed_data('text') end) local function pass_attrs() @@ -77,7 +78,7 @@ describe(':terminal highlight', function() table.insert(lines, 'line' .. tostring(i)) end table.insert(lines, '') - thelpers.feed_data(lines) + tt.feed_data(lines) screen:expect([[ line4 | line5 | @@ -102,28 +103,28 @@ describe(':terminal highlight', function() end descr('foreground', 1, function() - thelpers.set_fg(45) + tt.set_fg(45) end) descr('background', 2, function() - thelpers.set_bg(46) + tt.set_bg(46) end) descr('foreground and background', 3, function() - thelpers.set_fg(45) - thelpers.set_bg(46) + tt.set_fg(45) + tt.set_bg(46) end) descr('bold, italics, underline and strikethrough', 4, function() - thelpers.set_bold() - thelpers.set_italic() - thelpers.set_underline() - thelpers.set_strikethrough() + tt.set_bold() + tt.set_italic() + tt.set_underline() + tt.set_strikethrough() end) descr('bold and underdouble', 12, function() - thelpers.set_bold() - thelpers.set_underdouble() + tt.set_bold() + tt.set_underdouble() end) descr('italics and undercurl', 13, function() - thelpers.set_italic() - thelpers.set_undercurl() + tt.set_italic() + tt.set_undercurl() end) end) @@ -191,6 +192,109 @@ it(':terminal highlight has lower precedence than editor #9964', function() ]]) end) +it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', function() + clear() + local screen = Screen.new(50, 7) + screen:set_default_attr_ids({ + [1] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn + [2] = { reverse = true }, -- TermCursor + [3] = { bold = true }, -- ModeMsg + [4] = { background = Screen.colors.Grey90, reverse = true }, + [5] = { background = Screen.colors.Red }, + }) + screen:attach() + command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) + screen:expect([[ + ^tty ready | + |*6 + ]]) + tt.feed_data((' foobar'):rep(30)) + screen:expect([[ + ^tty ready | + foobar foobar foobar foobar foobar foobar foobar | + foobar foobar foobar foobar foobar foobar foobar f| + oobar foobar foobar foobar foobar foobar foobar fo| + obar foobar foobar foobar foobar foobar foobar foo| + bar foobar | + | + ]]) + command('set cursorline cursorcolumn') + feed('j10w') + screen:expect([[ + tty ready {1: } | + foobar foobar{1: }foobar foobar foobar foobar foobar | + {1:foobar foobar ^foobar foobar foobar foobar foobar f}| + oobar foobar f{1:o}obar foobar foobar foobar foobar fo| + obar foobar fo{1:o}bar foobar foobar foobar foobar foo| + bar foobar {1: } | + | + ]]) + -- Entering terminal mode disables 'cursorline' and 'cursorcolumn'. + feed('i') + screen:expect([[ + tty ready | + foobar foobar foobar foobar foobar foobar foobar | + foobar foobar foobar foobar foobar foobar foobar f| + oobar foobar foobar foobar foobar foobar foobar fo| + obar foobar foobar foobar foobar foobar foobar foo| + bar foobar{2: } | + {3:-- TERMINAL --} | + ]]) + -- Leaving terminal mode restores old values. + feed([[<C-\><C-N>]]) + screen:expect([[ + tty ready{1: } | + foobar f{1:o}obar foobar foobar foobar foobar foobar | + foobar fo{1:o}bar foobar foobar foobar foobar foobar f| + oobar foo{1:b}ar foobar foobar foobar foobar foobar fo| + obar foob{1:a}r foobar foobar foobar foobar foobar foo| + {1:bar fooba^r }| + | + ]]) + -- CursorLine and CursorColumn are combined with TermCursorNC. + command('highlight TermCursorNC gui=reverse') + screen:expect([[ + tty ready{1: } | + foobar f{1:o}obar foobar foobar foobar foobar foobar | + foobar fo{1:o}bar foobar foobar foobar foobar foobar f| + oobar foo{1:b}ar foobar foobar foobar foobar foobar fo| + obar foob{1:a}r foobar foobar foobar foobar foobar foo| + {1:bar fooba^r}{4: }{1: }| + | + ]]) + feed('2gg11|') + screen:expect([[ + tty ready {1: } | + {1: foobar fo^obar foobar foobar foobar foobar foobar }| + foobar foo{1:b}ar foobar foobar foobar foobar foobar f| + oobar foob{1:a}r foobar foobar foobar foobar foobar fo| + obar fooba{1:r} foobar foobar foobar foobar foobar foo| + bar foobar{4: } | + | + ]]) + -- TermCursorNC has higher precedence. + command('highlight TermCursorNC gui=NONE guibg=Red') + screen:expect([[ + tty ready {1: } | + {1: foobar fo^obar foobar foobar foobar foobar foobar }| + foobar foo{1:b}ar foobar foobar foobar foobar foobar f| + oobar foob{1:a}r foobar foobar foobar foobar foobar fo| + obar fooba{1:r} foobar foobar foobar foobar foobar foo| + bar foobar{5: } | + | + ]]) + feed('G$') + screen:expect([[ + tty ready{1: } | + foobar f{1:o}obar foobar foobar foobar foobar foobar | + foobar fo{1:o}bar foobar foobar foobar foobar foobar f| + oobar foo{1:b}ar foobar foobar foobar foobar foobar fo| + obar foob{1:a}r foobar foobar foobar foobar foobar foo| + {1:bar fooba^r}{5: }{1: }| + | + ]]) +end) + describe(':terminal highlight forwarding', function() local screen @@ -217,12 +321,12 @@ describe(':terminal highlight forwarding', function() it('will handle cterm and rgb attributes', function() skip(is_os('win')) - thelpers.set_fg(3) - thelpers.feed_data('text') - thelpers.feed_termcode('[38:2:255:128:0m') - thelpers.feed_data('color') - thelpers.clear_attrs() - thelpers.feed_data('text') + tt.set_fg(3) + tt.feed_data('text') + tt.feed_termcode('[38:2:255:128:0m') + tt.feed_data('color') + tt.clear_attrs() + tt.feed_data('text') screen:expect { grid = [[ tty ready | @@ -264,10 +368,10 @@ describe(':terminal highlight with custom palette', function() it('will use the custom color', function() skip(is_os('win')) - thelpers.set_fg(3) - thelpers.feed_data('text') - thelpers.clear_attrs() - thelpers.feed_data('text') + tt.set_fg(3) + tt.feed_data('text') + tt.clear_attrs() + tt.feed_data('text') screen:expect([[ tty ready | {1:text}text{7: } | @@ -276,115 +380,3 @@ describe(':terminal highlight with custom palette', function() ]]) end) end) - -describe('synIDattr()', function() - local screen - before_each(function() - clear() - screen = Screen.new(50, 7) - command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black') - -- Salmon #fa8072 Maroon #800000 - command( - 'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough' - ) - end) - - it('returns cterm-color if RGB-capable UI is _not_ attached', function() - eq('252', eval('synIDattr(hlID("Normal"), "fg")')) - eq('252', eval('synIDattr(hlID("Normal"), "fg#")')) - eq('', eval('synIDattr(hlID("Normal"), "bg")')) - eq('', eval('synIDattr(hlID("Normal"), "bg#")')) - eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) - eq('79', eval('synIDattr(hlID("Keyword"), "fg#")')) - eq('', eval('synIDattr(hlID("Keyword"), "sp")')) - eq('', eval('synIDattr(hlID("Keyword"), "sp#")')) - end) - - it('returns gui-color if "gui" arg is passed', function() - eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")')) - eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")')) - end) - - it('returns gui-color if RGB-capable UI is attached', function() - screen:attach({ rgb = true }) - eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")')) - eq('Black', eval('synIDattr(hlID("Normal"), "bg")')) - eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")')) - eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")')) - end) - - it('returns #RRGGBB value for fg#/bg#/sp#', function() - screen:attach({ rgb = true }) - eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")')) - eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")')) - eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")')) - eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")')) - end) - - it('returns color number if non-GUI', function() - screen:attach({ rgb = false }) - eq('252', eval('synIDattr(hlID("Normal"), "fg")')) - eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) - end) - - it('returns "1" if group has given highlight attribute', function() - local hl_attrs = { - 'underline', - 'undercurl', - 'underdouble', - 'underdotted', - 'underdashed', - 'strikethrough', - } - for _, hl_attr in ipairs(hl_attrs) do - local context = 'using ' .. hl_attr .. ' attr' - command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr) - eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context) - eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context) - eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context) - end - end) -end) - -describe('fg/bg special colors', function() - local screen - before_each(function() - clear() - screen = Screen.new(50, 7) - command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black') - command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg') - end) - - it('resolve to "Normal" values', function() - eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")')) - eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")')) - eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")')) - eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")')) - eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")')) - eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")')) - eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")')) - eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")')) - eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")')) - eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")')) - end) - - it('resolve to "Normal" values in RGB-capable UI', function() - screen:attach({ rgb = true }) - eq('bg', eval('synIDattr(hlID("Visual"), "fg")')) - eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")')) - eq('fg', eval('synIDattr(hlID("Visual"), "bg")')) - eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")')) - eq('bg', eval('synIDattr(hlID("Visual"), "sp")')) - eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")')) - end) - - it('resolve after the "Normal" group is modified', function() - screen:attach({ rgb = true }) - local new_guibg = '#282c34' - local new_guifg = '#abb2bf' - command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg) - eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")')) - eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")')) - eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")')) - end) -end) diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 0395d5ee16..ad98dfc6c3 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval -local feed, api, command = helpers.feed, helpers.api, helpers.command -local feed_data = thelpers.feed_data -local is_os = helpers.is_os -local skip = helpers.skip +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local tt = require('test.functional.terminal.testutil') +local clear, eq, eval = n.clear, t.eq, n.eval +local feed, api, command = n.feed, n.api, n.command +local feed_data = tt.feed_data +local is_os = t.is_os +local skip = t.skip describe(':terminal mouse', function() local screen @@ -15,7 +17,7 @@ describe(':terminal mouse', function() command('highlight StatusLine cterm=NONE') command('highlight StatusLineNC cterm=NONE') command('highlight VertSplit cterm=NONE') - screen = thelpers.screen_setup() + screen = tt.screen_setup() local lines = {} for i = 1, 30 do table.insert(lines, 'line' .. tostring(i)) @@ -41,6 +43,7 @@ describe(':terminal mouse', function() end) it('will exit focus and trigger Normal mode mapping on mouse click', function() + feed([[<C-\><C-N>qri]]) command('let g:got_leftmouse = 0') command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>') eq('t', eval('mode(1)')) @@ -48,9 +51,12 @@ describe(':terminal mouse', function() feed('<LeftMouse>') eq('nt', eval('mode(1)')) eq(1, eval('g:got_leftmouse')) + feed('q') + eq('i<LeftMouse>', eval('keytrans(@r)')) end) it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function() + feed([[<C-\><C-N>qri]]) command('let g:got_ctrl_leftmouse = 0') command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>') eq('t', eval('mode(1)')) @@ -58,6 +64,8 @@ describe(':terminal mouse', function() feed('<C-LeftMouse>') eq('nt', eval('mode(1)')) eq(1, eval('g:got_ctrl_leftmouse')) + feed('q') + eq('i<C-LeftMouse>', eval('keytrans(@r)')) end) it('will exit focus on <C-\\> + mouse-scroll', function() @@ -89,8 +97,8 @@ describe(':terminal mouse', function() describe('with mouse events enabled by the program', function() before_each(function() - thelpers.enable_mouse() - thelpers.feed_data('mouse enabled\n') + tt.enable_mouse() + tt.feed_data('mouse enabled\n') screen:expect([[ line27 | line28 | @@ -417,8 +425,8 @@ describe(':terminal mouse', function() ]]) -- enabling mouse won't affect interaction with other windows - thelpers.enable_mouse() - thelpers.feed_data('mouse enabled\n') + tt.enable_mouse() + tt.feed_data('mouse enabled\n') screen:expect([[ {7: 27 }line │line30 | {7: 28 }line │rows: 5, cols: 25 | diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index 858e23984d..229a169996 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -1,26 +1,28 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local clear, eq = helpers.clear, helpers.eq -local feed, testprg = helpers.feed, helpers.testprg -local eval = helpers.eval -local command = helpers.command -local poke_eventloop = helpers.poke_eventloop -local retry = helpers.retry -local api = helpers.api -local feed_data = thelpers.feed_data -local pcall_err = helpers.pcall_err -local exec_lua = helpers.exec_lua -local assert_alive = helpers.assert_alive -local skip = helpers.skip -local is_os = helpers.is_os +local tt = require('test.functional.terminal.testutil') + +local clear, eq = n.clear, t.eq +local feed, testprg = n.feed, n.testprg +local eval = n.eval +local command = n.command +local poke_eventloop = n.poke_eventloop +local retry = t.retry +local api = n.api +local feed_data = tt.feed_data +local pcall_err = t.pcall_err +local exec_lua = n.exec_lua +local assert_alive = n.assert_alive +local skip = t.skip +local is_os = t.is_os describe(':terminal scrollback', function() local screen before_each(function() clear() - screen = thelpers.screen_setup(nil, nil, 30) + screen = tt.screen_setup(nil, nil, 30) end) describe('when the limit is exceeded', function() @@ -361,16 +363,19 @@ describe(':terminal prints more lines than the screen height and exits', functio line8 | line9 | | - [Process exited 0] | - -- TERMINAL -- | + [Process exited 0]{2: } | + {5:-- TERMINAL --} | ]]) feed('<cr>') -- closes the buffer correctly after pressing a key - screen:expect([[ + screen:expect { + grid = [[ ^ | - ~ |*5 + {1:~ }|*5 | - ]]) + ]], + attr_ids = { [1] = { foreground = 12 } }, + } end) end) @@ -394,9 +399,9 @@ describe("'scrollback' option", function() it('set to 0 behaves as 1', function() local screen if is_os('win') then - screen = thelpers.screen_setup(nil, { 'cmd.exe' }, 30) + screen = tt.screen_setup(nil, { 'cmd.exe' }, 30) else - screen = thelpers.screen_setup(nil, { 'sh' }, 30) + screen = tt.screen_setup(nil, { 'sh' }, 30) end api.nvim_set_option_value('scrollback', 0, {}) @@ -411,10 +416,10 @@ describe("'scrollback' option", function() local screen if is_os('win') then command([[let $PROMPT='$$']]) - screen = thelpers.screen_setup(nil, { 'cmd.exe' }, 30) + screen = tt.screen_setup(nil, { 'cmd.exe' }, 30) else command('let $PS1 = "$"') - screen = thelpers.screen_setup(nil, { 'sh' }, 30) + screen = tt.screen_setup(nil, { 'sh' }, 30) end api.nvim_set_option_value('scrollback', 200, {}) @@ -476,7 +481,7 @@ describe("'scrollback' option", function() it('deletes extra lines immediately', function() -- Scrollback is 10 on screen_setup - local screen = thelpers.screen_setup(nil, nil, 30) + local screen = tt.screen_setup(nil, nil, 30) local lines = {} for i = 1, 30 do table.insert(lines, 'line' .. tostring(i)) diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/testutil.lua index 05db1b3c8c..f3fc5d3f93 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/testutil.lua @@ -1,12 +1,13 @@ -- To test tui/input.c, this module spawns `nvim` inside :terminal and sends --- bytes via jobsend(). Note: the functional/helpers.lua test-session methods +-- bytes via jobsend(). Note: the functional/testutil.lua test-session methods -- operate on the _host_ session, _not_ the child session. -local helpers = require('test.functional.helpers')(nil) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local testprg = helpers.testprg -local exec_lua = helpers.exec_lua -local api = helpers.api -local nvim_prog = helpers.nvim_prog + +local testprg = n.testprg +local exec_lua = n.exec_lua +local api = n.api +local nvim_prog = n.nvim_prog local function feed_data(data) if type(data) == 'table' then @@ -30,7 +31,7 @@ local function make_lua_executor(session) end end --- some helpers for controlling the terminal. the codes were taken from +-- some t for controlling the terminal. the codes were taken from -- infocmp xterm-256color which is less what libvterm understands -- civis/cnorm local function hide_cursor() diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 94690524d3..d4628ea626 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -4,33 +4,38 @@ -- "bracketed paste" terminal feature: -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local feed_data = thelpers.feed_data -local clear = helpers.clear -local command = helpers.command -local dedent = helpers.dedent -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local testprg = helpers.testprg -local retry = helpers.retry -local nvim_prog = helpers.nvim_prog -local nvim_set = helpers.nvim_set -local ok = helpers.ok -local read_file = helpers.read_file -local fn = helpers.fn -local api = helpers.api -local is_ci = helpers.is_ci -local is_os = helpers.is_os -local new_pipename = helpers.new_pipename -local spawn_argv = helpers.spawn_argv -local set_session = helpers.set_session -local write_file = helpers.write_file -local eval = helpers.eval - -if helpers.skip(is_os('win')) then +local tt = require('test.functional.terminal.testutil') + +local eq = t.eq +local feed_data = tt.feed_data +local clear = n.clear +local command = n.command +local dedent = t.dedent +local exec = n.exec +local exec_lua = n.exec_lua +local testprg = n.testprg +local retry = t.retry +local nvim_prog = n.nvim_prog +local nvim_set = n.nvim_set +local ok = t.ok +local read_file = t.read_file +local fn = n.fn +local api = n.api +local is_ci = t.is_ci +local is_os = t.is_os +local new_pipename = n.new_pipename +local spawn_argv = n.spawn_argv +local set_session = n.set_session +local write_file = t.write_file +local eval = n.eval +local assert_log = t.assert_log + +local testlog = 'Xtest-tui-log' + +if t.skip(is_os('win')) then return end @@ -42,7 +47,7 @@ describe('TUI', function() before_each(function() clear() local child_server = new_pipename() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '--listen', child_server, '-u', @@ -61,8 +66,8 @@ describe('TUI', function() | {3:-- TERMINAL --} | ]]) - child_session = helpers.connect(child_server) - child_exec_lua = thelpers.make_lua_executor(child_session) + child_session = n.connect(child_server) + child_exec_lua = tt.make_lua_executor(child_session) end) -- Wait for mode in the child Nvim (avoid "typeahead race" #10826). @@ -83,7 +88,6 @@ describe('TUI', function() end it('rapid resize #7572 #7628', function() - helpers.skip(helpers.is_asan(), 'Test extra unstable with ASAN. See #23762') -- Need buffer rows to provoke the behavior. feed_data(':edit test/functional/fixtures/bigfile.txt\n') screen:expect([[ @@ -1345,15 +1349,15 @@ describe('TUI', function() it('paste: big burst of input', function() feed_data(':set ruler\n') - local t = {} + local q = {} for i = 1, 3000 do - t[i] = 'item ' .. tostring(i) + q[i] = 'item ' .. tostring(i) end feed_data('i') wait_for_mode('i') -- "bracketed paste" - feed_data('\027[200~' .. table.concat(t, '\n') .. '\027[201~') - expect_child_buf_lines(t) + feed_data('\027[200~' .. table.concat(q, '\n') .. '\027[201~') + expect_child_buf_lines(q) feed_data(' end') screen:expect([[ item 2997 | @@ -1486,7 +1490,8 @@ describe('TUI', function() feed_data('\027[201~') -- phase 3 screen:expect_unchanged() local _, rv = child_session:request('nvim_exec_lua', [[return _G.paste_phases]], {}) - eq({ 1, 2, 3 }, rv) + -- In rare cases there may be multiple chunks of phase 2 because of timing. + eq({ 1, 2, 3 }, { rv[1], rv[2], rv[#rv] }) end) it('allows termguicolors to be set at runtime', function() @@ -1588,6 +1593,35 @@ describe('TUI', function() } end) + -- Note: libvterm doesn't support colored underline or undercurl. + it('supports undercurl and underdouble when run in :terminal', function() + screen:set_default_attr_ids({ + [1] = { reverse = true }, + [2] = { bold = true, reverse = true }, + [3] = { bold = true }, + [4] = { foreground = 12 }, + [5] = { undercurl = true }, + [6] = { underdouble = true }, + }) + child_session:request('nvim_set_hl', 0, 'Visual', { undercurl = true }) + feed_data('ifoobar\027V') + screen:expect([[ + {5:fooba}{1:r} | + {4:~ }|*3 + {2:[No Name] [+] }| + {3:-- VISUAL LINE --} | + {3:-- TERMINAL --} | + ]]) + child_session:request('nvim_set_hl', 0, 'Visual', { underdouble = true }) + screen:expect([[ + {6:fooba}{1:r} | + {4:~ }|*3 + {2:[No Name] [+] }| + {3:-- VISUAL LINE --} | + {3:-- TERMINAL --} | + ]]) + end) + it('in nvim_list_uis()', function() -- $TERM in :terminal. local exp_term = is_os('bsd') and 'builtin_xterm' or 'xterm-256color' @@ -1618,7 +1652,7 @@ describe('TUI', function() eq(expected, rv) end) - it('allows grid to assume wider ambiguous-width characters than host terminal #19686', function() + it('allows grid to assume wider ambiwidth chars than host terminal', function() child_session:request( 'nvim_buf_set_lines', 0, @@ -1662,8 +1696,52 @@ describe('TUI', function() screen:expect(singlewidth_screen) end) + it('allows grid to assume wider non-ambiwidth chars than host terminal', function() + child_session:request( + 'nvim_buf_set_lines', + 0, + 0, + -1, + true, + { ('✓'):rep(60), ('✓'):rep(60) } + ) + child_session:request('nvim_set_option_value', 'cursorline', true, {}) + child_session:request('nvim_set_option_value', 'list', true, {}) + child_session:request('nvim_set_option_value', 'listchars', 'eol:$', { win = 0 }) + feed_data('gg') + local singlewidth_screen = [[ + {13:✓}{12:✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓}| + {12:✓✓✓✓✓✓✓✓✓✓}{15:$}{12: }| + ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓| + ✓✓✓✓✓✓✓✓✓✓{4:$} | + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]] + -- When grid assumes "✓" to be double-width but host terminal assumes it to be single-width, + -- the second cell of "✓" is a space and the attributes of the "✓" are applied to it. + local doublewidth_screen = [[ + {13:✓}{12: ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }| + {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }| + {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }{15:$}{12: }| + ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ {4:@@@@}| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]] + screen:expect(singlewidth_screen) + child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {}) + screen:expect_unchanged() + child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 2 } } }) + screen:expect(doublewidth_screen) + child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {}) + screen:expect_unchanged() + child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 1 } } }) + screen:expect(singlewidth_screen) + end) + it('draws correctly when cursor_address overflows #21643', function() - helpers.skip(is_os('mac'), 'FIXME: crashes/errors on macOS') + t.skip(is_os('mac'), 'FIXME: crashes/errors on macOS') screen:try_resize(77, 855) retry(nil, nil, function() eq({ true, 852 }, { child_session:request('nvim_win_get_height', 0) }) @@ -1925,6 +2003,39 @@ describe('TUI', function() ]]) end) + it('invalidated regions are cleared with terminal background attr', function() + local screen = Screen.new(50, 10) + screen:set_default_attr_ids({ [1] = { foreground = Screen.colors.Black } }) + screen:attach() + fn.termopen({ + nvim_prog, + '--clean', + '--cmd', + 'set termguicolors', + '--cmd', + 'sleep 10', + }, { + env = { + VIMRUNTIME = os.getenv('VIMRUNTIME'), + }, + }) + screen:expect({ + grid = [[ + {1:^ }| + {1: }|*8 + | + ]], + }) + screen:try_resize(51, 11) + screen:expect({ + grid = [[ + {1:^ }| + {1: }|*9 + | + ]], + }) + end) + it('argv[0] can be overridden #23953', function() if not exec_lua('return pcall(require, "ffi")') then pending('missing LuaJIT FFI') @@ -1941,7 +2052,7 @@ describe('TUI', function() finally(function() os.remove(script_file) end) - local screen = thelpers.setup_child_nvim({ '--clean', '-l', script_file }) + local screen = tt.setup_child_nvim({ '--clean', '-l', script_file }) screen:expect { grid = [[ {1: } | @@ -1969,7 +2080,7 @@ describe('TUI', function() finally(function() os.remove('testF') end) - local screen = thelpers.screen_setup( + local screen = tt.screen_setup( 0, ('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format( nvim_prog @@ -1990,7 +2101,7 @@ describe('TUI', function() end) it('<C-h> #10134', function() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2023,7 +2134,7 @@ describe('TUI', function() end) it('draws line with many trailing spaces correctly #24955', function() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2062,7 +2173,7 @@ describe('TUI', function() it('no heap-buffer-overflow when changing &columns', function() -- Set a different bg colour and change $TERM to something dumber so the `print_spaces()` -- codepath in `clear_region()` is hit. - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2105,7 +2216,7 @@ end) describe('TUI UIEnter/UILeave', function() it('fires exactly once, after VimEnter', function() clear() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2152,7 +2263,7 @@ describe('TUI FocusGained/FocusLost', function() before_each(function() clear() local child_server = new_pipename() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '--listen', child_server, '-u', @@ -2172,7 +2283,7 @@ describe('TUI FocusGained/FocusLost', function() | {3:-- TERMINAL --} | ]]) - child_session = helpers.connect(child_server) + child_session = n.connect(child_server) child_session:request( 'nvim_exec2', [[ @@ -2364,14 +2475,14 @@ describe('TUI FocusGained/FocusLost', function() end) end) --- These tests require `thelpers` because --headless/--embed +-- These tests require `tt` because --headless/--embed -- does not initialize the TUI. describe("TUI 't_Co' (terminal colors)", function() local screen local function assert_term_colors(term, colorterm, maxcolors) clear({ env = { TERM = term }, args = {} }) - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2647,14 +2758,14 @@ describe("TUI 't_Co' (terminal colors)", function() end) end) --- These tests require `thelpers` because --headless/--embed +-- These tests require `tt` because --headless/--embed -- does not initialize the TUI. describe("TUI 'term' option", function() local screen local function assert_term(term_envvar, term_expected) clear() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2702,7 +2813,7 @@ describe("TUI 'term' option", function() end) end) --- These tests require `thelpers` because --headless/--embed +-- These tests require `tt` because --headless/--embed -- does not initialize the TUI. describe('TUI', function() local screen @@ -2714,7 +2825,7 @@ describe('TUI', function() -- Runs (child) `nvim` in a TTY (:terminal), to start the builtin TUI. local function nvim_tui(extra_args) clear() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2795,7 +2906,7 @@ describe('TUI', function() ]]) local child_server = new_pipename() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '--listen', child_server, '-u', @@ -2815,7 +2926,7 @@ describe('TUI', function() screen:expect({ any = '%[No Name%]' }) - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) retry(nil, 1000, function() eq({ Tc = true, @@ -2845,7 +2956,7 @@ describe('TUI', function() ]]) local child_server = new_pipename() - screen = thelpers.setup_child_nvim({ + screen = tt.setup_child_nvim({ '--listen', child_server, -- Use --clean instead of -u NONE to load the osc52 plugin @@ -2861,7 +2972,7 @@ describe('TUI', function() screen:expect({ any = '%[No Name%]' }) - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) retry(nil, 1000, function() eq('Ms', eval("get(g:, 'xtgettcap', '')")) eq({ true, 'OSC 52' }, { child_session:request('nvim_eval', 'g:clipboard.name') }) @@ -2876,7 +2987,7 @@ describe('TUI bg color', function() command('highlight clear Normal') command('set background=dark') -- set outer Nvim background local child_server = new_pipename() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '--listen', child_server, '-u', @@ -2889,7 +3000,7 @@ describe('TUI bg color', function() 'set noswapfile', }) screen:expect({ any = '%[No Name%]' }) - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) retry(nil, nil, function() eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') }) end) @@ -2899,7 +3010,7 @@ describe('TUI bg color', function() command('highlight clear Normal') command('set background=light') -- set outer Nvim background local child_server = new_pipename() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '--listen', child_server, '-u', @@ -2912,7 +3023,7 @@ describe('TUI bg color', function() 'set noswapfile', }) screen:expect({ any = '%[No Name%]' }) - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) retry(nil, nil, function() eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') }) end) @@ -2930,7 +3041,7 @@ describe('TUI bg color', function() end, }) ]]) - thelpers.setup_child_nvim({ + tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2946,7 +3057,7 @@ describe('TUI bg color', function() end) it('triggers OptionSet from automatic background processing', function() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -2968,16 +3079,20 @@ describe('TUI bg color', function() end) end) --- These tests require `thelpers` because --headless/--embed +-- These tests require `tt` because --headless/--embed -- does not initialize the TUI. describe('TUI as a client', function() + after_each(function() + os.remove(testlog) + end) + it('connects to remote instance (with its own TUI)', function() local server_super = spawn_argv(false) -- equivalent to clear() local client_super = spawn_argv(true) set_session(server_super) local server_pipe = new_pipename() - local screen_server = thelpers.setup_child_nvim({ + local screen_server = tt.setup_child_nvim({ '--listen', server_pipe, '-u', @@ -3012,7 +3127,7 @@ describe('TUI as a client', function() } set_session(client_super) - local screen_client = thelpers.setup_child_nvim({ + local screen_client = tt.setup_child_nvim({ '--server', server_pipe, '--remote-ui', @@ -3048,7 +3163,7 @@ describe('TUI as a client', function() it('connects to remote instance (--headless)', function() local server = spawn_argv(false) -- equivalent to clear() - local client_super = spawn_argv(true) + local client_super = spawn_argv(true, { env = { NVIM_LOG_FILE = testlog } }) set_session(server) local server_pipe = api.nvim_get_vvar('servername') @@ -3056,7 +3171,7 @@ describe('TUI as a client', function() server:request('nvim_command', 'set notermguicolors') set_session(client_super) - local screen_client = thelpers.setup_child_nvim({ + local screen_client = tt.setup_child_nvim({ '--server', server_pipe, '--remote-ui', @@ -3091,11 +3206,14 @@ describe('TUI as a client', function() client_super:close() server:close() + if is_os('mac') then + assert_log('uv_tty_set_mode failed: Unknown system error %-102', testlog) + end end) it('throws error when no server exists', function() clear() - local screen = thelpers.setup_child_nvim({ + local screen = tt.setup_child_nvim({ '--server', '127.0.0.1:2436546', '--remote-ui', @@ -3116,7 +3234,7 @@ describe('TUI as a client', function() set_session(server_super) local server_pipe = new_pipename() - local screen_server = thelpers.setup_child_nvim({ + local screen_server = tt.setup_child_nvim({ '--listen', server_pipe, '-u', @@ -3160,7 +3278,7 @@ describe('TUI as a client', function() } set_session(client_super) - local screen_client = thelpers.setup_child_nvim({ + local screen_client = tt.setup_child_nvim({ '--server', server_pipe, '--remote-ui', diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index 3781933cad..f85e26a66d 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -1,21 +1,23 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local feed_data = thelpers.feed_data -local feed, clear = helpers.feed, helpers.clear -local poke_eventloop = helpers.poke_eventloop -local command = helpers.command -local retry = helpers.retry -local eq = helpers.eq -local eval = helpers.eval -local skip = helpers.skip -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local tt = require('test.functional.terminal.testutil') +local feed_data = tt.feed_data +local feed, clear = n.feed, n.clear +local poke_eventloop = n.poke_eventloop +local command = n.command +local retry = t.retry +local eq = t.eq +local eval = n.eval +local skip = t.skip +local is_os = t.is_os describe(':terminal window', function() local screen before_each(function() clear() - screen = thelpers.screen_setup() + screen = tt.screen_setup() end) it('sets topline correctly #8556', function() @@ -35,6 +37,7 @@ describe(':terminal window', function() describe("with 'number'", function() it('wraps text', function() + skip(is_os('win')) -- todo(clason): unskip when reenabling reflow feed([[<C-\><C-N>]]) feed([[:set numberwidth=1 number<CR>i]]) screen:expect([[ @@ -64,7 +67,7 @@ describe(':terminal window', function() {7: 1 }tty ready | {7: 2 }rows: 6, cols: 48 | {7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO| - {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 | + {7: 4 }WXYZrows: 6, cols: 41 | {7: 5 }{1: } | {7: 6 } | {3:-- TERMINAL --} | @@ -74,7 +77,7 @@ describe(':terminal window', function() {7: 1 }tty ready | {7: 2 }rows: 6, cols: 48 | {7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO| - {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 | + {7: 4 }WXYZrows: 6, cols: 41 | {7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN| {7: 6 }OPQRSTUVWXYZ{1: } | {3:-- TERMINAL --} | @@ -84,6 +87,7 @@ describe(':terminal window', function() describe("with 'statuscolumn'", function() it('wraps text', function() + skip(is_os('win')) -- todo(clason): unskip when reenabling reflow command([[set number statuscolumn=++%l\ \ ]]) screen:expect([[ {7:++1 }tty ready | @@ -108,9 +112,9 @@ describe(':terminal window', function() screen:expect([[ {7:++7 } | {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR| - {7:++9 }STUVWXYZ | + {7:++9 }TUVWXYZ | {7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR| - {7:++11 }STUVWXYZrows: 6, cols: 44 | + {7:++11 }TUVWXYZrows: 6, cols: 44 | {7:++12 }{1: } | {3:-- TERMINAL --} | ]]) @@ -174,7 +178,7 @@ describe(':terminal with multigrid', function() before_each(function() clear() - screen = thelpers.screen_setup(0, nil, 50, nil, { ext_multigrid = true }) + screen = tt.screen_setup(0, nil, 50, nil, { ext_multigrid = true }) end) it('resizes to requested size', function() diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua index 17411e2724..04d2e0bca7 100644 --- a/test/functional/terminal/window_split_tab_spec.lua +++ b/test/functional/terminal/window_split_tab_spec.lua @@ -1,16 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) -local thelpers = require('test.functional.terminal.helpers') -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local feed = helpers.feed -local feed_command = helpers.feed_command -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local tt = require('test.functional.terminal.testutil') +local assert_alive = n.assert_alive +local clear = n.clear +local feed = n.feed +local feed_command = n.feed_command +local command = n.command +local eq = t.eq +local eval = n.eval +local api = n.api local sleep = vim.uv.sleep -local retry = helpers.retry -local is_os = helpers.is_os +local retry = t.retry +local is_os = t.is_os describe(':terminal', function() local screen @@ -23,7 +25,7 @@ describe(':terminal', function() command('highlight StatusLine cterm=NONE') command('highlight StatusLineNC cterm=NONE') command('highlight VertSplit cterm=NONE') - screen = thelpers.screen_setup(3) + screen = tt.screen_setup(3) end) after_each(function() diff --git a/test/functional/helpers.lua b/test/functional/testnvim.lua index d1d26919a0..6b858e4d69 100644 --- a/test/functional/helpers.lua +++ b/test/functional/testnvim.lua @@ -1,32 +1,33 @@ local uv = vim.uv -local global_helpers = require('test.helpers') +local t = require('test.testutil') local Session = require('test.client.session') local uv_stream = require('test.client.uv_stream') local SocketStream = uv_stream.SocketStream local ChildProcessStream = uv_stream.ChildProcessStream -local check_cores = global_helpers.check_cores -local check_logs = global_helpers.check_logs -local dedent = global_helpers.dedent -local eq = global_helpers.eq -local is_os = global_helpers.is_os -local ok = global_helpers.ok +local check_cores = t.check_cores +local check_logs = t.check_logs +local dedent = t.dedent +local eq = t.eq +local is_os = t.is_os +local ok = t.ok local sleep = uv.sleep -local fail = global_helpers.fail -local module = {} +--- This module uses functions from the context of the test session, i.e. in the context of the +--- nvim being tests. +local M = {} local runtime_set = 'set runtimepath^=./build/lib/nvim/' -module.nvim_prog = (os.getenv('NVIM_PRG') or global_helpers.paths.test_build_dir .. '/bin/nvim') +M.nvim_prog = (os.getenv('NVIM_PRG') or t.paths.test_build_dir .. '/bin/nvim') -- Default settings for the test session. -module.nvim_set = ( +M.nvim_set = ( 'set shortmess+=IS background=light termguicolors noswapfile noautoindent startofline' .. ' laststatus=1 undodir=. directory=. viewdir=. backupdir=.' .. ' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid' ) -module.nvim_argv = { - module.nvim_prog, +M.nvim_argv = { + M.nvim_prog, '-u', 'NONE', '-i', @@ -35,10 +36,10 @@ module.nvim_argv = { '--cmd', runtime_set, '--cmd', - module.nvim_set, - -- Remove default mappings. + M.nvim_set, + -- Remove default user commands and mappings. '--cmd', - 'mapclear | mapclear!', + 'comclear | mapclear | mapclear!', -- Make screentest work after changing to the new default color scheme -- Source 'vim' color scheme without side effects -- TODO: rewrite tests @@ -50,9 +51,9 @@ module.nvim_argv = { } -- Directory containing nvim. -module.nvim_dir = module.nvim_prog:gsub('[/\\][^/\\]+$', '') -if module.nvim_dir == module.nvim_prog then - module.nvim_dir = '.' +M.nvim_dir = M.nvim_prog:gsub('[/\\][^/\\]+$', '') +if M.nvim_dir == M.nvim_prog then + M.nvim_dir = '.' end local prepend_argv --- @type string[]? @@ -84,11 +85,11 @@ if prepend_argv then for i = 1, len do new_nvim_argv[i] = prepend_argv[i] end - for i = 1, #module.nvim_argv do - new_nvim_argv[i + len] = module.nvim_argv[i] + for i = 1, #M.nvim_argv do + new_nvim_argv[i + len] = M.nvim_argv[i] end - module.nvim_argv = new_nvim_argv - module.prepend_argv = prepend_argv + M.nvim_argv = new_nvim_argv + M.prepend_argv = prepend_argv end local session --- @type test.Session? @@ -103,19 +104,19 @@ if not is_os('win') then end) end -function module.get_session() +function M.get_session() return session end -function module.set_session(s) +function M.set_session(s) session = s end --- @param method string --- @param ... any --- @return any -function module.request(method, ...) - assert(session) +function M.request(method, ...) + assert(session, 'no Nvim session') local status, rv = session:request(method, ...) if not status then if loop_running then @@ -132,21 +133,21 @@ end --- @param method string --- @param ... any --- @return any -function module.request_lua(method, ...) - return module.exec_lua([[return vim.api[...](select(2, ...))]], method, ...) +function M.request_lua(method, ...) + return M.exec_lua([[return vim.api[...](select(2, ...))]], method, ...) end --- @param timeout? integer --- @return string? -function module.next_msg(timeout) +function M.next_msg(timeout) assert(session) return session:next_message(timeout or 10000) end -function module.expect_twostreams(msgs1, msgs2) +function M.expect_twostreams(msgs1, msgs2) local pos1, pos2 = 1, 1 while pos1 <= #msgs1 or pos2 <= #msgs2 do - local msg = module.next_msg() + local msg = M.next_msg() if pos1 <= #msgs1 and pcall(eq, msgs1[pos1], msg) then pos1 = pos1 + 1 elseif pos2 <= #msgs2 then @@ -169,7 +170,7 @@ end -- -- ignore: List of ignored event names. -- seqs: List of one or more potential event sequences. -function module.expect_msg_seq(...) +function M.expect_msg_seq(...) if select('#', ...) < 1 then error('need at least 1 argument') end @@ -196,12 +197,12 @@ function module.expect_msg_seq(...) end return string.format('%s\n%s\n%s', err1, string.rep('=', 78), err2) end - local msg_timeout = module.load_adjust(10000) -- Big timeout for ASAN/valgrind. + local msg_timeout = M.load_adjust(10000) -- Big timeout for ASAN/valgrind. for anum = 1, #seqs do local expected_seq = seqs[anum] -- Collect enough messages to compare the next expected sequence. while #actual_seq < #expected_seq do - local msg = module.next_msg(msg_timeout) + local msg = M.next_msg(msg_timeout) local msg_type = msg and msg[2] or nil if msg == nil then error( @@ -246,7 +247,7 @@ local function call_and_stop_on_error(lsession, ...) return result end -function module.set_method_error(err) +function M.set_method_error(err) method_error = err end @@ -256,7 +257,7 @@ end --- @param setup_cb function? --- @param timeout integer --- @return {[1]: integer, [2]: string} -function module.run_session(lsession, request_cb, notification_cb, setup_cb, timeout) +function M.run_session(lsession, request_cb, notification_cb, setup_cb, timeout) local on_request --- @type function? local on_notification --- @type function? local on_setup --- @type function? @@ -296,35 +297,35 @@ function module.run_session(lsession, request_cb, notification_cb, setup_cb, tim return lsession.eof_err end -function module.run(request_cb, notification_cb, setup_cb, timeout) +function M.run(request_cb, notification_cb, setup_cb, timeout) assert(session) - return module.run_session(session, request_cb, notification_cb, setup_cb, timeout) + return M.run_session(session, request_cb, notification_cb, setup_cb, timeout) end -function module.stop() +function M.stop() assert(session):stop() end -function module.nvim_prog_abs() +function M.nvim_prog_abs() -- system(['build/bin/nvim']) does not work for whatever reason. It must -- be executable searched in $PATH or something starting with / or ./. - if module.nvim_prog:match('[/\\]') then - return module.request('nvim_call_function', 'fnamemodify', { module.nvim_prog, ':p' }) + if M.nvim_prog:match('[/\\]') then + return M.request('nvim_call_function', 'fnamemodify', { M.nvim_prog, ':p' }) else - return module.nvim_prog + return M.nvim_prog end end -- Use for commands which expect nvim to quit. -- The first argument can also be a timeout. -function module.expect_exit(fn_or_timeout, ...) +function M.expect_exit(fn_or_timeout, ...) local eof_err_msg = 'EOF was received from Nvim. Likely the Nvim process crashed.' if type(fn_or_timeout) == 'function' then - eq(eof_err_msg, module.pcall_err(fn_or_timeout, ...)) + eq(eof_err_msg, t.pcall_err(fn_or_timeout, ...)) else eq( eof_err_msg, - module.pcall_err(function(timeout, fn, ...) + t.pcall_err(function(timeout, fn, ...) fn(...) assert(session) while session:next_message(timeout) do @@ -342,8 +343,8 @@ end --- @param name string --- @param ... any --- @return any -function module.call_lua(name, ...) - return module.exec_lua([[return vim.call(...)]], name, ...) +function M.call_lua(name, ...) + return M.exec_lua([[return vim.call(...)]], name, ...) end --- Sends user input to Nvim. @@ -351,9 +352,9 @@ end --- @param input string local function nvim_feed(input) while #input > 0 do - local written = module.request('nvim_input', input) + local written = M.request('nvim_input', input) if written == nil then - module.assert_alive() + M.assert_alive() error('crash? (nvim_input returned nil)') end input = input:sub(written + 1) @@ -361,14 +362,7 @@ local function nvim_feed(input) end --- @param ... string -function module.feed(...) - for _, v in ipairs({ ... }) do - nvim_feed(dedent(v)) - end -end - ---- @param ... string -function module.rawfeed(...) +function M.feed(...) for _, v in ipairs({ ... }) do nvim_feed(dedent(v)) end @@ -376,7 +370,7 @@ end ---@param ... string[]? ---@return string[] -function module.merge_args(...) +function M.merge_args(...) local i = 1 local argv = {} --- @type string[] for anum = 1, select('#', ...) do @@ -438,7 +432,7 @@ local function remove_args(args, args_rm) return new_args end -function module.check_close() +function M.check_close() if not session then return end @@ -465,18 +459,18 @@ end --- @param keep boolean --- @param io_extra uv.uv_pipe_t? used for stdin_fd, see :help ui-option --- @return test.Session -function module.spawn(argv, merge, env, keep, io_extra) +function M.spawn(argv, merge, env, keep, io_extra) if not keep then - module.check_close() + M.check_close() end local child_stream = - ChildProcessStream.spawn(merge and module.merge_args(prepend_argv, argv) or argv, env, io_extra) + ChildProcessStream.spawn(merge and M.merge_args(prepend_argv, argv) or argv, env, io_extra) return Session.new(child_stream) end -- Creates a new Session connected by domain socket (named pipe) or TCP. -function module.connect(file_or_address) +function M.connect(file_or_address) local addr, port = string.match(file_or_address, '(.*):(%d+)') local stream = (addr and port) and SocketStream.connect(addr, port) or SocketStream.open(file_or_address) @@ -495,17 +489,17 @@ end -- Example: -- clear('-e') -- clear{args={'-e'}, args_rm={'-i'}, env={TERM=term}} -function module.clear(...) - module.set_session(module.spawn_argv(false, ...)) - return module.get_session() +function M.clear(...) + M.set_session(M.spawn_argv(false, ...)) + return M.get_session() end --- same params as clear, but does returns the session instead --- of replacing the default session --- @return test.Session -function module.spawn_argv(keep, ...) - local argv, env, io_extra = module.new_argv(...) - return module.spawn(argv, nil, env, keep, io_extra) +function M.spawn_argv(keep, ...) + local argv, env, io_extra = M.new_argv(...) + return M.spawn(argv, nil, env, keep, io_extra) end --- @class test.new_argv.Opts @@ -521,8 +515,8 @@ end --- @return string[] --- @return string[]? --- @return uv.uv_pipe_t? -function module.new_argv(...) - local args = { unpack(module.nvim_argv) } +function M.new_argv(...) + local args = { unpack(M.nvim_argv) } table.insert(args, '--headless') if _G._nvim_test_id then -- Set the server name to the test-id for logging. #8519 @@ -579,11 +573,11 @@ function module.new_argv(...) end --- @param ... string -function module.insert(...) +function M.insert(...) nvim_feed('i') for _, v in ipairs({ ... }) do local escaped = v:gsub('<', '<lt>') - module.rawfeed(escaped) + M.feed(escaped) end nvim_feed('<ESC>') end @@ -591,7 +585,7 @@ end --- Executes an ex-command by user input. Because nvim_input() is used, Vimscript --- errors will not manifest as client (lua) errors. Use command() for that. --- @param ... string -function module.feed_command(...) +function M.feed_command(...) for _, v in ipairs({ ... }) do if v:sub(1, 1) ~= '/' then -- not a search command, prefix with colon @@ -603,12 +597,12 @@ function module.feed_command(...) end -- @deprecated use nvim_exec2() -function module.source(code) - module.exec(dedent(code)) +function M.source(code) + M.exec(dedent(code)) end -function module.has_powershell() - return module.eval('executable("' .. (is_os('win') and 'powershell' or 'pwsh') .. '")') == 1 +function M.has_powershell() + return M.eval('executable("' .. (is_os('win') and 'powershell' or 'pwsh') .. '")') == 1 end --- Sets Nvim shell to powershell. @@ -616,12 +610,12 @@ end --- @param fake (boolean) If true, a fake will be used if powershell is not --- found on the system. --- @returns true if powershell was found on the system, else false. -function module.set_shell_powershell(fake) - local found = module.has_powershell() +function M.set_shell_powershell(fake) + local found = M.has_powershell() if not fake then assert(found) end - local shell = found and (is_os('win') and 'powershell' or 'pwsh') or module.testprg('pwsh-test') + local shell = found and (is_os('win') and 'powershell' or 'pwsh') or M.testprg('pwsh-test') local cmd = 'Remove-Item -Force ' .. table.concat( is_os('win') and { 'alias:cat', 'alias:echo', 'alias:sleep', 'alias:sort', 'alias:tee' } @@ -629,7 +623,7 @@ function module.set_shell_powershell(fake) ',' ) .. ';' - module.exec([[ + M.exec([[ let &shell = ']] .. shell .. [[' set shellquote= shellxquote= let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command ' @@ -644,7 +638,7 @@ end ---@param func function ---@return table<string,function> -function module.create_callindex(func) +function M.create_callindex(func) return setmetatable({}, { --- @param tbl table<any,function> --- @param arg1 string @@ -661,7 +655,7 @@ end --- @param method string --- @param ... any -function module.nvim_async(method, ...) +function M.nvim_async(method, ...) assert(session):notify(method, ...) end @@ -670,27 +664,27 @@ end --- @param name string --- @param ... any --- @return any -function module.call(name, ...) - return module.request('nvim_call_function', name, { ... }) +function M.call(name, ...) + return M.request('nvim_call_function', name, { ... }) end -module.async_meths = module.create_callindex(module.nvim_async) +M.async_meths = M.create_callindex(M.nvim_async) -module.rpc = { - fn = module.create_callindex(module.call), - api = module.create_callindex(module.request), +M.rpc = { + fn = M.create_callindex(M.call), + api = M.create_callindex(M.request), } -module.lua = { - fn = module.create_callindex(module.call_lua), - api = module.create_callindex(module.request_lua), +M.lua = { + fn = M.create_callindex(M.call_lua), + api = M.create_callindex(M.request_lua), } -module.describe_lua_and_rpc = function(describe) +M.describe_lua_and_rpc = function(describe) return function(what, tests) local function d(flavour) describe(string.format('%s (%s)', what, flavour), function(...) - return tests(module[flavour].api, ...) + return tests(M[flavour].api, ...) end) end @@ -700,85 +694,64 @@ module.describe_lua_and_rpc = function(describe) end --- add for typing. The for loop after will overwrite this -module.api = vim.api -module.fn = vim.fn +M.api = vim.api +M.fn = vim.fn -for name, fns in pairs(module.rpc) do +for name, fns in pairs(M.rpc) do --- @diagnostic disable-next-line:no-unknown - module[name] = fns + M[name] = fns end -- Executes an ex-command. Vimscript errors manifest as client (lua) errors, but -- v:errmsg will not be updated. -module.command = module.api.nvim_command +M.command = M.api.nvim_command -- Evaluates a Vimscript expression. -- Fails on Vimscript error, but does not update v:errmsg. -module.eval = module.api.nvim_eval +M.eval = M.api.nvim_eval -function module.poke_eventloop() +function M.poke_eventloop() -- Execute 'nvim_eval' (a deferred function) to -- force at least one main_loop iteration - module.api.nvim_eval('1') + M.api.nvim_eval('1') end -function module.buf_lines(bufnr) - return module.exec_lua('return vim.api.nvim_buf_get_lines((...), 0, -1, false)', bufnr) +function M.buf_lines(bufnr) + return M.exec_lua('return vim.api.nvim_buf_get_lines((...), 0, -1, false)', bufnr) end ---@see buf_lines() -function module.curbuf_contents() - module.poke_eventloop() -- Before inspecting the buffer, do whatever. - return table.concat(module.api.nvim_buf_get_lines(0, 0, -1, true), '\n') +function M.curbuf_contents() + M.poke_eventloop() -- Before inspecting the buffer, do whatever. + return table.concat(M.api.nvim_buf_get_lines(0, 0, -1, true), '\n') end -function module.expect(contents) - return eq(dedent(contents), module.curbuf_contents()) +function M.expect(contents) + return eq(dedent(contents), M.curbuf_contents()) end -function module.expect_any(contents) +function M.expect_any(contents) contents = dedent(contents) - return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true)) -end - ---- @param expected any[] ---- @param received any[] ---- @param kind string ---- @return any -function module.expect_events(expected, received, kind) - if not pcall(eq, expected, received) then - local msg = 'unexpected ' .. kind .. ' received.\n\n' - - msg = msg .. 'received events:\n' - for _, e in ipairs(received) do - msg = msg .. ' ' .. vim.inspect(e) .. ';\n' - end - msg = msg .. '\nexpected events:\n' - for _, e in ipairs(expected) do - msg = msg .. ' ' .. vim.inspect(e) .. ';\n' - end - fail(msg) - end - return received + return ok(nil ~= string.find(M.curbuf_contents(), contents, 1, true)) end -- Checks that the Nvim session did not terminate. -function module.assert_alive() - assert(2 == module.eval('1+1'), 'crash? request failed') +function M.assert_alive() + assert(2 == M.eval('1+1'), 'crash? request failed') end -- Asserts that buffer is loaded and visible in the current tabpage. -function module.assert_visible(bufnr, visible) +function M.assert_visible(bufnr, visible) assert(type(visible) == 'boolean') - eq(visible, module.api.nvim_buf_is_loaded(bufnr)) + eq(visible, M.api.nvim_buf_is_loaded(bufnr)) if visible then assert( - -1 ~= module.fn.bufwinnr(bufnr), + -1 ~= M.fn.bufwinnr(bufnr), 'expected buffer to be visible in current tabpage: ' .. tostring(bufnr) ) else assert( - -1 == module.fn.bufwinnr(bufnr), + -1 == M.fn.bufwinnr(bufnr), 'expected buffer NOT visible in current tabpage: ' .. tostring(bufnr) ) end @@ -796,7 +769,7 @@ local function do_rmdir(path) for file in vim.fs.dir(path) do if file ~= '.' and file ~= '..' then local abspath = path .. '/' .. file - if global_helpers.isdir(abspath) then + if t.isdir(abspath) then do_rmdir(abspath) -- recurse else local ret, err = os.remove(abspath) @@ -806,7 +779,7 @@ local function do_rmdir(path) else -- Try Nvim delete(): it handles `readonly` attribute on Windows, -- and avoids Lua cross-version/platform incompatibilities. - if -1 == module.call('delete', abspath) then + if -1 == M.call('delete', abspath) then local hint = (is_os('win') and ' (hint: try :%bwipeout! before rmdir())' or '') error('delete() failed' .. hint .. ': ' .. abspath) end @@ -823,12 +796,12 @@ end local start_dir = uv.cwd() -function module.rmdir(path) +function M.rmdir(path) local ret, _ = pcall(do_rmdir, path) if not ret and is_os('win') then -- Maybe "Permission denied"; try again after changing the nvim -- process to the top-level directory. - module.command([[exe 'cd '.fnameescape(']] .. start_dir .. "')") + M.command([[exe 'cd '.fnameescape(']] .. start_dir .. "')") ret, _ = pcall(do_rmdir, path) end -- During teardown, the nvim process may not exit quickly enough, then rmdir() @@ -839,94 +812,65 @@ function module.rmdir(path) end end -function module.exc_exec(cmd) - module.command(([[ +function M.exc_exec(cmd) + M.command(([[ try execute "%s" catch let g:__exception = v:exception endtry ]]):format(cmd:gsub('\n', '\\n'):gsub('[\\"]', '\\%0'))) - local ret = module.eval('get(g:, "__exception", 0)') - module.command('unlet! g:__exception') + local ret = M.eval('get(g:, "__exception", 0)') + M.command('unlet! g:__exception') return ret end ---- @param cond boolean ---- @param reason string ---- @return boolean -function module.skip(cond, reason) - if cond then - --- @type fun(reason: string) - local pending = getfenv(2).pending - pending(reason or 'FIXME') - return true - end - return false -end - --- Calls pending() and returns `true` if the system is too slow to --- run fragile or expensive tests. Else returns `false`. -function module.skip_fragile(pending_fn, cond) - if pending_fn == nil or type(pending_fn) ~= type(function() end) then - error('invalid pending_fn') - end - if cond then - pending_fn('skipped (test is fragile on this system)', function() end) - return true - elseif os.getenv('TEST_SKIP_FRAGILE') then - pending_fn('skipped (TEST_SKIP_FRAGILE)', function() end) - return true - end - return false -end - -function module.exec(code) - module.api.nvim_exec2(code, {}) +function M.exec(code) + M.api.nvim_exec2(code, {}) end --- @param code string --- @return string -function module.exec_capture(code) - return module.api.nvim_exec2(code, { output = true }).output +function M.exec_capture(code) + return M.api.nvim_exec2(code, { output = true }).output end --- @param code string --- @return any -function module.exec_lua(code, ...) - return module.api.nvim_exec_lua(code, { ... }) +function M.exec_lua(code, ...) + return M.api.nvim_exec_lua(code, { ... }) end -function module.get_pathsep() +function M.get_pathsep() return is_os('win') and '\\' or '/' end --- Gets the filesystem root dir, namely "/" or "C:/". -function module.pathroot() +function M.pathroot() local pathsep = package.config:sub(1, 1) - return is_os('win') and (module.nvim_dir:sub(1, 2) .. pathsep) or '/' + return is_os('win') and (M.nvim_dir:sub(1, 2) .. pathsep) or '/' end --- Gets the full `…/build/bin/{name}` path of a test program produced by --- `test/functional/fixtures/CMakeLists.txt`. --- --- @param name (string) Name of the test program. -function module.testprg(name) - local ext = module.is_os('win') and '.exe' or '' - return ('%s/%s%s'):format(module.nvim_dir, name, ext) +function M.testprg(name) + local ext = is_os('win') and '.exe' or '' + return ('%s/%s%s'):format(M.nvim_dir, name, ext) end -function module.is_asan() - local version = module.eval('execute("verbose version")') +function M.is_asan() + local version = M.eval('execute("verbose version")') return version:match('-fsanitize=[a-z,]*address') end -- Returns a valid, platform-independent Nvim listen address. -- Useful for communicating with child instances. -function module.new_pipename() +function M.new_pipename() -- HACK: Start a server temporarily, get the name, then stop it. - local pipename = module.eval('serverstart()') - module.fn.serverstop(pipename) + local pipename = M.eval('serverstart()') + M.fn.serverstop(pipename) -- Remove the pipe so that trying to connect to it without a server listening -- will be an error instead of a hang. os.remove(pipename) @@ -935,24 +879,24 @@ end --- @param provider string --- @return string|boolean? -function module.missing_provider(provider) +function M.missing_provider(provider) if provider == 'ruby' or provider == 'perl' then --- @type string? - local e = module.exec_lua("return {require('vim.provider." .. provider .. "').detect()}")[2] + local e = M.exec_lua("return {require('vim.provider." .. provider .. "').detect()}")[2] return e ~= '' and e or false elseif provider == 'node' then --- @type string? - local e = module.fn['provider#node#Detect']()[2] + local e = M.fn['provider#node#Detect']()[2] return e ~= '' and e or false elseif provider == 'python' then - return module.exec_lua([[return {require('vim.provider.python').detect_by_module('neovim')}]])[2] + return M.exec_lua([[return {require('vim.provider.python').detect_by_module('neovim')}]])[2] end assert(false, 'Unknown provider: ' .. provider) end --- @param obj string|table --- @return any -function module.alter_slashes(obj) +function M.alter_slashes(obj) if not is_os('win') then return obj end @@ -963,7 +907,7 @@ function module.alter_slashes(obj) --- @cast obj table<any,any> local ret = {} --- @type table<any,any> for k, v in pairs(obj) do - ret[k] = module.alter_slashes(v) + ret[k] = M.alter_slashes(v) end return ret end @@ -971,28 +915,28 @@ function module.alter_slashes(obj) end local load_factor = 1 -if global_helpers.is_ci() then +if t.is_ci() then -- Compute load factor only once (but outside of any tests). - module.clear() - module.request('nvim_command', 'source test/old/testdir/load.vim') - load_factor = module.request('nvim_eval', 'g:test_load_factor') + M.clear() + M.request('nvim_command', 'source test/old/testdir/load.vim') + load_factor = M.request('nvim_eval', 'g:test_load_factor') end --- @param num number --- @return number -function module.load_adjust(num) +function M.load_adjust(num) return math.ceil(num * load_factor) end --- @param ctx table<string,any> --- @return table -function module.parse_context(ctx) +function M.parse_context(ctx) local parsed = {} --- @type table<string,any> for _, item in ipairs({ 'regs', 'jumps', 'bufs', 'gvars' }) do --- @param v any parsed[item] = vim.tbl_filter(function(v) return type(v) == 'table' - end, module.call('msgpackparse', ctx[item])) + end, M.call('msgpackparse', ctx[item])) end parsed['bufs'] = parsed['bufs'][1] --- @param v any @@ -1004,15 +948,15 @@ function module.parse_context(ctx) end, parsed) end -function module.add_builddir_to_rtp() +function M.add_builddir_to_rtp() -- Add runtime from build dir for doc/tags (used with :help). - module.command(string.format([[set rtp+=%s/runtime]], module.paths.test_build_dir)) + M.command(string.format([[set rtp+=%s/runtime]], t.paths.test_build_dir)) end --- Kill (reap) a process by PID. --- @param pid string --- @return boolean? -function module.os_kill(pid) +function M.os_kill(pid) return os.execute( ( is_os('win') and 'taskkill /f /t /pid ' .. pid .. ' > nul' @@ -1024,15 +968,33 @@ end --- Create folder with non existing parents --- @param path string --- @return boolean? -function module.mkdir_p(path) +function M.mkdir_p(path) return os.execute((is_os('win') and 'mkdir ' .. path or 'mkdir -p ' .. path)) end ---- @class test.functional.helpers: test.helpers -module = vim.tbl_extend('error', module, global_helpers) +local testid = (function() + local id = 0 + return function() + id = id + 1 + return id + end +end)() + +return function() + local g = getfenv(2) + + --- @type function? + local before_each = g.before_each + --- @type function? + local after_each = g.after_each + + if before_each then + before_each(function() + local id = ('T%d'):format(testid()) + _G._nvim_test_id = id + end) + end ---- @return test.functional.helpers -return function(after_each) if after_each then after_each(function() check_logs() @@ -1047,5 +1009,5 @@ return function(after_each) end end) end - return module + return M end diff --git a/test/functional/treesitter/fold_spec.lua b/test/functional/treesitter/fold_spec.lua index 9428432f66..a7f278aa01 100644 --- a/test/functional/treesitter/fold_spec.lua +++ b/test/functional/treesitter/fold_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local insert = helpers.insert -local exec_lua = helpers.exec_lua -local command = helpers.command -local feed = helpers.feed -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local clear = n.clear +local eq = t.eq +local insert = n.insert +local exec_lua = n.exec_lua +local command = n.command +local feed = n.feed +local poke_eventloop = n.poke_eventloop + before_each(clear) describe('treesitter foldexpr', function() @@ -404,6 +406,28 @@ t3]]) }, get_fold_levels()) end) + it('handles quantified patterns', function() + insert([[ +import hello +import hello +import hello +import hello +import hello +import hello]]) + + exec_lua([[vim.treesitter.query.set('python', 'folds', '(import_statement)+ @fold')]]) + parse('python') + + eq({ + [1] = '>1', + [2] = '1', + [3] = '1', + [4] = '1', + [5] = '1', + [6] = '1', + }, get_fold_levels()) + end) + it('updates folds in all windows', function() local screen = Screen.new(60, 48) screen:attach() diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 2bf230fe69..69984b3233 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -1,13 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local insert = helpers.insert -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local command = helpers.command -local api = helpers.api -local eq = helpers.eq +local clear = n.clear +local insert = n.insert +local exec_lua = n.exec_lua +local feed = n.feed +local command = n.command +local api = n.api +local eq = t.eq before_each(clear) @@ -483,7 +484,7 @@ describe('treesitter highlighting (C)', function() exec_lua [[ vim.treesitter.language.register("c", "foo") local parser = vim.treesitter.get_parser(0, "c", { - injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "fOO")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "fOO"))'} + injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "foo")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "foo"))'} }) local highlighter = vim.treesitter.highlighter test_hl = highlighter.new(parser, {queries = {c = hl_query}}) @@ -681,6 +682,12 @@ describe('treesitter highlighting (C)', function() ((identifier) @Identifier (#set! conceal "") (#eq? @Identifier "lstate")) + + ((call_expression + function: (identifier) @function + arguments: (argument_list) @arguments) + (#eq? @function "multiqueue_put") + (#set! @function conceal "V")) ]]}}) ]=] @@ -697,7 +704,7 @@ describe('treesitter highlighting (C)', function() | LuaRef cb = nlua_ref(, 1); | | - multiqueue_put(main_loop.events, nlua_schedule_event, | + {11:V}(main_loop.events, nlua_schedule_event, | 1, (void *)(ptrdiff_t)cb); | return 0; | ^} | @@ -756,6 +763,75 @@ describe('treesitter highlighting (C)', function() ]], } end) + + it('gives higher priority to more specific captures #27895', function() + insert([[ + void foo(int *bar); + ]]) + + local query = [[ + "*" @operator + + (parameter_declaration + declarator: (pointer_declarator) @variable.parameter) + ]] + + exec_lua( + [[ + local query = ... + vim.treesitter.query.set('c', 'highlights', query) + vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c')) + ]], + query + ) + + screen:expect { + grid = [[ + void foo(int {4:*}{11:bar}); | + ^ | + {1:~ }|*15 + | + ]], + } + end) +end) + +describe('treesitter highlighting (lua)', function() + local screen + + before_each(function() + screen = Screen.new(65, 18) + screen:attach() + screen:set_default_attr_ids { + [1] = { bold = true, foreground = Screen.colors.Blue }, + [2] = { foreground = Screen.colors.DarkCyan }, + [3] = { foreground = Screen.colors.Magenta }, + [4] = { foreground = Screen.colors.SlateBlue }, + [5] = { bold = true, foreground = Screen.colors.Brown }, + } + end) + + it('supports language injections', function() + insert [[ + local ffi = require('ffi') + ffi.cdef("int (*fun)(int, char *);") + ]] + + exec_lua [[ + vim.bo.filetype = 'lua' + vim.treesitter.start() + ]] + + screen:expect { + grid = [[ + {5:local} {2:ffi} {5:=} {4:require(}{3:'ffi'}{4:)} | + {2:ffi}{4:.}{2:cdef}{4:(}{3:"}{4:int}{3: }{4:(}{5:*}{3:fun}{4:)(int,}{3: }{4:char}{3: }{5:*}{4:);}{3:"}{4:)} | + ^ | + {1:~ }|*14 + | + ]], + } + end) end) describe('treesitter highlighting (help)', function() @@ -788,7 +864,7 @@ describe('treesitter highlighting (help)', function() screen:expect { grid = [[ - {1:>ruby} | + {1:>}{3:ruby} | {1: -- comment} | {1: local this_is = 'actually_lua'} | {1:<} | @@ -797,11 +873,11 @@ describe('treesitter highlighting (help)', function() ]], } - helpers.api.nvim_buf_set_text(0, 0, 1, 0, 5, { 'lua' }) + n.api.nvim_buf_set_text(0, 0, 1, 0, 5, { 'lua' }) screen:expect { grid = [[ - {1:>lua} | + {1:>}{3:lua} | {1: -- comment} | {1: }{3:local}{1: }{4:this_is}{1: }{3:=}{1: }{5:'actually_lua'} | {1:<} | @@ -810,11 +886,11 @@ describe('treesitter highlighting (help)', function() ]], } - helpers.api.nvim_buf_set_text(0, 0, 1, 0, 4, { 'ruby' }) + n.api.nvim_buf_set_text(0, 0, 1, 0, 4, { 'ruby' }) screen:expect { grid = [[ - {1:>ruby} | + {1:>}{3:ruby} | {1: -- comment} | {1: local this_is = 'actually_lua'} | {1:<} | @@ -823,6 +899,40 @@ describe('treesitter highlighting (help)', function() ]], } end) + + it('correctly redraws injections subpriorities', function() + -- The top level string node will be highlighted first + -- with an extmark spanning multiple lines. + -- When the next line is drawn, which includes an injection, + -- make sure the highlight appears above the base tree highlight + + insert([=[ + local s = [[ + local also = lua + ]] + ]=]) + + exec_lua [[ + parser = vim.treesitter.get_parser(0, "lua", { + injections = { + lua = '(string content: (_) @injection.content (#set! injection.language lua))' + } + }) + + vim.treesitter.highlighter.new(parser) + ]] + + screen:expect { + grid = [=[ + {3:local} {4:s} {3:=} {5:[[} | + {5: }{3:local}{5: }{4:also}{5: }{3:=}{5: }{4:lua} | + {5:]]} | + ^ | + {2:~ }| + | + ]=], + } + end) end) describe('treesitter highlighting (nested injections)', function() @@ -891,3 +1001,46 @@ vim.cmd([[ } end) end) + +describe('treesitter highlighting (markdown)', function() + local screen + + before_each(function() + screen = Screen.new(40, 6) + screen:attach() + screen:set_default_attr_ids { + [1] = { foreground = Screen.colors.Blue1 }, + [2] = { bold = true, foreground = Screen.colors.Blue1 }, + [3] = { bold = true, foreground = Screen.colors.Brown }, + [4] = { foreground = Screen.colors.Cyan4 }, + [5] = { foreground = Screen.colors.Magenta1 }, + } + end) + + it('supports hyperlinks', function() + local url = 'https://example.com' + insert(string.format('[This link text](%s) is a hyperlink.', url)) + exec_lua([[ + vim.bo.filetype = 'markdown' + vim.treesitter.start() + ]]) + + screen:expect { + grid = [[ + {4:[}{6:This link text}{4:](}{7:https://example.com}{4:)} is| + a hyperlink^. | + {2:~ }|*3 + | + ]], + attr_ids = { + [1] = { foreground = Screen.colors.Blue1 }, + [2] = { bold = true, foreground = Screen.colors.Blue1 }, + [3] = { bold = true, foreground = Screen.colors.Brown }, + [4] = { foreground = Screen.colors.Cyan4 }, + [5] = { foreground = Screen.colors.Magenta }, + [6] = { foreground = Screen.colors.Cyan4, url = url }, + [7] = { underline = true, foreground = Screen.colors.SlateBlue }, + }, + } + end) +end) diff --git a/test/functional/treesitter/inspect_tree_spec.lua b/test/functional/treesitter/inspect_tree_spec.lua index a3d44ff906..f5acfe7c4a 100644 --- a/test/functional/treesitter/inspect_tree_spec.lua +++ b/test/functional/treesitter/inspect_tree_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local insert = helpers.insert -local dedent = helpers.dedent -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local insert = n.insert +local dedent = t.dedent +local eq = t.eq +local exec_lua = n.exec_lua +local feed = n.feed describe('vim.treesitter.inspect_tree', function() before_each(clear) local expect_tree = function(x) local expected = vim.split(vim.trim(dedent(x)), '\n') - local actual = helpers.buf_lines(0) ---@type string[] + local actual = n.buf_lines(0) ---@type string[] eq(expected, actual) end diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua index 65d9e0e81c..40c974beee 100644 --- a/test/functional/treesitter/language_spec.lua +++ b/test/functional/treesitter/language_spec.lua @@ -1,12 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local command = helpers.command -local exec_lua = helpers.exec_lua -local pcall_err = helpers.pcall_err -local matches = helpers.matches -local insert = helpers.insert +local clear = n.clear +local eq = t.eq +local command = n.command +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err +local matches = t.matches +local insert = n.insert before_each(clear) @@ -120,6 +121,20 @@ describe('treesitter language API', function() eq('<node translation_unit>', exec_lua('return tostring(tree:root())')) end) + it('retrieve the tree given a range when range is out of bounds relative to buffer', function() + insert([[ + int main() { + int x = 3; + }]]) + + exec_lua([[ + langtree = vim.treesitter.get_parser(0, "c") + tree = langtree:tree_for_range({10, 10, 10, 10}) + ]]) + + eq('<node translation_unit>', exec_lua('return tostring(tree:root())')) + end) + it('retrieve the node given a range', function() insert([[ int main() { diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua index f114d36823..96579f296b 100644 --- a/test/functional/treesitter/node_spec.lua +++ b/test/functional/treesitter/node_spec.lua @@ -1,10 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local insert = helpers.insert -local assert_alive = helpers.assert_alive +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua +local insert = n.insert +local assert_alive = n.assert_alive before_each(clear) @@ -142,4 +143,30 @@ describe('treesitter node API', function() eq(28, lua_eval('root:byte_length()')) eq(3, lua_eval('child:byte_length()')) end) + + it('child_containing_descendant() works', function() + insert([[ + int main() { + int x = 3; + }]]) + + exec_lua([[ + tree = vim.treesitter.get_parser(0, "c"):parse()[1] + root = tree:root() + main = root:child(0) + body = main:child(2) + statement = body:child(1) + declarator = statement:child(1) + value = declarator:child(1) + ]]) + + eq(lua_eval('main:type()'), lua_eval('root:child_containing_descendant(value):type()')) + eq(lua_eval('body:type()'), lua_eval('main:child_containing_descendant(value):type()')) + eq(lua_eval('statement:type()'), lua_eval('body:child_containing_descendant(value):type()')) + eq( + lua_eval('declarator:type()'), + lua_eval('statement:child_containing_descendant(value):type()') + ) + eq(vim.NIL, lua_eval('declarator:child_containing_descendant(value)')) + end) end) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 875b772fec..dbd6bb3c23 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -1,15 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local dedent = helpers.dedent -local eq = helpers.eq -local insert = helpers.insert -local exec_lua = helpers.exec_lua -local pcall_err = helpers.pcall_err -local feed = helpers.feed -local is_os = helpers.is_os -local api = helpers.api -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local dedent = t.dedent +local eq = t.eq +local insert = n.insert +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err +local feed = n.feed describe('treesitter parser API', function() before_each(function() @@ -121,7 +119,7 @@ void ui_refresh(void) res = {} for node, field in func_node:iter_children() do - table.insert(res, {node:type(), field}) + table.insert(res, { node:type(), field }) end return res ]]) @@ -157,7 +155,7 @@ void ui_refresh(void) local res = {} for _, node in ipairs(func_node:field("type")) do - table.insert(res, {node:type(), node:range()}) + table.insert(res, { node:type(), node:range() }) end return res ]]) @@ -173,185 +171,6 @@ void ui_refresh(void) assert(res_fail) end) - local test_query = [[ - ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (#eq? @minfunc "MIN")) - "for" @keyword - (primitive_type) @type - (field_expression argument: (identifier) @fieldarg) - ]] - - it('supports runtime queries', function() - local ret = exec_lua [[ - return vim.treesitter.query.get("c", "highlights").captures[1] - ]] - - eq('variable', ret) - end) - - it('supports caching queries', function() - local long_query = test_query:rep(100) - local function q(n) - return exec_lua( - [[ - local query, n = ... - local before = vim.uv.hrtime() - for i=1,n,1 do - cquery = vim.treesitter.query.parse("c", ...) - end - local after = vim.uv.hrtime() - return after - before - ]], - long_query, - n - ) - end - - local firstrun = q(1) - local manyruns = q(100) - - -- First run should be at least 200x slower than an 100 subsequent runs. - local factor = is_os('win') and 100 or 200 - assert( - factor * manyruns < firstrun, - ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6) - ) - end) - - it('support query and iter by capture', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, {cquery.captures[cid], node:type(), node:range()}) - end - return res - ]], - test_query - ) - - eq({ - { 'type', 'primitive_type', 8, 2, 8, 6 }, - { 'keyword', 'for', 9, 2, 9, 5 }, - { 'type', 'primitive_type', 9, 7, 9, 13 }, - { 'minfunc', 'identifier', 11, 12, 11, 15 }, - { 'fieldarg', 'identifier', 11, 16, 11, 18 }, - { 'min_id', 'identifier', 11, 27, 11, 32 }, - { 'minfunc', 'identifier', 12, 13, 12, 16 }, - { 'fieldarg', 'identifier', 12, 17, 12, 19 }, - { 'min_id', 'identifier', 12, 29, 12, 35 }, - { 'fieldarg', 'identifier', 13, 14, 13, 16 }, - }, res) - end) - - it('support query and iter by match', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do - -- can't transmit node over RPC. just check the name and range - local mrepr = {} - for cid, nodes in pairs(match) do - for _, node in ipairs(nodes) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) - end - end - table.insert(res, {pattern, mrepr}) - end - return res - ]], - test_query - ) - - eq({ - { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, - { - 1, - { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } }, - }, - { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } }, - { - 1, - { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } }, - }, - { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } }, - }, res) - end) - - it('support query and iter by capture for quantifiers', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, {cquery.captures[cid], node:type(), node:range()}) - end - return res - ]], - '(expression_statement (assignment_expression (call_expression)))+ @funccall' - ) - - eq({ - { 'funccall', 'expression_statement', 11, 4, 11, 34 }, - { 'funccall', 'expression_statement', 12, 4, 12, 37 }, - { 'funccall', 'expression_statement', 13, 4, 13, 34 }, - }, res) - end) - - it('support query and iter by match for quantifiers', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do - -- can't transmit node over RPC. just check the name and range - local mrepr = {} - for cid, nodes in pairs(match) do - for _, node in ipairs(nodes) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) - end - end - table.insert(res, {pattern, mrepr}) - end - return res - ]], - '(expression_statement (assignment_expression (call_expression)))+ @funccall' - ) - - eq({ - { - 1, - { - { 'funccall', 'expression_statement', 11, 4, 11, 34 }, - { 'funccall', 'expression_statement', 12, 4, 12, 37 }, - { 'funccall', 'expression_statement', 13, 4, 13, 34 }, - }, - }, - }, res) - end) - it('supports getting text of multiline node', function() insert(test_text) local res = exec_lua([[ @@ -369,7 +188,7 @@ void ui_refresh(void) eq('void', res2) end) - it('support getting text where start of node is one past EOF', function() + it('supports getting text where start of node is one past EOF', function() local text = [[ def run a = <<~E @@ -378,25 +197,25 @@ end]] eq( '', exec_lua [[ - local fake_node = {} - function fake_node:start() - return 3, 0, 23 - end - function fake_node:end_() - return 3, 0, 23 - end - function fake_node:range(bytes) - if bytes then - return 3, 0, 23, 3, 0, 23 + local fake_node = {} + function fake_node:start() + return 3, 0, 23 end - return 3, 0, 3, 0 - end - return vim.treesitter.get_node_text(fake_node, 0) - ]] + function fake_node:end_() + return 3, 0, 23 + end + function fake_node:range(bytes) + if bytes then + return 3, 0, 23, 3, 0, 23 + end + return 3, 0, 3, 0 + end + return vim.treesitter.get_node_text(fake_node, 0) + ]] ) end) - it('support getting empty text if node range is zero width', function() + it('supports getting empty text if node range is zero width', function() local text = [[ ```lua {} @@ -418,387 +237,6 @@ end]] eq(true, result) end) - it('can match special regex characters like \\ * + ( with `vim-match?`', function() - insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') - - local res = exec_lua([[ - cquery = vim.treesitter.query.parse("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. - '([_] @times (#vim-match? @times "^\\\\*$"))'.. - '([_] @paren (#vim-match? @paren "^\\\\($"))'.. - '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'.. - '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))') - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do - -- can't transmit node over RPC. just check the name and range - local mrepr = {} - for cid, nodes in pairs(match) do - for _, node in ipairs(nodes) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) - end - end - table.insert(res, {pattern, mrepr}) - end - return res - ]]) - - eq({ - { 2, { { 'times', '*', 0, 4, 0, 5 } } }, - { 5, { { 'string', 'string_literal', 0, 16, 0, 20 } } }, - { 4, { { 'escape', 'escape_sequence', 0, 17, 0, 19 } } }, - { 3, { { 'paren', '(', 0, 22, 0, 23 } } }, - { 1, { { 'plus', '+', 0, 25, 0, 26 } } }, - { 2, { { 'times', '*', 0, 30, 0, 31 } } }, - }, res) - end) - - it('supports builtin query predicate any-of?', function() - insert([[ - #include <stdio.h> - - int main(void) { - int i; - for(i=1; i<=100; i++) { - if(((i%3)||(i%5))== 0) - printf("number= %d FizzBuzz\n", i); - else if((i%3)==0) - printf("number= %d Fizz\n", i); - else if((i%5)==0) - printf("number= %d Buzz\n", i); - else - printf("number= %d\n",i); - } - return 0; - } - ]]) - exec_lua([[ - function get_query_result(query_text) - cquery = vim.treesitter.query.parse("c", query_text) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0) do - -- can't transmit node over RPC. just check the name, range, and text - local text = vim.treesitter.get_node_text(node, 0) - local range = {node:range()} - table.insert(res, {cquery.captures[cid], node:type(), range, text}) - end - return res - end - ]]) - - local res0 = exec_lua( - [[return get_query_result(...)]], - [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]] - ) - eq({ - { 'c-keyword', 'primitive_type', { 2, 2, 2, 5 }, 'int' }, - { 'c-keyword', 'primitive_type', { 3, 4, 3, 7 }, 'int' }, - }, res0) - - local res1 = exec_lua( - [[return get_query_result(...)]], - [[ - ((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings - "\"number= %d FizzBuzz\\n\"" - "\"number= %d Fizz\\n\"" - "\"number= %d Buzz\\n\"" - )) - ]] - ) - eq({ - { 'fizzbuzz-strings', 'string_literal', { 6, 15, 6, 38 }, '"number= %d FizzBuzz\\n"' }, - { 'fizzbuzz-strings', 'string_literal', { 8, 15, 8, 34 }, '"number= %d Fizz\\n"' }, - { 'fizzbuzz-strings', 'string_literal', { 10, 15, 10, 34 }, '"number= %d Buzz\\n"' }, - }, res1) - end) - - it( - 'allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', - function() - insert('char* astring = "Hello World!";') - - local res = exec_lua([[ - cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do - -- can't transmit node over RPC. just check the name and range - local mrepr = {} - for cid, nodes in pairs(match) do - for _, node in ipairs(nodes) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) - end - end - table.insert(res, {pattern, mrepr}) - end - return res - ]]) - - eq({ - { 1, { { 'quote', '"', 0, 16, 0, 17 } } }, - { 2, { { 'quote', '"', 0, 16, 0, 17 } } }, - { 1, { { 'quote', '"', 0, 29, 0, 30 } } }, - { 2, { { 'quote', '"', 0, 29, 0, 30 } } }, - }, res) - end - ) - - it('allows to add predicates', function() - insert([[ - int main(void) { - return 0; - } - ]]) - - local custom_query = '((identifier) @main (#is-main? @main))' - - do - local res = exec_lua( - [[ - local query = vim.treesitter.query - - local function is_main(match, pattern, bufnr, predicate) - local nodes = match[ predicate[2] ] - for _, node in ipairs(nodes) do - if vim.treesitter.get_node_text(node, bufnr) == 'main' then - return true - end - end - return false - end - - local parser = vim.treesitter.get_parser(0, "c") - - -- Time bomb: update this in 0.12 - if vim.fn.has('nvim-0.12') == 1 then - return 'Update this test to remove this message and { all = true } from add_predicate' - end - query.add_predicate("is-main?", is_main, { all = true }) - - local query = query.parse("c", ...) - - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end - - return nodes - ]], - custom_query - ) - - eq({ { 0, 4, 0, 8 } }, res) - end - - -- Once with the old API. Remove this whole 'do' block in 0.12 - do - local res = exec_lua( - [[ - local query = vim.treesitter.query - - local function is_main(match, pattern, bufnr, predicate) - local node = match[ predicate[2] ] - - return vim.treesitter.get_node_text(node, bufnr) == 'main' - end - - local parser = vim.treesitter.get_parser(0, "c") - - query.add_predicate("is-main?", is_main, true) - - local query = query.parse("c", ...) - - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end - - return nodes - ]], - custom_query - ) - - -- Remove this 'do' block in 0.12 - eq(0, fn.has('nvim-0.12')) - eq({ { 0, 4, 0, 8 } }, res) - end - - do - local res = exec_lua [[ - local query = vim.treesitter.query - - local t = {} - for _, v in ipairs(query.list_predicates()) do - t[v] = true - end - - return t - ]] - - eq(true, res['is-main?']) - end - end) - - it('supports "all" and "any" semantics for predicates on quantified captures #24738', function() - local query_all = [[ - (((comment (comment_content))+) @bar - (#lua-match? @bar "Yes")) - ]] - - local query_any = [[ - (((comment (comment_content))+) @bar - (#any-lua-match? @bar "Yes")) - ]] - - local function test(input, query) - api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n')) - return exec_lua( - [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], - query - ) - end - - eq( - {}, - test( - [[ - -- Yes - -- No - -- Yes - ]], - query_all - ) - ) - - eq( - { - { 0, 2, 0, 8 }, - { 1, 2, 1, 8 }, - { 2, 2, 2, 8 }, - }, - test( - [[ - -- Yes - -- Yes - -- Yes - ]], - query_all - ) - ) - - eq( - {}, - test( - [[ - -- No - -- No - -- No - ]], - query_any - ) - ) - - eq( - { - { 0, 2, 0, 7 }, - { 1, 2, 1, 8 }, - { 2, 2, 2, 7 }, - }, - test( - [[ - -- No - -- Yes - -- No - ]], - query_any - ) - ) - end) - - it('supports any- prefix to match any capture when using quantifiers #24738', function() - insert([[ - -- Comment - -- Comment - -- Comment - ]]) - - local query = [[ - (((comment (comment_content))+) @bar - (#lua-match? @bar "Comment")) - ]] - - local result = exec_lua( - [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], - query - ) - - eq({ - { 0, 2, 0, 12 }, - { 1, 2, 1, 12 }, - { 2, 2, 2, 12 }, - }, result) - end) - - it('supports the old broken version of iter_matches #24738', function() - -- Delete this test in 0.12 when iter_matches is removed - eq(0, fn.has('nvim-0.12')) - - insert(test_text) - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do - local mrepr = {} - for cid, node in pairs(match) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) - end - table.insert(res, {pattern, mrepr}) - end - return res - ]], - test_query - ) - - eq({ - { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, - { - 1, - { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } }, - }, - { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } }, - { - 1, - { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } }, - }, - { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } }, - }, res) - end) - it('allows to set simple ranges', function() insert(test_text) @@ -828,7 +266,7 @@ end]] return parser:included_regions() ]] - eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } }) + eq({ { { 0, 0, 0, 17, 1, 508 } } }, range_tbl) end) it('allows to set complex ranges', function() @@ -882,56 +320,31 @@ end]] local ret = exec_lua( [[ - local str = ... - local parser = vim.treesitter.get_string_parser(str, "c") + local str = ... + local parser = vim.treesitter.get_string_parser(str, "c") - local nodes = {} - local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))') + local nodes = {} + local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))') - for _, node in query:iter_captures(parser:parse()[1]:root(), str) do - table.insert(nodes, { node:range() }) - end + for _, node in query:iter_captures(parser:parse()[1]:root(), str) do + table.insert(nodes, { node:range() }) + end - return nodes]], + return nodes + ]], txt ) eq({ { 0, 10, 0, 13 } }, ret) end) - it('should use node range when omitted', function() - local txt = [[ - int foo = 42; - int bar = 13; - ]] - - local ret = exec_lua( - [[ - local str = ... - local parser = vim.treesitter.get_string_parser(str, "c") - - local nodes = {} - local query = vim.treesitter.query.parse("c", '((identifier) @foo)') - local first_child = parser:parse()[1]:root():child(1) - - for _, node in query:iter_captures(first_child, str) do - table.insert(nodes, { node:range() }) - end - - return nodes]], - txt - ) - - eq({ { 1, 10, 1, 13 } }, ret) - end) - describe('when creating a language tree', function() local function get_ranges() - return exec_lua([[ - local result = {} - parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end) - return result - ]]) + return exec_lua [[ + local result = {} + parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end) + return result + ]] end before_each(function() @@ -948,10 +361,14 @@ int x = INT_MAX; describe('when parsing regions independently', function() it('should inject a language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -965,7 +382,7 @@ int x = INT_MAX; { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y)) }, get_ranges()) - helpers.feed('ggo<esc>') + n.feed('ggo<esc>') eq(5, exec_lua('return #parser:children().c:trees()')) eq({ { 0, 0, 8, 0 }, -- root tree @@ -981,10 +398,14 @@ int x = INT_MAX; describe('when parsing regions combined', function() it('should inject a language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -998,7 +419,7 @@ int x = INT_MAX; -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y)) }, get_ranges()) - helpers.feed('ggo<esc>') + n.feed('ggo<esc>') eq('table', exec_lua('return type(parser:children().c)')) eq(2, exec_lua('return #parser:children().c:trees()')) eq({ @@ -1010,7 +431,7 @@ int x = INT_MAX; -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y)) }, get_ranges()) - helpers.feed('7ggI//<esc>') + n.feed('7ggI//<esc>') exec_lua([[parser:parse({6, 7})]]) eq('table', exec_lua('return type(parser:children().c)')) eq(2, exec_lua('return #parser:children().c:trees()')) @@ -1027,10 +448,14 @@ int x = INT_MAX; describe('when using injection.self', function() it('should inject the source language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -1044,7 +469,7 @@ int x = INT_MAX; { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y)) }, get_ranges()) - helpers.feed('ggo<esc>') + n.feed('ggo<esc>') eq(5, exec_lua('return #parser:children().c:trees()')) eq({ { 0, 0, 8, 0 }, -- root tree @@ -1060,10 +485,14 @@ int x = INT_MAX; describe('when using the offset directive', function() it('should shift the range by the directive amount', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -1078,13 +507,13 @@ int x = INT_MAX; end) it('should list all directives', function() local res_list = exec_lua [[ - local query = vim.treesitter.query + local query = vim.treesitter.query - local list = query.list_directives() + local list = query.list_directives() - table.sort(list) + table.sort(list) - return list + return list ]] eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list) @@ -1102,16 +531,49 @@ int x = INT_MAX; it('should return the correct language tree', function() local result = exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))' + } + }) + parser:parse(true) + + local sub_tree = parser:language_for_range({1, 18, 1, 19}) + + return sub_tree == parser:children().c + ]]) - local sub_tree = parser:language_for_range({1, 18, 1, 19}) + eq(true, result) + end) + end) - return sub_tree == parser:children().c + describe('when setting the node for an injection', function() + before_each(function() + insert([[ +print() ]]) + end) - eq(result, true) + it('ignores optional captures #23100', function() + local result = exec_lua([[ + parser = vim.treesitter.get_parser(0, "lua", { + injections = { + lua = ( + '(function_call ' .. + '(arguments ' .. + '(string)? @injection.content ' .. + '(number)? @injection.content ' .. + '(#offset! @injection.content 0 1 0 -1) ' .. + '(#set! injection.language "c")))' + ) + } + }) + parser:parse(true) + + return parser:is_valid() + ]]) + + eq(true, result) end) end) @@ -1135,7 +597,7 @@ int x = INT_MAX; return result ]]) - eq(result, 'value') + eq('value', result) end) describe('when setting a key on a capture', function() @@ -1158,7 +620,7 @@ int x = INT_MAX; end ]]) - eq(result, 'value') + eq('value', result) end) it('it should not overwrite the nested table', function() @@ -1208,15 +670,15 @@ int x = INT_MAX; local function run_query() return exec_lua( [[ - local query = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser() - tree = parser:parse()[1] - res = {} - for id, node in query:iter_captures(tree:root()) do - table.insert(res, {query.captures[id], node:range()}) - end - return res - ]], + local query = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser() + tree = parser:parse()[1] + res = {} + for id, node in query:iter_captures(tree:root()) do + table.insert(res, {query.captures[id], node:range()}) + end + return res + ]], query0 ) end @@ -1226,7 +688,7 @@ int x = INT_MAX; { 'declaration', 1, 2, 1, 12 }, }, run_query()) - helpers.command 'normal ggO' + n.command 'normal ggO' insert('int a;') eq({ @@ -1258,14 +720,14 @@ int x = INT_MAX; local r = exec_lua( [[ - local parser = vim.treesitter.get_string_parser(..., 'lua') - parser:parse(true) - local ranges = {} - parser:for_each_tree(function(tstree, tree) - ranges[tree:lang()] = { tstree:root():range(true) } - end) - return ranges - ]], + local parser = vim.treesitter.get_string_parser(..., 'lua') + parser:parse(true) + local ranges = {} + parser:for_each_tree(function(tstree, tree) + ranges[tree:lang()] = { tstree:root():range(true) } + end) + return ranges + ]], source ) @@ -1281,14 +743,14 @@ int x = INT_MAX; local rb = exec_lua( [[ - local r, source = ... - local add_bytes = require('vim.treesitter._range').add_bytes - for lang, range in pairs(r) do - r[lang] = {range[1], range[2], range[4], range[5]} - r[lang] = add_bytes(source, r[lang]) - end - return r - ]], + local r, source = ... + local add_bytes = require('vim.treesitter._range').add_bytes + for lang, range in pairs(r) do + r[lang] = {range[1], range[2], range[4], range[5]} + r[lang] = add_bytes(source, r[lang]) + end + return r + ]], r, source ) @@ -1402,53 +864,7 @@ int x = INT_MAX; ) end) - it('fails to load queries', function() - local function test(exp, cquery) - eq(exp, pcall_err(exec_lua, "vim.treesitter.query.parse('c', ...)", cquery)) - end - - -- Invalid node type - test( - '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n' - .. '(dentifier) @variable\n' - .. ' ^', - '(dentifier) @variable' - ) - - -- Impossible pattern - test( - '.../query.lua:0: Query error at 1:13. Impossible pattern:\n' - .. '(identifier (identifier) @variable)\n' - .. ' ^', - '(identifier (identifier) @variable)' - ) - - -- Invalid syntax - test( - '.../query.lua:0: Query error at 1:13. Invalid syntax:\n' - .. '(identifier @variable\n' - .. ' ^', - '(identifier @variable' - ) - - -- Invalid field name - test( - '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n' - .. '((identifier) invalid_field: (identifier))\n' - .. ' ^', - '((identifier) invalid_field: (identifier))' - ) - - -- Invalid capture name - test( - '.../query.lua:0: Query error at 3:2. Invalid capture name "ok.capture":\n' - .. '@ok.capture\n' - .. ' ^', - '((identifier) @id \n(#eq? @id\n@ok.capture\n))' - ) - end) - - describe('is_valid()', function() + describe('languagetree is_valid()', function() before_each(function() insert(dedent [[ Treesitter integration *treesitter* diff --git a/test/functional/treesitter/query_spec.lua b/test/functional/treesitter/query_spec.lua new file mode 100644 index 0000000000..c3a376cd71 --- /dev/null +++ b/test/functional/treesitter/query_spec.lua @@ -0,0 +1,808 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local dedent = t.dedent +local eq = t.eq +local insert = n.insert +local exec_lua = n.exec_lua +local pcall_err = t.pcall_err +local api = n.api +local fn = n.fn + +local get_query_result_code = [[ + function get_query_result(query_text) + cquery = vim.treesitter.query.parse("c", query_text) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0) do + -- can't transmit node over RPC. just check the name, range, and text + local text = vim.treesitter.get_node_text(node, 0) + local range = {node:range()} + table.insert(res, { cquery.captures[cid], node:type(), range, text }) + end + return res + end +]] + +describe('treesitter query API', function() + before_each(function() + clear() + exec_lua [[ + vim.g.__ts_debug = 1 + ]] + end) + + local test_text = [[ +void ui_refresh(void) +{ + int width = INT_MAX, height = INT_MAX; + bool ext_widgets[kUIExtCount]; + for (UIExtension i = 0; (int)i < kUIExtCount; i++) { + ext_widgets[i] = true; + } + + bool inclusive = ui_override(); + for (size_t i = 0; i < ui_count; i++) { + UI *ui = uis[i]; + width = MIN(ui->width, width); + height = MIN(ui->height, height); + foo = BAR(ui->bazaar, bazaar); + for (UIExtension j = 0; (int)j < kUIExtCount; j++) { + ext_widgets[j] &= (ui->ui_ext[j] || inclusive); + } + } +}]] + + local test_query = [[ + ((call_expression + function: (identifier) @minfunc + (argument_list (identifier) @min_id)) + (#eq? @minfunc "MIN") + ) + + "for" @keyword + + (primitive_type) @type + + (field_expression argument: (identifier) @fieldarg) + ]] + + it('supports runtime queries', function() + ---@type string[] + local ret = exec_lua [[ + return vim.treesitter.query.get("c", "highlights").captures + ]] + + -- see $VIMRUNTIME/queries/c/highlights.scm + eq('variable', ret[1]) + eq('keyword', ret[2]) + end) + + it('supports caching queries', function() + local long_query = test_query:rep(100) + ---@return number + local function q(_n) + return exec_lua( + [[ + local query, n = ... + local before = vim.api.nvim__stats().ts_query_parse_count + collectgarbage("stop") + for i=1, n, 1 do + cquery = vim.treesitter.query.parse("c", ...) + end + collectgarbage("restart") + collectgarbage("collect") + local after = vim.api.nvim__stats().ts_query_parse_count + return after - before + ]], + long_query, + _n + ) + end + + eq(1, q(1)) + -- cache is cleared by garbage collection even if valid "cquery" reference is kept around + eq(1, q(100)) + end) + + it('supports query and iter by capture (iter_captures)', function() + insert(test_text) + + local res = exec_lua( + [[ + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do + -- can't transmit node over RPC. just check the name and range + table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + return res + ]], + test_query + ) + + eq({ + { '@type', 'primitive_type', 8, 2, 8, 6 }, -- bool + { '@keyword', 'for', 9, 2, 9, 5 }, -- for + { '@type', 'primitive_type', 9, 7, 9, 13 }, -- size_t + { '@minfunc', 'identifier', 11, 12, 11, 15 }, -- "MIN"(ui->width, width); + { '@fieldarg', 'identifier', 11, 16, 11, 18 }, -- ui + { '@min_id', 'identifier', 11, 27, 11, 32 }, -- width + { '@minfunc', 'identifier', 12, 13, 12, 16 }, -- "MIN"(ui->height, height); + { '@fieldarg', 'identifier', 12, 17, 12, 19 }, -- ui + { '@min_id', 'identifier', 12, 29, 12, 35 }, -- height + { '@fieldarg', 'identifier', 13, 14, 13, 16 }, -- ui ; in BAR(..) + }, res) + end) + + it('supports query and iter by match (iter_matches)', function() + insert(test_text) + + ---@type table + local res = exec_lua( + [[ + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do + -- can't transmit node over RPC. just check the name and range + local mrepr = {} + for cid, nodes in pairs(match) do + for _, node in ipairs(nodes) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + end + table.insert(res, { pattern, mrepr }) + end + return res + ]], + test_query + ) + + eq({ + { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, + { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, + { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, + { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, + { + 1, + { + { '@minfunc', 'identifier', 11, 12, 11, 15 }, + { '@min_id', 'identifier', 11, 27, 11, 32 }, + }, + }, + { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, + { + 1, + { + { '@minfunc', 'identifier', 12, 13, 12, 16 }, + { '@min_id', 'identifier', 12, 29, 12, 35 }, + }, + }, + { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, + }, res) + end) + + it('supports query and iter by capture for quantifiers', function() + insert(test_text) + + local res = exec_lua( + [[ + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do + -- can't transmit node over RPC. just check the name and range + table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + return res + ]], + '(expression_statement (assignment_expression (call_expression)))+ @funccall' + ) + + eq({ + { '@funccall', 'expression_statement', 11, 4, 11, 34 }, + { '@funccall', 'expression_statement', 12, 4, 12, 37 }, + { '@funccall', 'expression_statement', 13, 4, 13, 34 }, + }, res) + end) + + it('supports query and iter by match for quantifiers', function() + insert(test_text) + + local res = exec_lua( + [[ + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do + -- can't transmit node over RPC. just check the name and range + local mrepr = {} + for cid, nodes in pairs(match) do + for _, node in ipairs(nodes) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + end + table.insert(res, {pattern, mrepr}) + end + return res + ]], + '(expression_statement (assignment_expression (call_expression)))+ @funccall' + ) + + eq({ + { + 1, + { + { '@funccall', 'expression_statement', 11, 4, 11, 34 }, + { '@funccall', 'expression_statement', 12, 4, 12, 37 }, + { '@funccall', 'expression_statement', 13, 4, 13, 34 }, + }, + }, + }, res) + end) + + it('can match special regex characters like \\ * + ( with `vim-match?`', function() + insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') + + ---@type table + local res = exec_lua([[ + query = ( + '([_] @plus (#vim-match? @plus "^\\\\+$"))' .. + '([_] @times (#vim-match? @times "^\\\\*$"))' .. + '([_] @paren (#vim-match? @paren "^\\\\($"))' .. + '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))' .. + '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))' + ) + cquery = vim.treesitter.query.parse("c", query) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do + -- can't transmit node over RPC. just check the name and range + local mrepr = {} + for cid, nodes in pairs(match) do + for _, node in ipairs(nodes) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + end + table.insert(res, { pattern, mrepr }) + end + return res + ]]) + + eq({ + { 2, { { '@times', '*', 0, 4, 0, 5 } } }, + { 5, { { '@string', 'string_literal', 0, 16, 0, 20 } } }, + { 4, { { '@escape', 'escape_sequence', 0, 17, 0, 19 } } }, + { 3, { { '@paren', '(', 0, 22, 0, 23 } } }, + { 1, { { '@plus', '+', 0, 25, 0, 26 } } }, + { 2, { { '@times', '*', 0, 30, 0, 31 } } }, + }, res) + end) + + it('supports builtin query predicate any-of?', function() + insert([[ + #include <stdio.h> + + int main(void) { + int i; + for(i=1; i<=100; i++) { + if(((i%3)||(i%5))== 0) + printf("number= %d FizzBuzz\n", i); + else if((i%3)==0) + printf("number= %d Fizz\n", i); + else if((i%5)==0) + printf("number= %d Buzz\n", i); + else + printf("number= %d\n",i); + } + return 0; + } + ]]) + exec_lua(get_query_result_code) + + local res0 = exec_lua( + [[return get_query_result(...)]], + [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]] + ) + eq({ + { 'c-keyword', 'primitive_type', { 2, 2, 2, 5 }, 'int' }, + { 'c-keyword', 'primitive_type', { 3, 4, 3, 7 }, 'int' }, + }, res0) + + local res1 = exec_lua( + [[return get_query_result(...)]], + [[ + ((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings + "\"number= %d FizzBuzz\\n\"" + "\"number= %d Fizz\\n\"" + "\"number= %d Buzz\\n\"" + )) + ]] + ) + eq({ + { 'fizzbuzz-strings', 'string_literal', { 6, 15, 6, 38 }, '"number= %d FizzBuzz\\n"' }, + { 'fizzbuzz-strings', 'string_literal', { 8, 15, 8, 34 }, '"number= %d Fizz\\n"' }, + { 'fizzbuzz-strings', 'string_literal', { 10, 15, 10, 34 }, '"number= %d Buzz\\n"' }, + }, res1) + end) + + it('supports builtin predicate has-ancestor?', function() + insert([[ + int x = 123; + enum C { y = 124 }; + int main() { int z = 125; }]]) + exec_lua(get_query_result_code) + + local result = exec_lua( + [[return get_query_result(...)]], + [[((number_literal) @literal (#has-ancestor? @literal "function_definition"))]] + ) + eq({ { 'literal', 'number_literal', { 2, 21, 2, 24 }, '125' } }, result) + + result = exec_lua( + [[return get_query_result(...)]], + [[((number_literal) @literal (#has-ancestor? @literal "function_definition" "enum_specifier"))]] + ) + eq({ + { 'literal', 'number_literal', { 1, 13, 1, 16 }, '124' }, + { 'literal', 'number_literal', { 2, 21, 2, 24 }, '125' }, + }, result) + + result = exec_lua( + [[return get_query_result(...)]], + [[((number_literal) @literal (#not-has-ancestor? @literal "enum_specifier"))]] + ) + eq({ + { 'literal', 'number_literal', { 0, 8, 0, 11 }, '123' }, + { 'literal', 'number_literal', { 2, 21, 2, 24 }, '125' }, + }, result) + end) + + it('allows loading query with escaped quotes and capture them `#{lua,vim}-match`?', function() + insert('char* astring = "Hello World!";') + + local res = exec_lua([[ + cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do + -- can't transmit node over RPC. just check the name and range + local mrepr = {} + for cid, nodes in pairs(match) do + for _, node in ipairs(nodes) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + end + table.insert(res, { pattern, mrepr }) + end + return res + ]]) + + eq({ + { 1, { { '@quote', '"', 0, 16, 0, 17 } } }, + { 2, { { '@quote', '"', 0, 16, 0, 17 } } }, + { 1, { { '@quote', '"', 0, 29, 0, 30 } } }, + { 2, { { '@quote', '"', 0, 29, 0, 30 } } }, + }, res) + end) + + it('allows to add predicates', function() + insert([[ + int main(void) { + return 0; + } + ]]) + + local custom_query = '((identifier) @main (#is-main? @main))' + + do + local res = exec_lua( + [[ + local query = vim.treesitter.query + + local function is_main(match, pattern, bufnr, predicate) + local nodes = match[ predicate[2] ] + for _, node in ipairs(nodes) do + if vim.treesitter.get_node_text(node, bufnr) == 'main' then + return true + end + end + return false + end + + local parser = vim.treesitter.get_parser(0, "c") + + -- Time bomb: update this in 0.12 + if vim.fn.has('nvim-0.12') == 1 then + return 'Update this test to remove this message and { all = true } from add_predicate' + end + query.add_predicate("is-main?", is_main, { all = true }) + + local query = query.parse("c", ...) + + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + table.insert(nodes, {node:range()}) + end + + return nodes + ]], + custom_query + ) + + eq({ { 0, 4, 0, 8 } }, res) + end + + -- Once with the old API. Remove this whole 'do' block in 0.12 + do + local res = exec_lua( + [[ + local query = vim.treesitter.query + + local function is_main(match, pattern, bufnr, predicate) + local node = match[ predicate[2] ] + + return vim.treesitter.get_node_text(node, bufnr) == 'main' + end + + local parser = vim.treesitter.get_parser(0, "c") + + query.add_predicate("is-main?", is_main, true) + + local query = query.parse("c", ...) + + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + table.insert(nodes, {node:range()}) + end + + return nodes + ]], + custom_query + ) + + -- Remove this 'do' block in 0.12 + eq(0, fn.has('nvim-0.12')) + eq({ { 0, 4, 0, 8 } }, res) + end + + do + local res = exec_lua [[ + local query = vim.treesitter.query + + local t = {} + for _, v in ipairs(query.list_predicates()) do + t[v] = true + end + + return t + ]] + + eq(true, res['is-main?']) + end + end) + + it('supports "all" and "any" semantics for predicates on quantified captures #24738', function() + local query_all = [[ + (((comment (comment_content))+) @bar + (#lua-match? @bar "Yes")) + ]] + + local query_any = [[ + (((comment (comment_content))+) @bar + (#any-lua-match? @bar "Yes")) + ]] + + local function test(input, query) + api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n')) + return exec_lua( + [[ + local parser = vim.treesitter.get_parser(0, "lua") + local query = vim.treesitter.query.parse("lua", ...) + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + nodes[#nodes+1] = { node:range() } + end + return nodes + ]], + query + ) + end + + eq( + {}, + test( + [[ + -- Yes + -- No + -- Yes + ]], + query_all + ) + ) + + eq( + { + { 0, 2, 0, 8 }, + { 1, 2, 1, 8 }, + { 2, 2, 2, 8 }, + }, + test( + [[ + -- Yes + -- Yes + -- Yes + ]], + query_all + ) + ) + + eq( + {}, + test( + [[ + -- No + -- No + -- No + ]], + query_any + ) + ) + + eq( + { + { 0, 2, 0, 7 }, + { 1, 2, 1, 8 }, + { 2, 2, 2, 7 }, + }, + test( + [[ + -- No + -- Yes + -- No + ]], + query_any + ) + ) + end) + + it('supports any- prefix to match any capture when using quantifiers #24738', function() + insert([[ + -- Comment + -- Comment + -- Comment + ]]) + + local query = [[ + (((comment (comment_content))+) @bar + (#lua-match? @bar "Comment")) + ]] + + local result = exec_lua( + [[ + local parser = vim.treesitter.get_parser(0, "lua") + local query = vim.treesitter.query.parse("lua", ...) + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + nodes[#nodes+1] = { node:range() } + end + return nodes + ]], + query + ) + + eq({ + { 0, 2, 0, 12 }, + { 1, 2, 1, 12 }, + { 2, 2, 2, 12 }, + }, result) + end) + + it('supports the old broken version of iter_matches #24738', function() + -- Delete this test in 0.12 when iter_matches is removed + eq(0, fn.has('nvim-0.12')) + + insert(test_text) + local res = exec_lua( + [[ + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do + local mrepr = {} + for cid, node in pairs(match) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + table.insert(res, { pattern, mrepr }) + end + return res + ]], + test_query + ) + + eq({ + { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, + { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, + { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, + { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, + { + 1, + { + { '@minfunc', 'identifier', 11, 12, 11, 15 }, + { '@min_id', 'identifier', 11, 27, 11, 32 }, + }, + }, + { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, + { + 1, + { + { '@minfunc', 'identifier', 12, 13, 12, 16 }, + { '@min_id', 'identifier', 12, 29, 12, 35 }, + }, + }, + { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, + }, res) + end) + + it('should use node range when omitted', function() + local txt = [[ + int foo = 42; + int bar = 13; + ]] + + local ret = exec_lua( + [[ + local str = ... + local parser = vim.treesitter.get_string_parser(str, "c") + + local nodes = {} + local query = vim.treesitter.query.parse("c", '((identifier) @foo)') + local first_child = parser:parse()[1]:root():child(1) + + for _, node in query:iter_captures(first_child, str) do + table.insert(nodes, { node:range() }) + end + + return nodes + ]], + txt + ) + + eq({ { 1, 10, 1, 13 } }, ret) + end) + + it('fails to load queries', function() + local function test(exp, cquery) + eq(exp, pcall_err(exec_lua, "vim.treesitter.query.parse('c', ...)", cquery)) + end + + -- Invalid node type + test( + '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n' + .. '(dentifier) @variable\n' + .. ' ^', + '(dentifier) @variable' + ) + + -- Impossible pattern + test( + '.../query.lua:0: Query error at 1:13. Impossible pattern:\n' + .. '(identifier (identifier) @variable)\n' + .. ' ^', + '(identifier (identifier) @variable)' + ) + + -- Invalid syntax + test( + '.../query.lua:0: Query error at 1:13. Invalid syntax:\n' + .. '(identifier @variable\n' + .. ' ^', + '(identifier @variable' + ) + + -- Invalid field name + test( + '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n' + .. '((identifier) invalid_field: (identifier))\n' + .. ' ^', + '((identifier) invalid_field: (identifier))' + ) + + -- Invalid capture name + test( + '.../query.lua:0: Query error at 3:2. Invalid capture name "ok.capture":\n' + .. '@ok.capture\n' + .. ' ^', + '((identifier) @id \n(#eq? @id\n@ok.capture\n))' + ) + end) + + describe('Query:iter_captures', function() + it('includes metadata for all captured nodes #23664', function() + insert([[ + const char *sql = "SELECT * FROM Students WHERE name = 'Robert'); DROP TABLE Students;--"; + ]]) + + local query = [[ + (declaration + type: (_) + declarator: (init_declarator + declarator: (pointer_declarator + declarator: (identifier)) @_id + value: (string_literal + (string_content) @injection.content)) + (#set! injection.language "sql") + (#contains? @_id "sql")) + ]] + + local result = exec_lua( + [=[ + local query = vim.treesitter.query.parse("c", ...) + local parser = vim.treesitter.get_parser(0, "c") + local root = parser:parse()[1]:root() + local t = {} + for id, node, metadata in query:iter_captures(root, 0) do + t[query.captures[id]] = metadata + end + return t + ]=], + query + ) + + eq({ + ['_id'] = { ['injection.language'] = 'sql' }, + ['injection.content'] = { ['injection.language'] = 'sql' }, + }, result) + end) + + it('only evaluates predicates once per match', function() + insert([[ + void foo(int x, int y); + ]]) + local query = [[ + (declaration + type: (_) + declarator: (function_declarator + declarator: (identifier) @function.name + parameters: (parameter_list + (parameter_declaration + type: (_) + declarator: (identifier) @argument))) + (#eq? @function.name "foo")) + ]] + + local result = exec_lua( + [[ + local query = vim.treesitter.query.parse("c", ...) + local match_preds = query.match_preds + local called = 0 + function query:match_preds(...) + called = called + 1 + return match_preds(self, ...) + end + local parser = vim.treesitter.get_parser(0, "c") + local root = parser:parse()[1]:root() + local captures = {} + for id, node in query:iter_captures(root, 0) do + captures[#captures + 1] = id + end + return { called, captures } + ]], + query + ) + + eq({ 2, { 1, 1, 2, 2 } }, result) + end) + end) +end) diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua index 2734c22499..bca0aca0cb 100644 --- a/test/functional/treesitter/utils_spec.lua +++ b/test/functional/treesitter/utils_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local insert = helpers.insert -local eq = helpers.eq -local exec_lua = helpers.exec_lua +local clear = n.clear +local insert = n.insert +local eq = t.eq +local exec_lua = n.exec_lua before_each(clear) diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 896f75a681..5590db5bc4 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, neq = helpers.command, helpers.neq -local api = helpers.api -local eq = helpers.eq -local pcall_err = helpers.pcall_err +local clear, feed, insert = n.clear, n.feed, n.insert +local command, neq = n.command, t.neq +local api = n.api +local eq = t.eq +local pcall_err = t.pcall_err local set_virtual_text = api.nvim_buf_set_virtual_text describe('Buffer highlighting', function() diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua index 6c4000ba41..1c6f19245a 100644 --- a/test/functional/ui/cmdline_highlight_spec.lua +++ b/test/functional/ui/cmdline_highlight_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local feed = helpers.feed -local clear = helpers.clear -local api = helpers.api -local fn = helpers.fn -local source = helpers.source -local exec_capture = helpers.exec_capture -local dedent = helpers.dedent -local command = helpers.command +local eq = t.eq +local feed = n.feed +local clear = n.clear +local api = n.api +local fn = n.fn +local source = n.source +local exec_capture = n.exec_capture +local dedent = t.dedent +local command = n.command local screen diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 0eb5770819..6edfb4a49c 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed = helpers.clear, helpers.feed -local source = helpers.source -local command = helpers.command -local assert_alive = helpers.assert_alive -local poke_eventloop = helpers.poke_eventloop -local exec = helpers.exec -local eval = helpers.eval -local eq = helpers.eq -local is_os = helpers.is_os -local api = helpers.api + +local clear, feed = n.clear, n.feed +local source = n.source +local command = n.command +local assert_alive = n.assert_alive +local poke_eventloop = n.poke_eventloop +local exec = n.exec +local eval = n.eval +local eq = t.eq +local is_os = t.is_os +local api = n.api local function new_screen(opt) local screen = Screen.new(25, 5) @@ -365,7 +367,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -377,7 +379,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -396,7 +398,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -416,7 +418,7 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1::}make^ | {3:[Command Line] }| | ]], @@ -824,6 +826,30 @@ local function test_cmdline(linegrid) | ]]) end) + + it('does not move cursor to curwin #20309', function() + local win = api.nvim_get_current_win() + command('norm icmdlinewin') + command('new') + command('norm icurwin') + feed(':') + api.nvim_win_set_cursor(win, { 1, 7 }) + api.nvim__redraw({ win = win, cursor = true }) + screen:expect { + grid = [[ + curwin | + {3:[No Name] [+] }| + cmdline^win | + {2:[No Name] [+] }| + | + ]], + cmdline = { { + content = { { '' } }, + firstc = ':', + pos = 0, + } }, + } + end) end -- the representation of cmdline and cmdline_block contents changed with ext_linegrid @@ -1242,15 +1268,6 @@ describe('cmdheight=0', function() before_each(function() clear() screen = Screen.new(25, 5) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue }, - [2] = { bold = true, reverse = true }, - [3] = { bold = true }, - [4] = { foreground = Screen.colors.White, background = Screen.colors.Red }, - [5] = { foreground = Screen.colors.SeaGreen4, bold = true }, - [6] = { reverse = true }, - [7] = { background = Screen.colors.Yellow }, - } screen:attach() end) @@ -1279,7 +1296,7 @@ describe('cmdheight=0', function() grid = [[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| | ]], } @@ -1291,7 +1308,7 @@ describe('cmdheight=0', function() grid = [[ ^ | {1:~ }|*3 - {2:[No Name] }| + {3:[No Name] }| ]], } end) @@ -1341,7 +1358,7 @@ describe('cmdheight=0', function() grid = [[ ^ | {1:~ }|*3 - {3:-- INSERT --} | + {5:-- INSERT --} | ]], } feed('<Esc>') @@ -1377,7 +1394,7 @@ describe('cmdheight=0', function() grid = [[ | {1:~ }| - {2: }| + {3: }| :call input("foo >") | foo >^ | ]], @@ -1399,26 +1416,26 @@ describe('cmdheight=0', function() feed(':split<CR>') screen:expect { grid = [[ - {2: }| + {3: }| :split | - {4:E36: Not enough room} | - {5:Press ENTER or type comma}| - {5:nd to continue}^ | + {9:E36: Not enough room} | + {6:Press ENTER or type comma}| + {6:nd to continue}^ | ]], } feed('<CR>') screen:expect { grid = [[ - {3:foo }| + {5:foo }| ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| ]], } feed(':') screen:expect { grid = [[ - {3:foo }| + {5:foo }| | {1:~ }|*2 :^ | @@ -1427,10 +1444,10 @@ describe('cmdheight=0', function() feed('<Esc>') screen:expect { grid = [[ - {3:foo }| + {5:foo }| ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| ]], showmode = {}, } @@ -1465,16 +1482,16 @@ describe('cmdheight=0', function() grid = [[ fo^o | {1:~ }|*3 - {2:[No Name] [+] }| + {3:[No Name] [+] }| ]], } feed(':%s/foo/bar/gc<CR>') screen:expect { grid = [[ - {6:foo} | + {2:foo} | {1:~ }|*3 - {5:replace wi...q/l/^E/^Y)?}^ | + {6:replace wi...q/l/^E/^Y)?}^ | ]], } @@ -1483,7 +1500,7 @@ describe('cmdheight=0', function() grid = [[ ^bar | {1:~ }|*3 - {2:[No Name] [+] }| + {3:[No Name] [+] }| ]], } @@ -1502,7 +1519,7 @@ describe('cmdheight=0', function() feed('iaabbaa<esc>/aa<cr>') screen:expect { grid = [[ - {7:^aa}bb{7:aa} | + {10:^aa}bb{10:aa} | {1:~ }|*4 ]], } @@ -1561,7 +1578,7 @@ describe('cmdheight=0', function() [2:-------------------------]|*4 [3:-------------------------]| ## grid 2 - {6:p} | + {2:p} | {1:~ }|*4 ## grid 3 /p^ | @@ -1572,7 +1589,7 @@ describe('cmdheight=0', function() topline = 0, botline = 2, curline = 0, - curcol = 0, + curcol = 1, linecount = 1, sum_scroll_delta = 0, }, @@ -1587,7 +1604,7 @@ describe('cmdheight=0', function() ]]) feed(':') screen:expect([[ - {3:c :}| + {5:c :}| | {1:~ }|*2 :^ | @@ -1595,14 +1612,14 @@ describe('cmdheight=0', function() feed('echo') -- not redrawn yet screen:expect([[ - {3:c :}| + {5:c :}| | {1:~ }|*2 :echo^ | ]]) command('redrawstatus') screen:expect([[ - {3:c :echo}| + {5:c :echo}| | {1:~ }|*2 :echo^ | @@ -1623,7 +1640,7 @@ describe('cmdheight=0', function() screen:expect([[ ^ │ | {1:~ }│{1:~ }|*3 - {2:[No Name] }│{1:~ }| + {3:[No Name] }│{1:~ }| │{1:~ }| {1:~ }│{1:~ }|*3 ]]) @@ -1631,7 +1648,7 @@ describe('cmdheight=0', function() screen:expect([[ ^ │ | {1:~ }│{1:~ }| - {2:[No Name] }│{1:~ }| + {3:[No Name] }│{1:~ }| │{1:~ }| {1:~ }│{1:~ }|*5 ]]) @@ -1641,7 +1658,7 @@ describe('cmdheight=0', function() screen:expect([[ ^ │ | {1:~ }│{1:~ }|*3 - {2:[No Name] }│{1:~ }| + {3:[No Name] }│{1:~ }| │{1:~ }| {1:~ }│{1:~ }|*3 ]]) @@ -1663,7 +1680,7 @@ describe('cmdheight=0', function() screen:expect([[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| | ]]) command('set cmdheight=0') @@ -1671,7 +1688,7 @@ describe('cmdheight=0', function() grid = [[ ^ | {1:~ }|*3 - {2:[No Name] }| + {3:[No Name] }| ]], } command('resize -1') @@ -1679,7 +1696,7 @@ describe('cmdheight=0', function() grid = [[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| | ]], } @@ -1687,23 +1704,28 @@ describe('cmdheight=0', function() screen:expect([[ ^ | {1:~ }|*3 - {2:[No Name] }| + {3:[No Name] }| ]]) end) - it('cannot be resized at all with external messages', function() + it('can be resized with external messages', function() clear() screen = new_screen({ rgb = true, ext_messages = true }) command('set laststatus=2 mouse=a') command('resize -1') screen:expect([[ ^ | - {1:~ }|*3 + {1:~ }|*2 {3:[No Name] }| + | ]]) - api.nvim_input_mouse('left', 'press', '', 0, 6, 10) + api.nvim_input_mouse('left', 'press', '', 0, 3, 10) poke_eventloop() - api.nvim_input_mouse('left', 'drag', '', 0, 5, 10) - screen:expect_unchanged() + api.nvim_input_mouse('left', 'drag', '', 0, 4, 10) + screen:expect([[ + ^ | + {1:~ }|*3 + {3:[No Name] }| + ]]) end) end) diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua index 871e9a0790..8bfceb8cce 100644 --- a/test/functional/ui/cursor_spec.lua +++ b/test/functional/ui/cursor_spec.lua @@ -1,8 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, api = helpers.clear, helpers.api -local eq = helpers.eq -local command = helpers.command + +local clear, api = n.clear, n.api +local eq = t.eq +local command = n.command describe('ui/cursor', function() local screen @@ -204,7 +206,7 @@ describe('ui/cursor', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 test | ]], condition = function() @@ -213,8 +215,8 @@ describe('ui/cursor', function() } -- Change the cursor style. - helpers.command('hi Cursor guibg=DarkGray') - helpers.command( + n.command('hi Cursor guibg=DarkGray') + n.command( 'set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20' .. ',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor' .. ',sm:block-blinkwait175-blinkoff150-blinkon175' @@ -260,8 +262,8 @@ describe('ui/cursor', function() end) -- Change hl groups only, should update the styles - helpers.command('hi Cursor guibg=Red') - helpers.command('hi lCursor guibg=Green') + n.command('hi Cursor guibg=Red') + n.command('hi lCursor guibg=Green') -- Update the expected values. for _, m in ipairs(expected_mode_info) do @@ -280,7 +282,7 @@ describe('ui/cursor', function() end) -- update the highlight again to hide cursor - helpers.command('hi Cursor blend=100') + n.command('hi Cursor blend=100') for _, m in ipairs(expected_mode_info) do if m.hl_id then @@ -290,7 +292,7 @@ describe('ui/cursor', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 test | ]], condition = function() diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index e57e719192..746bfb3262 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -1,18 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed = helpers.feed -local insert = helpers.insert -local exec_lua = helpers.exec_lua -local exec = helpers.exec -local expect_events = helpers.expect_events -local api = helpers.api -local fn = helpers.fn -local command = helpers.command -local eq = helpers.eq -local assert_alive = helpers.assert_alive -local pcall_err = helpers.pcall_err +local clear = n.clear +local feed = n.feed +local insert = n.insert +local exec_lua = n.exec_lua +local exec = n.exec +local expect_events = t.expect_events +local api = n.api +local fn = n.fn +local command = n.command +local eq = t.eq +local assert_alive = n.assert_alive +local pcall_err = t.pcall_err describe('decorations providers', function() local screen @@ -667,6 +668,33 @@ describe('decorations providers', function() ]]) end) + it('on_line is invoked only for buffer lines', function() + insert(mulholland) + command('vnew') + insert(mulholland) + feed('dd') + command('windo diffthis') + + exec_lua([[ + out_of_bound = false + ]]) + setup_provider([[ + local function on_do(kind, _, bufnr, row) + if kind == 'line' then + if not api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] then + out_of_bound = true + end + end + end + ]]) + + feed('<C-e>') + + exec_lua([[ + assert(out_of_bound == false) + ]]) + end) + it('errors gracefully', function() insert(mulholland) @@ -696,48 +724,7 @@ describe('decorations providers', function() end ]] - helpers.assert_alive() - end) - - it('supports subpriorities (order of definitions in a query file #27131)', function() - insert(mulholland) - setup_provider [[ - local test_ns = api.nvim_create_namespace('mulholland') - function on_do(event, ...) - if event == "line" then - local win, buf, line = ... - api.nvim_buf_set_extmark(buf, test_ns, line, 0, { - end_row = line + 1, - hl_eol = true, - hl_group = 'Comment', - ephemeral = true, - priority = 100, - _subpriority = 20, - }) - - -- This extmark is set last but has a lower subpriority, so the first extmark "wins" - api.nvim_buf_set_extmark(buf, test_ns, line, 0, { - end_row = line + 1, - hl_eol = true, - hl_group = 'String', - ephemeral = true, - priority = 100, - _subpriority = 10, - }) - end - end - ]] - - screen:expect{grid=[[ - {4:// just to see if there was an accident }| - {4:// on Mulholland Drive }| - {4:try_start(); }| - {4:bufref_T save_buf; }| - {4:switch_buffer(&save_buf, buf); }| - {4:posp = getmark(mark, false); }| - {4:restore_buffer(&save_buf);^ }| - | - ]]} + n.assert_alive() end) it('is not invoked repeatedly in Visual mode with vim.schedule() #20235', function() @@ -2301,8 +2288,21 @@ describe('extmark decorations', function() ]]} end) + it('virtual text does not crash with blend, conceal and wrap #27836', function() + screen:try_resize(50, 3) + insert(('a'):rep(45) .. '|hidden|' .. ('b'):rep(45)) + command('syntax match test /|hidden|/ conceal') + command('set conceallevel=2 concealcursor=n') + api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{'FOO'}}, virt_text_pos='right_align', hl_mode='blend'}) + screen:expect{grid=[[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa FOO| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b | + | + ]]} + end) + it('works with both hl_group and sign_hl_group', function() - screen:try_resize(screen._width, 3) + screen:try_resize(50, 3) insert('abcdefghijklmn') api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S', sign_hl_group='NonText', hl_group='Error', end_col=14}) screen:expect{grid=[[ @@ -2343,10 +2343,9 @@ describe('extmark decorations', function() local url = 'https://example.com' - screen:set_default_attr_ids({ - e = { bold = true, foreground = Screen.colors.Blue }, - u = { url = url }, - }) + screen:add_extra_attr_ids { + u = { url = "https://example.com" }, + } api.nvim_buf_set_extmark(0, ns, 1, 4, { end_col = 14, @@ -2366,8 +2365,8 @@ describe('extmark decorations', function() colpos = colpos+1 | end | en^d | - {e:~ }| - {e:~ }| + {1:~ }| + {1:~ }| | ]]} end) @@ -2399,7 +2398,7 @@ describe('extmark decorations', function() | ]]} - helpers.assert_alive() + n.assert_alive() end) it('priority ordering of overlay or win_col virtual text at same position', function() @@ -4042,16 +4041,8 @@ describe('decorations: virtual lines', function() clear() screen = Screen.new(50, 12) screen:attach() - screen:set_default_attr_ids { - [1] = {bold=true, foreground=Screen.colors.Blue}; - [2] = {foreground = Screen.colors.DarkCyan}; - [3] = {background = Screen.colors.Yellow1}; - [4] = {bold = true}; - [5] = {background = Screen.colors.Yellow, foreground = Screen.colors.Blue}; - [6] = {foreground = Screen.colors.Blue}; - [7] = {foreground = Screen.colors.SlateBlue}; - [8] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue}; - [9] = {foreground = Screen.colors.Brown}; + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow }, } ns = api.nvim_create_namespace 'test' @@ -4092,7 +4083,7 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | - {1:>> }{2:krealloc}: change the size of an allocation | + {1:>> }{25:krealloc}: change the size of an allocation | ^khkey_t *new_keys = (khkey_t *)krealloc((void *)| h->keys, new_n_buckets * sizeof(khkey_t)); | h->keys = new_keys; | @@ -4108,12 +4099,12 @@ if (h->n_buckets < new_n_buckets) { // expand feed '/krealloc<cr>' screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | - {1:>> }{2:krealloc}: change the size of an allocation | - khkey_t *new_keys = (khkey_t *){3:^krealloc}((void *)| + {1:>> }{25:krealloc}: change the size of an allocation | + khkey_t *new_keys = (khkey_t *){10:^krealloc}((void *)| h->keys, new_n_buckets * sizeof(khkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + char *new_vals = {10:krealloc}( h->vals_buf, new_n_| buckets * val_size); | h->vals_buf = new_vals; | } | @@ -4126,28 +4117,28 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *) | - {1:>> }{2:krealloc}: change the size of an allocation | - {3:^krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + {1:>> }{25:krealloc}: change the size of an allocation | + {10:^krealloc}((void *)h->keys, new_n_buckets * sizeof(k| hkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + char *new_vals = {10:krealloc}( h->vals_buf, new_n_| buckets * val_size); | h->vals_buf = new_vals; | } | - {4:-- INSERT --} | + {5:-- INSERT --} | ]]} feed '<esc>3+' screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *) | - {1:>> }{2:krealloc}: change the size of an allocation | - {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + {1:>> }{25:krealloc}: change the size of an allocation | + {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| hkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_| buckets * val_size); | h->vals_buf = new_vals; | } | @@ -4160,14 +4151,14 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *) | - {1:>> }{2:krealloc}: change the size of an allocation | - {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + {1:>> }{25:krealloc}: change the size of an allocation | + {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| hkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_| buckets * val_size); | - {5:^^ REVIEW:}{6: new_vals variable seems unnecessary?} | + {100:^^ REVIEW:}{18: new_vals variable seems unnecessary?} | h->vals_buf = new_vals; | | ]]} @@ -4176,11 +4167,11 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *) | - {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| hkey_t)); | h->keys = new_keys; | if (kh_is_map && val_size) { | - ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_| buckets * val_size); | h->vals_buf = new_vals; | } | @@ -4235,9 +4226,9 @@ if (h->n_buckets < new_n_buckets) { // expand feed '<c-b>' screen:expect{grid=[[ - {7:refactor(khash): }take size of values as parameter | - Author: Dev Devsson, {6:Tue Aug 31 10:13:37 2021} | - ^if (h->n_buckets < new_n_buckets) { // expand | + {16:refactor(khash): }take size of values as parameter | + Author: Dev Devsson, {18:Tue Aug 31 10:13:37 2021} | + if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *)krealloc((void *)| h->keys, new_n_buckets * sizeof(khkey_t)); | h->keys = new_keys; | @@ -4245,7 +4236,7 @@ if (h->n_buckets < new_n_buckets) { // expand char *new_vals = krealloc( h->vals_buf, new_n_| buckets * val_size); | h->vals_buf = new_vals; | - } | + ^} | | ]]} end) @@ -4461,7 +4452,7 @@ if (h->n_buckets < new_n_buckets) { // expand api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'bar', 'Comment'}}}}) screen:expect([[ fo^o | - {6:bar} | + {18:bar} | {1:~ }|*9 | ]]) @@ -4520,7 +4511,7 @@ if (h->n_buckets < new_n_buckets) { // expand ff | gg | they see me | - {7:scrolling} | + {16:scrolling} | | ]]} @@ -4530,7 +4521,7 @@ if (h->n_buckets < new_n_buckets) { // expand ff | gg | they see me | - {7:scrolling} | + {16:scrolling} | they | | ]]} @@ -4540,9 +4531,9 @@ if (h->n_buckets < new_n_buckets) { // expand ^ff | gg | they see me | - {7:scrolling} | + {16:scrolling} | they | - {7:hatin'} | + {16:hatin'} | | ]]} @@ -4550,9 +4541,9 @@ if (h->n_buckets < new_n_buckets) { // expand screen:expect{grid=[[ ^gg | they see me | - {7:scrolling} | + {16:scrolling} | they | - {7:hatin'} | + {16:hatin'} | hh | | ]]} @@ -4560,9 +4551,9 @@ if (h->n_buckets < new_n_buckets) { // expand feed '<c-e>' screen:expect{grid=[[ they see me | - {7:scrolling} | + {16:scrolling} | they | - {7:hatin'} | + {16:hatin'} | ^hh | {1:~ }| | @@ -4570,9 +4561,9 @@ if (h->n_buckets < new_n_buckets) { // expand feed '<c-e>' screen:expect{grid=[[ - {7:scrolling} | + {16:scrolling} | they | - {7:hatin'} | + {16:hatin'} | ^hh | {1:~ }|*2 | @@ -4581,7 +4572,7 @@ if (h->n_buckets < new_n_buckets) { // expand feed '<c-e>' screen:expect{grid=[[ they | - {7:hatin'} | + {16:hatin'} | ^hh | {1:~ }|*3 | @@ -4589,7 +4580,7 @@ if (h->n_buckets < new_n_buckets) { // expand feed '<c-e>' screen:expect{grid=[[ - {7:hatin'} | + {16:hatin'} | ^hh | {1:~ }|*4 | @@ -4608,17 +4599,17 @@ if (h->n_buckets < new_n_buckets) { // expand feed 'gg' command 'set number signcolumn=yes' screen:expect{grid=[[ - {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| - {8: }{9: }d | - {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| - {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| - {8: }{9: }t)); | - {8: }{9: 3 } h->keys = new_keys; | - {8: }{9: 4 } if (kh_is_map && val_size) { | - {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | - {8: }{9: }new_n_buckets * val_size); | - {8: }{9: 6 } h->vals_buf = new_vals; | - {8: }{9: 7 } } | + {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {7: }{8: }d | + {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {7: }{8: }t)); | + {7: }{8: 3 } h->keys = new_keys; | + {7: }{8: 4 } if (kh_is_map && val_size) { | + {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, | + {7: }{8: }new_n_buckets * val_size); | + {7: }{8: 6 } h->vals_buf = new_vals; | + {7: }{8: 7 } } | | ]]} @@ -4630,17 +4621,17 @@ if (h->n_buckets < new_n_buckets) { // expand }) screen:expect{grid=[[ - {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| - {8: }{9: }d | - {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| - {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| - {8: }{9: }t)); | - {8: }{9: 3 } h->keys = new_keys; | - {8: }{9: }{7:Some special} | - {8: }{9: }{6:remark about codes} | - {8: }{9: 4 } if (kh_is_map && val_size) { | - {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | - {8: }{9: }new_n_buckets * val_size); | + {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {7: }{8: }d | + {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {7: }{8: }t)); | + {7: }{8: 3 } h->keys = new_keys; | + {7: }{8: }{16:Some special} | + {7: }{8: }{18:remark about codes} | + {7: }{8: 4 } if (kh_is_map && val_size) { | + {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, | + {7: }{8: }new_n_buckets * val_size); | | ]]} @@ -4653,17 +4644,17 @@ if (h->n_buckets < new_n_buckets) { // expand id=markid; }) screen:expect{grid=[[ - {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| - {8: }{9: }d | - {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| - {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| - {8: }{9: }t)); | - {8: }{9: 3 } h->keys = new_keys; | - {7:Some special} | - {6:remark about codes} | - {8: }{9: 4 } if (kh_is_map && val_size) { | - {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | - {8: }{9: }new_n_buckets * val_size); | + {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {7: }{8: }d | + {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {7: }{8: }t)); | + {7: }{8: 3 } h->keys = new_keys; | + {16:Some special} | + {18:remark about codes} | + {7: }{8: 4 } if (kh_is_map && val_size) { | + {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, | + {7: }{8: }new_n_buckets * val_size); | | ]]} end) @@ -4679,7 +4670,7 @@ if (h->n_buckets < new_n_buckets) { // expand ^if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *)krealloc((void *)| h->keys, new_n_buckets * sizeof(khkey_t)); | - {1:>>}{2: very tabby}text with tabs | + {1:>>}{25: very tabby}text with tabs | h->keys = new_keys; | if (kh_is_map && val_size) { | char *new_vals = krealloc( h->vals_buf, new_n_| @@ -4695,7 +4686,7 @@ if (h->n_buckets < new_n_buckets) { // expand ^if (h->n_buckets < new_n_buckets) { // expand | khkey_t *new_keys = (khkey_t *)krealloc((void *)| h->keys, new_n_buckets * sizeof(khkey_t)); | - {1:>>}{2: very tabby}text with tabs | + {1:>>}{25: very tabby}text with tabs | h->keys = new_keys; | if (kh_is_map && val_size) { | char *new_vals = krealloc( h->vals_buf, new_n_| @@ -4708,33 +4699,33 @@ if (h->n_buckets < new_n_buckets) { // expand command 'set number' screen:expect{grid=[[ - {9: 1 }^if (h->n_buckets < new_n_buckets) { // expand | - {9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| - {9: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| - {9: }{1:>>}{2: very tabby}text with tabs | - {9: 3 } h->keys = new_keys; | - {9: 4 } if (kh_is_map && val_size) { | - {9: 5 } char *new_vals = krealloc( h->vals_buf, ne| - {9: }w_n_buckets * val_size); | - {9: 6 } h->vals_buf = new_vals; | - {9: 7 } } | - {9: 8 }} | + {8: 1 }^if (h->n_buckets < new_n_buckets) { // expand | + {8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| + {8: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| + {8: }{1:>>}{25: very tabby}text with tabs | + {8: 3 } h->keys = new_keys; | + {8: 4 } if (kh_is_map && val_size) { | + {8: 5 } char *new_vals = krealloc( h->vals_buf, ne| + {8: }w_n_buckets * val_size); | + {8: 6 } h->vals_buf = new_vals; | + {8: 7 } } | + {8: 8 }} | | ]]} command 'set tabstop&' screen:expect{grid=[[ - {9: 1 }^if (h->n_buckets < new_n_buckets) { // expand | - {9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| - {9: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| - {9: }{1:>>}{2: very tabby}text with tabs | - {9: 3 } h->keys = new_keys; | - {9: 4 } if (kh_is_map && val_size) { | - {9: 5 } char *new_vals = krealloc( h->vals_buf, ne| - {9: }w_n_buckets * val_size); | - {9: 6 } h->vals_buf = new_vals; | - {9: 7 } } | - {9: 8 }} | + {8: 1 }^if (h->n_buckets < new_n_buckets) { // expand | + {8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| + {8: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| + {8: }{1:>>}{25: very tabby}text with tabs | + {8: 3 } h->keys = new_keys; | + {8: 4 } if (kh_is_map && val_size) { | + {8: 5 } char *new_vals = krealloc( h->vals_buf, ne| + {8: }w_n_buckets * val_size); | + {8: 6 } h->vals_buf = new_vals; | + {8: 7 } } | + {8: 8 }} | | ]]} end) @@ -4771,12 +4762,12 @@ if (h->n_buckets < new_n_buckets) { // expand api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'VIRT LINE 1', 'NonText'}}}, virt_lines_leftcol = true}) api.nvim_buf_set_extmark(0, ns, 3, 0, {virt_lines = {{{'VIRT LINE 2', 'NonText'}}}}) screen:expect{grid=[[ - aaa{9: 1 }| + aaa{8: 1 }| {1:1 ENIL TRIV}| - bbb{9: 2 }| - ccc{9: 3 }| - ^ddd{9: 4 }| - {1:2 ENIL TRIV}{9: }| + bbb{8: 2 }| + ccc{8: 3 }| + ^ddd{8: 4 }| + {1:2 ENIL TRIV}{8: }| {1: ~}| | ]]} @@ -4847,6 +4838,104 @@ if (h->n_buckets < new_n_buckets) { // expand ]]) end) + it('does not break cursor position with concealcursor #27887', function() + command('vsplit') + insert('\n') + api.nvim_set_option_value('conceallevel', 2, {}) + api.nvim_set_option_value('concealcursor', 'niv', {}) + api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'VIRT1'}}, {{'VIRT2'}}} }) + screen:expect([[ + │ | + VIRT1 │VIRT1 | + VIRT2 │VIRT2 | + ^ │ | + {1:~ }│{1:~ }|*6 + {3:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + end) + + it('works with full page scrolling #28290', function() + screen:try_resize(20, 8) + command('call setline(1, range(20))') + api.nvim_buf_set_extmark(0, ns, 10, 0, { virt_lines = {{{'VIRT1'}}, {{'VIRT2'}}} }) + screen:expect([[ + ^0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + | + ]]) + feed('<C-F>') + screen:expect([[ + ^5 | + 6 | + 7 | + 8 | + 9 | + 10 | + VIRT1 | + | + ]]) + feed('<C-F>') + screen:expect([[ + ^10 | + VIRT1 | + VIRT2 | + 11 | + 12 | + 13 | + 14 | + | + ]]) + feed('<C-F>') + screen:expect([[ + ^13 | + 14 | + 15 | + 16 | + 17 | + 18 | + 19 | + | + ]]) + feed('<C-B>') + screen:expect([[ + 10 | + VIRT1 | + VIRT2 | + 11 | + 12 | + 13 | + ^14 | + | + ]]) + feed('<C-B>') + screen:expect([[ + 5 | + 6 | + 7 | + 8 | + 9 | + ^10 | + VIRT1 | + | + ]]) + feed('<C-B>') + screen:expect([[ + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + ^6 | + | + ]]) + end) end) describe('decorations: signs', function() @@ -4855,11 +4944,8 @@ describe('decorations: signs', function() clear() screen = Screen.new(50, 10) screen:attach() - screen:set_default_attr_ids { - [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey}; - [2] = {foreground = Screen.colors.Blue1, bold = true}; - [3] = {background = Screen.colors.Yellow1, foreground = Screen.colors.Blue1}; - [4] = {foreground = Screen.colors.Gray100, background = Screen.colors.Red}; + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow }, } ns = api.nvim_create_namespace 'test' @@ -4881,13 +4967,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S'}) screen:expect{grid=[[ - {1: }^l1 | + {7: }^l1 | S l2 | - {1: }l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }l3 | + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -4899,13 +4985,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1}) screen:expect{grid=[[ - {1: }^l1 | + {7: }^l1 | S l2 | - {1: }l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }l3 | + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -4916,13 +5002,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text='S', hl_group='Todo', end_col=1}) screen:expect{grid=[[ - {1: }^l1 | - S {3:l}2 | - {1: }l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }^l1 | + S {100:l}2 | + {7: }l3 | + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} @@ -4936,13 +5022,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2}) screen:expect{grid=[[ - {1: }^l1 | + {7: }^l1 | S l2 | S l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -4955,13 +5041,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S2', end_row = 4}) screen:expect{grid=[[ - {1: }^l1 | + {7: }^l1 | S1l2 | - {1: }l3 | + {7: }l3 | S2l4 | S2l5 | - {1: } | - {2:~ }|*3 + {7: } | + {1:~ }|*3 | ]]} end) @@ -4973,13 +5059,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S1'}) api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row = 3}) screen:expect{grid=[[ - {1: }^l1 | - S2{1: }l2 | - S2{1: }l3 | - S1S2l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }^l1 | + S2{7: }l2 | + S2{7: }l3 | + S2S1l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -4993,13 +5079,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S2', end_row=3}) screen:expect{grid=[[ - {1: }^l1 | - S1{1: }l2 | - S1S2l3 | - S2{1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }^l1 | + S1{7: }l2 | + S2S1l3 | + S2{7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -5014,11 +5100,11 @@ l5 screen:expect{grid=[[ S1^l1 | S2l2 | - {1: }l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + {7: }l3 | + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -5027,8 +5113,8 @@ l5 insert(example_test3) feed 'gg' - helpers.command('sign define Oldsign text=x') - helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) + n.command('sign define Oldsign text=x') + n.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'}) api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'}) @@ -5036,13 +5122,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) screen:expect{grid=[[ - S1S4^l1 | - x S2l2 | - S5{1: }l3 | - {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*3 + S4S1^l1 | + S2x l2 | + S5{7: }l3 | + {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -5051,8 +5137,8 @@ l5 insert(example_test3) feed 'gg' - helpers.command('sign define Oldsign text=x') - helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) + n.command('sign define Oldsign text=x') + n.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'}) api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'}) @@ -5061,13 +5147,13 @@ l5 api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) screen:expect{grid=[[ - S1S3S4^l1 | - x S2S3l2 | - S3S5{1: }l3 | - S3{1: }l4 | - S3{1: }l5 | - {1: } | - {2:~ }|*3 + S4S3S1^l1 | + S3S2x l2 | + S5S3{7: }l3 | + S3{7: }l4 | + S3{7: }l5 | + {7: } | + {1:~ }|*3 | ]]} end) @@ -5081,11 +5167,11 @@ l5 api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='X', end_row=3}) screen:expect{grid=[[ - X {1: }^l3 | - X {1: }l4 | - {1: }l5 | - {1: } | - {2:~ }|*5 + X {7: }^l3 | + X {7: }l4 | + {7: }l5 | + {7: } | + {1:~ }|*5 | ]]} end) @@ -5110,8 +5196,8 @@ l5 end screen:expect{grid=[[ - W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |*8 - W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:^h} | + Z Y X W {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:h} |*8 + Z Y X W {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:^h} | | ]]} end) @@ -5130,8 +5216,8 @@ l5 api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1}) screen:expect{grid=[[ - S1S2O3S4S5^l1 | - {1: }l2 | + S5S4O3S2S1^l1 | + {7: }l2 | | ]]} @@ -5140,7 +5226,7 @@ l5 screen:expect{grid=[[ S5^l1 | - {1: }l2 | + {7: }l2 | | ]]} end) @@ -5161,7 +5247,7 @@ l5 command([[exe 'sign place 09 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]]) screen:expect{grid=[[ O3O3O3O3O3O3O3O3O3^ | - {2:~ }| + {1:~ }| | ]]} @@ -5170,8 +5256,8 @@ l5 api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200}) screen:expect{grid=[[ - O3O3O3O3O3O3O3O3S5^ | - {2:~ }| + S5O3O3O3O3O3O3O3O3^ | + {1:~ }| | ]]} @@ -5216,34 +5302,34 @@ l5 feed('gg') local s1 = [[ - S1S2^l1 | - S2S3l2 | - S2S3l3 | + S2S1^l1 | + S3S2l2 | + S3S2l3 | | ]] screen:expect{grid=s1} -- Correct width when :move'ing a line with signs command('move2') screen:expect{grid=[[ - S3{1: }l2 | - S1S2S3^l1 | - {1: }l3 | + S3{7: }l2 | + S3S2S1^l1 | + {7: }l3 | | ]]} command('silent undo') screen:expect{grid=s1} command('d') screen:expect{grid=[[ - S1S2S3^l2 | - S2S3{1: }l3 | - {1: }l4 | + S3S2S1^l2 | + S3S2{7: }l3 | + {7: }l4 | | ]]} command('d') screen:expect{grid=[[ - S1S2S3^l3 | - {1: }l4 | - {1: }l5 | + S3S2S1^l3 | + {7: }l4 | + {7: }l5 | | ]]} end) @@ -5289,9 +5375,9 @@ l5 norm 4Gdd ]]) screen:expect{grid=[[ - {1: }l3 | - S1S2l5 | - {1: }^ | + {7: }l3 | + S2S1l5 | + {7: }^ | | ]]} end) @@ -5306,7 +5392,7 @@ l5 screen:expect{grid=[[ S1l | S2^1 | - {1: }l2 | + {7: }l2 | | ]]} end) @@ -5319,8 +5405,8 @@ l5 api.nvim_buf_set_extmark(buf, ns, 0, 0, { sign_text = 'h' }) screen:expect{grid=[[ h ^l1 | - {1: }l2 | - {1: }l3 | + {7: }l2 | + {7: }l3 | | ]]} api.nvim_win_set_buf(0, api.nvim_create_buf(false, true)) @@ -5329,7 +5415,7 @@ l5 api.nvim_win_set_buf(0, buf) screen:expect{grid=[[ ^ | - {2:~ }|*2 + {1:~ }|*2 | ]]} end) @@ -5370,8 +5456,8 @@ l5 api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text = 'S1'}) screen:expect{grid=[[ - S1{4:^a} | - {2:~ }|*2 + S1{9:^a} | + {1:~ }|*2 | ]]} end) @@ -5382,8 +5468,8 @@ l5 api.nvim_buf_set_extmark(0, ns2, 0, 0, {sign_text = 'S2', id = 1}) screen:expect{grid=[[ - S1S2^ | - {2:~ }|*8 + S2S1^ | + {1:~ }|*8 | ]]} end) @@ -5403,9 +5489,9 @@ l5 command('0d29') screen:expect{grid=[[ - S1S2S3S4{4:^foo} | - S5{1: }{4:foo} | - {2:~ }|*7 + S4S3S2S1{9:^foo} | + S5{7: }{9:foo} | + {1:~ }|*7 29 fewer lines | ]]} @@ -5420,11 +5506,6 @@ describe('decorations: virt_text', function() clear() screen = Screen.new(50, 10) screen:attach() - screen:set_default_attr_ids { - [1] = {foreground = Screen.colors.Brown}; - [2] = {foreground = Screen.colors.Fuchsia}; - [3] = {bold = true, foreground = Screen.colors.Blue1}; - } end) it('avoids regression in #17638', function() @@ -5444,12 +5525,12 @@ describe('decorations: virt_text', function() }) screen:expect{grid=[[ - {1: 4 } | - {1: 3 }hello | - {1: 2 }hello {2:hello} | - {1: 1 }hello | - {1:5 }helloVIRTUA^L | - {3:~ }|*4 + {8: 4 } | + {8: 3 }hello | + {8: 2 }hello {26:hello} | + {8: 1 }hello | + {8:5 }helloVIRTUA^L | + {1:~ }|*4 | ]]} @@ -5457,12 +5538,12 @@ describe('decorations: virt_text', function() feed('k') screen:expect{grid=[[ - {1: 3 } | - {1: 2 }hello | - {1: 1 }hello {2:hello} | - {1:4 }hell^o | - {1: 1 }helloVIRTUAL | - {3:~ }|*4 + {8: 3 } | + {8: 2 }hello | + {8: 1 }hello {26:hello} | + {8:4 }hell^o | + {8: 1 }helloVIRTUAL | + {1:~ }|*4 | ]]} end) @@ -5474,7 +5555,7 @@ describe('decorations: virt_text', function() | hello |*4 hell^o | - {3:~ }|*3 + {1:~ }|*3 | ]]} @@ -5487,7 +5568,7 @@ describe('decorations: virt_text', function() | hello |*4 hell^o world | - {3:~ }|*3 + {1:~ }|*3 | ]]} end) @@ -5495,13 +5576,14 @@ end) describe('decorations: window scoped', function() local screen, ns + local url = 'https://example.com' before_each(function() clear() screen = Screen.new(20, 10) screen:attach() - screen:set_default_attr_ids { - [1] = { foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, + screen:add_extra_attr_ids { + [100] = { special = Screen.colors.Red, undercurl = true }, + [101] = { url = "https://example.com" }, } ns = api.nvim_create_namespace 'test' @@ -5512,7 +5594,7 @@ describe('decorations: window scoped', function() local noextmarks = { grid = [[ 1234^5 | - {2:~ }|*8 + {1:~ }|*8 | ]]} @@ -5528,12 +5610,12 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - {1:123}4^5 | - {2:~ }|*8 + {18:123}4^5 | + {1:~ }|*8 | ]]} @@ -5563,12 +5645,12 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - 1{1:c}34^5{1:b} {1:a} {1:d}| - {2:~ }|*8 + 1{18:c}34^5{18:b} {18:a} {18:d}| + {1:~ }|*8 | ]]} @@ -5585,13 +5667,13 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ 1234^5 | - {1:a} | - {2:~ }|*7 + {18:a} | + {1:~ }|*7 | ]]} @@ -5609,17 +5691,17 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - 12{1:bbbbbbbbbbbbbbbbbb}| + 12{18:bbbbbbbbbbbbbbbbbb}| 34^5 | - {2:~ }|*7 + {1:~ }|*7 | ]]} - api.nvim_win_remove_ns(0, ns) + api.nvim__win_del_ns(0, ns) screen:expect(noextmarks) end) @@ -5634,7 +5716,7 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ @@ -5650,12 +5732,6 @@ describe('decorations: window scoped', function() end) it('statuscolumn hl group', function() - local attrs = screen:get_default_attr_ids() - table.insert(attrs, { - foreground = Screen.colors.Brown, - }) - screen:set_default_attr_ids(attrs) - set_scoped_extmark(0, 0, { number_hl_group='comment', }) @@ -5667,17 +5743,17 @@ describe('decorations: window scoped', function() screen:expect { grid = [[ - {3: 1 }1234^5 | - {2:~ }|*8 + {8: 1 }1234^5 | + {1:~ }|*8 | ]]} - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - {1: 1 1234^5 }| - {2:~ }|*8 + {18: 1 1234^5 }| + {1:~ }|*8 | ]]} @@ -5686,18 +5762,13 @@ describe('decorations: window scoped', function() screen:expect { grid = [[ - {3: 1 }1234^5 | - {2:~ }|*8 + {8: 1 }1234^5 | + {1:~ }|*8 | ]]} end) it('spell', function() - local attrs = screen:get_default_attr_ids() - table.insert(attrs, { - special = Screen.colors.Red, undercurl = true - }) - screen:set_default_attr_ids(attrs) api.nvim_buf_set_lines(0,0,-1,true,{'aa'}) set_scoped_extmark(0, 0, { @@ -5712,16 +5783,16 @@ describe('decorations: window scoped', function() screen:expect { grid = [[ a^a | - {2:~ }|*8 + {1:~ }|*8 | ]]} - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - {3:a^a} | - {2:~ }|*8 + {100:a^a} | + {1:~ }|*8 | ]]} @@ -5731,19 +5802,12 @@ describe('decorations: window scoped', function() screen:expect { grid = [[ a^a | - {2:~ }|*8 + {1:~ }|*8 | ]]} end) it('url', function() - local url = 'https://example.com' - local attrs = screen:get_default_attr_ids() - table.insert(attrs, { - url = url, - }) - screen:set_default_attr_ids(attrs) - set_scoped_extmark(0, 0, { end_col=3, url=url, @@ -5751,12 +5815,12 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - {3:123}4^5 | - {2:~ }|*8 + {101:123}4^5 | + {1:~ }|*8 | ]]} @@ -5772,12 +5836,12 @@ describe('decorations: window scoped', function() end_col = 3, }) - api.nvim_win_add_ns(0, ns) + api.nvim__win_add_ns(0, ns) screen:expect { grid = [[ - {1:123}4^5 | - {2:~ }|*8 + {18:123}4^5 | + {1:~ }|*8 | ]]} @@ -5795,8 +5859,8 @@ describe('decorations: window scoped', function() screen:expect { grid = [[ - {1:123}4^5 | - {2:~ }|*8 + {18:123}4^5 | + {1:~ }|*8 | ]]} @@ -5816,34 +5880,34 @@ describe('decorations: window scoped', function() end_col = 3, }) - eq(true, api.nvim_win_add_ns(0, ns)) - eq({ ns }, api.nvim_win_get_ns(0)) + eq(true, api.nvim__win_add_ns(0, ns)) + eq({ ns }, api.nvim__win_get_ns(0)) screen:expect { grid = [[ - {1:123}4^5 | - {2:~ }|*8 + {18:123}4^5 | + {1:~ }|*8 | ]]} command 'split' command 'only' - eq({}, api.nvim_win_get_ns(0)) + eq({}, api.nvim__win_get_ns(0)) screen:expect(noextmarks) - eq(true, api.nvim_win_add_ns(0, ns)) - eq({ ns }, api.nvim_win_get_ns(0)) + eq(true, api.nvim__win_add_ns(0, ns)) + eq({ ns }, api.nvim__win_get_ns(0)) screen:expect { grid = [[ - {1:123}4^5 | - {2:~ }|*8 + {18:123}4^5 | + {1:~ }|*8 | ]]} - eq(true, api.nvim_win_remove_ns(0, ns)) - eq({}, api.nvim_win_get_ns(0)) + eq(true, api.nvim__win_del_ns(0, ns)) + eq({}, api.nvim__win_get_ns(0)) screen:expect(noextmarks) end) diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index e0dfde35f2..e79621f364 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local clear = helpers.clear -local command = helpers.command -local insert = helpers.insert -local write_file = helpers.write_file -local dedent = helpers.dedent -local exec = helpers.exec -local eq = helpers.eq -local api = helpers.api +local feed = n.feed +local clear = n.clear +local command = n.command +local insert = n.insert +local write_file = t.write_file +local dedent = t.dedent +local exec = n.exec +local eq = t.eq +local api = n.api before_each(clear) @@ -40,17 +41,6 @@ describe('Diff mode screen', function() screen = Screen.new(40, 16) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray }, - [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey }, - [6] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { bold = true, reverse = true }, - [8] = { bold = true, background = Screen.colors.Red }, - [9] = { background = Screen.colors.LightMagenta }, - }) end) it('Add a line in beginning of file 2', function() @@ -60,31 +50,31 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }{2:------------------}│{1: }{4:0 }| - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }{23:------------------}│{7: }{22:0 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7:+ }{13:+-- 4 lines: 7···}│{7:+ }{13:+-- 4 lines: 7··}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }{2:------------------}│{1: }{4:0 }| - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }{23:------------------}│{7: }{22:0 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7:+ }{13:+-- 4 lines: 7···}│{7:+ }{13:+-- 4 lines: 7··}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -96,31 +86,31 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }{4:^0 }│{1: }{2:-----------------}| - {1: }1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }{22:^0 }│{7: }{23:-----------------}| + {7: }1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7:+ }{13:+-- 4 lines: 7···}│{7:+ }{13:+-- 4 lines: 7··}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }{4:^0 }│{1: }{2:-----------------}| - {1: }1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }{22:^0 }│{7: }{23:-----------------}| + {7: }1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7:+ }{13:+-- 4 lines: 7···}│{7:+ }{13:+-- 4 lines: 7··}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -132,44 +122,44 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{2:------------------}│{1: }{4:11 }| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{23:------------------}│{7: }{22:11 }| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{2:------------------}│{1: }{4:11 }| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{23:------------------}│{7: }{22:11 }| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) screen:try_resize(40, 9) screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) end) @@ -181,44 +171,44 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{4:11 }│{1: }{2:-----------------}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{22:11 }│{7: }{23:-----------------}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{4:11 }│{1: }{2:-----------------}| - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{22:11 }│{7: }{23:-----------------}| + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) screen:try_resize(40, 9) screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 4 lines: 1···}│{7:+ }{13:+-- 4 lines: 1··}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) end) @@ -230,39 +220,39 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }{2:------------------}│{1: }{4:4 }| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{4:11 }│{1: }{2:-----------------}| - {6:~ }│{6:~ }|*2 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }{23:------------------}│{7: }{22:4 }| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{22:11 }│{7: }{23:-----------------}| + {1:~ }│{1:~ }|*2 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }{2:------------------}│{1: }{4:4 }| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{4:11 }│{1: }{2:-----------------}| - {6:~ }│{6:~ }|*2 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }{23:------------------}│{7: }{22:4 }| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{22:11 }│{7: }{23:-----------------}| + {1:~ }│{1:~ }|*2 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -274,39 +264,39 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }{4:4 }│{1: }{2:-----------------}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{2:------------------}│{1: }{4:11 }| - {6:~ }│{6:~ }|*2 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }{22:4 }│{7: }{23:-----------------}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{23:------------------}│{7: }{22:11 }| + {1:~ }│{1:~ }|*2 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^1 │{1: }1 | - {1: }2 │{1: }2 | - {1: }3 │{1: }3 | - {1: }4 │{1: }4 | - {1: }{4:4 }│{1: }{2:-----------------}| - {1: }5 │{1: }5 | - {1: }6 │{1: }6 | - {1: }7 │{1: }7 | - {1: }8 │{1: }8 | - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }{2:------------------}│{1: }{4:11 }| - {6:~ }│{6:~ }|*2 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^1 │{7: }1 | + {7: }2 │{7: }2 | + {7: }3 │{7: }3 | + {7: }4 │{7: }4 | + {7: }{22:4 }│{7: }{23:-----------------}| + {7: }5 │{7: }5 | + {7: }6 │{7: }6 | + {7: }7 │{7: }7 | + {7: }8 │{7: }8 | + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }{23:------------------}│{7: }{22:11 }| + {1:~ }│{1:~ }|*2 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -372,41 +362,41 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler<cr>') screen:expect([[ - {1: }^#include <stdio.h>│{1: }#include <stdio.h| - {1: } │{1: } | - {1: }{8:// Frobs foo heart}│{1: }{8:int fib(int n)}{9: }| - {1: }{4:int frobnitz(int f}│{1: }{2:-----------------}| - {1: }{ │{1: }{ | - {1: }{9: i}{8:nt i;}{9: }│{1: }{9: i}{8:f(n > 2)}{9: }| - {1: }{4: for(i = 0; i <}│{1: }{2:-----------------}| - {1: } { │{1: } { | - {1: }{9: }{8:printf("Yo}│{1: }{9: }{8:return fi}| - {1: }{4: printf("%d}│{1: }{2:-----------------}| - {1: } } │{1: } } | - {1: }{2:------------------}│{1: }{4: return 1; }| - {1: }} │{1: }} | - {1: } │{1: } | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^#include <stdio.h>│{7: }#include <stdio.h| + {7: } │{7: } | + {7: }{27:// Frobs foo heart}│{7: }{27:int fib(int n)}{4: }| + {7: }{22:int frobnitz(int f}│{7: }{23:-----------------}| + {7: }{ │{7: }{ | + {7: }{4: i}{27:nt i;}{4: }│{7: }{4: i}{27:f(n > 2)}{4: }| + {7: }{22: for(i = 0; i <}│{7: }{23:-----------------}| + {7: } { │{7: } { | + {7: }{4: }{27:printf("Yo}│{7: }{4: }{27:return fi}| + {7: }{22: printf("%d}│{7: }{23:-----------------}| + {7: } } │{7: } } | + {7: }{23:------------------}│{7: }{22: return 1; }| + {7: }} │{7: }} | + {7: } │{7: } | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) feed('G') screen:expect([[ - {1: }{2:------------------}│{1: }{4:int frobnitz(int }| - {1: }{ │{1: }{ | - {1: }{9: i}{8:f(n > 1)}{9: }│{1: }{9: i}{8:nt i;}{9: }| - {1: }{2:------------------}│{1: }{4: for(i = 0; i }| - {1: } { │{1: } { | - {1: }{9: }{8:return fac}│{1: }{9: }{8:printf("%}| - {1: } } │{1: } } | - {1: }{4: return 1; }│{1: }{2:-----------------}| - {1: }} │{1: }} | - {1: } │{1: } | - {1: }int main(int argc,│{1: }int main(int argc| - {1: }{ │{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} │{1: }} | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }{23:------------------}│{7: }{22:int frobnitz(int }| + {7: }{ │{7: }{ | + {7: }{4: i}{27:f(n > 1)}{4: }│{7: }{4: i}{27:nt i;}{4: }| + {7: }{23:------------------}│{7: }{22: for(i = 0; i }| + {7: } { │{7: } { | + {7: }{4: }{27:return fac}│{7: }{4: }{27:printf("%}| + {7: } } │{7: } } | + {7: }{22: return 1; }│{7: }{23:-----------------}| + {7: }} │{7: }} | + {7: } │{7: } | + {7: }int main(int argc,│{7: }int main(int argc| + {7: }{ │{7: }{ | + {7: }{4: frobnitz(f}{27:act}{4:(}│{7: }{4: frobnitz(f}{27:ib}{4:(}| + {7: }^} │{7: }} | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) end) @@ -415,41 +405,41 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,algorithm:patience<cr>') screen:expect([[ - {1: }^#include <stdio.h>│{1: }#include <stdio.h| - {1: } │{1: } | - {1: }{2:------------------}│{1: }{4:int fib(int n) }| - {1: }{2:------------------}│{1: }{4:{ }| - {1: }{2:------------------}│{1: }{4: if(n > 2) }| - {1: }{2:------------------}│{1: }{4: { }| - {1: }{2:------------------}│{1: }{4: return fi}| - {1: }{2:------------------}│{1: }{4: } }| - {1: }{2:------------------}│{1: }{4: return 1; }| - {1: }{2:------------------}│{1: }{4:} }| - {1: }{2:------------------}│{1: }{4: }| - {1: }// Frobs foo heart│{1: }// Frobs foo hear| - {1: }int frobnitz(int f│{1: }int frobnitz(int | - {1: }{ │{1: }{ | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^#include <stdio.h>│{7: }#include <stdio.h| + {7: } │{7: } | + {7: }{23:------------------}│{7: }{22:int fib(int n) }| + {7: }{23:------------------}│{7: }{22:{ }| + {7: }{23:------------------}│{7: }{22: if(n > 2) }| + {7: }{23:------------------}│{7: }{22: { }| + {7: }{23:------------------}│{7: }{22: return fi}| + {7: }{23:------------------}│{7: }{22: } }| + {7: }{23:------------------}│{7: }{22: return 1; }| + {7: }{23:------------------}│{7: }{22:} }| + {7: }{23:------------------}│{7: }{22: }| + {7: }// Frobs foo heart│{7: }// Frobs foo hear| + {7: }int frobnitz(int f│{7: }int frobnitz(int | + {7: }{ │{7: }{ | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) feed('G') screen:expect([[ - {1: } │{1: } | - {1: }{4:int fact(int n) }│{1: }{2:-----------------}| - {1: }{4:{ }│{1: }{2:-----------------}| - {1: }{4: if(n > 1) }│{1: }{2:-----------------}| - {1: }{4: { }│{1: }{2:-----------------}| - {1: }{4: return fac}│{1: }{2:-----------------}| - {1: }{4: } }│{1: }{2:-----------------}| - {1: }{4: return 1; }│{1: }{2:-----------------}| - {1: }{4:} }│{1: }{2:-----------------}| - {1: }{4: }│{1: }{2:-----------------}| - {1: }int main(int argc,│{1: }int main(int argc| - {1: }{ │{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} │{1: }} | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: } │{7: } | + {7: }{22:int fact(int n) }│{7: }{23:-----------------}| + {7: }{22:{ }│{7: }{23:-----------------}| + {7: }{22: if(n > 1) }│{7: }{23:-----------------}| + {7: }{22: { }│{7: }{23:-----------------}| + {7: }{22: return fac}│{7: }{23:-----------------}| + {7: }{22: } }│{7: }{23:-----------------}| + {7: }{22: return 1; }│{7: }{23:-----------------}| + {7: }{22:} }│{7: }{23:-----------------}| + {7: }{22: }│{7: }{23:-----------------}| + {7: }int main(int argc,│{7: }int main(int argc| + {7: }{ │{7: }{ | + {7: }{4: frobnitz(f}{27:act}{4:(}│{7: }{4: frobnitz(f}{27:ib}{4:(}| + {7: }^} │{7: }} | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) end) @@ -458,41 +448,41 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,algorithm:histogram<cr>') screen:expect([[ - {1: }^#include <stdio.h>│{1: }#include <stdio.h| - {1: } │{1: } | - {1: }{2:------------------}│{1: }{4:int fib(int n) }| - {1: }{2:------------------}│{1: }{4:{ }| - {1: }{2:------------------}│{1: }{4: if(n > 2) }| - {1: }{2:------------------}│{1: }{4: { }| - {1: }{2:------------------}│{1: }{4: return fi}| - {1: }{2:------------------}│{1: }{4: } }| - {1: }{2:------------------}│{1: }{4: return 1; }| - {1: }{2:------------------}│{1: }{4:} }| - {1: }{2:------------------}│{1: }{4: }| - {1: }// Frobs foo heart│{1: }// Frobs foo hear| - {1: }int frobnitz(int f│{1: }int frobnitz(int | - {1: }{ │{1: }{ | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^#include <stdio.h>│{7: }#include <stdio.h| + {7: } │{7: } | + {7: }{23:------------------}│{7: }{22:int fib(int n) }| + {7: }{23:------------------}│{7: }{22:{ }| + {7: }{23:------------------}│{7: }{22: if(n > 2) }| + {7: }{23:------------------}│{7: }{22: { }| + {7: }{23:------------------}│{7: }{22: return fi}| + {7: }{23:------------------}│{7: }{22: } }| + {7: }{23:------------------}│{7: }{22: return 1; }| + {7: }{23:------------------}│{7: }{22:} }| + {7: }{23:------------------}│{7: }{22: }| + {7: }// Frobs foo heart│{7: }// Frobs foo hear| + {7: }int frobnitz(int f│{7: }int frobnitz(int | + {7: }{ │{7: }{ | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) feed('G') screen:expect([[ - {1: } │{1: } | - {1: }{4:int fact(int n) }│{1: }{2:-----------------}| - {1: }{4:{ }│{1: }{2:-----------------}| - {1: }{4: if(n > 1) }│{1: }{2:-----------------}| - {1: }{4: { }│{1: }{2:-----------------}| - {1: }{4: return fac}│{1: }{2:-----------------}| - {1: }{4: } }│{1: }{2:-----------------}| - {1: }{4: return 1; }│{1: }{2:-----------------}| - {1: }{4:} }│{1: }{2:-----------------}| - {1: }{4: }│{1: }{2:-----------------}| - {1: }int main(int argc,│{1: }int main(int argc| - {1: }{ │{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} │{1: }} | - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: } │{7: } | + {7: }{22:int fact(int n) }│{7: }{23:-----------------}| + {7: }{22:{ }│{7: }{23:-----------------}| + {7: }{22: if(n > 1) }│{7: }{23:-----------------}| + {7: }{22: { }│{7: }{23:-----------------}| + {7: }{22: return fac}│{7: }{23:-----------------}| + {7: }{22: } }│{7: }{23:-----------------}| + {7: }{22: return 1; }│{7: }{23:-----------------}| + {7: }{22:} }│{7: }{23:-----------------}| + {7: }{22: }│{7: }{23:-----------------}| + {7: }int main(int argc,│{7: }int main(int argc| + {7: }{ │{7: }{ | + {7: }{4: frobnitz(f}{27:act}{4:(}│{7: }{4: frobnitz(f}{27:ib}{4:(}| + {7: }^} │{7: }} | + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) end) @@ -525,17 +515,17 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler<cr>') screen:expect([[ - {1: }^def finalize(value│{1: }def finalize(valu| - {1: } │{1: } | - {1: } values.each do |│{1: } values.each do | - {1: }{2:------------------}│{1: }{4: v.prepare }| - {1: }{2:------------------}│{1: }{4: end }| - {1: }{2:------------------}│{1: }{4: }| - {1: }{2:------------------}│{1: }{4: values.each do }| - {1: } v.finalize │{1: } v.finalize | - {1: } end │{1: } end | - {6:~ }│{6:~ }|*5 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^def finalize(value│{7: }def finalize(valu| + {7: } │{7: } | + {7: } values.each do |│{7: } values.each do | + {7: }{23:------------------}│{7: }{22: v.prepare }| + {7: }{23:------------------}│{7: }{22: end }| + {7: }{23:------------------}│{7: }{22: }| + {7: }{23:------------------}│{7: }{22: values.each do }| + {7: } v.finalize │{7: } v.finalize | + {7: } end │{7: } end | + {1:~ }│{1:~ }|*5 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) end) @@ -544,17 +534,17 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,indent-heuristic<cr>') screen:expect([[ - {1: }^def finalize(value│{1: }def finalize(valu| - {1: } │{1: } | - {1: }{2:------------------}│{1: }{4: values.each do }| - {1: }{2:------------------}│{1: }{4: v.prepare }| - {1: }{2:------------------}│{1: }{4: end }| - {1: }{2:------------------}│{1: }{4: }| - {1: } values.each do |│{1: } values.each do | - {1: } v.finalize │{1: } v.finalize | - {1: } end │{1: } end | - {6:~ }│{6:~ }|*5 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^def finalize(value│{7: }def finalize(valu| + {7: } │{7: } | + {7: }{23:------------------}│{7: }{22: values.each do }| + {7: }{23:------------------}│{7: }{22: v.prepare }| + {7: }{23:------------------}│{7: }{22: end }| + {7: }{23:------------------}│{7: }{22: }| + {7: } values.each do |│{7: } values.each do | + {7: } v.finalize │{7: } v.finalize | + {7: } end │{7: } end | + {1:~ }│{1:~ }|*5 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) end) @@ -564,17 +554,17 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,indent-heuristic,algorithm:patience<cr>') feed(':<cr>') screen:expect([[ - {1: }^def finalize(value│{1: }def finalize(valu| - {1: } │{1: } | - {1: }{2:------------------}│{1: }{4: values.each do }| - {1: }{2:------------------}│{1: }{4: v.prepare }| - {1: }{2:------------------}│{1: }{4: end }| - {1: }{2:------------------}│{1: }{4: }| - {1: } values.each do |│{1: } values.each do | - {1: } v.finalize │{1: } v.finalize | - {1: } end │{1: } end | - {6:~ }│{6:~ }|*5 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^def finalize(value│{7: }def finalize(valu| + {7: } │{7: } | + {7: }{23:------------------}│{7: }{22: values.each do }| + {7: }{23:------------------}│{7: }{22: v.prepare }| + {7: }{23:------------------}│{7: }{22: end }| + {7: }{23:------------------}│{7: }{22: }| + {7: } values.each do |│{7: } values.each do | + {7: } v.finalize │{7: } v.finalize | + {7: } end │{7: } end | + {1:~ }│{1:~ }|*5 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -587,17 +577,17 @@ int main(int argc, char **argv) feed(':set diffopt=filler<cr>') screen:expect([[ - {1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}| - {6:~ }│{6:~ }|*13 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 10 lines: 1···}│{7:+ }{13:+-- 10 lines: 1··}| + {1:~ }│{1:~ }|*13 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}| - {6:~ }│{6:~ }|*13 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:+ }{13:^+-- 10 lines: 1···}│{7:+ }{13:+-- 10 lines: 1··}| + {1:~ }│{1:~ }|*13 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -609,17 +599,17 @@ int main(int argc, char **argv) feed(':set diffopt=filler<cr>') screen:expect([[ - {1:- }^ │{1:- } | - {6:~ }│{6:~ }|*13 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:- }^ │{7:- } | + {1:~ }│{1:~ }|*13 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:- }^ │{1:- } | - {6:~ }│{6:~ }|*13 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7:- }^ │{7:- } | + {1:~ }│{1:~ }|*13 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -631,21 +621,21 @@ int main(int argc, char **argv) feed(':set diffopt=filler,icase<cr>') screen:expect([[ - {1: }^a │{1: }A | - {1: }b │{1: }b | - {1: }{9:cd }│{1: }{9:cD}{8:e}{9: }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }A | + {7: }b │{7: }b | + {7: }{4:cd }│{7: }{4:cD}{27:e}{4: }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler,icase | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^a │{1: }A | - {1: }b │{1: }b | - {1: }{9:cd }│{1: }{9:cD}{8:e}{9: }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }A | + {7: }b │{7: }b | + {7: }{4:cd }│{7: }{4:cD}{27:e}{4: }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) end) @@ -664,16 +654,16 @@ int main(int argc, char **argv) reread() feed(':set diffopt=filler,iwhite<cr>') screen:expect([[ - {1: }^int main() │{1: }int main() | - {1: }{ │{1: }{ | - {1: }{2:------------------}│{1: }{4: if (0) }| - {1: }{2:------------------}│{1: }{4: { }| - {1: } printf("Hello, │{1: } printf("Hel| - {1: } return 0; │{1: } return 0; | - {1: }{2:------------------}│{1: }{4: } }| - {1: }} │{1: }} | - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^int main() │{7: }int main() | + {7: }{ │{7: }{ | + {7: }{23:------------------}│{7: }{22: if (0) }| + {7: }{23:------------------}│{7: }{22: { }| + {7: } printf("Hello, │{7: } printf("Hel| + {7: } return 0; │{7: } return 0; | + {7: }{23:------------------}│{7: }{22: } }| + {7: }} │{7: }} | + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler,iwhite | ]]) end) @@ -682,16 +672,16 @@ int main(int argc, char **argv) reread() feed(':set diffopt=filler,iwhite,internal<cr>') screen:expect([[ - {1: }^int main() │{1: }int main() | - {1: }{ │{1: }{ | - {1: }{2:------------------}│{1: }{4: if (0) }| - {1: }{2:------------------}│{1: }{4: { }| - {1: } printf("Hello, │{1: } printf("Hel| - {1: } return 0; │{1: } return 0; | - {1: }{2:------------------}│{1: }{4: } }| - {1: }} │{1: }} | - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^int main() │{7: }int main() | + {7: }{ │{7: }{ | + {7: }{23:------------------}│{7: }{22: if (0) }| + {7: }{23:------------------}│{7: }{22: { }| + {7: } printf("Hello, │{7: } printf("Hel| + {7: } return 0; │{7: } return 0; | + {7: }{23:------------------}│{7: }{22: } }| + {7: }} │{7: }} | + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=filler,iwhite,internal | ]]) end) @@ -708,14 +698,14 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,iblank<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: }{4: }│{1: }{2:-----------------}|*2 - {1: }cd │{1: }cd | - {1: }ef │{1: } | - {1: }{8:xxx}{9: }│{1: }ef | - {6:~ }│{1: }{8:yyy}{9: }| - {6:~ }│{6:~ }|*7 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: }{22: }│{7: }{23:-----------------}|*2 + {7: }cd │{7: }cd | + {7: }ef │{7: } | + {7: }{27:xxx}{4: }│{7: }ef | + {1:~ }│{7: }{27:yyy}{4: }| + {1:~ }│{1:~ }|*7 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=internal,filler,iblank | ]]) end) @@ -725,14 +715,14 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhite<cr>') feed(':<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: } │{1: }cd | - {1: } │{1: } | - {1: }cd │{1: }ef | - {1: }ef │{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }│{6:~ }| - {6:~ }│{6:~ }|*8 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: } │{7: }cd | + {7: } │{7: } | + {7: }cd │{7: }ef | + {7: }ef │{7: }{27:yyy}{4: }| + {7: }{27:xxx}{4: }│{1:~ }| + {1:~ }│{1:~ }|*8 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -742,14 +732,14 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhiteall<cr>') feed(':<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: } │{1: }cd | - {1: } │{1: } | - {1: }cd │{1: }ef | - {1: }ef │{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }│{6:~ }| - {6:~ }│{6:~ }|*8 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: } │{7: }cd | + {7: } │{7: } | + {7: }cd │{7: }ef | + {7: }ef │{7: }{27:yyy}{4: }| + {7: }{27:xxx}{4: }│{1:~ }| + {1:~ }│{1:~ }|*8 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -759,14 +749,14 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhiteeol<cr>') feed(':<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: } │{1: }cd | - {1: } │{1: } | - {1: }cd │{1: }ef | - {1: }ef │{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }│{6:~ }| - {6:~ }│{6:~ }|*8 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: } │{7: }cd | + {7: } │{7: } | + {7: }cd │{7: }ef | + {7: }ef │{7: }{27:yyy}{4: }| + {7: }{27:xxx}{4: }│{1:~ }| + {1:~ }│{1:~ }|*8 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -784,16 +774,16 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iwhiteeol<cr>') feed(':<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: }x │{1: }x | - {1: }{9:cd }│{1: }{9:c}{8: }{9:d }| - {1: }{9:ef }│{1: }{8: }{9:ef }| - {1: }{9:xx }{8: }{9:xx }│{1: }{9:xx xx }| - {1: }foo │{1: }foo | - {1: }{2:------------------}│{1: }{4: }| - {1: }bar │{1: }bar | - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: }x │{7: }x | + {7: }{4:cd }│{7: }{4:c}{27: }{4:d }| + {7: }{4:ef }│{7: }{27: }{4:ef }| + {7: }{4:xx }{27: }{4:xx }│{7: }{4:xx xx }| + {7: }foo │{7: }foo | + {7: }{23:------------------}│{7: }{22: }| + {7: }bar │{7: }bar | + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -803,16 +793,16 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iwhiteall<cr>') feed(':<cr>') screen:expect([[ - {1: }^a │{1: }a | - {1: }x │{1: }x | - {1: }cd │{1: }c d | - {1: }ef │{1: } ef | - {1: }xx xx │{1: }xx xx | - {1: }foo │{1: }foo | - {1: }{2:------------------}│{1: }{4: }| - {1: }bar │{1: }bar | - {6:~ }│{6:~ }|*6 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^a │{7: }a | + {7: }x │{7: }x | + {7: }cd │{7: }c d | + {7: }ef │{7: } ef | + {7: }xx xx │{7: }xx xx | + {7: }foo │{7: }foo | + {7: }{23:------------------}│{7: }{22: }| + {7: }bar │{7: }bar | + {1:~ }│{1:~ }|*6 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| : | ]]) end) @@ -883,32 +873,32 @@ int main(int argc, char **argv) feed('<C-W><C-W>jjjj') screen:expect([[ - {1: }line 1 │{1: }line 1 | - {1: }line 2 │{1: }line 2 | - {1: }line 3 │{1: }line 3 | - {1: }line 4 │{1: }line 4 | - {1: } │{1: }^ | - {1: }{2:-----------------}│{1: }{4:Lorem }| - {1: }{2:-----------------}│{1: }{4:ipsum }| - {1: }{2:-----------------}│{1: }{4:dolor }| - {1: }{2:-----------------}│{1: }{4:sit }| - {1: }{2:-----------------}│{1: }{4:amet, }| - {3:<nal-diff-screen-1 }{7:<al-diff-screen-1.2 }| + {7: }line 1 │{7: }line 1 | + {7: }line 2 │{7: }line 2 | + {7: }line 3 │{7: }line 3 | + {7: }line 4 │{7: }line 4 | + {7: } │{7: }^ | + {7: }{23:-----------------}│{7: }{22:Lorem }| + {7: }{23:-----------------}│{7: }{22:ipsum }| + {7: }{23:-----------------}│{7: }{22:dolor }| + {7: }{23:-----------------}│{7: }{22:sit }| + {7: }{23:-----------------}│{7: }{22:amet, }| + {2:<nal-diff-screen-1 }{3:<al-diff-screen-1.2 }| :e | ]]) feed('j') screen:expect([[ - {1: }line 1 │{1: }line 1 | - {1: }line 2 │{1: }line 2 | - {1: }line 3 │{1: }line 3 | - {1: }line 4 │{1: }line 4 | - {1: } │{1: } | - {1: }{2:-----------------}│{1: }{4:^Lorem }| - {1: }{2:-----------------}│{1: }{4:ipsum }| - {1: }{2:-----------------}│{1: }{4:dolor }| - {1: }{2:-----------------}│{1: }{4:sit }| - {1: }{2:-----------------}│{1: }{4:amet, }| - {3:<nal-diff-screen-1 }{7:<al-diff-screen-1.2 }| + {7: }line 1 │{7: }line 1 | + {7: }line 2 │{7: }line 2 | + {7: }line 3 │{7: }line 3 | + {7: }line 4 │{7: }line 4 | + {7: } │{7: } | + {7: }{23:-----------------}│{7: }{22:^Lorem }| + {7: }{23:-----------------}│{7: }{22:ipsum }| + {7: }{23:-----------------}│{7: }{22:dolor }| + {7: }{23:-----------------}│{7: }{22:sit }| + {7: }{23:-----------------}│{7: }{22:amet, }| + {2:<nal-diff-screen-1 }{3:<al-diff-screen-1.2 }| :e | ]]) end) @@ -942,38 +932,38 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler<cr>') screen:expect([[ - {1: }^if __name__ == "__│{1: }if __name__ == "_| - {1: } import sys │{1: } import sys | - {1: }{9: }{8:app = QWidgets}│{1: }{9: }{8:comment these}| - {1: }{9: }{8:MainWindow = Q}│{1: }{9: }{8:#app = QWidge}| - {1: }{9: }{8:ui = UI_}{9:MainWi}│{1: }{9: }{8:#MainWindow =}| - {1: }{2:------------------}│{1: }{4: add a complet}| - {1: }{2:------------------}│{1: }{4: #ui = UI_Main}| - {1: }{2:------------------}│{1: }{4: add another n}| - {1: } ui.setupUI(Mai│{1: } ui.setupUI(Ma| - {1: } MainWindow.sho│{1: } MainWindow.sh| - {1: } sys.exit(app.e│{1: } sys.exit(app.| - {6:~ }│{6:~ }|*3 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^if __name__ == "__│{7: }if __name__ == "_| + {7: } import sys │{7: } import sys | + {7: }{4: }{27:app = QWidgets}│{7: }{4: }{27:comment these}| + {7: }{4: }{27:MainWindow = Q}│{7: }{4: }{27:#app = QWidge}| + {7: }{4: }{27:ui = UI_}{4:MainWi}│{7: }{4: }{27:#MainWindow =}| + {7: }{23:------------------}│{7: }{22: add a complet}| + {7: }{23:------------------}│{7: }{22: #ui = UI_Main}| + {7: }{23:------------------}│{7: }{22: add another n}| + {7: } ui.setupUI(Mai│{7: } ui.setupUI(Ma| + {7: } MainWindow.sho│{7: } MainWindow.sh| + {7: } sys.exit(app.e│{7: } sys.exit(app.| + {1:~ }│{1:~ }|*3 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) feed('G') feed(':set diffopt+=linematch:20<cr>') screen:expect([[ - {1: }if __name__ == "__│{1: }if __name__ == "_| - {1: } import sys │{1: } import sys | - {1: }{2:------------------}│{1: }{4: comment these}| - {1: }{9: app = QWidgets}│{1: }{9: }{8:#}{9:app = QWidge}| - {1: }{9: MainWindow = Q}│{1: }{9: }{8:#}{9:MainWindow =}| - {1: }{2:------------------}│{1: }{4: add a complet}| - {1: }{9: ui = UI_MainWi}│{1: }{9: }{8:#}{9:ui = UI_Main}| - {1: }{2:------------------}│{1: }{4: add another n}| - {1: } ui.setupUI(Mai│{1: } ui.setupUI(Ma| - {1: } MainWindow.sho│{1: } MainWindow.sh| - {1: } ^sys.exit(app.e│{1: } sys.exit(app.| - {6:~ }│{6:~ }|*3 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }if __name__ == "__│{7: }if __name__ == "_| + {7: } import sys │{7: } import sys | + {7: }{23:------------------}│{7: }{22: comment these}| + {7: }{4: app = QWidgets}│{7: }{4: }{27:#}{4:app = QWidge}| + {7: }{4: MainWindow = Q}│{7: }{4: }{27:#}{4:MainWindow =}| + {7: }{23:------------------}│{7: }{22: add a complet}| + {7: }{4: ui = UI_MainWi}│{7: }{4: }{27:#}{4:ui = UI_Main}| + {7: }{23:------------------}│{7: }{22: add another n}| + {7: } ui.setupUI(Mai│{7: } ui.setupUI(Ma| + {7: } MainWindow.sho│{7: } MainWindow.sh| + {7: } ^sys.exit(app.e│{7: } sys.exit(app.| + {1:~ }│{1:~ }|*3 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=linematch:20 | ]]) end) @@ -993,20 +983,20 @@ ccca]] reread() feed(':set diffopt=internal,filler,linematch:20<cr>') screen:expect([[ - {1: }^DDD │{1: }DDD | - {1: }{2:------------------}│{1: }{4:AAA }| - {1: }{8:_a}{9:a }│{1: }{8:ccc}{9:a }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^DDD │{7: }DDD | + {7: }{23:------------------}│{7: }{22:AAA }| + {7: }{27:_a}{4:a }│{7: }{27:ccc}{4:a }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]]) feed(':set diffopt+=icase<cr>') screen:expect([[ - {1: }^DDD │{1: }DDD | - {1: }{8:_}{9:aa }│{1: }{8:A}{9:AA }| - {1: }{2:------------------}│{1: }{4:ccca }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^DDD │{7: }DDD | + {7: }{27:_}{4:aa }│{7: }{27:A}{4:AA }| + {7: }{23:------------------}│{7: }{22:ccca }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=icase | ]]) end) @@ -1027,22 +1017,22 @@ AAAB]] feed(':set diffopt=internal,filler,linematch:20<cr>') screen:expect { grid = [[ - {1: }^BB │{1: }BB | - {1: }{9: AA}{8:A}{9: }│{1: }{9: AA}{8:B}{9: }| - {1: }{2:------------------}│{1: }{4:AAAB }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^BB │{7: }BB | + {7: }{4: AA}{27:A}{4: }│{7: }{4: AA}{27:B}{4: }| + {7: }{23:------------------}│{7: }{22:AAAB }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| | ]], } feed(':set diffopt+=iwhiteall<cr>') screen:expect { grid = [[ - {1: }^BB │{1: }BB | - {1: }{2:------------------}│{1: }{4: AAB }| - {1: }{9: AAA }│{1: }{9:AAA}{8:B}{9: }| - {6:~ }│{6:~ }|*11 - {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + {7: }^BB │{7: }BB | + {7: }{23:------------------}│{7: }{22: AAB }| + {7: }{4: AAA }│{7: }{4:AAA}{27:B}{4: }| + {1:~ }│{1:~ }|*11 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| :set diffopt+=iwhiteall | ]], } @@ -1057,16 +1047,16 @@ AAAB]] command('botright new') screen:expect { grid = [[ - {1: }aaa │{1: }aaa | - {1: }bbb │{1: }bbb | - {1: }ccc │{1: }ccc | - {1: } │{1: } | - {1: }{8:xx}{9: }│{1: }{8:yy}{9: }| - {6:~ }│{6:~ }| - {3:<onal-diff-screen-1 <l-diff-screen-1.2 }| + {7: }aaa │{7: }aaa | + {7: }bbb │{7: }bbb | + {7: }ccc │{7: }ccc | + {7: } │{7: } | + {7: }{27:xx}{4: }│{7: }{27:yy}{4: }| + {1:~ }│{1:~ }| + {2:<onal-diff-screen-1 <l-diff-screen-1.2 }| ^ | - {6:~ }|*6 - {7:[No Name] }| + {1:~ }|*6 + {3:[No Name] }| :e | ]], } @@ -1074,16 +1064,16 @@ AAAB]] api.nvim_buf_set_lines(buf, 1, 2, true, { 'BBB' }) screen:expect { grid = [[ - {1: }aaa │{1: }aaa | - {1: }{8:BBB}{9: }│{1: }{8:bbb}{9: }| - {1: }ccc │{1: }ccc | - {1: } │{1: } | - {1: }{8:xx}{9: }│{1: }{8:yy}{9: }| - {6:~ }│{6:~ }| - {3:<-diff-screen-1 [+] <l-diff-screen-1.2 }| + {7: }aaa │{7: }aaa | + {7: }{27:BBB}{4: }│{7: }{27:bbb}{4: }| + {7: }ccc │{7: }ccc | + {7: } │{7: } | + {7: }{27:xx}{4: }│{7: }{27:yy}{4: }| + {1:~ }│{1:~ }| + {2:<-diff-screen-1 [+] <l-diff-screen-1.2 }| ^ | - {6:~ }|*6 - {7:[No Name] }| + {1:~ }|*6 + {3:[No Name] }| :e | ]], } @@ -1097,20 +1087,20 @@ AAAB]] command('botright split | diffoff') screen:expect { grid = [[ - {1: }aaa │{1: }aaa | - {1: }bbb │{1: }bbb | - {1: }ccc │{1: }ccc | - {1: } │{1: } | - {1: }{8:xx}{9: }│{1: }{8:yy}{9: }| - {6:~ }│{6:~ }| - {3:<onal-diff-screen-1 <l-diff-screen-1.2 }| + {7: }aaa │{7: }aaa | + {7: }bbb │{7: }bbb | + {7: }ccc │{7: }ccc | + {7: } │{7: } | + {7: }{27:xx}{4: }│{7: }{27:yy}{4: }| + {1:~ }│{1:~ }| + {2:<onal-diff-screen-1 <l-diff-screen-1.2 }| ^aaa | bbb | ccc | | xx | - {6:~ }|*2 - {7:Xtest-functional-diff-screen-1 }| + {1:~ }|*2 + {3:Xtest-functional-diff-screen-1 }| :e | ]], } @@ -1118,20 +1108,20 @@ AAAB]] api.nvim_buf_set_lines(buf, 1, 2, true, { 'BBB' }) screen:expect { grid = [[ - {1: }aaa │{1: }aaa | - {1: }{8:BBB}{9: }│{1: }{8:bbb}{9: }| - {1: }ccc │{1: }ccc | - {1: } │{1: } | - {1: }{8:xx}{9: }│{1: }{8:yy}{9: }| - {6:~ }│{6:~ }| - {3:<-diff-screen-1 [+] <l-diff-screen-1.2 }| + {7: }aaa │{7: }aaa | + {7: }{27:BBB}{4: }│{7: }{27:bbb}{4: }| + {7: }ccc │{7: }ccc | + {7: } │{7: } | + {7: }{27:xx}{4: }│{7: }{27:yy}{4: }| + {1:~ }│{1:~ }| + {2:<-diff-screen-1 [+] <l-diff-screen-1.2 }| ^aaa | BBB | ccc | | xx | - {6:~ }|*2 - {7:Xtest-functional-diff-screen-1 [+] }| + {1:~ }|*2 + {3:Xtest-functional-diff-screen-1 [+] }| :e | ]], } @@ -1220,19 +1210,6 @@ end) it('diff updates line numbers below filler lines', function() local screen = Screen.new(40, 14) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray }, - [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey }, - [6] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { bold = true, reverse = true }, - [8] = { bold = true, background = Screen.colors.Red }, - [9] = { background = Screen.colors.LightMagenta }, - [10] = { bold = true, foreground = Screen.colors.Brown }, - [11] = { foreground = Screen.colors.Brown }, - }) exec([[ call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b']) vnew @@ -1241,50 +1218,50 @@ it('diff updates line numbers below filler lines', function() setlocal number rnu cursorline cursorlineopt=number foldcolumn=0 ]]) screen:expect([[ - {1: }a │{10:1 }^a | - {1: }a │{11: 1 }a | - {1: }a │{11: 2 }a | - {1: }{8:x}{9: }│{11: 3 }{8:y}{9: }| - {1: }{4:x }│{11: }{2:----------------}|*2 - {1: }b │{11: 4 }b | - {1: }b │{11: 5 }b | - {1: }b │{11: 6 }b | - {1: }b │{11: 7 }b | - {1: }b │{11: 8 }b | - {6:~ }│{6:~ }| - {3:[No Name] [+] }{7:[No Name] [+] }| + {7: }a │{15:1 }^a | + {7: }a │{8: 1 }a | + {7: }a │{8: 2 }a | + {7: }{27:x}{4: }│{8: 3 }{27:y}{4: }| + {7: }{22:x }│{8: }{23:----------------}|*2 + {7: }b │{8: 4 }b | + {7: }b │{8: 5 }b | + {7: }b │{8: 6 }b | + {7: }b │{8: 7 }b | + {7: }b │{8: 8 }b | + {1:~ }│{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]]) feed('j') screen:expect([[ - {1: }a │{11: 1 }a | - {1: }a │{10:2 }^a | - {1: }a │{11: 1 }a | - {1: }{8:x}{9: }│{11: 2 }{8:y}{9: }| - {1: }{4:x }│{11: }{2:----------------}|*2 - {1: }b │{11: 3 }b | - {1: }b │{11: 4 }b | - {1: }b │{11: 5 }b | - {1: }b │{11: 6 }b | - {1: }b │{11: 7 }b | - {6:~ }│{6:~ }| - {3:[No Name] [+] }{7:[No Name] [+] }| + {7: }a │{8: 1 }a | + {7: }a │{15:2 }^a | + {7: }a │{8: 1 }a | + {7: }{27:x}{4: }│{8: 2 }{27:y}{4: }| + {7: }{22:x }│{8: }{23:----------------}|*2 + {7: }b │{8: 3 }b | + {7: }b │{8: 4 }b | + {7: }b │{8: 5 }b | + {7: }b │{8: 6 }b | + {7: }b │{8: 7 }b | + {1:~ }│{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]]) feed('j') screen:expect([[ - {1: }a │{11: 2 }a | - {1: }a │{11: 1 }a | - {1: }a │{10:3 }^a | - {1: }{8:x}{9: }│{11: 1 }{8:y}{9: }| - {1: }{4:x }│{11: }{2:----------------}|*2 - {1: }b │{11: 2 }b | - {1: }b │{11: 3 }b | - {1: }b │{11: 4 }b | - {1: }b │{11: 5 }b | - {1: }b │{11: 6 }b | - {6:~ }│{6:~ }| - {3:[No Name] [+] }{7:[No Name] [+] }| + {7: }a │{8: 2 }a | + {7: }a │{8: 1 }a | + {7: }a │{15:3 }^a | + {7: }{27:x}{4: }│{8: 1 }{27:y}{4: }| + {7: }{22:x }│{8: }{23:----------------}|*2 + {7: }b │{8: 2 }b | + {7: }b │{8: 3 }b | + {7: }b │{8: 4 }b | + {7: }b │{8: 5 }b | + {7: }b │{8: 6 }b | + {1:~ }│{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]]) end) @@ -1293,16 +1270,6 @@ end) it('Align the filler lines when changing text in diff mode', function() local screen = Screen.new(40, 20) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, - [2] = { background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1, bold = true }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { background = Screen.colors.LightMagenta }, - [6] = { background = Screen.colors.Red, bold = true }, - [7] = { foreground = Screen.colors.Blue1, bold = true }, - [8] = { reverse = true, bold = true }, - }) exec([[ call setline(1, range(1, 15)) vnew @@ -1313,54 +1280,54 @@ it('Align the filler lines when changing text in diff mode', function() ]]) screen:expect { grid = [[ - {1: }{2:------------------}│{1: }{4:6 }| - {1: }{2:------------------}│{1: }{4:7 }| - {1: }{2:------------------}│{1: }{4:8 }| - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }11 │{1: }11 | - {1: }12 │{1: }12 | - {1: }13 │{1: }13 | - {1: }14 │{1: }14 | - {1:- }1^5 │{1:- }15 | - {7:~ }│{7:~ }|*8 - {8:[No Name] [+] }{3:[No Name] [+] }| + {7: }{23:------------------}│{7: }{22:6 }| + {7: }{23:------------------}│{7: }{22:7 }| + {7: }{23:------------------}│{7: }{22:8 }| + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }11 │{7: }11 | + {7: }12 │{7: }12 | + {7: }13 │{7: }13 | + {7: }14 │{7: }14 | + {7:- }1^5 │{7:- }15 | + {1:~ }│{1:~ }|*8 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]], } feed('ax<Esc>') screen:expect { grid = [[ - {1: }{2:------------------}│{1: }{4:6 }| - {1: }{2:------------------}│{1: }{4:7 }| - {1: }{2:------------------}│{1: }{4:8 }| - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }11 │{1: }11 | - {1: }12 │{1: }12 | - {1: }13 │{1: }13 | - {1: }14 │{1: }14 | - {1: }{5:15}{6:^x}{5: }│{1: }{5:15 }| - {7:~ }│{7:~ }|*8 - {8:[No Name] [+] }{3:[No Name] [+] }| + {7: }{23:------------------}│{7: }{22:6 }| + {7: }{23:------------------}│{7: }{22:7 }| + {7: }{23:------------------}│{7: }{22:8 }| + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }11 │{7: }11 | + {7: }12 │{7: }12 | + {7: }13 │{7: }13 | + {7: }14 │{7: }14 | + {7: }{4:15}{27:^x}{4: }│{7: }{4:15 }| + {1:~ }│{1:~ }|*8 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]], } feed('<C-W>lay<Esc>') screen:expect { grid = [[ - {1: }{2:-----------------}│{1: }{4:6 }| - {1: }{2:-----------------}│{1: }{4:7 }| - {1: }{2:-----------------}│{1: }{4:8 }| - {1: }9 │{1: }9 | - {1: }10 │{1: }10 | - {1: }11 │{1: }11 | - {1: }12 │{1: }12 | - {1: }13 │{1: }13 | - {1: }14 │{1: }14 | - {1: }{5:15}{6:x}{5: }│{1: }{5:15}{6:^y}{5: }| - {7:~ }│{7:~ }|*8 - {3:[No Name] [+] }{8:[No Name] [+] }| + {7: }{23:-----------------}│{7: }{22:6 }| + {7: }{23:-----------------}│{7: }{22:7 }| + {7: }{23:-----------------}│{7: }{22:8 }| + {7: }9 │{7: }9 | + {7: }10 │{7: }10 | + {7: }11 │{7: }11 | + {7: }12 │{7: }12 | + {7: }13 │{7: }13 | + {7: }14 │{7: }14 | + {7: }{4:15}{27:x}{4: }│{7: }{4:15}{27:^y}{4: }| + {1:~ }│{1:~ }|*8 + {2:[No Name] [+] }{3:[No Name] [+] }| | ]], } @@ -1368,15 +1335,12 @@ end) it("diff mode doesn't restore invalid 'foldcolumn' value #21647", function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue, bold = true }, - }) screen:attach() eq('0', api.nvim_get_option_value('foldcolumn', {})) command('diffsplit | bd') screen:expect([[ ^ | - {0:~ }|*4 + {1:~ }|*4 | ]]) eq('0', api.nvim_get_option_value('foldcolumn', {})) @@ -1385,16 +1349,9 @@ end) -- oldtest: Test_diff_binary() it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function() local screen = Screen.new(40, 20) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, - [2] = { reverse = true }, - [3] = { background = Screen.colors.LightBlue }, - [4] = { background = Screen.colors.LightMagenta }, - [5] = { background = Screen.colors.Red, bold = true }, - [6] = { foreground = Screen.colors.Blue, bold = true }, - [7] = { background = Screen.colors.Red, foreground = Screen.colors.Blue, bold = true }, - [8] = { reverse = true, bold = true }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Blue, bold = true, background = Screen.colors.Red }, + } screen:attach() exec([[ call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g']) @@ -1408,15 +1365,15 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun -- Test using internal diff screen:expect([[ - {1: }{5:^A}{4: }│{1: }{5:a}{4: }| - {1: }b │{1: }b | - {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| - {1: }d │{1: }d | - {1: }{5:E}{4: }│{1: }{5:e}{4: }| - {1: }f │{1: }f | - {1: }g │{1: }g | - {6:~ }│{6:~ }|*11 - {8:[No Name] [+] }{2:[No Name] [+] }| + {7: }{27:^A}{4: }│{7: }{27:a}{4: }| + {7: }b │{7: }b | + {7: }{4:c }│{7: }{4:c}{100:^@}{4: }| + {7: }d │{7: }d | + {7: }{27:E}{4: }│{7: }{27:e}{4: }| + {7: }f │{7: }f | + {7: }g │{7: }g | + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) @@ -1424,15 +1381,15 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun command('set diffopt+=icase') feed('<C-L>') screen:expect([[ - {1: }^A │{1: }a | - {1: }b │{1: }b | - {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| - {1: }d │{1: }d | - {1: }E │{1: }e | - {1: }f │{1: }f | - {1: }g │{1: }g | - {6:~ }│{6:~ }|*11 - {8:[No Name] [+] }{2:[No Name] [+] }| + {7: }^A │{7: }a | + {7: }b │{7: }b | + {7: }{4:c }│{7: }{4:c}{100:^@}{4: }| + {7: }d │{7: }d | + {7: }E │{7: }e | + {7: }f │{7: }f | + {7: }g │{7: }g | + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) @@ -1440,15 +1397,15 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun command('set diffopt=filler') feed('<C-L>') screen:expect([[ - {1: }{5:^A}{4: }│{1: }{5:a}{4: }| - {1: }b │{1: }b | - {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| - {1: }d │{1: }d | - {1: }{5:E}{4: }│{1: }{5:e}{4: }| - {1: }f │{1: }f | - {1: }g │{1: }g | - {6:~ }│{6:~ }|*11 - {8:[No Name] [+] }{2:[No Name] [+] }| + {7: }{27:^A}{4: }│{7: }{27:a}{4: }| + {7: }b │{7: }b | + {7: }{4:c }│{7: }{4:c}{100:^@}{4: }| + {7: }d │{7: }d | + {7: }{27:E}{4: }│{7: }{27:e}{4: }| + {7: }f │{7: }f | + {7: }g │{7: }g | + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) @@ -1456,15 +1413,15 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun command('set diffopt+=filler,icase') feed('<C-L>') screen:expect([[ - {1: }^A │{1: }a | - {1: }b │{1: }b | - {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| - {1: }d │{1: }d | - {1: }E │{1: }e | - {1: }f │{1: }f | - {1: }g │{1: }g | - {6:~ }│{6:~ }|*11 - {8:[No Name] [+] }{2:[No Name] [+] }| + {7: }^A │{7: }a | + {7: }b │{7: }b | + {7: }{4:c }│{7: }{4:c}{100:^@}{4: }| + {7: }d │{7: }d | + {7: }E │{7: }e | + {7: }f │{7: }f | + {7: }g │{7: }g | + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) end) @@ -1473,12 +1430,6 @@ end) it("diff mode draws 'breakindent' correctly after filler lines", function() local screen = Screen.new(45, 8) screen:attach() - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, - [2] = { background = Screen.colors.LightBlue }, - [3] = { background = Screen.colors.LightCyan, bold = true, foreground = Screen.colors.Blue }, - [4] = { foreground = Screen.colors.Blue, bold = true }, - }) exec([[ set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0 call setline(1, ['a', ' ' .. repeat('c', 50)]) @@ -1488,11 +1439,11 @@ it("diff mode draws 'breakindent' correctly after filler lines", function() norm! G$ ]]) screen:expect([[ - {1: }a │{1: }a | - {1: }{2:b }│{1: }{3:--------------------}| - {1: } cccccccccccccccccc│{1: } cccccccccccccccccc|*2 - {1: } cccccccccccccc │{1: } ccccccccccccc^c | - {4:~ }│{4:~ }|*2 + {7: }a │{7: }a | + {7: }{22:b }│{7: }{23:--------------------}| + {7: } cccccccccccccccccc│{7: } cccccccccccccccccc|*2 + {7: } cccccccccccccc │{7: } ccccccccccccc^c | + {1:~ }│{1:~ }|*2 | ]]) end) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index 0445476780..e1abd43e20 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -1,18 +1,23 @@ -local uv = vim.uv - -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local uv = vim.uv -local api = helpers.api -local feed = helpers.feed -local eq = helpers.eq -local neq = helpers.neq -local clear = helpers.clear -local ok = helpers.ok -local fn = helpers.fn -local nvim_prog = helpers.nvim_prog -local retry = helpers.retry -local write_file = helpers.write_file +local api = n.api +local feed = n.feed +local eq = t.eq +local neq = t.neq +local clear = n.clear +local ok = t.ok +local fn = n.fn +local nvim_prog = n.nvim_prog +local retry = t.retry +local write_file = t.write_file +local assert_log = t.assert_log +local check_close = n.check_close +local is_os = t.is_os + +local testlog = 'Xtest-embed-log' local function test_embed(ext_linegrid) local screen @@ -53,7 +58,7 @@ local function test_embed(ext_linegrid) end) it("doesn't erase output when setting color scheme", function() - if helpers.is_os('openbsd') then + if t.is_os('openbsd') then pending('FIXME #10804') end startup('--cmd', 'echoerr "foo"', '--cmd', 'color default', '--cmd', 'echoerr "bar"') @@ -93,13 +98,18 @@ describe('--embed UI on startup (ext_linegrid=false)', function() end) describe('--embed UI', function() + after_each(function() + check_close() + os.remove(testlog) + end) + it('can pass stdin', function() local pipe = assert(uv.pipe()) local writer = assert(uv.new_pipe(false)) writer:open(pipe.write) - clear { args_rm = { '--headless' }, io_extra = pipe.read } + clear { args_rm = { '--headless' }, io_extra = pipe.read, env = { NVIM_LOG_FILE = testlog } } -- attach immediately after startup, for early UI local screen = Screen.new(40, 8) @@ -131,6 +141,10 @@ describe('--embed UI', function() {1:~ }|*4 {2:-- INSERT --} | ]] + + if not is_os('win') then + assert_log('Failed to get flags on descriptor 3: Bad file descriptor', testlog, 100) + end end) it('can pass stdin to -q - #17523', function() @@ -219,7 +233,7 @@ describe('--embed UI', function() } eq({ [16777215] = true }, seen) - -- NB: by accident how functional/helpers.lua currently handles the default color scheme, the + -- NB: by accident how functional/testutil.lua currently handles the default color scheme, the -- above is sufficient to test the behavior. But in case that workaround is removed, we need -- a test with an explicit override like below, so do it to remain safe. startup('--cmd', 'hi NORMAL guibg=#FF00FF') @@ -239,44 +253,44 @@ describe('--embed UI', function() screen:expect { condition = function() - eq(helpers.paths.test_source_path, screen.pwd) + eq(t.paths.test_source_path, screen.pwd) end, } -- Change global cwd - helpers.command(string.format('cd %s/src/nvim', helpers.paths.test_source_path)) + n.command(string.format('cd %s/src/nvim', t.paths.test_source_path)) screen:expect { condition = function() - eq(string.format('%s/src/nvim', helpers.paths.test_source_path), screen.pwd) + eq(string.format('%s/src/nvim', t.paths.test_source_path), screen.pwd) end, } -- Split the window and change the cwd in the split - helpers.command('new') - helpers.command(string.format('lcd %s/test', helpers.paths.test_source_path)) + n.command('new') + n.command(string.format('lcd %s/test', t.paths.test_source_path)) screen:expect { condition = function() - eq(string.format('%s/test', helpers.paths.test_source_path), screen.pwd) + eq(string.format('%s/test', t.paths.test_source_path), screen.pwd) end, } -- Move to the original window - helpers.command('wincmd p') + n.command('wincmd p') screen:expect { condition = function() - eq(string.format('%s/src/nvim', helpers.paths.test_source_path), screen.pwd) + eq(string.format('%s/src/nvim', t.paths.test_source_path), screen.pwd) end, } -- Change global cwd again - helpers.command(string.format('cd %s', helpers.paths.test_source_path)) + n.command(string.format('cd %s', t.paths.test_source_path)) screen:expect { condition = function() - eq(helpers.paths.test_source_path, screen.pwd) + eq(t.paths.test_source_path, screen.pwd) end, } end) @@ -284,9 +298,9 @@ end) describe('--embed --listen UI', function() it('waits for connection on listening address', function() - helpers.skip(helpers.is_os('win')) + t.skip(t.is_os('win')) clear() - local child_server = assert(helpers.new_pipename()) + local child_server = assert(n.new_pipename()) fn.jobstart({ nvim_prog, '--embed', @@ -300,7 +314,7 @@ describe('--embed --listen UI', function() neq(nil, uv.fs_stat(child_server)) end) - local child_session = helpers.connect(child_server) + local child_session = n.connect(child_server) local info_ok, api_info = child_session:request('nvim_get_api_info') ok(info_ok) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index cdb3b79963..248220e28b 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -1,24 +1,26 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') local os = require('os') -local clear, feed = helpers.clear, helpers.feed -local assert_alive = helpers.assert_alive -local command, feed_command = helpers.command, helpers.feed_command -local eval = helpers.eval -local eq = helpers.eq -local neq = helpers.neq -local expect = helpers.expect -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local insert = helpers.insert -local api = helpers.api -local fn = helpers.fn -local run = helpers.run -local pcall_err = helpers.pcall_err + +local clear, feed = n.clear, n.feed +local assert_alive = n.assert_alive +local command, feed_command = n.command, n.feed_command +local eval = n.eval +local eq = t.eq +local neq = t.neq +local expect = n.expect +local exec = n.exec +local exec_lua = n.exec_lua +local insert = n.insert +local api = n.api +local fn = n.fn +local run = n.run +local pcall_err = t.pcall_err local tbl_contains = vim.tbl_contains -local curbuf = helpers.api.nvim_get_current_buf -local curwin = helpers.api.nvim_get_current_win -local curtab = helpers.api.nvim_get_current_tabpage +local curbuf = n.api.nvim_get_current_buf +local curwin = n.api.nvim_get_current_win +local curtab = n.api.nvim_get_current_tabpage local NIL = vim.NIL describe('float window', function() @@ -325,6 +327,27 @@ describe('float window', function() eq(12, pos[2]) end) + it('error message when reconfig missing relative field', function() + local bufnr = api.nvim_create_buf(false, true) + local opts = { + width = 10, + height = 10, + col = 5, + row = 5, + relative = 'editor', + style = 'minimal', + } + local win_id = api.nvim_open_win(bufnr, true, opts) + eq( + "Missing 'relative' field when reconfiguring floating window 1001", + pcall_err(api.nvim_win_set_config, win_id, { + width = 3, + height = 3, + row = 10, + col = 10, + })) + end) + it('is not operated on by windo when non-focusable #15374', function() command([[ let winids = [] @@ -413,6 +436,25 @@ describe('float window', function() eq(winid, eval('win_getid()')) end) + it('is not active after closing window when non-focusable #28454', function() + command('copen') + local winid = exec_lua([[ + local bufnr = vim.api.nvim_create_buf(false, true) + local opts = { + relative = 'editor', + focusable = false, + height = 5, + width = 5, + col = 5, + row = 5, + } + return vim.api.nvim_open_win(bufnr, false, opts) + ]]) + command('wincmd t') + command('wincmd q') + neq(winid, curwin()) + end) + it('supports windo with focusable and non-focusable floats', function() local winids = exec_lua([[ local result = {vim.api.nvim_get_current_win()} @@ -490,7 +532,10 @@ describe('float window', function() local closed_win = api.nvim_get_current_win() command('close') local buf = api.nvim_create_buf(false,false) - api.nvim_open_win(buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}}) + eq( + 'Invalid window id: ' .. closed_win, + pcall_err(api.nvim_open_win, buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}}) + ) assert_alive() end) @@ -550,6 +595,43 @@ describe('float window', function() eq({ w0 }, api.nvim_list_wins()) end) + it('win_splitmove() can move float into a split', function() + command('split') + eq({'col', {{'leaf', 1001}, {'leaf', 1000}}}, fn.winlayout()) + + local win1 = api.nvim_open_win(0, true, {relative = 'editor', row = 1, col = 1, width = 5, height = 5}) + fn.win_splitmove(win1, 1001, {vertical = true}) + eq({'col', {{'row', {{'leaf', win1}, {'leaf', 1001}}}, {'leaf', 1000}}}, fn.winlayout()) + eq('', api.nvim_win_get_config(win1).relative) + + -- Should be unable to create a split relative to a float, though. + local win2 = api.nvim_open_win(0, true, {relative = 'editor', row = 1, col = 1, width = 5, height = 5}) + eq('Vim:E957: Invalid window number', pcall_err(fn.win_splitmove, win1, win2, {vertical = true})) + end) + + it('tp_curwin updated if external window is moved into split', function() + local screen = Screen.new(20, 7) + screen:attach { ext_multigrid = true } + + command('tabnew') + local external_win = api.nvim_open_win(0, true, {external = true, width = 5, height = 5}) + eq(external_win, api.nvim_get_current_win()) + eq(2, fn.tabpagenr()) + command('tabfirst') + api.nvim_set_current_win(external_win) + eq(external_win, api.nvim_get_current_win()) + eq(1, fn.tabpagenr()) + + command('wincmd J') + eq(external_win, api.nvim_get_current_win()) + eq(false, api.nvim_win_get_config(external_win).external) + command('tabnext') + eq(2, fn.tabpagenr()) + neq(external_win, api.nvim_get_current_win()) + + screen:detach() + end) + describe('with only one tabpage,', function() local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} local old_buf, old_win @@ -836,6 +918,57 @@ describe('float window', function() end) end) + describe(':close on non-float with floating windows', function() + -- XXX: it isn't really clear whether this should quit Nvim, as if the autocommand + -- here is BufUnload then it does quit Nvim. + -- But with BufWinLeave, this doesn't quit Nvim if there are no floating windows, + -- so it shouldn't quit Nvim if there are floating windows. + it('does not quit Nvim if BufWinLeave makes it the only non-float', function() + exec([[ + let g:buf = bufnr() + new + let s:midwin = win_getid() + new + setlocal bufhidden=wipe + call nvim_win_set_config(s:midwin, + \ #{relative: 'editor', row: 5, col: 5, width: 5, height: 5}) + autocmd BufWinLeave * ++once exe g:buf .. 'bwipe!' + ]]) + eq('Vim(close):E855: Autocommands caused command to abort', pcall_err(command, 'close')) + assert_alive() + end) + + pending('does not crash if BufUnload makes it the only non-float in tabpage', function() + exec([[ + tabnew + let g:buf = bufnr() + new + let s:midwin = win_getid() + new + setlocal bufhidden=wipe + call nvim_win_set_config(s:midwin, + \ #{relative: 'editor', row: 5, col: 5, width: 5, height: 5}) + autocmd BufUnload * ++once exe g:buf .. 'bwipe!' + ]]) + command('close') + assert_alive() + end) + + it('does not crash if WinClosed from floating window closes it', function() + exec([[ + tabnew + new + let s:win = win_getid() + call nvim_win_set_config(s:win, + \ #{relative: 'editor', row: 5, col: 5, width: 5, height: 5}) + wincmd t + exe $"autocmd WinClosed {s:win} 1close" + ]]) + command('close') + assert_alive() + end) + end) + local function with_ext_multigrid(multigrid) local screen, attrs before_each(function() @@ -1448,7 +1581,12 @@ describe('float window', function() }, win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; - }} + }, + win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 1, bottom = 1, left = 1, right = 1}; + } + } else screen:expect{grid=[[ ^ | @@ -1648,7 +1786,12 @@ describe('float window', function() }, win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; - }} + }, + win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 0, bottom = 0, left = 1, right = 1}; + } + } else screen:expect{grid=[[ ^ | @@ -1681,6 +1824,10 @@ describe('float window', function() }, win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }, + win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 1, bottom = 1, left = 0, right = 0}; }} else screen:expect{grid=[[ @@ -1726,6 +1873,10 @@ describe('float window', function() }, win_viewport={ [2] = {win = 1000, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }, + win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 0, bottom = 1, left = 0, right = 1}; }} else screen:expect{grid=[[ @@ -2256,6 +2407,7 @@ describe('float window', function() command('hi B0 guibg=Red guifg=Black') command('hi B1 guifg=White') + api.nvim_win_set_config(win, { title = {{"🦄"}, {"BB", {"B0", "B1"}}}, title_pos = "right", footer= {{"🦄"}, {"BB", {"B0", "B1"}}}, footer_pos = "right", @@ -2292,6 +2444,47 @@ describe('float window', function() | ]]} end + eq({{"🦄"}, {"BB", {"B0", "B1"}}}, api.nvim_win_get_config(win).title) + eq({{"🦄"}, {"BB", {"B0", "B1"}}}, api.nvim_win_get_config(win).footer) + + api.nvim_win_set_config(win, { + title = {{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, title_pos = "left", + footer= {{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, footer_pos = "left", + }) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 + {5:╔}🦄{7:BB}{5:═════╗}| + {5:║}{1: halloj! }{5:║}| + {5:║}{1: BORDAA }{5:║}| + {5:╚}🦄{7:BB}{5:═════╝}| + ]], float_pos={ + [4] = { 1001, "NW", 1, 2, 5, true } + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }{5:╔}🦄{7:BB}{5:═════╗}{0: }| + {0:~ }{5:║}{1: halloj! }{5:║}{0: }| + {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| + {0:~ }{5:╚}🦄{7:BB}{5:═════╝}{0: }| + | + ]]} + end + eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).title) + eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).footer) end) it('terminates border on edge of viewport when window extends past viewport', function() @@ -3974,7 +4167,7 @@ describe('float window', function() if multigrid then pending("supports second UI without multigrid", function() - local session2 = helpers.connect(eval('v:servername')) + local session2 = n.connect(eval('v:servername')) print(session2:request("nvim_eval", "2+2")) local screen2 = Screen.new(40,7) screen2:attach(nil, session2) @@ -6169,7 +6362,7 @@ describe('float window', function() run(on_request, nil, on_setup) os.remove('Xtest_written') os.remove('Xtest_written2') - eq(exited, true) + eq(true, exited) end) it(':quit two floats in a row', function() @@ -7872,7 +8065,7 @@ describe('float window', function() end) it("correctly redraws when overlaid windows are resized #13991", function() - helpers.source([[ + n.source([[ let popup_config = {"relative" : "editor", \ "width" : 7, \ "height" : 3, @@ -7936,7 +8129,7 @@ describe('float window', function() ]]) end - helpers.source([[ + n.source([[ let new_popup_config = {"width" : 1, "height" : 3} let new_border_config = {"width" : 3, "height" : 5} @@ -7951,7 +8144,7 @@ describe('float window', function() nnoremap zz <cmd>call Resize()<cr> ]]) - helpers.feed("zz") + n.feed("zz") if multigrid then screen:expect{grid=[[ ## grid 1 @@ -8273,6 +8466,10 @@ describe('float window', function() }, win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, + win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 2, bottom = 1, left = 1, right = 1}; }} else screen:expect{grid=[[ @@ -9101,6 +9298,67 @@ describe('float window', function() ]]} end end) + + it('attempt to turn into split with no room', function() + eq('Vim(split):E36: Not enough room', pcall_err(command, 'execute "split |"->repeat(&lines)')) + command('vsplit | wincmd | | wincmd p') + api.nvim_open_win(0, true, {relative = "editor", row = 0, col = 0, width = 5, height = 5}) + local config = api.nvim_win_get_config(0) + eq('editor', config.relative) + + local layout = fn.winlayout() + local restcmd = fn.winrestcmd() + eq('Vim(wincmd):E36: Not enough room', pcall_err(command, 'wincmd K')) + eq('Vim(wincmd):E36: Not enough room', pcall_err(command, 'wincmd J')) + eq(layout, fn.winlayout()) + eq(restcmd, fn.winrestcmd()) + eq(config, api.nvim_win_get_config(0)) + end) + + it("error when relative to itself", function() + local buf = api.nvim_create_buf(false, true) + local config = { relative='win', width=5, height=2, row=3, col=3 } + local winid = api.nvim_open_win(buf, false, config) + api.nvim_set_current_win(winid) + eq("floating window cannot be relative to itself", pcall_err(api.nvim_win_set_config, winid, config)) + end) + + it("bufpos out of range", function() + local buf = api.nvim_create_buf(false, true) + api.nvim_buf_set_lines(0, 0, -1, false, {}) + local config = { relative='win', width=5, height=2, row=0, col=0, bufpos = { 3, 3 } } + api.nvim_open_win(buf, false, config) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {1001, "NW", 2, 0, 0, true, 50}; + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }}) + else + screen:expect({ + grid = [[ + {1:^ } | + {2:~ }{0: }| + {0:~ }|*4 + | + ]] + }) + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 7f13b6bd03..2712e5ff48 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq -local command = helpers.command -local feed_command = helpers.feed_command -local insert = helpers.insert -local fn = helpers.fn -local api = helpers.api -local exec = helpers.exec -local assert_alive = helpers.assert_alive + +local clear, feed, eq = n.clear, n.feed, t.eq +local command = n.command +local feed_command = n.feed_command +local insert = n.insert +local fn = n.fn +local api = n.api +local exec = n.exec +local assert_alive = n.assert_alive local content1 = [[ This is a diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 727dc38829..b7b46ddfae 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') local os = require('os') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, exec = helpers.command, helpers.exec -local eval = helpers.eval -local feed_command, eq = helpers.feed_command, helpers.eq -local fn = helpers.fn -local api = helpers.api -local exec_lua = helpers.exec_lua + +local clear, feed, insert = n.clear, n.feed, n.insert +local command, exec = n.command, n.exec +local eval = n.eval +local feed_command, eq = n.feed_command, t.eq +local fn = n.fn +local api = n.api +local exec_lua = n.exec_lua describe('colorscheme compatibility', function() before_each(function() @@ -32,11 +34,6 @@ describe('highlight: `:syntax manual`', function() screen = Screen.new(20, 5) screen:attach() -- syntax highlight for vimscript's "echo" - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { bold = true, foreground = Screen.colors.Brown }, - [2] = { foreground = Screen.colors.Magenta1 }, - }) end) after_each(function() @@ -57,8 +54,8 @@ describe('highlight: `:syntax manual`', function() command('bn') feed_command('bp') screen:expect([[ - {1:^echo} {2:1} | - {0:~ }|*3 + {15:^echo} {26:1} | + {1:~ }|*3 :bp | ]]) end) @@ -79,8 +76,8 @@ describe('highlight: `:syntax manual`', function() feed_command('silent bp') eq('Xtest-functional-ui-highlight.tmp.vim', eval("fnamemodify(bufname('%'), ':t')")) screen:expect([[ - {1:^echo} {2:1} | - {0:~ }|*3 + {15:^echo} {26:1} | + {1:~ }|*3 :silent bp | ]]) end) @@ -92,17 +89,9 @@ describe('highlight defaults', function() before_each(function() clear() screen = Screen.new() - screen:set_default_attr_ids { - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { reverse = true, bold = true }, - [2] = { reverse = true }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen }, - [5] = { foreground = Screen.colors.Red1, background = Screen.colors.WebGreen }, - [6] = { background = Screen.colors.Red1, foreground = Screen.colors.Grey100 }, - [7] = { foreground = Screen.colors.Red }, - [8] = { foreground = Screen.colors.Blue }, - [9] = { italic = true }, + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Red, background = Screen.colors.WebGreen }, + [101] = { italic = true }, } screen:attach() end) @@ -111,10 +100,10 @@ describe('highlight defaults', function() feed_command('sp', 'vsp', 'vsp') screen:expect([[ ^ │ │ | - {0:~ }│{0:~ }│{0:~ }|*5 - {1:[No Name] }{2:[No Name] [No Name] }| + {1:~ }│{1:~ }│{1:~ }|*5 + {3:[No Name] }{2:[No Name] [No Name] }| | - {0:~ }|*4 + {1:~ }|*4 {2:[No Name] }| :vsp | ]]) @@ -122,11 +111,11 @@ describe('highlight defaults', function() feed('<c-w>j') screen:expect([[ │ │ | - {0:~ }│{0:~ }│{0:~ }|*5 + {1:~ }│{1:~ }│{1:~ }|*5 {2:[No Name] [No Name] [No Name] }| ^ | - {0:~ }|*4 - {1:[No Name] }| + {1:~ }|*4 + {3:[No Name] }| :vsp | ]]) -- note that when moving to a window with small width nvim will increase @@ -135,30 +124,30 @@ describe('highlight defaults', function() feed('<c-w>k<c-w>l') screen:expect([[ │^ │ | - {0:~ }│{0:~ }│{0:~ }|*5 - {2:[No Name] }{1:[No Name] }{2:[No Name] }| + {1:~ }│{1:~ }│{1:~ }|*5 + {2:[No Name] }{3:[No Name] }{2:[No Name] }| | - {0:~ }|*4 + {1:~ }|*4 {2:[No Name] }| :vsp | ]]) feed('<c-w>l') screen:expect([[ │ │^ | - {0:~ }│{0:~ }│{0:~ }|*5 - {2:[No Name] [No Name] }{1:[No Name] }| + {1:~ }│{1:~ }│{1:~ }|*5 + {2:[No Name] [No Name] }{3:[No Name] }| | - {0:~ }|*4 + {1:~ }|*4 {2:[No Name] }| :vsp | ]]) feed('<c-w>h<c-w>h') screen:expect([[ ^ │ │ | - {0:~ }│{0:~ }│{0:~ }|*5 - {1:[No Name] }{2:[No Name] [No Name] }| + {1:~ }│{1:~ }│{1:~ }|*5 + {3:[No Name] }{2:[No Name] [No Name] }| | - {0:~ }|*4 + {1:~ }|*4 {2:[No Name] }| :vsp | ]]) @@ -169,8 +158,8 @@ describe('highlight defaults', function() screen:try_resize(53, 4) screen:expect([[ ^ | - {0:~ }|*2 - {3:-- INSERT --} | + {1:~ }|*2 + {5:-- INSERT --} | ]]) end) @@ -178,7 +167,7 @@ describe('highlight defaults', function() screen:try_resize(53, 4) screen:expect([[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]]) end) @@ -187,10 +176,10 @@ describe('highlight defaults', function() screen:try_resize(53, 4) feed(':ls<cr>') screen:expect([[ - {1: }| + {3: }| :ls | 1 %a "[No Name]" line 1 | - {4:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') -- skip the "Press ENTER..." state or tests will hang end) @@ -201,7 +190,7 @@ describe('highlight defaults', function() feed('i') screen:expect([[ ^ | - {0:~ }|*2 + {1:~ }|*2 -- INSERT -- | ]]) feed('<esc>') @@ -210,8 +199,8 @@ describe('highlight defaults', function() feed('i') screen:expect([[ ^ | - {0:~ }|*2 - {5:-- INSERT --} | + {1:~ }|*2 + {100:-- INSERT --} | ]]) end) @@ -221,8 +210,8 @@ describe('highlight defaults', function() feed_command('hi link TmpKeyword ErrorMsg') insert('neovim') screen:expect([[ - {6:neovi^m} | - {0:~ }|*2 + {9:neovi^m} | + {1:~ }|*2 | ]]) feed_command( @@ -231,7 +220,7 @@ describe('highlight defaults', function() ) screen:expect([[ neovi^m | - {0:~ }|*2 + {1:~ }|*2 | ]]) end) @@ -240,19 +229,16 @@ describe('highlight defaults', function() screen:try_resize(53, 4) screen:expect([[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]]) feed_command('hi NonTextAlt guifg=Red') feed_command('hi! link NonText NonTextAlt') - screen:expect( - [[ + screen:expect([[ ^ | - {0:~ }|*2 + {19:~ }|*2 :hi! link NonText NonTextAlt | - ]], - { [0] = { foreground = Screen.colors.Red } } - ) + ]]) end) it('Cursor after `:hi clear|syntax reset` #6508', function() @@ -266,47 +252,48 @@ describe('highlight defaults', function() feed_command('set listchars=space:.,tab:>-,trail:*,eol:¬ list') insert(' ne \t o\tv im ') screen:expect([[ - ne{7:.>----.}o{7:>-----}v{7:..}im{7:*^*¬} | - {7:~ }|*2 + ne{19:.>----.}o{19:>-----}v{19:..}im{19:*^*¬} | + {19:~ }|*2 | ]]) feed_command('highlight Whitespace gui=NONE guifg=#0000FF') screen:expect([[ - ne{8:.>----.}o{8:>-----}v{8:..}im{8:*^*}{7:¬} | - {7:~ }|*2 + ne{18:.>----.}o{18:>-----}v{18:..}im{18:*^*}{19:¬} | + {19:~ }|*2 :highlight Whitespace gui=NONE guifg=#0000FF | ]]) end) it('are sent to UIs', function() screen:try_resize(53, 4) + screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], - hl_groups = { EndOfBuffer = 0, MsgSeparator = 1 }, + hl_groups = { EndOfBuffer = 1, MsgSeparator = 3 }, } command('highlight EndOfBuffer gui=italic') screen:expect { grid = [[ ^ | - {9:~ }|*2 + {101:~ }|*2 | ]], - hl_groups = { EndOfBuffer = 9, MsgSeparator = 1 }, + hl_groups = { EndOfBuffer = 101, MsgSeparator = 3 }, } command('highlight clear EndOfBuffer') screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], - hl_groups = { EndOfBuffer = 0, MsgSeparator = 1 }, + hl_groups = { EndOfBuffer = 1, MsgSeparator = 3 }, } end) end) @@ -317,14 +304,6 @@ describe('highlight', function() it('Visual', function() local screen = Screen.new(45, 5) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey }, - [2] = { bold = true, foreground = Screen.colors.Blue }, - [3] = { bold = true }, - [4] = { reverse = true, bold = true }, - [5] = { reverse = true }, - [6] = { background = Screen.colors.Grey90 }, - }) insert([[ line1 foo bar abcdefghijklmnopqrs @@ -337,137 +316,136 @@ describe('highlight', function() command('set guicursor=a:block-blinkon0') feed('V') screen:expect([[ - {1: }^l{1:ine1 foo bar} │{1: line1 foo bar} | + {17: }^l{17:ine1 foo bar} │{17: line1 foo bar} | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL LINE --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL LINE --} | ]]) feed('<Esc>$vhhh') screen:expect([[ - line1 foo^ {1:bar} │ line1 foo{1: bar} | + line1 foo^ {17:bar} │ line1 foo{17: bar} | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL --} | ]]) -- Vertical cursor: highlights char-at-cursor. #8983 command('set guicursor=a:block-blinkon175') screen:expect([[ - line1 foo{1:^ bar} │ line1 foo{1: bar} | + line1 foo{17:^ bar} │ line1 foo{17: bar} | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL --} | ]]) command('set selection=exclusive') screen:expect([[ - line1 foo{1:^ ba}r │ line1 foo{1: ba}r | + line1 foo{17:^ ba}r │ line1 foo{17: ba}r | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL --} | ]]) feed('o') screen:expect([[ - line1 foo{1: ba}^r │ line1 foo{1: ba}r | + line1 foo{17: ba}^r │ line1 foo{17: ba}r | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL --} | ]]) feed('V') screen:expect([[ - {1: line1 foo ba^r} │{1: line1 foo bar} | + {17: line1 foo ba^r} │{17: line1 foo bar} | abcdefghijklmnopqrs │abcdefghijklmnopqrs | ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL LINE --} | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL LINE --} | ]]) command('set cursorcolumn') feed('<C-V>') screen:expect([[ - line1 foo{1: ba}^r │ line1 foo{1: ba}r | - abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs | - ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + line1 foo{17: ba}^r │ line1 foo{17: ba}r | + abcdefghijklmn{21:o}pqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMN{21:O}PQRS │ABCDEFGHIJKLMNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) command('set selection&') screen:expect([[ - line1 foo{1: ba^r} │ line1 foo{1: bar} | - abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs | - ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + line1 foo{17: ba^r} │ line1 foo{17: bar} | + abcdefghijklmn{21:o}pqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMN{21:O}PQRS │ABCDEFGHIJKLMNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) feed('^') screen:expect([[ - {1:^line1 foo }bar │ {1:line1 foo }bar | - ab{6:c}defghijklmnopqrs │abcdefghijklmnopqrs | - AB{6:C}DEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + {17:^line1 foo }bar │ {17:line1 foo }bar | + ab{21:c}defghijklmnopqrs │abcdefghijklmnopqrs | + AB{21:C}DEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) feed('2j') screen:expect([[ - {1:line1 foo }bar │ {1:line1 foo }bar | - ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs | - AB{1:^CDEFGHIJKL}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + {17:line1 foo }bar │ {17:line1 foo }bar | + ab{17:cdefghijkl}mnopqrs │ab{17:cdefghijkl}mnopqrs | + AB{17:^CDEFGHIJKL}MNOPQRS │AB{17:CDEFGHIJKL}MNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) command('set nocursorcolumn') feed('O') screen:expect([[ - {1:line1 foo }bar │ {1:line1 foo }bar | - ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs | - AB{1:CDEFGHIJK^L}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + {17:line1 foo }bar │ {17:line1 foo }bar | + ab{17:cdefghijkl}mnopqrs │ab{17:cdefghijkl}mnopqrs | + AB{17:CDEFGHIJK^L}MNOPQRS │AB{17:CDEFGHIJKL}MNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) command('set selection=exclusive') screen:expect([[ - {1:line1 foo} bar │ {1:line1 foo} bar | - ab{1:cdefghijk}lmnopqrs │ab{1:cdefghijk}lmnopqrs | - AB{1:CDEFGHIJK}^LMNOPQRS │AB{1:CDEFGHIJK}LMNOPQRS | - {4:[No Name] [+] }{5:[No Name] [+] }| - {3:-- VISUAL BLOCK --} | + {17:line1 foo} bar │ {17:line1 foo} bar | + ab{17:cdefghijk}lmnopqrs │ab{17:cdefghijk}lmnopqrs | + AB{17:CDEFGHIJK}^LMNOPQRS │AB{17:CDEFGHIJK}LMNOPQRS | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- VISUAL BLOCK --} | ]]) end) it('cterm=standout gui=standout', function() local screen = Screen.new(20, 5) screen:attach() - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { - standout = true, + screen:add_extra_attr_ids { + [100] = { + foreground = Screen.colors.Blue1, bold = true, + background = Screen.colors.Grey90, underline = true, - background = Screen.colors.Gray90, - foreground = Screen.colors.Blue1, + standout = true, }, - [3] = { standout = true, underline = true, background = Screen.colors.Gray90 }, - }) + [101] = { underline = true, standout = true, background = Screen.colors.Grey90 }, + } feed_command('hi CursorLine cterm=standout,underline gui=standout,underline') feed_command('set cursorline') feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') feed('i\t abcd <cr>\t abcd <cr><esc>k') screen:expect([[ {1:>-------.}abcd{1:*¬} | - {2:^>-------.}{3:abcd}{2:*¬}{3: }| + {100:^>-------.}{101:abcd}{100:*¬}{101: }| {1:¬} | {1:~ }| | @@ -504,16 +482,13 @@ describe('highlight', function() it('nocombine', function() local screen = Screen.new(25, 6) - screen:set_default_attr_ids { - [1] = { foreground = Screen.colors.SlateBlue, underline = true }, - [2] = { bold = true, foreground = Screen.colors.Blue1 }, - [3] = { underline = true, reverse = true, foreground = Screen.colors.SlateBlue }, - [4] = { - background = Screen.colors.Yellow, - reverse = true, + screen:add_extra_attr_ids { + [100] = { underline = true, reverse = true, foreground = Screen.colors.SlateBlue }, + [101] = { foreground = Screen.colors.SlateBlue, + reverse = true, + background = Screen.colors.Yellow, }, - [5] = { foreground = Screen.colors.Red }, } screen:attach() feed_command('syntax on') @@ -526,9 +501,9 @@ describe('highlight', function() ]]) screen:expect { grid = [[ - {1:foobar} |*2 + {28:foobar} |*2 ^ | - {2:~ }|*2 + {1:~ }|*2 | ]], } @@ -536,21 +511,21 @@ describe('highlight', function() feed('/foo') screen:expect { grid = [[ - {3:foo}{1:bar} | - {4:foo}{1:bar} | + {100:foo}{28:bar} | + {101:foo}{28:bar} | | - {2:~ }|*2 + {1:~ }|*2 /foo^ | ]], } feed('<cr>') screen:expect { grid = [[ - {4:^foo}{1:bar} | - {4:foo}{1:bar} | + {101:^foo}{28:bar} | + {101:foo}{28:bar} | | - {2:~ }|*2 - {5:search hit...uing at TOP} | + {1:~ }|*2 + {19:search hit...uing at TOP} | ]], } end) @@ -660,44 +635,40 @@ describe("'listchars' highlight", function() end) it("'cursorline' and 'cursorcolumn'", function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Grey90 }, - }) feed_command('highlight clear ModeMsg') feed_command('set cursorline') feed('i') screen:expect([[ - {1:^ }| - {0:~ }|*3 + {21:^ }| + {1:~ }|*3 -- INSERT -- | ]]) feed('abcdefg<cr>kkasdf') screen:expect([[ abcdefg | - {1:kkasdf^ }| - {0:~ }|*2 + {21:kkasdf^ }| + {1:~ }|*2 -- INSERT -- | ]]) feed('<esc>') screen:expect([[ abcdefg | - {1:kkasd^f }| - {0:~ }|*2 + {21:kkasd^f }| + {1:~ }|*2 | ]]) feed_command('set nocursorline') screen:expect([[ abcdefg | kkasd^f | - {0:~ }|*2 + {1:~ }|*2 :set nocursorline | ]]) feed('k') screen:expect([[ abcde^fg | kkasdf | - {0:~ }|*2 + {1:~ }|*2 :set nocursorline | ]]) feed('jjji<cr><cr><cr><esc>') @@ -711,42 +682,27 @@ describe("'listchars' highlight", function() feed_command('set cursorcolumn') feed('kkiabcdefghijk<esc>hh') screen:expect([[ - kkasd {1: } | - {1:abcdefgh^ijk }| - {1: } | - f {1: } | + kkasd {21: } | + {21:abcdefgh^ijk }| + {21: } | + f {21: } | | ]]) feed('khh') screen:expect([[ - {1:kk^asd }| - ab{1:c}defghijk | - {1: } | - f {1: } | + {21:kk^asd }| + ab{21:c}defghijk | + {21: } | + f {21: } | | ]]) end) it("'cursorline' and with 'listchars' option", function() - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Grey90 }, - [2] = { - foreground = Screen.colors.Red, - background = Screen.colors.Grey90, - }, - [3] = { - background = Screen.colors.Grey90, - foreground = Screen.colors.Blue, - bold = true, - }, - [4] = { - foreground = Screen.colors.Blue, - bold = true, - }, - [5] = { - foreground = Screen.colors.Red, - }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 }, + [101] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Grey90 }, + } feed_command('highlight clear ModeMsg') feed_command('highlight Whitespace guifg=#FF0000') feed_command('set cursorline') @@ -754,73 +710,70 @@ describe("'listchars' highlight", function() feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') feed('i\t abcd <cr>\t abcd <cr><esc>k') screen:expect([[ - {5:>-------.}abcd{5:*}{4:¬} | - {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| - {4:¬} | - {4:~ }| + {19:>-------.}abcd{19:*}{1:¬} | + {100:^>-------.}{21:abcd}{100:*}{101:¬}{21: }| + {1:¬} | + {1:~ }| | ]]) feed('k') screen:expect([[ - {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| - {5:>-------.}abcd{5:*}{4:¬} | - {4:¬} | - {4:~ }| + {100:^>-------.}{21:abcd}{100:*}{101:¬}{21: }| + {19:>-------.}abcd{19:*}{1:¬} | + {1:¬} | + {1:~ }| | ]]) feed_command('set nocursorline') screen:expect([[ - {5:^>-------.}abcd{5:*}{4:¬} | - {5:>-------.}abcd{5:*}{4:¬} | - {4:¬} | - {4:~ }| + {19:^>-------.}abcd{19:*}{1:¬} | + {19:>-------.}abcd{19:*}{1:¬} | + {1:¬} | + {1:~ }| :set nocursorline | ]]) feed_command('set nowrap') feed('ALorem ipsum dolor sit amet<ESC>0') screen:expect([[ - {5:^>-------.}abcd{5:.}Lorem{4:>}| - {5:>-------.}abcd{5:*}{4:¬} | - {4:¬} | - {4:~ }| + {19:^>-------.}abcd{19:.}Lorem{1:>}| + {19:>-------.}abcd{19:*}{1:¬} | + {1:¬} | + {1:~ }| | ]]) feed_command('set cursorline') screen:expect([[ - {2:^>-------.}{1:abcd}{2:.}{1:Lorem}{3:>}| - {5:>-------.}abcd{5:*}{4:¬} | - {4:¬} | - {4:~ }| + {100:^>-------.}{21:abcd}{100:.}{21:Lorem}{101:>}| + {19:>-------.}abcd{19:*}{1:¬} | + {1:¬} | + {1:~ }| :set cursorline | ]]) feed('$') screen:expect([[ - {3:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| - {4:<} |*2 - {4:~ }| + {101:<}{21:r}{100:.}{21:sit}{100:.}{21:ame^t}{101:¬}{21: }| + {1:<} |*2 + {1:~ }| :set cursorline | ]]) feed('G') screen:expect([[ - {5:>-------.}abcd{5:.}Lorem{4:>}| - {5:>-------.}abcd{5:*}{4:¬} | - {3:^¬}{1: }| - {4:~ }| + {19:>-------.}abcd{19:.}Lorem{1:>}| + {19:>-------.}abcd{19:*}{1:¬} | + {101:^¬}{21: }| + {1:~ }| :set cursorline | ]]) end) it("'listchar' with wrap", function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - }) feed_command('set wrap') feed_command('set listchars=eol:¬,precedes:< list') feed('90ia<esc>') screen:expect([[ - {0:<}aaaaaaaaaaaaaaaaaaa| + {1:<}aaaaaaaaaaaaaaaaaaa| aaaaaaaaaaaaaaaaaaaa|*2 - aaaaaaaaa^a{0:¬} | + aaaaaaaaa^a{1:¬} | | ]]) feed('0') @@ -832,16 +785,16 @@ describe("'listchars' highlight", function() end) it("'listchar' in visual mode", function() - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Grey90 }, - [2] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 }, - [3] = { background = Screen.colors.Grey90, foreground = Screen.colors.Blue, bold = true }, - [4] = { foreground = Screen.colors.Blue, bold = true }, - [5] = { foreground = Screen.colors.Red }, - [6] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, - [7] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Red }, - [8] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue, bold = true }, - }) + screen:add_extra_attr_ids { + [100] = { + foreground = Screen.colors.Blue1, + bold = true, + background = Screen.colors.LightGray, + }, + [101] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 }, + [102] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Grey90 }, + [103] = { foreground = Screen.colors.Red, background = Screen.colors.LightGray }, + } command('highlight clear ModeMsg') command('highlight Whitespace guifg=#FF0000') command('set cursorline') @@ -850,45 +803,42 @@ describe("'listchars' highlight", function() command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0') screen:expect([[ - {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| - {5:>-------.}abcd{5:.}Lorem{4:>}| - {4:¬} | - {4:~ }| + {101:^>-------.}{21:abcd}{101:*}{102:¬}{21: }| + {19:>-------.}abcd{19:.}Lorem{1:>}| + {1:¬} | + {1:~ }| | ]]) feed('lllvj') screen:expect([[ - {5:>-------.}a{6:bcd}{7:*}{8:¬} | - {7:>-------.}{6:a}^bcd{5:.}Lorem{4:>}| - {4:¬} | - {4:~ }| + {19:>-------.}a{17:bcd}{103:*}{100:¬} | + {103:>-------.}{17:a}^bcd{19:.}Lorem{1:>}| + {1:¬} | + {1:~ }| -- VISUAL -- | ]]) feed('<esc>V') screen:expect([[ - {5:>-------.}abcd{5:*}{4:¬} | - {7:>-------.}{6:a}^b{6:cd}{7:.}{6:Lorem}{4:>}| - {4:¬} | - {4:~ }| + {19:>-------.}abcd{19:*}{1:¬} | + {103:>-------.}{17:a}^b{17:cd}{103:.}{17:Lorem}{1:>}| + {1:¬} | + {1:~ }| -- VISUAL LINE -- | ]]) feed('<esc>$') screen:expect([[ - {4:<} | - {3:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| - {4:<} | - {4:~ }| + {1:<} | + {102:<}{21:r}{101:.}{21:sit}{101:.}{21:ame^t}{102:¬}{21: }| + {1:<} | + {1:~ }| | ]]) end) it("'cursorline' with :match", function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Grey90 }, - [2] = { foreground = Screen.colors.Red }, - [3] = { foreground = Screen.colors.X11Green, background = Screen.colors.Red1 }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Lime, background = Screen.colors.Red }, + } feed_command('highlight clear ModeMsg') feed_command('highlight Whitespace guifg=#FF0000') feed_command('highlight Error guifg=#00FF00') @@ -896,19 +846,19 @@ describe("'listchars' highlight", function() feed('ia \t bc \t <esc>') screen:expect([[ a bc ^ | - {0:~ }|*3 + {1:~ }|*3 | ]]) feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') screen:expect([[ - a{2:.>-----.}bc{2:*>---*^*}{0:¬} | - {0:~ }|*3 + a{19:.>-----.}bc{19:*>---*^*}{1:¬} | + {1:~ }|*3 | ]]) feed_command('match Error /\\s\\+$/') screen:expect([[ - a{2:.>-----.}bc{3:*>---*^*}{0:¬} | - {0:~ }|*3 + a{19:.>-----.}bc{100:*>---*^*}{1:¬} | + {1:~ }|*3 | ]]) end) @@ -919,15 +869,10 @@ describe('CursorLine and CursorLineNr highlights', function() it('overridden by Error, ColorColumn if fg not set', function() local screen = Screen.new(50, 5) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.SlateBlue }, - [2] = { bold = true, foreground = Screen.colors.Brown }, - [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 }, - [5] = { background = Screen.colors.Gray90 }, - [6] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { background = Screen.colors.LightRed }, - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.LightRed }, + [101] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 }, + } screen:attach() command('filetype on') @@ -935,32 +880,32 @@ describe('CursorLine and CursorLineNr highlights', function() command('set cursorline ft=json') feed('i{<cr>"a" : abc // 10;<cr>}<cr><esc>') screen:expect([[ - {1:{} | - "{2:a}" : {3:abc} {3:// 10;} | - {1:}} | - {5:^ }| + {16:{} | + "{15:a}" : {9:abc} {9:// 10;} | + {16:}} | + {21:^ }| | ]]) command('set colorcolumn=3') feed('i <esc>') screen:expect([[ - {1:{} {7: } | - "{2:a}{7:"} : {3:abc} {3:// 10;} | - {1:}} {7: } | - {5: ^ }{7: }{5: }| + {16:{} {100: } | + "{15:a}{100:"} : {9:abc} {9:// 10;} | + {16:}} {100: } | + {21: ^ }{100: }{21: }| | ]]) end) it("overridden by NonText in 'showbreak' characters", function() local screen = Screen.new(20, 5) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Yellow, background = Screen.colors.Blue }, - [2] = { foreground = Screen.colors.Black, background = Screen.colors.White }, - [3] = { foreground = Screen.colors.Yellow, background = Screen.colors.White }, - [4] = { foreground = Screen.colors.Yellow }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Yellow1 }, + [101] = { foreground = Screen.colors.Yellow1, background = Screen.colors.Blue }, + [102] = { foreground = Screen.colors.Grey0, background = Screen.colors.Grey100 }, + [103] = { foreground = Screen.colors.Yellow1, background = Screen.colors.Grey100 }, + } screen:attach() feed_command('set wrap cursorline') @@ -973,46 +918,45 @@ describe('CursorLine and CursorLineNr highlights', function() feed('30iø<esc>o<esc>30ia<esc>') screen:expect([[ øøøøøøøøøøøøøøøøøøøø| - {1:>>>}øøøøøøøøøø | - {2:aaaaaaaaaaaaaaaaaaaa}| - {1:>>>}{2:aaaaaaaaa^a }| + {101:>>>}øøøøøøøøøø | + {102:aaaaaaaaaaaaaaaaaaaa}| + {101:>>>}{102:aaaaaaaaa^a }| | ]]) feed('k') screen:expect([[ - {2:øøøøøøøøøøøøøøøøøøøø}| - {1:>>>}{2:øøøøøøøøø^ø }| + {102:øøøøøøøøøøøøøøøøøøøø}| + {101:>>>}{102:øøøøøøøøø^ø }| aaaaaaaaaaaaaaaaaaaa| - {1:>>>}aaaaaaaaaa | + {101:>>>}aaaaaaaaaa | | ]]) feed_command('highlight NonText guibg=NONE') screen:expect([[ - {2:øøøøøøøøøøøøøøøøøøøø}| - {3:>>>}{2:øøøøøøøøø^ø }| + {102:øøøøøøøøøøøøøøøøøøøø}| + {103:>>>}{102:øøøøøøøøø^ø }| aaaaaaaaaaaaaaaaaaaa| - {4:>>>}aaaaaaaaaa | + {100:>>>}aaaaaaaaaa | | ]]) feed_command('set nocursorline') screen:expect([[ øøøøøøøøøøøøøøøøøøøø| - {4:>>>}øøøøøøøøø^ø | + {100:>>>}øøøøøøøøø^ø | aaaaaaaaaaaaaaaaaaaa| - {4:>>>}aaaaaaaaaa | + {100:>>>}aaaaaaaaaa | :set nocursorline | ]]) end) it("'cursorlineopt' screenline", function() local screen = Screen.new(20, 5) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Black, background = Screen.colors.White }, - [2] = { foreground = Screen.colors.Yellow }, - [3] = { foreground = Screen.colors.Red, background = Screen.colors.Green }, - [4] = { foreground = Screen.colors.Green, background = Screen.colors.Red }, - [5] = { bold = true }, -- ModeMsg - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Yellow }, + [101] = { foreground = Screen.colors.Red, background = Screen.colors.WebGreen }, + [102] = { foreground = Screen.colors.Black, background = Screen.colors.Grey100 }, + [103] = { foreground = Screen.colors.WebGreen, background = Screen.colors.Red }, + } screen:attach() command('set wrap cursorline cursorlineopt=screenline') @@ -1029,107 +973,107 @@ describe('CursorLine and CursorLineNr highlights', function() -- CursorLine should not apply to 'showbreak' when 'cursorlineopt' contains "screenline" screen:expect([[ øøøøøøøøøøøøøøøøøøøø| - {2:>>>}øøøøøøøøøø | + {100:>>>}øøøøøøøøøø | aaaaaaaaaaaaaaaaaaaa| - {2:>>>}{1:aaaaaaaaa^a }| + {100:>>>}{102:aaaaaaaaa^a }| | ]]) feed('gk') screen:expect([[ øøøøøøøøøøøøøøøøøøøø| - {2:>>>}øøøøøøøøøø | - {1:aaaaaaaaaaaa^aaaaaaaa}| - {2:>>>}aaaaaaaaaa | + {100:>>>}øøøøøøøøøø | + {102:aaaaaaaaaaaa^aaaaaaaa}| + {100:>>>}aaaaaaaaaa | | ]]) feed('k') screen:expect([[ - {1:øøøøøøøøøøøø^øøøøøøøø}| - {2:>>>}øøøøøøøøøø | + {102:øøøøøøøøøøøø^øøøøøøøø}| + {100:>>>}øøøøøøøøøø | aaaaaaaaaaaaaaaaaaaa| - {2:>>>}aaaaaaaaaa | + {100:>>>}aaaaaaaaaa | | ]]) -- CursorLineNr should not apply to line number when 'cursorlineopt' does not contain "number" command('set relativenumber numberwidth=2') screen:expect([[ - {3:0 }{1:øøøøøøøøøøøø^øøøøøø}| - {3: }{2:>>>}øøøøøøøøøøøø | - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {101:0 }{102:øøøøøøøøøøøø^øøøøøø}| + {101: }{100:>>>}øøøøøøøøøøøø | + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | | ]]) -- CursorLineNr should apply to line number when 'cursorlineopt' contains "number" command('set cursorlineopt+=number') screen:expect([[ - {4:0 }{1:øøøøøøøøøøøø^øøøøøø}| - {3: }{2:>>>}øøøøøøøøøøøø | - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {103:0 }{102:øøøøøøøøøøøø^øøøøøø}| + {101: }{100:>>>}øøøøøøøøøøøø | + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | | ]]) feed('gj') screen:expect([[ - {4:0 }øøøøøøøøøøøøøøøøøø| - {3: }{2:>>>}{1:øøøøøøøøø^øøø }| - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {103:0 }øøøøøøøøøøøøøøøøøø| + {101: }{100:>>>}{102:øøøøøøøøø^øøø }| + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | | ]]) feed('gj') screen:expect([[ - {3:1 }øøøøøøøøøøøøøøøøøø| - {3: }{2:>>>}øøøøøøøøøøøø | - {4:0 }{1:aaaaaaaaaaaa^aaaaaa}| - {3: }{2:>>>}aaaaaaaaaaaa | + {101:1 }øøøøøøøøøøøøøøøøøø| + {101: }{100:>>>}øøøøøøøøøøøø | + {103:0 }{102:aaaaaaaaaaaa^aaaaaa}| + {101: }{100:>>>}aaaaaaaaaaaa | | ]]) feed('gj') screen:expect([[ - {3:1 }øøøøøøøøøøøøøøøøøø| - {3: }{2:>>>}øøøøøøøøøøøø | - {4:0 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}{1:aaaaaaaaa^aaa }| + {101:1 }øøøøøøøøøøøøøøøøøø| + {101: }{100:>>>}øøøøøøøøøøøø | + {103:0 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}{102:aaaaaaaaa^aaa }| | ]]) -- updated in Insert mode feed('I') screen:expect([[ - {3:1 }øøøøøøøøøøøøøøøøøø| - {3: }{2:>>>}øøøøøøøøøøøø | - {4:0 }{1:^aaaaaaaaaaaaaaaaaa}| - {3: }{2:>>>}aaaaaaaaaaaa | + {101:1 }øøøøøøøøøøøøøøøøøø| + {101: }{100:>>>}øøøøøøøøøøøø | + {103:0 }{102:^aaaaaaaaaaaaaaaaaa}| + {101: }{100:>>>}aaaaaaaaaaaa | {5:-- INSERT --} | ]]) feed('<Esc>gg') screen:expect([[ - {4:0 }{1:^øøøøøøøøøøøøøøøøøø}| - {3: }{2:>>>}øøøøøøøøøøøø | - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {103:0 }{102:^øøøøøøøøøøøøøøøøøø}| + {101: }{100:>>>}øøøøøøøøøøøø | + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | | ]]) command('inoremap <F2> <Cmd>call cursor(1, 1)<CR>') feed('A') screen:expect([[ - {4:0 }øøøøøøøøøøøøøøøøøø| - {3: }{2:>>>}{1:øøøøøøøøøøøø^ }| - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {103:0 }øøøøøøøøøøøøøøøøøø| + {101: }{100:>>>}{102:øøøøøøøøøøøø^ }| + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | {5:-- INSERT --} | ]]) feed('<F2>') screen:expect([[ - {4:0 }{1:^øøøøøøøøøøøøøøøøøø}| - {3: }{2:>>>}øøøøøøøøøøøø | - {3:1 }aaaaaaaaaaaaaaaaaa| - {3: }{2:>>>}aaaaaaaaaaaa | + {103:0 }{102:^øøøøøøøøøøøøøøøøøø}| + {101: }{100:>>>}øøøøøøøøøøøø | + {101:1 }aaaaaaaaaaaaaaaaaa| + {101: }{100:>>>}aaaaaaaaaaaa | {5:-- INSERT --} | ]]) end) @@ -1137,22 +1081,16 @@ describe('CursorLine and CursorLineNr highlights', function() -- oldtest: Test_cursorline_after_yank() it('always updated. vim-patch:8.1.0849', function() local screen = Screen.new(50, 5) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.SlateBlue }, - [2] = { bold = true, foreground = Screen.colors.Brown }, - [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 }, - [5] = { background = Screen.colors.Gray90 }, - [6] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { background = Screen.colors.LightRed }, - [8] = { foreground = Screen.colors.Brown }, - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.LightRed }, + [101] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 }, + } screen:attach() command('set cursorline relativenumber') command('call setline(1, ["","1","2","3",""])') feed('Gy3k') screen:expect([[ - {2: 0 }{5:^1 }| + {15: 0 }{21:^1 }| {8: 1 }2 | {8: 2 }3 | {8: 3 } | @@ -1162,7 +1100,7 @@ describe('CursorLine and CursorLineNr highlights', function() screen:expect([[ {8: 2 }1 | {8: 1 }2 | - {2: 0 }{5:^3 }| + {15: 0 }{21:^3 }| {8: 1 } | 4 lines yanked | ]]) @@ -1171,37 +1109,25 @@ describe('CursorLine and CursorLineNr highlights', function() -- oldtest: Test_cursorline_with_visualmode() it('with visual area. vim-patch:8.1.1001', function() local screen = Screen.new(50, 5) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.SlateBlue }, - [2] = { bold = true, foreground = Screen.colors.Brown }, - [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 }, - [5] = { background = Screen.colors.Gray90 }, - [6] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { background = Screen.colors.LightRed }, - [8] = { foreground = Screen.colors.Brown }, - [9] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey }, - [10] = { bold = true }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 }, + [101] = { background = Screen.colors.LightRed }, + } screen:attach() command('set cursorline') command('call setline(1, repeat(["abc"], 50))') feed('V<C-f>zbkkjk') screen:expect([[ - {9:abc} | - ^a{9:bc} | + {17:abc} | + ^a{17:bc} | abc |*2 - {10:-- VISUAL LINE --} | + {5:-- VISUAL LINE --} | ]]) end) -- oldtest: Test_cursorline_callback() it('is updated if cursor is moved up from timer vim-patch:8.2.4591', function() local screen = Screen.new(50, 8) - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Gray90 }, -- CursorLine - [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText - }) screen:attach() exec([[ call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) @@ -1219,8 +1145,8 @@ describe('CursorLine and CursorLineNr highlights', function() aaaaa | bbbbb | ccccc | - {1:^ddddd }| - {2:~ }|*3 + {21:^ddddd }| + {1:~ }|*3 | ]], timeout = 100, @@ -1228,10 +1154,10 @@ describe('CursorLine and CursorLineNr highlights', function() screen:expect({ grid = [[ aaaaa | - {1:^bbbbb }| + {21:^bbbbb }| ccccc | ddddd | - {2:~ }|*3 + {1:~ }|*3 | ]], }) @@ -1239,17 +1165,10 @@ describe('CursorLine and CursorLineNr highlights', function() it('with split windows in diff mode', function() local screen = Screen.new(50, 12) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray }, - [2] = { bold = true, background = Screen.colors.Red }, - [3] = { background = Screen.colors.LightMagenta }, - [4] = { reverse = true }, - [5] = { background = Screen.colors.LightBlue }, - [6] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 }, - [7] = { background = Screen.colors.Red, foreground = Screen.colors.White }, - [8] = { bold = true, foreground = Screen.colors.Blue1 }, - [9] = { bold = true, reverse = true }, - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Plum1, underline = true }, + [101] = { background = Screen.colors.Red1, bold = true, underline = true }, + } screen:attach() command('hi CursorLine ctermbg=red ctermfg=white guibg=red guifg=white') @@ -1264,26 +1183,26 @@ describe('CursorLine and CursorLineNr highlights', function() feed('<esc>gg') command('windo diffthis') screen:expect([[ - {1: }{7:line 1 some text }│{1: }{7:^line 1 some text }| - {1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }| - {1: }{5:extra line! }│{1: }{6:----------------------}| - {1: }extra line! │{1: }extra line! |*2 - {1: }last line ... │{1: }last line ... | - {1: } │{1: } | - {8:~ }│{8:~ }|*3 - {4:[No Name] [+] }{9:[No Name] [+] }| + {7: }{9:line 1 some text }│{7: }{9:^line 1 some text }| + {7: }{4:line 2 mo}{27:Re text!}{4: }│{7: }{4:line 2 mo}{27:re text}{4: }| + {7: }{22:extra line! }│{7: }{23:----------------------}| + {7: }extra line! │{7: }extra line! |*2 + {7: }last line ... │{7: }last line ... | + {7: } │{7: } | + {1:~ }│{1:~ }|*3 + {2:[No Name] [+] }{3:[No Name] [+] }| | ]]) feed('jjjjj') screen:expect([[ - {1: }line 1 some text │{1: }line 1 some text | - {1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }| - {1: }{5:extra line! }│{1: }{6:----------------------}| - {1: }extra line! │{1: }extra line! |*2 - {1: }last line ... │{1: }last line ... | - {1: }{7: }│{1: }{7:^ }| - {8:~ }│{8:~ }|*3 - {4:[No Name] [+] }{9:[No Name] [+] }| + {7: }line 1 some text │{7: }line 1 some text | + {7: }{4:line 2 mo}{27:Re text!}{4: }│{7: }{4:line 2 mo}{27:re text}{4: }| + {7: }{22:extra line! }│{7: }{23:----------------------}| + {7: }extra line! │{7: }extra line! |*2 + {7: }last line ... │{7: }last line ... | + {7: }{9: }│{7: }{9:^ }| + {1:~ }│{1:~ }|*3 + {2:[No Name] [+] }{3:[No Name] [+] }| | ]]) @@ -1291,53 +1210,25 @@ describe('CursorLine and CursorLineNr highlights', function() -- Rendered as underline in a diff-line. #9028 command('hi CursorLine ctermbg=red ctermfg=NONE guibg=red guifg=NONE') feed('kkkk') - screen:expect( - [[ - {1: }line 1 some text │{1: }line 1 some text | - {1: }{11:line 2 mo}{12:Re text!}{11: }│{1: }{11:^line 2 mo}{12:re text}{11: }| - {1: }{5:extra line! }│{1: }{6:----------------------}| - {1: }extra line! │{1: }extra line! |*2 - {1: }last line ... │{1: }last line ... | - {1: } │{1: } | - {8:~ }│{8:~ }|*3 - {4:[No Name] [+] }{9:[No Name] [+] }| + screen:expect([[ + {7: }line 1 some text │{7: }line 1 some text | + {7: }{100:line 2 mo}{101:Re text!}{100: }│{7: }{100:^line 2 mo}{101:re text}{100: }| + {7: }{22:extra line! }│{7: }{23:----------------------}| + {7: }extra line! │{7: }extra line! |*2 + {7: }last line ... │{7: }last line ... | + {7: } │{7: } | + {1:~ }│{1:~ }|*3 + {2:[No Name] [+] }{3:[No Name] [+] }| | - ]], - { - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray }, - [2] = { bold = true, background = Screen.colors.Red }, - [3] = { background = Screen.colors.LightMagenta }, - [4] = { reverse = true }, - [5] = { background = Screen.colors.LightBlue }, - [6] = { - background = Screen.colors.LightCyan1, - bold = true, - foreground = Screen.colors.Blue1, - }, - [7] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [8] = { bold = true, foreground = Screen.colors.Blue1 }, - [9] = { bold = true, reverse = true }, - [10] = { bold = true }, - [11] = { underline = true, background = Screen.colors.LightMagenta }, - [12] = { bold = true, underline = true, background = Screen.colors.Red }, - } - ) + ]]) end) -- oldtest: Test_diff_with_cursorline_number() it('CursorLineNr shows correctly just below filler lines', function() local screen = Screen.new(50, 12) - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray }, - [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, - [6] = { background = Screen.colors.White, bold = true, foreground = Screen.colors.Black }, - [7] = { bold = true, foreground = Screen.colors.Blue1 }, - [8] = { bold = true, reverse = true }, - [9] = { foreground = Screen.colors.Brown }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Black, bold = true, background = Screen.colors.Grey100 }, + } screen:attach() command('hi CursorLine guibg=red guifg=white') @@ -1350,22 +1241,22 @@ describe('CursorLine and CursorLineNr highlights', function() command('windo diffthis') command('1wincmd w') screen:expect([[ - {1: }{9: }{2:-------------------}│{1: }{9: 1 }{4:baz }| - {1: }{6: 1 }{5:^foo }│{1: }{6: 2 }{5:foo }| - {1: }{9: 2 }foo │{1: }{9: 3 }foo | - {1: }{9: 3 }bar │{1: }{9: 4 }bar | - {7:~ }│{7:~ }|*6 - {8:[No Name] [+] }{3:[No Name] [+] }| + {7: }{8: }{23:-------------------}│{7: }{8: 1 }{22:baz }| + {7: }{100: 1 }{9:^foo }│{7: }{100: 2 }{9:foo }| + {7: }{8: 2 }foo │{7: }{8: 3 }foo | + {7: }{8: 3 }bar │{7: }{8: 4 }bar | + {1:~ }│{1:~ }|*6 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) command('set cursorlineopt=number') screen:expect([[ - {1: }{9: }{2:-------------------}│{1: }{9: 1 }{4:baz }| - {1: }{6: 1 }^foo │{1: }{6: 2 }{5:foo }| - {1: }{9: 2 }foo │{1: }{9: 3 }foo | - {1: }{9: 3 }bar │{1: }{9: 4 }bar | - {7:~ }│{7:~ }|*6 - {8:[No Name] [+] }{3:[No Name] [+] }| + {7: }{8: }{23:-------------------}│{7: }{8: 1 }{22:baz }| + {7: }{100: 1 }^foo │{7: }{100: 2 }{9:foo }| + {7: }{8: 2 }foo │{7: }{8: 3 }foo | + {7: }{8: 3 }bar │{7: }{8: 4 }bar | + {1:~ }│{1:~ }|*6 + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) end) @@ -1376,11 +1267,9 @@ describe('CursorColumn highlight', function() before_each(function() clear() screen = Screen.new(50, 8) - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Gray90 }, -- CursorColumn - [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText - [3] = { bold = true }, -- ModeMsg - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Blue1 }, + } screen:attach() end) @@ -1391,31 +1280,31 @@ describe('CursorColumn highlight', function() call cursor(2, 2) ]]) screen:expect([[ - 1234567{1:8}9 | + 1234567{21:8}9 | a ^ b | - {2:~ }|*5 + {1:~ }|*5 | ]]) feed('i') screen:expect([[ - 1{1:2}3456789 | + 1{21:2}3456789 | a^ b | - {2:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) feed('<C-O>') screen:expect([[ - 1234567{1:8}9 | + 1234567{21:8}9 | a ^ b | - {2:~ }|*5 - {3:-- (insert) --} | + {1:~ }|*5 + {5:-- (insert) --} | ]]) feed('i') screen:expect([[ - 1{1:2}3456789 | + 1{21:2}3456789 | a^ b | - {2:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) end) @@ -1434,11 +1323,11 @@ describe('CursorColumn highlight', function() ]]) screen:expect({ grid = [[ - aaaa{1:a} | - bbbb{1:b} | - cccc{1:c} | + aaaa{21:a} | + bbbb{21:b} | + cccc{21:c} | dddd^d | - {2:~ }|*3 + {1:~ }|*3 | ]], timeout = 100, @@ -1446,14 +1335,55 @@ describe('CursorColumn highlight', function() screen:expect({ grid = [[ ^aaaaa | - {1:b}bbbb | - {1:c}cccc | - {1:d}dddd | - {2:~ }|*3 + {21:b}bbbb | + {21:c}cccc | + {21:d}dddd | + {1:~ }|*3 | ]], }) end) + + it('is not shown on current line with virtualedit', function() + exec([[ + hi! CursorColumn guibg=Red + hi! CursorLine guibg=Blue + set virtualedit=all cursorline cursorcolumn + ]]) + insert('line 1\nline 2\nline 3') + feed('k') + screen:expect([[ + line {30:1} | + {100:line ^2 }| + line {30:3} | + {1:~ }|*4 + | + ]]) + feed('l') + screen:expect([[ + line 1{30: } | + {100:line 2^ }| + line 3{30: } | + {1:~ }|*4 + | + ]]) + feed('l') + screen:expect([[ + line 1 {30: } | + {100:line 2 ^ }| + line 3 {30: } | + {1:~ }|*4 + | + ]]) + feed('l') + screen:expect([[ + line 1 {30: } | + {100:line 2 ^ }| + line 3 {30: } | + {1:~ }|*4 + | + ]]) + end) end) describe('ColorColumn highlight', function() @@ -1462,17 +1392,11 @@ describe('ColorColumn highlight', function() before_each(function() clear() screen = Screen.new(40, 15) - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.LightRed }, -- ColorColumn - [2] = { background = Screen.colors.Grey90 }, -- CursorLine - [3] = { foreground = Screen.colors.Brown }, -- LineNr - [4] = { foreground = Screen.colors.Brown, bold = true }, -- CursorLineNr - [5] = { foreground = Screen.colors.Blue, bold = true }, -- NonText - [6] = { foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true }, - [7] = { reverse = true, bold = true }, -- StatusLine - [8] = { reverse = true }, -- StatusLineNC - [9] = { background = Screen.colors.Grey90, foreground = Screen.colors.Red }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 }, + [101] = { background = Screen.colors.LightRed }, + [102] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightRed }, + } screen:attach() end) @@ -1490,16 +1414,16 @@ describe('ColorColumn highlight', function() buf X ]]) screen:expect([[ - {4: 1 }11{1:1}11111{1:1}1 | - {3: 2 }22{1:2}22222{1:2}22 | - {3: 3 }33{1:3}33333{1:3}3 | - {5:~ }|*3 - {8:X }| - {4: 1 }^11{1:1}11111{1:1}1 | - {3: 2 }22{1:2}22222{1:2}22 | - {3: 3 }33{1:3}33333{1:3}3 | - {5:~ }|*3 - {7:X }| + {15: 1 }11{101:1}11111{101:1}1 | + {8: 2 }22{101:2}22222{101:2}22 | + {8: 3 }33{101:3}33333{101:3}3 | + {1:~ }|*3 + {2:X }| + {15: 1 }^11{101:1}11111{101:1}1 | + {8: 2 }22{101:2}22222{101:2}22 | + {8: 3 }33{101:3}33333{101:3}3 | + {1:~ }|*3 + {3:X }| | ]]) end) @@ -1511,9 +1435,9 @@ describe('ColorColumn highlight', function() set co=40 linebreak bri briopt=shift:2 cc=40,41,43 ]]) screen:expect([[ - ^The quick brown fox jumped over the {1: }| - {1: } {1:l}azy dogs | - {5:~ }|*12 + ^The quick brown fox jumped over the {101: }| + {101: } {101:l}azy dogs | + {1:~ }|*12 | ]]) end) @@ -1525,9 +1449,9 @@ describe('ColorColumn highlight', function() set co=40 showbreak=+++>\\ cc=40,41,43 ]]) screen:expect([[ - ^The quick brown fox jumped over the laz{1:y}| - {6:+}{5:+}{6:+}{5:>\} dogs | - {5:~ }|*12 + ^The quick brown fox jumped over the laz{101:y}| + {102:+}{1:+}{102:+}{1:>\} dogs | + {1:~ }|*12 | ]]) end) @@ -1536,17 +1460,17 @@ describe('ColorColumn highlight', function() screen:try_resize(40, 2) command('set colorcolumn=30 cursorline') screen:expect([[ - {2:^ }{1: }{2: }| + {21:^ }{101: }{21: }| | ]]) command('hi clear ColorColumn') screen:expect([[ - {2:^ }| + {21:^ }| | ]]) command('hi ColorColumn guifg=Red') screen:expect([[ - {2:^ }{9: }{2: }| + {21:^ }{100: }{21: }| | ]]) end) @@ -2274,7 +2198,7 @@ describe("'winhighlight' highlight", function() ]], } - helpers.assert_alive() + n.assert_alive() end) it('can redraw statusline on cursor movement', function() @@ -2494,3 +2418,115 @@ describe('highlight namespaces', function() } end) end) + +describe('synIDattr()', function() + local screen + before_each(function() + clear() + screen = Screen.new(50, 7) + command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black') + -- Salmon #fa8072 Maroon #800000 + command( + 'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough' + ) + end) + + it('returns cterm-color if RGB-capable UI is _not_ attached', function() + eq('252', eval('synIDattr(hlID("Normal"), "fg")')) + eq('252', eval('synIDattr(hlID("Normal"), "fg#")')) + eq('', eval('synIDattr(hlID("Normal"), "bg")')) + eq('', eval('synIDattr(hlID("Normal"), "bg#")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg#")')) + eq('', eval('synIDattr(hlID("Keyword"), "sp")')) + eq('', eval('synIDattr(hlID("Keyword"), "sp#")')) + end) + + it('returns gui-color if "gui" arg is passed', function() + eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")')) + eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")')) + end) + + it('returns gui-color if RGB-capable UI is attached', function() + screen:attach({ rgb = true }) + eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")')) + eq('Black', eval('synIDattr(hlID("Normal"), "bg")')) + eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")')) + eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")')) + end) + + it('returns #RRGGBB value for fg#/bg#/sp#', function() + screen:attach({ rgb = true }) + eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")')) + eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")')) + eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")')) + eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")')) + end) + + it('returns color number if non-GUI', function() + screen:attach({ rgb = false }) + eq('252', eval('synIDattr(hlID("Normal"), "fg")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) + end) + + it('returns "1" if group has given highlight attribute', function() + local hl_attrs = { + 'underline', + 'undercurl', + 'underdouble', + 'underdotted', + 'underdashed', + 'strikethrough', + } + for _, hl_attr in ipairs(hl_attrs) do + local context = 'using ' .. hl_attr .. ' attr' + command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr) + eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context) + eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context) + eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context) + end + end) +end) + +describe('fg/bg special colors', function() + local screen + before_each(function() + clear() + screen = Screen.new(50, 7) + command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black') + command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg') + end) + + it('resolve to "Normal" values', function() + eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")')) + eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")')) + eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")')) + eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")')) + eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")')) + eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")')) + eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")')) + eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")')) + eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")')) + eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")')) + end) + + it('resolve to "Normal" values in RGB-capable UI', function() + screen:attach({ rgb = true }) + eq('bg', eval('synIDattr(hlID("Visual"), "fg")')) + eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")')) + eq('fg', eval('synIDattr(hlID("Visual"), "bg")')) + eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")')) + eq('bg', eval('synIDattr(hlID("Visual"), "sp")')) + eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")')) + end) + + it('resolve after the "Normal" group is modified', function() + screen:attach({ rgb = true }) + local new_guibg = '#282c34' + local new_guifg = '#abb2bf' + command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg) + eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")')) + eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")')) + eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")')) + end) +end) diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua index 8b36ad5431..8d14c9f73d 100644 --- a/test/functional/ui/hlstate_spec.lua +++ b/test/functional/ui/hlstate_spec.lua @@ -1,13 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local tt = require('test.functional.terminal.testutil') -local clear, insert = helpers.clear, helpers.insert -local command = helpers.command -local api = helpers.api -local testprg = helpers.testprg -local thelpers = require('test.functional.terminal.helpers') -local skip = helpers.skip -local is_os = helpers.is_os +local clear, insert = n.clear, n.insert +local command = n.command +local api = n.api +local testprg = n.testprg +local skip = t.skip +local is_os = t.is_os describe('ext_hlstate detailed highlights', function() local screen @@ -236,11 +237,11 @@ describe('ext_hlstate detailed highlights', function() {7: }| ]]) - thelpers.feed_data('x ') - thelpers.set_fg(45) - thelpers.feed_data('y ') - thelpers.set_bold() - thelpers.feed_data('z\n') + tt.feed_data('x ') + tt.set_fg(45) + tt.feed_data('y ') + tt.set_bold() + tt.feed_data('z\n') -- TODO(bfredl): check if this distinction makes sense if is_os('win') then screen:expect([[ @@ -260,8 +261,8 @@ describe('ext_hlstate detailed highlights', function() ]]) end - thelpers.feed_termcode('[A') - thelpers.feed_termcode('[2C') + tt.feed_termcode('[A') + tt.feed_termcode('[2C') if is_os('win') then screen:expect([[ ^tty ready | @@ -381,7 +382,7 @@ describe('ext_hlstate detailed highlights', function() }, } - helpers.feed('3ggV2jd') + n.feed('3ggV2jd') --screen:redraw_debug() screen:expect { grid = [[ @@ -478,7 +479,7 @@ describe('ext_hlstate detailed highlights', function() }, } - helpers.feed('3ggV2jd') + n.feed('3ggV2jd') --screen:redraw_debug() screen:expect { grid = [[ @@ -512,7 +513,7 @@ describe('ext_hlstate detailed highlights', function() end insert('last line') - helpers.feed('gg') + n.feed('gg') screen:expect { grid = [[ ^first line | @@ -555,7 +556,7 @@ describe('ext_hlstate detailed highlights', function() }, } - helpers.feed(string.format('3ggV%ijd', num_lines - 2)) + n.feed(string.format('3ggV%ijd', num_lines - 2)) --screen:redraw_debug(nil, nil, 100000) local expected_ids = {} diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 29c8c43ca1..c11e009fef 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -1,22 +1,24 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local expect = helpers.expect -local feed = helpers.feed -local insert = helpers.insert -local fn = helpers.fn -local api = helpers.api -local neq = helpers.neq -local ok = helpers.ok -local retry = helpers.retry -local source = helpers.source -local poke_eventloop = helpers.poke_eventloop + +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local expect = n.expect +local feed = n.feed +local insert = n.insert +local fn = n.fn +local api = n.api +local neq = t.neq +local ok = t.ok +local retry = t.retry +local source = n.source +local poke_eventloop = n.poke_eventloop local sleep = vim.uv.sleep -local testprg = helpers.testprg -local assert_alive = helpers.assert_alive +local testprg = n.testprg +local assert_alive = n.assert_alive local default_text = [[ Inc substitution on @@ -65,26 +67,12 @@ local function common_setup(screen, inccommand, text) command('set nohlsearch') command('hi Substitute guifg=red guibg=yellow') screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.Fuchsia }, - [2] = { foreground = Screen.colors.Brown, bold = true }, - [3] = { foreground = Screen.colors.SlateBlue }, - [4] = { bold = true, foreground = Screen.colors.SlateBlue }, - [5] = { foreground = Screen.colors.DarkCyan }, - [6] = { bold = true }, - [7] = { underline = true, bold = true, foreground = Screen.colors.SlateBlue }, - [8] = { foreground = Screen.colors.Slateblue, underline = true }, - [9] = { background = Screen.colors.Yellow }, - [10] = { reverse = true }, - [11] = { reverse = true, bold = true }, - [12] = { foreground = Screen.colors.Red, background = Screen.colors.Yellow }, - [13] = { bold = true, foreground = Screen.colors.SeaGreen }, - [14] = { foreground = Screen.colors.White, background = Screen.colors.Red }, - [15] = { bold = true, foreground = Screen.colors.Blue }, - [16] = { background = Screen.colors.Grey90 }, -- cursorline - [17] = { foreground = Screen.colors.Blue1 }, + + screen:add_extra_attr_ids { + [100] = { underline = true }, + [101] = { underline = true, foreground = Screen.colors.SlateBlue, bold = true }, vis = { background = Screen.colors.LightGrey }, - }) + } end command('set inccommand=' .. (inccommand or '')) @@ -142,13 +130,13 @@ describe(":substitute, 'inccommand' preserves", function() screen:expect([[ BAC | - {15:~ }|*3 - {11: }| + {1:~ }|*3 + {3: }| :ls | 1 %a + "[No Name]" | line 1 | - {13:Press ENTER or type command to}| - {13: continue}^ | + {6:Press ENTER or type command to}| + {6: continue}^ | ]]) end) @@ -204,8 +192,8 @@ describe(":substitute, 'inccommand' preserves", function() feed(':%s/as/glork/') poke_eventloop() feed('<enter>') - eq(api.nvim_get_option_value('undolevels', { scope = 'global' }), 139) - eq(api.nvim_get_option_value('undolevels', { buf = 0 }), 34) + eq(139, api.nvim_get_option_value('undolevels', { scope = 'global' })) + eq(34, api.nvim_get_option_value('undolevels', { buf = 0 })) end) end @@ -577,7 +565,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | two lines | ^ | - {15:~ }|*6 + {1:~ }|*6 | ]]) command('set undolevels=1') @@ -613,7 +601,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) else @@ -621,7 +609,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) end @@ -655,7 +643,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | two line^s | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) else @@ -663,7 +651,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | two line^s | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) end @@ -693,7 +681,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) else @@ -701,7 +689,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) end @@ -725,7 +713,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) else @@ -733,7 +721,7 @@ describe(":substitute, 'inccommand' preserves undo", function() Inc substitution on | ^MOo lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) end @@ -754,7 +742,7 @@ describe(":substitute, 'inccommand' preserves undo", function() ^LInc substitution on| two lines | | - {15:~ }|*6 + {1:~ }|*6 Already ...t change | ]]) end @@ -775,15 +763,15 @@ describe(':substitute, inccommand=split', function() feed(':%s/tw') screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {11:[No Name] }| - |2| {12:tw}o lines | - |4| {12:tw}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] }| + |2| {20:tw}o lines | + |4| {20:tw}o lines | + {1:~ }|*5 + {2:[Preview] }| :%s/tw^ | ]]) feed([[<C-\><C-N>]]) -- Cancel the :substitute command. @@ -793,13 +781,13 @@ describe(':substitute, inccommand=split', function() it('shows preview when cmd modifiers are present', function() -- one modifier feed(':keeppatterns %s/tw/to') - screen:expect { any = [[{12:to}o lines]] } + screen:expect { any = [[{20:to}o lines]] } feed('<Esc>') screen:expect { any = [[two lines]] } -- multiple modifiers feed(':keeppatterns silent %s/tw/to') - screen:expect { any = [[{12:to}o lines]] } + screen:expect { any = [[{20:to}o lines]] } feed('<Esc>') screen:expect { any = [[two lines]] } @@ -811,14 +799,14 @@ describe(':substitute, inccommand=split', function() Inc substitution on | two lines | | - {15:~ }|*9 + {1:~ }|*9 :silent tabedit %s/tw/to^ | ]]) feed('<Esc>') -- leading colons feed(':::%s/tw/to') - screen:expect { any = [[{12:to}o lines]] } + screen:expect { any = [[{20:to}o lines]] } feed('<Esc>') screen:expect { any = [[two lines]] } end) @@ -828,15 +816,15 @@ describe(':substitute, inccommand=split', function() feed(':topleft %s/tw/to') screen:expect([[ Inc substitution on | - {12:to}o lines | + {20:to}o lines | Inc substitution on | - {12:to}o lines | + {20:to}o lines | | - {11:[No Name] [+] }| - |2| {12:to}o lines | - |4| {12:to}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:to}o lines | + |4| {20:to}o lines | + {1:~ }|*5 + {2:[Preview] }| :topleft %s/tw/to^ | ]]) feed('<Esc>') @@ -846,15 +834,15 @@ describe(':substitute, inccommand=split', function() feed(':topleft vert %s/tw/to') screen:expect([[ Inc substitution on | - {12:to}o lines | + {20:to}o lines | Inc substitution on | - {12:to}o lines | + {20:to}o lines | | - {11:[No Name] [+] }| - |2| {12:to}o lines | - |4| {12:to}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:to}o lines | + |4| {20:to}o lines | + {1:~ }|*5 + {2:[Preview] }| :topleft vert %s/tw/to^ | ]]) feed('<Esc>') @@ -865,15 +853,15 @@ describe(':substitute, inccommand=split', function() feed(':%s/tw') screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {11:[No Name] [+] }| - |2| {12:tw}o lines | - |4| {12:tw}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:tw}o lines | + |4| {20:tw}o lines | + {1:~ }|*5 + {2:[Preview] }| :%s/tw^ | ]]) end) @@ -886,26 +874,26 @@ describe(':substitute, inccommand=split', function() Inc substitution on | o lines | | - {11:[No Name] [+] }| + {3:[No Name] [+] }| |2| o lines | |4| o lines | - {15:~ }|*5 - {10:[Preview] }| + {1:~ }|*5 + {2:[Preview] }| :%s/tw/^ | ]]) feed('x') screen:expect([[ Inc substitution on | - {12:x}o lines | + {20:x}o lines | Inc substitution on | - {12:x}o lines | + {20:x}o lines | | - {11:[No Name] [+] }| - |2| {12:x}o lines | - |4| {12:x}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:x}o lines | + |4| {20:x}o lines | + {1:~ }|*5 + {2:[Preview] }| :%s/tw/x^ | ]]) @@ -916,11 +904,11 @@ describe(':substitute, inccommand=split', function() Inc substitution on | o lines | | - {11:[No Name] [+] }| + {3:[No Name] [+] }| |2| o lines | |4| o lines | - {15:~ }|*5 - {10:[Preview] }| + {1:~ }|*5 + {2:[Preview] }| :%s/tw/^ | ]]) end) @@ -929,15 +917,15 @@ describe(':substitute, inccommand=split', function() feed(':%s/tw/XX') screen:expect([[ Inc substitution on | - {12:XX}o lines | + {20:XX}o lines | Inc substitution on | - {12:XX}o lines | + {20:XX}o lines | | - {11:[No Name] [+] }| - |2| {12:XX}o lines | - |4| {12:XX}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:XX}o lines | + |4| {20:XX}o lines | + {1:~ }|*5 + {2:[Preview] }| :%s/tw/XX^ | ]]) end) @@ -947,11 +935,11 @@ describe(':substitute, inccommand=split', function() feed(':s/tw') screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | Inc substitution on | two lines | | - {15:~ }|*9 + {1:~ }|*9 :s/tw^ | ]]) end) @@ -962,12 +950,12 @@ describe(':substitute, inccommand=split', function() -- Assert that 'cursorline' is active. screen:expect([[ - {16:^Inc substitution on }| + {21:^Inc substitution on }| two lines | Inc substitution on | two lines | | - {15:~ }|*9 + {1:~ }|*9 | ]]) @@ -975,15 +963,15 @@ describe(':substitute, inccommand=split', function() -- 'cursorline' is NOT active during preview. screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {11:[No Name] [+] }| - |2| {12:tw}o lines | - |4| {12:tw}o lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |2| {20:tw}o lines | + |4| {20:tw}o lines | + {1:~ }|*5 + {2:[Preview] }| :%s/tw^ | ]]) end) @@ -993,15 +981,15 @@ describe(':substitute, inccommand=split', function() feed('M M M<esc>') feed(':%s/M/123/g') screen:expect([[ - {12:123} {12:123} {12:123} | + {20:123} {20:123} {20:123} | Inc substitution on | two lines | Inc substitution on | two lines | - {11:[No Name] [+] }| - |1| {12:123} {12:123} {12:123} | - {15:~ }|*6 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| {20:123} {20:123} {20:123} | + {1:~ }|*6 + {2:[Preview] }| :%s/M/123/g^ | ]]) end) @@ -1015,10 +1003,10 @@ describe(':substitute, inccommand=split', function() Inc substitution on | two lines | | - {11:[No Name] [+] }| + {3:[No Name] [+] }| | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*6 + {2:[Preview] }| :%s/Inx^ | ]]) end) @@ -1030,12 +1018,12 @@ describe(':substitute, inccommand=split', function() insert(string.rep('abc abc abc\n', 20)) feed(':%s/abc/MMM/g') screen:expect([[ - {12:MMM} {12:MMM} {12:MMM} |*9 - {11:[No Name] [+] }| - | 1| {12:MMM} {12:MMM} {12:MMM} | - | 2| {12:MMM} {12:MMM} {12:MMM} | - | 3| {12:MMM} {12:MMM} {12:MMM} | - {10:[Preview] }| + {20:MMM} {20:MMM} {20:MMM} |*9 + {3:[No Name] [+] }| + | 1| {20:MMM} {20:MMM} {20:MMM} | + | 2| {20:MMM} {20:MMM} {20:MMM} | + | 3| {20:MMM} {20:MMM} {20:MMM} | + {2:[Preview] }| :%s/abc/MMM/g^ | ]]) end) @@ -1051,7 +1039,7 @@ describe(':substitute, inccommand=split', function() Inc substitution on | ^XXo lines | | - {15:~ }|*9 + {1:~ }|*9 :%s/tw/XX/g | ]]) end) @@ -1067,17 +1055,17 @@ describe(':substitute, inccommand=split', function() Inc substitution on | BBo lines | Inc substitution on | - {12:X}o lines | + {20:X}o lines | Inc substitution on | - {11:[No Name] [+] }| - |1001| {12:X}o lines | - |1003| {12:X}o lines | - |1005| {12:X}o lines | - |1007| {12:X}o lines | - |1009| {12:X}o lines | - |1011| {12:X}o lines | - |1013| {12:X}o lines | - {10:[Preview] }| + {3:[No Name] [+] }| + |1001| {20:X}o lines | + |1003| {20:X}o lines | + |1005| {20:X}o lines | + |1007| {20:X}o lines | + |1009| {20:X}o lines | + |1011| {20:X}o lines | + |1013| {20:X}o lines | + {2:[Preview] }| :%s/tw/X^ | ]]) end) @@ -1111,7 +1099,7 @@ describe(':substitute, inccommand=split', function() Inc substitution on | two lines | ^ | - {15:~ }|*9 + {1:~ }|*9 2 matches on 2 lines | ]]) end) @@ -1196,16 +1184,16 @@ describe(':substitute, inccommand=split', function() feed(':1,2s/t/X') screen:expect([[ - Inc subs{12:X}itution on | - {12:X}wo lines | + Inc subs{20:X}itution on | + {20:X}wo lines | Inc substitution on | two lines | | - {11:[No Name] [+] }| - |1| Inc subs{12:X}itution on | - |2| {12:X}wo lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| Inc subs{20:X}itution on | + |2| {20:X}wo lines | + {1:~ }|*5 + {2:[Preview] }| :1,2s/t/X^ | ]]) @@ -1218,7 +1206,7 @@ describe(':substitute, inccommand=split', function() Inc substitution on | two lines | | - {15:~ }|*9 + {1:~ }|*9 :echo 'foo'^ | ]]) end) @@ -1227,65 +1215,65 @@ describe(':substitute, inccommand=split', function() feed('gg') feed(':1,2s/t/X') screen:expect([[ - Inc subs{12:X}itution on | - {12:X}wo lines | + Inc subs{20:X}itution on | + {20:X}wo lines | Inc substitution on | two lines | | - {11:[No Name] [+] }| - |1| Inc subs{12:X}itution on | - |2| {12:X}wo lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| Inc subs{20:X}itution on | + |2| {20:X}wo lines | + {1:~ }|*5 + {2:[Preview] }| :1,2s/t/X^ | ]]) feed([[<C-R>='Y']]) -- preview should be unchanged during c_CTRL-R_= editing screen:expect([[ - Inc subs{12:X}itution on | - {12:X}wo lines | + Inc subs{20:X}itution on | + {20:X}wo lines | Inc substitution on | two lines | | - {11:[No Name] [+] }| - |1| Inc subs{12:X}itution on | - |2| {12:X}wo lines | - {15:~ }|*5 - {10:[Preview] }| - ={1:'Y'}^ | + {3:[No Name] [+] }| + |1| Inc subs{20:X}itution on | + |2| {20:X}wo lines | + {1:~ }|*5 + {2:[Preview] }| + ={26:'Y'}^ | ]]) feed('<CR>') -- preview should be changed by the result of the expression screen:expect([[ - Inc subs{12:XY}itution on | - {12:XY}wo lines | + Inc subs{20:XY}itution on | + {20:XY}wo lines | Inc substitution on | two lines | | - {11:[No Name] [+] }| - |1| Inc subs{12:XY}itution on | - |2| {12:XY}wo lines | - {15:~ }|*5 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| Inc subs{20:XY}itution on | + |2| {20:XY}wo lines | + {1:~ }|*5 + {2:[Preview] }| :1,2s/t/XY^ | ]]) feed([[<C-\>e'echo']]) -- preview should be unchanged during c_CTRL-\_e editing screen:expect([[ - Inc subs{12:XY}itution on | - {12:XY}wo lines | + Inc subs{20:XY}itution on | + {20:XY}wo lines | Inc substitution on | two lines | | - {11:[No Name] [+] }| - |1| Inc subs{12:XY}itution on | - |2| {12:XY}wo lines | - {15:~ }|*5 - {10:[Preview] }| - ={1:'echo'}^ | + {3:[No Name] [+] }| + |1| Inc subs{20:XY}itution on | + |2| {20:XY}wo lines | + {1:~ }|*5 + {2:[Preview] }| + ={26:'echo'}^ | ]]) feed('<CR>') @@ -1296,7 +1284,7 @@ describe(':substitute, inccommand=split', function() Inc substitution on | two lines | | - {15:~ }|*9 + {1:~ }|*9 :echo^ | ]]) end) @@ -1321,8 +1309,8 @@ describe('inccommand=nosplit', function() two lines | Inc substitution on | two lines | - Line *.{12:X} | - {15:~ }|*4 + Line *.{20:X} | + {1:~ }|*4 :%smagic/3.*/X^ | ]]) @@ -1333,8 +1321,8 @@ describe('inccommand=nosplit', function() two lines | Inc substitution on | two lines | - Line *.{12:X} here | - {15:~ }|*4 + Line *.{20:X} here | + {1:~ }|*4 :%snomagic/3.*/X^ | ]]) end) @@ -1342,13 +1330,13 @@ describe('inccommand=nosplit', function() it('shows preview when cmd modifiers are present', function() -- one modifier feed(':keeppatterns %s/tw/to') - screen:expect { any = [[{12:to}o lines]] } + screen:expect { any = [[{20:to}o lines]] } feed('<Esc>') screen:expect { any = [[two lines]] } -- multiple modifiers feed(':keeppatterns silent %s/tw/to') - screen:expect { any = [[{12:to}o lines]] } + screen:expect { any = [[{20:to}o lines]] } feed('<Esc>') screen:expect { any = [[two lines]] } @@ -1360,8 +1348,8 @@ describe('inccommand=nosplit', function() Inc substitution on | two lines | | - {15:~ }|*2 - {11: }| + {1:~ }|*2 + {3: }| :silent tabedit %s/t| w/to^ | ]]) @@ -1378,11 +1366,11 @@ describe('inccommand=nosplit', function() poke_eventloop() screen:expect([[ Inc substitution on | - {12:OKOK}o lines | + {20:OKOK}o lines | Inc substitution on | - {12:OKOK}o lines | + {20:OKOK}o lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/tw/OKOK^ | ]]) end) @@ -1393,33 +1381,33 @@ describe('inccommand=nosplit', function() feed(':%s/tw') screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/tw^ | ]]) feed('/BM') screen:expect([[ Inc substitution on | - {12:BM}o lines | + {20:BM}o lines | Inc substitution on | - {12:BM}o lines | + {20:BM}o lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/tw/BM^ | ]]) feed('/') screen:expect([[ Inc substitution on | - {12:BM}o lines | + {20:BM}o lines | Inc substitution on | - {12:BM}o lines | + {20:BM}o lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/tw/BM/^ | ]]) @@ -1430,7 +1418,7 @@ describe('inccommand=nosplit', function() Inc substitution on | ^BMo lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/tw/BM/ | ]]) end) @@ -1442,12 +1430,12 @@ describe('inccommand=nosplit', function() feed(':1,2s/t/X') screen:expect([[ - Inc subs{12:X}itution on | - {12:X}wo lines | + Inc subs{20:X}itution on | + {20:X}wo lines | Inc substitution on | two lines | | - {15:~ }|*4 + {1:~ }|*4 :1,2s/t/X^ | ]]) @@ -1460,7 +1448,7 @@ describe('inccommand=nosplit', function() Inc substitution on | two lines | | - {15:~ }|*4 + {1:~ }|*4 :echo 'foo'^ | ]]) end) @@ -1469,11 +1457,11 @@ describe('inccommand=nosplit', function() feed(':%s/two/three/g|q!') screen:expect([[ Inc substitution on | - {12:three} lines | + {20:three} lines | Inc substitution on | - {12:three} lines | + {20:three} lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/two/three/g|q!^ | ]]) eq(eval('v:null'), eval('v:exiting')) @@ -1494,7 +1482,7 @@ describe('inccommand=nosplit', function() Inc substitution on | two lines | | - {15:~ }|*4 + {1:~ }|*4 :%s/^ | ]]) end) @@ -1546,7 +1534,7 @@ describe(":substitute, 'inccommand' with a failing expression", function() Inc substitution on | two lines | | - {15:~ }|*6 + {1:~ }|*6 :100s/^ | ]]) @@ -1555,8 +1543,8 @@ describe(":substitute, 'inccommand' with a failing expression", function() Inc substitution on | two lines | ^ | - {15:~ }|*6 - {14:E16: Invalid range} | + {1:~ }|*6 + {9:E16: Invalid range} | ]]) end end) @@ -1649,7 +1637,7 @@ describe("'inccommand' and :cnoremap", function() command("cnoremap <expr> x execute('bwipeout!')[-1].'x'") feed(':%s/tw/tox<enter>') - screen:expect { any = [[{14:^E565:]] } + screen:expect { any = [[{9:^E565:]] } feed('<c-c>') -- error thrown b/c of the mapping @@ -1736,9 +1724,9 @@ describe("'inccommand' autocommands", function() CmdwinLeave = {}, } - local function bufferlist(t) + local function bufferlist(q) local s = '' - for _, buffer in pairs(t) do + for _, buffer in pairs(q) do s = s .. ', ' .. tostring(buffer) end return s @@ -1807,18 +1795,18 @@ describe("'inccommand' split windows", function() feed(':%s/tw') screen:expect([[ Inc substitution on │Inc substitution on| - {12:tw}o lines │{12:tw}o lines | + {20:tw}o lines │{20:tw}o lines | │ | - {15:~ }│{15:~ }|*11 - {11:[No Name] [+] }│{15:~ }| - Inc substitution on │{15:~ }| - {12:tw}o lines │{15:~ }| - │{15:~ }| - {15:~ }│{15:~ }|*2 - {10:[No Name] [+] [No Name] [+] }| - |2| {12:tw}o lines | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }│{1:~ }| + Inc substitution on │{1:~ }| + {20:tw}o lines │{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }|*2 + {2:[No Name] [+] [No Name] [+] }| + |2| {20:tw}o lines | + {1:~ }|*6 + {2:[Preview] }| :%s/tw^ | ]]) @@ -1830,18 +1818,18 @@ describe("'inccommand' split windows", function() feed(':%s/tw') screen:expect([[ Inc substitution on │Inc substitution on| - {12:tw}o lines │{12:tw}o lines | + {20:tw}o lines │{20:tw}o lines | │ | - {15:~ }│{15:~ }|*11 - {11:[No Name] [+] }{10:[No Name] [+] }| + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {15:~ }|*2 - {10:[No Name] [+] }| - |2| {12:tw}o lines | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*2 + {2:[No Name] [+] }| + |2| {20:tw}o lines | + {1:~ }|*6 + {2:[Preview] }| :%s/tw^ | ]]) end) @@ -1864,13 +1852,13 @@ describe("'inccommand' split windows", function() screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | | - {15:~ }|*17 - {11:[No Name] [+] }| - |2| {12:tw}o lines | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*17 + {3:[No Name] [+] }| + |2| {20:tw}o lines | + {1:~ }|*6 + {2:[Preview] }| :%s/tw^ | ]]) end @@ -1882,7 +1870,7 @@ describe("'inccommand' split windows", function() feed('gg:%s/tw') screen:expect([[ Inc substitution on | - {12:tw}o lines | + {20:tw}o lines | :%s/tw^ | ]]) end) @@ -1931,10 +1919,10 @@ describe("'inccommand' with 'gdefault'", function() feed(':%s/\\%1c/a/') screen:expect([[ - {12:a}Inc substitution on | - {12:a}two lines | - {12:a} | - {15:~ }| + {20:a}Inc substitution on | + {20:a}two lines | + {20:a} | + {1:~ }| :%s/\%1c/a/^ | ]]) @@ -1943,7 +1931,7 @@ describe("'inccommand' with 'gdefault'", function() Inc substitution on | two lines | ^ | - {15:~ }| + {1:~ }| | ]]) end) @@ -1962,47 +1950,47 @@ describe(':substitute', function() feed(':%s/2\\_.*X') screen:expect([[ - 1 {12:2 3} | - {12:A B C} | - {12:4 5 6} | - {12:X} Y Z | + 1 {20:2 3} | + {20:A B C} | + {20:4 5 6} | + {20:X} Y Z | 7 8 9 | - {11:[No Name] [+] }| - |1| 1 {12:2 3} | - |2|{12: A B C} | - |3|{12: 4 5 6} | - |4|{12: X} Y Z | - {15:~ }|*3 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| 1 {20:2 3} | + |2|{20: A B C} | + |3|{20: 4 5 6} | + |4|{20: X} Y Z | + {1:~ }|*3 + {2:[Preview] }| :%s/2\_.*X^ | ]]) feed('/MMM') screen:expect([[ - 1 {12:MMM} Y Z | + 1 {20:MMM} Y Z | 7 8 9 | | - {15:~ }|*2 - {11:[No Name] [+] }| - |1| 1 {12:MMM} Y Z | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*2 + {3:[No Name] [+] }| + |1| 1 {20:MMM} Y Z | + {1:~ }|*6 + {2:[Preview] }| :%s/2\_.*X/MMM^ | ]]) feed('\\rK\\rLLL') screen:expect([[ - 1 {12:MMM} | - {12:K} | - {12:LLL} Y Z | + 1 {20:MMM} | + {20:K} | + {20:LLL} Y Z | 7 8 9 | | - {11:[No Name] [+] }| - |1| 1 {12:MMM} | - |2|{12: K} | - |3|{12: LLL} Y Z | - {15:~ }|*4 - {10:[Preview] }| + {3:[No Name] [+] }| + |1| 1 {20:MMM} | + |2|{20: K} | + |3|{20: LLL} Y Z | + {1:~ }|*4 + {2:[Preview] }| :%s/2\_.*X/MMM\rK\rLLL^ | ]]) end) @@ -2013,21 +2001,21 @@ describe(':substitute', function() feed(':%s/2\\_.*X/MMM') screen:expect([[ - 1 {12:MMM} Y Z | + 1 {20:MMM} Y Z | 7 8 9 | | - {15:~ }|*11 + {1:~ }|*11 :%s/2\_.*X/MMM^ | ]]) feed('\\rK\\rLLL') screen:expect([[ - 1 {12:MMM} | - {12:K} | - {12:LLL} Y Z | + 1 {20:MMM} | + {20:K} | + {20:LLL} Y Z | 7 8 9 | | - {15:~ }|*9 + {1:~ }|*9 :%s/2\_.*X/MMM\rK\rLLL^ | ]]) end) @@ -2039,15 +2027,15 @@ describe(':substitute', function() feed(':%s/a/XLK') screen:expect([[ - {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r| + {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:XLK} r| x | | - {15:~ }|*2 - {11:[No Name] [+] }| - |1| {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:X}| - {12:LK} r | - {15:~ }|*5 - {10:[Preview] }| + {1:~ }|*2 + {3:[No Name] [+] }| + |1| {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:X}| + {20:LK} r | + {1:~ }|*5 + {2:[Preview] }| :%s/a/XLK^ | ]]) end) @@ -2059,10 +2047,10 @@ describe(':substitute', function() feed(':%s/a/XLK') screen:expect([[ - {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r| + {20:XLK} bdc e{20:XLK}e {20:XLK} fgl lzi{20:XLK} r| x | | - {15:~ }|*11 + {1:~ }|*11 :%s/a/XLK^ | ]]) end) @@ -2073,18 +2061,18 @@ describe(':substitute', function() feed(':%s/[0-9]\\n\\zs[A-Z]/OKO') screen:expect([[ - {12:OKO} B C | + {20:OKO} B C | 4 5 6 | - {12:OKO} Y Z | + {20:OKO} Y Z | 7 8 9 | | - {11:[No Name] [+] }| + {3:[No Name] [+] }| |1| 1 2 3 | - |2| {12:OKO} B C | + |2| {20:OKO} B C | |3| 4 5 6 | - |4| {12:OKO} Y Z | - {15:~ }|*3 - {10:[Preview] }| + |4| {20:OKO} Y Z | + {1:~ }|*3 + {2:[Preview] }| :%s/[0-9]\n\zs[A-Z]/OKO^ | ]]) end) @@ -2096,12 +2084,12 @@ describe(':substitute', function() feed(':%s/[0-9]\\n\\zs[A-Z]/OKO') screen:expect([[ 1 2 3 | - {12:OKO} B C | + {20:OKO} B C | 4 5 6 | - {12:OKO} Y Z | + {20:OKO} Y Z | 7 8 9 | | - {15:~ }|*8 + {1:~ }|*8 :%s/[0-9]\n\zs[A-Z]/OKO^ | ]]) end) @@ -2111,14 +2099,14 @@ describe(':substitute', function() feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g') screen:expect([[ - T {12:123123} {12:22}T TTT {12:090804090804} | + T {20:123123} {20:22}T TTT {20:090804090804} | x | - {15:~ }|*3 - {11:[No Name] [+] }| - |1| T {12:123123} {12:22}T TTT {12:090804090}| - {12:804} | - {15:~ }|*5 - {10:[Preview] }| + {1:~ }|*3 + {3:[No Name] [+] }| + |1| T {20:123123} {20:22}T TTT {20:090804090}| + {20:804} | + {1:~ }|*5 + {2:[Preview] }| :%s/T\([0-9]\+\)/\1\1/g^ | ]]) end) @@ -2128,9 +2116,9 @@ describe(':substitute', function() feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g') screen:expect([[ - T {12:123123} {12:22}T TTT {12:090804090804} | + T {20:123123} {20:22}T TTT {20:090804090804} | x | - {15:~ }|*12 + {1:~ }|*12 :%s/T\([0-9]\+\)/\1\1/g^ | ]]) end) @@ -2147,17 +2135,17 @@ describe(':substitute', function() common_setup(screen, 'split', text) feed(':%s/[QR]\\n') screen:expect([[ - afa {12:Q} | - adf la;lkd {12:R} | + afa {20:Q} | + adf la;lkd {20:R} | alx | | - {15:~ }| - {11:[No Name] [+] }| - |3| afa {12:Q} | - |4|{12: }adf la;lkd {12:R} | - |5|{12: }alx | - {15:~ }|*4 - {10:[Preview] }| + {1:~ }| + {3:[No Name] [+] }| + |3| afa {20:Q} | + |4|{20: }adf la;lkd {20:R} | + |5|{20: }alx | + {1:~ }|*4 + {2:[Preview] }| :%s/[QR]\n^ | ]]) @@ -2165,13 +2153,13 @@ describe(':substitute', function() screen:expect([[ T T123 T T123 T2T TT T23423424| x | - afa {12:KKK}adf la;lkd {12:KKK}alx | + afa {20:KKK}adf la;lkd {20:KKK}alx | | - {15:~ }| - {11:[No Name] [+] }| - |3| afa {12:KKK}adf la;lkd {12:KKK}alx | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }| + {3:[No Name] [+] }| + |3| afa {20:KKK}adf la;lkd {20:KKK}alx | + {1:~ }|*6 + {2:[Preview] }| :%s/[QR]\n/KKK^ | ]]) end) @@ -2190,9 +2178,9 @@ describe(':substitute', function() screen:expect([[ T T123 T T123 T2T TT T23423424| x | - afa {12:KKK}adf la;lkd {12:KKK}alx | + afa {20:KKK}adf la;lkd {20:KKK}alx | | - {15:~ }|*10 + {1:~ }|*10 :%s/[QR]\n/KKK^ | ]]) end) @@ -2218,16 +2206,16 @@ describe(':substitute', function() BBB BB | CCC CC | | - {11:[No Name] [+] }| + {3:[No Name] [+] }| | 1| AAA AA | - | 2|{12: }BBB BB | - | 3|{12: }CCC CC | - | 4|{12: }AAA AA | - | 5|{12: }BBB BB | - | 6|{12: }CCC CC | - | 7|{12: }AAA AA | - {10:[Preview] }| - :%s/\n\n/{17:^M}/g^ | + | 2|{20: }BBB BB | + | 3|{20: }CCC CC | + | 4|{20: }AAA AA | + | 5|{20: }BBB BB | + | 6|{20: }CCC CC | + | 7|{20: }AAA AA | + {2:[Preview] }| + :%s/\n\n/{18:^M}/g^ | ]], } assert_alive() @@ -2261,7 +2249,7 @@ describe(':substitute', function() BBB BB | CCC CC | | - :%s/\n\n/{17:^M}/g^ | + :%s/\n\n/{18:^M}/g^ | ]], } assert_alive() @@ -2271,36 +2259,36 @@ describe(':substitute', function() common_setup(screen, 'split', multibyte_text) feed(':%s/£.*ѫ/X¥¥') screen:expect([[ - a{12:X¥¥}¥KOL | + a{20:X¥¥}¥KOL | £ ¥ libm | £ ¥ | | - {15:~ }| - {11:[No Name] [+] }| - |1| {12:X¥¥} PEPPERS | - |2| {12:X¥¥} | - |3| a{12:X¥¥}¥KOL | - {15:~ }|*4 - {10:[Preview] }| + {1:~ }| + {3:[No Name] [+] }| + |1| {20:X¥¥} PEPPERS | + |2| {20:X¥¥} | + |3| a{20:X¥¥}¥KOL | + {1:~ }|*4 + {2:[Preview] }| :%s/£.*ѫ/X¥¥^ | ]]) feed('\\ra££ ¥') screen:expect([[ - a{12:X¥¥} | - {12:a££ ¥}¥KOL | + a{20:X¥¥} | + {20:a££ ¥}¥KOL | £ ¥ libm | £ ¥ | | - {11:[No Name] [+] }| - |1| {12:X¥¥} | - |2|{12: a££ ¥} PEPPERS | - |3| {12:X¥¥} | - |4|{12: a££ ¥} | - |5| a{12:X¥¥} | - |6|{12: a££ ¥}¥KOL | - {15:~ }| - {10:[Preview] }| + {3:[No Name] [+] }| + |1| {20:X¥¥} | + |2|{20: a££ ¥} PEPPERS | + |3| {20:X¥¥} | + |4|{20: a££ ¥} | + |5| a{20:X¥¥} | + |6|{20: a££ ¥}¥KOL | + {1:~ }| + {2:[Preview] }| :%s/£.*ѫ/X¥¥\ra££ ¥^ | ]]) end) @@ -2309,28 +2297,28 @@ describe(':substitute', function() common_setup(screen, 'nosplit', multibyte_text) feed(':%s/£.*ѫ/X¥¥') screen:expect([[ - {12:X¥¥} PEPPERS | - {12:X¥¥} | - a{12:X¥¥}¥KOL | + {20:X¥¥} PEPPERS | + {20:X¥¥} | + a{20:X¥¥}¥KOL | £ ¥ libm | £ ¥ | | - {15:~ }|*8 + {1:~ }|*8 :%s/£.*ѫ/X¥¥^ | ]]) feed('\\ra££ ¥') screen:expect([[ - {12:X¥¥} | - {12:a££ ¥} PEPPERS | - {12:X¥¥} | - {12:a££ ¥} | - a{12:X¥¥} | - {12:a££ ¥}¥KOL | + {20:X¥¥} | + {20:a££ ¥} PEPPERS | + {20:X¥¥} | + {20:a££ ¥} | + a{20:X¥¥} | + {20:a££ ¥}¥KOL | £ ¥ libm | £ ¥ | | - {15:~ }|*5 + {1:~ }|*5 :%s/£.*ѫ/X¥¥\ra££ ¥^ | ]]) end) @@ -2344,17 +2332,17 @@ describe(':substitute', function() X Y Z | 7 8 9 | K L M | - {12:a} b c | - {12:d} e f | - {12:q} r s | - {12:x} y z | - £ {12:m} n | - {12:t} œ ¥ | + {20:a} b c | + {20:d} e f | + {20:q} r s | + {20:x} y z | + £ {20:m} n | + {20:t} œ ¥ | | - {11:[No Name] [+] }| - | 7| {12:a} b c | - | 8| {12:d} e f | - {10:[Preview] }| + {3:[No Name] [+] }| + | 7| {20:a} b c | + | 8| {20:d} e f | + {2:[Preview] }| :%s/[a-z]^ | ]]) @@ -2363,17 +2351,17 @@ describe(':substitute', function() X Y Z | 7 8 9 | K L M | - {12:JLKR £} b c | - {12:JLKR £} e f | - {12:JLKR £} r s | - {12:JLKR £} y z | - £ {12:JLKR £} n | - {12:JLKR £} œ ¥ | + {20:JLKR £} b c | + {20:JLKR £} e f | + {20:JLKR £} r s | + {20:JLKR £} y z | + £ {20:JLKR £} n | + {20:JLKR £} œ ¥ | | - {11:[No Name] [+] }| - | 7| {12:JLKR £} b c | - | 8| {12:JLKR £} e f | - {10:[Preview] }| + {3:[No Name] [+] }| + | 7| {20:JLKR £} b c | + | 8| {20:JLKR £} e f | + {2:[Preview] }| :%s/[a-z]/JLKR £^ | ]]) @@ -2381,17 +2369,17 @@ describe(':substitute', function() screen:expect([[ 7 8 9 | K L M | - {12:JLKR £} | - {12:ѫ ab } | - {12:XXXX} b c | - {12:JLKR £} | - {12:ѫ ab } | - {12:XXXX} e f | - {12:JLKR £} | - {12:ѫ ab } | - {11:[No Name] [+] }| - | 7| {12:JLKR £} | - {11: }| + {20:JLKR £} | + {20:ѫ ab } | + {20:XXXX} b c | + {20:JLKR £} | + {20:ѫ ab } | + {20:XXXX} e f | + {20:JLKR £} | + {20:ѫ ab } | + {3:[No Name] [+] }| + | 7| {20:JLKR £} | + {3: }| :%s/[a-z]/JLKR £\rѫ ab \rXXX| X^ | ]]) @@ -2403,58 +2391,58 @@ describe(':substitute', function() feed(':%s/. .$') screen:expect([[ - t {12:œ ¥} | - {11:[No Name] [+] }| - | 1| 1 {12:2 3} | - | 2| A {12:B C} | - | 3| 4 {12:5 6} | - | 4| X {12:Y Z} | - | 5| 7 {12:8 9} | - | 6| K {12:L M} | - | 7| a {12:b c} | - | 8| d {12:e f} | - | 9| q {12:r s} | - |10| x {12:y z} | - |11| £ {12:m n} | - {10:[Preview] }| + t {20:œ ¥} | + {3:[No Name] [+] }| + | 1| 1 {20:2 3} | + | 2| A {20:B C} | + | 3| 4 {20:5 6} | + | 4| X {20:Y Z} | + | 5| 7 {20:8 9} | + | 6| K {20:L M} | + | 7| a {20:b c} | + | 8| d {20:e f} | + | 9| q {20:r s} | + |10| x {20:y z} | + |11| £ {20:m n} | + {2:[Preview] }| :%s/. .$^ | ]]) feed('/ YYY') screen:expect([[ - t {12: YYY} | - {11:[No Name] [+] }| - | 1| 1 {12: YYY} | - | 2| A {12: YYY} | - | 3| 4 {12: YYY} | - | 4| X {12: YYY} | - | 5| 7 {12: YYY} | - | 6| K {12: YYY} | - | 7| a {12: YYY} | - | 8| d {12: YYY} | - | 9| q {12: YYY} | - |10| x {12: YYY} | - |11| £ {12: YYY} | - {10:[Preview] }| + t {20: YYY} | + {3:[No Name] [+] }| + | 1| 1 {20: YYY} | + | 2| A {20: YYY} | + | 3| 4 {20: YYY} | + | 4| X {20: YYY} | + | 5| 7 {20: YYY} | + | 6| K {20: YYY} | + | 7| a {20: YYY} | + | 8| d {20: YYY} | + | 9| q {20: YYY} | + |10| x {20: YYY} | + |11| £ {20: YYY} | + {2:[Preview] }| :%s/. .$/ YYY^ | ]]) feed('\\r KKK') screen:expect([[ - a {12: YYY} | - {11:[No Name] [+] }| - | 1| 1 {12: YYY} | - | 2|{12: KKK} | - | 3| A {12: YYY} | - | 4|{12: KKK} | - | 5| 4 {12: YYY} | - | 6|{12: KKK} | - | 7| X {12: YYY} | - | 8|{12: KKK} | - | 9| 7 {12: YYY} | - |10|{12: KKK} | - |11| K {12: YYY} | - {10:[Preview] }| + a {20: YYY} | + {3:[No Name] [+] }| + | 1| 1 {20: YYY} | + | 2|{20: KKK} | + | 3| A {20: YYY} | + | 4|{20: KKK} | + | 5| 4 {20: YYY} | + | 6|{20: KKK} | + | 7| X {20: YYY} | + | 8|{20: KKK} | + | 9| 7 {20: YYY} | + |10|{20: KKK} | + |11| K {20: YYY} | + {2:[Preview] }| :%s/. .$/ YYY\r KKK^ | ]]) end) @@ -2463,14 +2451,14 @@ describe(':substitute', function() common_setup(screen, 'split', 'something\neverything\nsomeone') feed([[:%s/\(some\)\@<lt>=thing/one/]]) screen:expect([[ - some{12:one} | + some{20:one} | everything | someone | - {15:~ }|*2 - {11:[No Name] [+] }| - |1| some{12:one} | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*2 + {3:[No Name] [+] }| + |1| some{20:one} | + {1:~ }|*6 + {2:[Preview] }| :%s/\(some\)\@<=thing/one/^ | ]]) @@ -2480,13 +2468,13 @@ describe(':substitute', function() feed([[:%s/\(some\)\@<lt>!thing/one/]]) screen:expect([[ something | - every{12:one} | + every{20:one} | someone | - {15:~ }|*2 - {11:[No Name] [+] }| - |2| every{12:one} | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*2 + {3:[No Name] [+] }| + |2| every{20:one} | + {1:~ }|*6 + {2:[Preview] }| :%s/\(some\)\@<!thing/one/^ | ]]) @@ -2494,14 +2482,14 @@ describe(':substitute', function() poke_eventloop() feed([[:%s/some\(thing\)\@=/every/]]) screen:expect([[ - {12:every}thing | + {20:every}thing | everything | someone | - {15:~ }|*2 - {11:[No Name] [+] }| - |1| {12:every}thing | - {15:~ }|*6 - {10:[Preview] }| + {1:~ }|*2 + {3:[No Name] [+] }| + |1| {20:every}thing | + {1:~ }|*6 + {2:[Preview] }| :%s/some\(thing\)\@=/every/^ | ]]) @@ -2511,12 +2499,12 @@ describe(':substitute', function() screen:expect([[ something | everything | - {12:every}one | - {15:~ }|*2 - {11:[No Name] [+] }| - |3| {12:every}one | - {15:~ }|*6 - {10:[Preview] }| + {20:every}one | + {1:~ }|*2 + {3:[No Name] [+] }| + |3| {20:every}one | + {1:~ }|*6 + {2:[Preview] }| :%s/some\(thing\)\@!/every/^ | ]]) end) @@ -2528,23 +2516,23 @@ describe(':substitute', function() -- substitution preview should have been made, without prompting screen:expect([[ - {12:MO}o lines | - {11:[No Name] [+] }| - |2| {12:MO}o lines | - {15:~ }|*3 - {10:[Preview] }| + {20:MO}o lines | + {3:[No Name] [+] }| + |2| {20:MO}o lines | + {1:~ }|*3 + {2:[Preview] }| :2,1s/tw/MO/g^ | ]]) -- but should be prompted on hitting enter feed('<CR>') screen:expect([[ - {12:MO}o lines | - {11:[No Name] [+] }| - |2| {12:MO}o lines | - {15:~ }|*3 - {10:[Preview] }| - {13:Backwards range given, OK to swap (y/n)?}^ | + {20:MO}o lines | + {3:[No Name] [+] }| + |2| {20:MO}o lines | + {1:~ }|*3 + {2:[Preview] }| + {6:Backwards range given, OK to swap (y/n)?}^ | ]]) feed('y') @@ -2552,14 +2540,14 @@ describe(':substitute', function() Inc substitution on | ^MOo lines | | - {15:~ }|*4 - {13:Backwards range given, OK to swap (y/n)?}y | + {1:~ }|*4 + {6:Backwards range given, OK to swap (y/n)?}y | ]]) end) end) it(':substitute with inccommand during :terminal activity', function() - if helpers.skip_fragile(pending) then + if t.skip_fragile(pending) then return end retry(2, 40000, function() @@ -2595,17 +2583,23 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function() feed(':%s/foo/ZZZ') sleep(20) -- Allow some timer activity. screen:expect([[ - {12:ZZZ} bar baz | + {20:ZZZ} bar baz | bar baz fox | - bar {12:ZZZ} baz | - {15:~ }|*3 - {11:[No Name] [+] }| - |1| {12:ZZZ} bar baz | - |3| bar {12:ZZZ} baz | - {15:~ }| - {10:[Preview] }| + bar {20:ZZZ} baz | + {1:~ }|*3 + {3:[No Name] [+] }| + |1| {20:ZZZ} bar baz | + |3| bar {20:ZZZ} baz | + {1:~ }| + {2:[Preview] }| :%s/foo/ZZZ^ | ]]) + + -- Also with nvim__redraw() + command('call timer_start(10, {-> nvim__redraw(#{flush:1})}, {"repeat":-1})') + command('call timer_start(10, {-> nvim__redraw(#{statusline:1})}, {"repeat":-1})') + sleep(20) -- Allow some timer activity. + screen:expect_unchanged() end) it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function() @@ -2627,8 +2621,8 @@ it(':substitute with inccommand, allows :redraw before first separator is typed foo bar baz | bar baz fox | bar foo baz | - {16: }{15: }| - {15:~ }| + {21: }{1: }| + {1:~ }| :^ | ]]) feed('%s') @@ -2636,8 +2630,8 @@ it(':substitute with inccommand, allows :redraw before first separator is typed foo bar baz | bar baz fox | bar foo baz | - {16: }{15: }| - {15:~ }| + {21: }{1: }| + {1:~ }| :%s^ | ]]) api.nvim_buf_set_lines(float_buf, 0, -1, true, { 'foo' }) @@ -2646,8 +2640,8 @@ it(':substitute with inccommand, allows :redraw before first separator is typed foo bar baz | bar baz fox | bar foo baz | - {16:foo }{15: }| - {15:~ }| + {21:foo }{1: }| + {1:~ }| :%s^ | ]]) end) @@ -2659,7 +2653,7 @@ it(':substitute with inccommand, does not crash if range contains invalid marks' feed([[:'a,'bs]]) screen:expect([[ test | - {15:~ }|*4 + {1:~ }|*4 :'a,'bs^ | ]]) -- v:errmsg shouldn't be set either before the first separator is typed @@ -2667,7 +2661,7 @@ it(':substitute with inccommand, does not crash if range contains invalid marks' feed('/') screen:expect([[ test | - {15:~ }|*4 + {1:~ }|*4 :'a,'bs/^ | ]]) end) @@ -2679,18 +2673,18 @@ it(':substitute with inccommand, no unnecessary redraw if preview is not shown', feed(':ls<CR>') screen:expect([[ test | - {15:~ }| - {11: }| + {1:~ }| + {3: }| :ls | 1 %a + "[No Name]" line 1 | - {13:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed(':s') -- no unnecessary redraw, so messages are still shown screen:expect([[ test | - {15:~ }| - {11: }| + {1:~ }| + {3: }| :ls | 1 %a + "[No Name]" line 1 | :s^ | @@ -2698,8 +2692,8 @@ it(':substitute with inccommand, no unnecessary redraw if preview is not shown', feed('o') screen:expect([[ test | - {15:~ }| - {11: }| + {1:~ }| + {3: }| :ls | 1 %a + "[No Name]" line 1 | :so^ | @@ -2707,8 +2701,8 @@ it(':substitute with inccommand, no unnecessary redraw if preview is not shown', feed('<BS>') screen:expect([[ test | - {15:~ }| - {11: }| + {1:~ }| + {3: }| :ls | 1 %a + "[No Name]" line 1 | :s^ | @@ -2716,8 +2710,8 @@ it(':substitute with inccommand, no unnecessary redraw if preview is not shown', feed('/test') -- now inccommand is shown, so screen is redrawn screen:expect([[ - {12:test} | - {15:~ }|*4 + {20:test} | + {1:~ }|*4 :s/test^ | ]]) end) @@ -2733,8 +2727,8 @@ it(":substitute doesn't crash with inccommand, if undo is empty #12932", functio sleep(100) feed('f') screen:expect([[ - {12:f} | - {15:~ }|*3 + {20:f} | + {1:~ }|*3 :%s/test/f^ | ]]) assert_alive() @@ -2756,11 +2750,11 @@ it(':substitute with inccommand works properly if undo is not synced #20029', fu ]]) feed('hjkl') screen:expect([[ - aaaaa {12:hjkl} | + aaaaa {20:hjkl} | foo | bar | baz | - bbbbb {12:hjkl} | + bbbbb {20:hjkl} | :'<,'>s/asdf/hjkl^ | ]]) feed('<CR>') @@ -2784,25 +2778,25 @@ it(':substitute with inccommand does not unexpectedly change viewport #25697', f command('vnew | tabnew | tabclose') screen:expect([[ ^ │£ m n | - {15:~ }│t œ ¥ | - {15:~ }│ | - {11:[No Name] }{10:[No Name] [+] }| + {1:~ }│t œ ¥ | + {1:~ }│ | + {3:[No Name] }{2:[No Name] [+] }| | ]]) feed(':s/') screen:expect([[ │£ m n | - {15:~ }│t œ ¥ | - {15:~ }│ | - {11:[No Name] }{10:[No Name] [+] }| + {1:~ }│t œ ¥ | + {1:~ }│ | + {3:[No Name] }{2:[No Name] [+] }| :s/^ | ]]) feed('<Esc>') screen:expect([[ ^ │£ m n | - {15:~ }│t œ ¥ | - {15:~ }│ | - {11:[No Name] }{10:[No Name] [+] }| + {1:~ }│t œ ¥ | + {1:~ }│ | + {3:[No Name] }{2:[No Name] [+] }| | ]]) end) @@ -2836,7 +2830,7 @@ it('long :%s/ with inccommand does not collapse cmdline', function() ) screen:expect([[ | - {11: }| + {3: }| :%s/AAAAAAAA| AAAAAAAAAAAA| AAAAAAA^ | @@ -2850,7 +2844,7 @@ it("with 'inccommand' typing invalid `={expr}` does not show error", function() feed(':edit `=`') screen:expect([[ | - {15:~ }|*4 + {1:~ }|*4 :edit `=`^ | ]]) end) @@ -2903,26 +2897,26 @@ it("'inccommand' value can be changed multiple times #27086", function() for _ = 1, 3 do feed(':%s/foo/bar') screen:expect([[ - {12:bar}1 | - {12:bar}2 | - {12:bar}3 | - {15:~ }|*7 - {11:[No Name] [+] }| - |1| {12:bar}1 | - |2| {12:bar}2 | - |3| {12:bar}3 | - {15:~ }|*4 - {10:[Preview] }| + {20:bar}1 | + {20:bar}2 | + {20:bar}3 | + {1:~ }|*7 + {3:[No Name] [+] }| + |1| {20:bar}1 | + |2| {20:bar}2 | + |3| {20:bar}3 | + {1:~ }|*4 + {2:[Preview] }| :%s/foo/bar^ | ]]) feed('<Esc>') command('set inccommand=nosplit') feed(':%s/foo/bar') screen:expect([[ - {12:bar}1 | - {12:bar}2 | - {12:bar}3 | - {15:~ }|*16 + {20:bar}1 | + {20:bar}2 | + {20:bar}3 | + {1:~ }|*16 :%s/foo/bar^ | ]]) feed('<Esc>') @@ -2938,10 +2932,10 @@ it("'inccommand' disables preview if preview buffer can't be created #27086", fu eq('split', api.nvim_get_option_value('inccommand', {})) feed(':%s/foo/bar') screen:expect([[ - {12:bar}1 | - {12:bar}2 | - {12:bar}3 | - {15:~ }|*16 + {20:bar}1 | + {20:bar}2 | + {20:bar}3 | + {1:~ }|*16 :%s/foo/bar^ | ]]) eq('nosplit', api.nvim_get_option_value('inccommand', {})) diff --git a/test/functional/ui/inccommand_user_spec.lua b/test/functional/ui/inccommand_user_spec.lua index a714df72b7..12f3640b54 100644 --- a/test/functional/ui/inccommand_user_spec.lua +++ b/test/functional/ui/inccommand_user_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local api = helpers.api -local clear = helpers.clear -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local insert = helpers.insert -local feed = helpers.feed -local command = helpers.command -local assert_alive = helpers.assert_alive + +local api = n.api +local clear = n.clear +local eq = t.eq +local exec_lua = n.exec_lua +local insert = n.insert +local feed = n.feed +local command = n.command +local assert_alive = n.assert_alive -- Implements a :Replace command that works like :substitute and has multibuffer support. local setup_replace_cmd = [[ @@ -237,13 +239,6 @@ describe("'inccommand' for user commands", function() before_each(function() clear() screen = Screen.new(40, 17) - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Yellow1 }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, - [3] = { reverse = true }, - [4] = { reverse = true, bold = true }, - [5] = { foreground = Screen.colors.Blue }, - }) screen:attach() exec_lua(setup_replace_cmd) command('set cmdwinheight=5') @@ -263,16 +258,16 @@ describe("'inccommand' for user commands", function() command('set inccommand=nosplit') feed(':Replace text cats') screen:expect([[ - {1:cats} on line 1 | - more {1:cats} on line 2 | - oh no, even more {1:cats} | - will the {1:cats} ever stop | + {10:cats} on line 1 | + more {10:cats} on line 2 | + oh no, even more {10:cats} | + will the {10:cats} ever stop | oh well | - did the {1:cats} stop | + did the {10:cats} stop | why won't it stop | - make the {1:cats} stop | + make the {10:cats} stop | | - {2:~ }|*7 + {1:~ }|*7 :Replace text cats^ | ]]) end) @@ -281,22 +276,22 @@ describe("'inccommand' for user commands", function() command('set inccommand=split') feed(':Replace text cats') screen:expect([[ - {1:cats} on line 1 | - more {1:cats} on line 2 | - oh no, even more {1:cats} | - will the {1:cats} ever stop | + {10:cats} on line 1 | + more {10:cats} on line 2 | + oh no, even more {10:cats} | + will the {10:cats} ever stop | oh well | - did the {1:cats} stop | + did the {10:cats} stop | why won't it stop | - make the {1:cats} stop | + make the {10:cats} stop | | - {4:[No Name] [+] }| - |1| {1:cats} on line 1 | - |2| more {1:cats} on line 2 | - |3| oh no, even more {1:cats} | - |4| will the {1:cats} ever stop | - |6| did the {1:cats} stop | - {3:[Preview] }| + {3:[No Name] [+] }| + |1| {10:cats} on line 1 | + |2| more {10:cats} on line 2 | + |3| oh no, even more {10:cats} | + |4| will the {10:cats} ever stop | + |6| did the {10:cats} stop | + {2:[Preview] }| :Replace text cats^ | ]]) end) @@ -314,7 +309,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the text stop | ^ | - {2:~ }|*7 + {1:~ }|*7 | ]]) end) @@ -332,7 +327,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the cats stop | ^ | - {2:~ }|*7 + {1:~ }|*7 :Replace text cats | ]]) end) @@ -341,7 +336,7 @@ describe("'inccommand' for user commands", function() command('set inccommand=split') feed('gg:.Replace text cats') screen:expect([[ - {1:cats} on line 1 | + {10:cats} on line 1 | more text on line 2 | oh no, even more text | will the text ever stop | @@ -350,7 +345,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the text stop | | - {2:~ }|*7 + {1:~ }|*7 :.Replace text cats^ | ]]) end) @@ -394,7 +389,7 @@ describe("'inccommand' for user commands", function() ]]) feed(':C') screen:expect([[ - {1: cats on line 1} | + {10: cats on line 1} | more cats on line 2 | oh no, even more cats | will the cats ever stop | @@ -403,7 +398,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the cats stop | | - {2:~ }|*7 + {1:~ }|*7 :C^ | ]]) assert_alive() @@ -453,7 +448,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the text stop | a.a.a.a. | - {2:~ }|*7 + {1:~ }|*7 :Test a.a.a.a.^ | ]]) feed('<C-V><Esc>u') @@ -467,8 +462,8 @@ describe("'inccommand' for user commands", function() why won't it stop | make the text stop | a.a.a. | - {2:~ }|*7 - :Test a.a.a.a.{5:^[}u^ | + {1:~ }|*7 + :Test a.a.a.a.{18:^[}u^ | ]]) feed('<Esc>') screen:expect([[ @@ -481,7 +476,7 @@ describe("'inccommand' for user commands", function() why won't it stop | make the text stop | ^ | - {2:~ }|*7 + {1:~ }|*7 | ]]) end @@ -521,12 +516,6 @@ describe("'inccommand' with multiple buffers", function() before_each(function() clear() screen = Screen.new(40, 17) - screen:set_default_attr_ids({ - [1] = { background = Screen.colors.Yellow1 }, - [2] = { foreground = Screen.colors.Blue1, bold = true }, - [3] = { reverse = true }, - [4] = { reverse = true, bold = true }, - }) screen:attach() exec_lua(setup_replace_cmd) command('set cmdwinheight=10') @@ -547,12 +536,12 @@ describe("'inccommand' with multiple buffers", function() command('set inccommand=nosplit') feed(':Replace foo bar') screen:expect([[ - bar baz {1:bar} │ {1:bar} bar baz | - baz {1:bar} bar │ bar baz {1:bar} | - {1:bar} bar baz │ baz {1:bar} bar | + bar baz {10:bar} │ {10:bar} bar baz | + baz {10:bar} bar │ bar baz {10:bar} | + {10:bar} bar baz │ baz {10:bar} bar | │ | - {2:~ }│{2:~ }|*11 - {4:[No Name] [+] }{3:[No Name] [+] }| + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| :Replace foo bar^ | ]]) feed('<CR>') @@ -561,8 +550,8 @@ describe("'inccommand' with multiple buffers", function() baz bar bar │ bar baz bar | bar bar baz │ baz bar bar | ^ │ | - {2:~ }│{2:~ }|*11 - {4:[No Name] [+] }{3:[No Name] [+] }| + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| :Replace foo bar | ]]) end) @@ -571,22 +560,22 @@ describe("'inccommand' with multiple buffers", function() command('set inccommand=split') feed(':Replace foo bar') screen:expect([[ - bar baz {1:bar} │ {1:bar} bar baz | - baz {1:bar} bar │ bar baz {1:bar} | - {1:bar} bar baz │ baz {1:bar} bar | + bar baz {10:bar} │ {10:bar} bar baz | + baz {10:bar} bar │ bar baz {10:bar} | + {10:bar} bar baz │ baz {10:bar} bar | │ | - {4:[No Name] [+] }{3:[No Name] [+] }| + {3:[No Name] [+] }{2:[No Name] [+] }| Buffer #1: | - |1| {1:bar} bar baz | - |2| bar baz {1:bar} | - |3| baz {1:bar} bar | + |1| {10:bar} bar baz | + |2| bar baz {10:bar} | + |3| baz {10:bar} bar | Buffer #2: | - |1| bar baz {1:bar} | - |2| baz {1:bar} bar | - |3| {1:bar} bar baz | + |1| bar baz {10:bar} | + |2| baz {10:bar} bar | + |3| {10:bar} bar baz | | - {2:~ }| - {3:[Preview] }| + {1:~ }| + {2:[Preview] }| :Replace foo bar^ | ]]) feed('<CR>') @@ -595,8 +584,8 @@ describe("'inccommand' with multiple buffers", function() baz bar bar │ bar baz bar | bar bar baz │ baz bar bar | ^ │ | - {2:~ }│{2:~ }|*11 - {4:[No Name] [+] }{3:[No Name] [+] }| + {1:~ }│{1:~ }|*11 + {3:[No Name] [+] }{2:[No Name] [+] }| :Replace foo bar | ]]) end) diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index b2899bf82d..f377939458 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -1,16 +1,18 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, feed_command = helpers.clear, helpers.feed_command -local feed, next_msg, eq = helpers.feed, helpers.next_msg, helpers.eq -local command = helpers.command -local expect = helpers.expect -local curbuf_contents = helpers.curbuf_contents -local api = helpers.api -local exec_lua = helpers.exec_lua -local write_file = helpers.write_file -local fn = helpers.fn -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') +local clear, feed_command = n.clear, n.feed_command +local feed, next_msg, eq = n.feed, n.next_msg, t.eq +local command = n.command +local expect = n.expect +local curbuf_contents = n.curbuf_contents +local api = n.api +local exec_lua = n.exec_lua +local write_file = t.write_file +local fn = n.fn +local eval = n.eval + before_each(clear) describe('mappings', function() @@ -280,21 +282,16 @@ end) it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2.0839', function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { bold = true, reverse = true }, -- MsgSeparator - [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - }) screen:attach() command([[nnoremap <C-6> <Cmd>echo 'hit ctrl-6'<CR>]]) feed_command('ls') screen:expect([[ | {1:~ }|*3 - {2: }| + {3: }| :ls | 1 %a "[No Name]" line 1 | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed('<C-6>') screen:expect([[ @@ -331,12 +328,6 @@ describe('input non-printable chars', function() it("doesn't crash when echoing them back", function() write_file('Xtest-overwrite', [[foobar]]) local screen = Screen.new(60, 8) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [4] = { bold = true, reverse = true }, - } screen:attach() command('set shortmess-=F') @@ -347,52 +338,52 @@ describe('input non-printable chars', function() "Xtest-overwrite" [noeol] 1L, 6B | ]]) - -- The timestamp is in second resolution, wait two seconds to be sure. - screen:sleep(2000) + -- Wait for some time so that the timestamp changes. + vim.uv.sleep(10) write_file('Xtest-overwrite', [[smurf]]) feed_command('w') screen:expect([[ foobar | {1:~ }|*3 - {4: }| + {3: }| "Xtest-overwrite" | - {2:WARNING: The file has been changed since reading it!!!} | - {3:Do you really want to write to it (y/n)?}^ | + {9:WARNING: The file has been changed since reading it!!!} | + {6:Do you really want to write to it (y/n)?}^ | ]]) feed('u') screen:expect([[ foobar | {1:~ }|*2 - {4: }| + {3: }| "Xtest-overwrite" | - {2:WARNING: The file has been changed since reading it!!!} | - {3:Do you really want to write to it (y/n)?}u | - {3:Do you really want to write to it (y/n)?}^ | + {9:WARNING: The file has been changed since reading it!!!} | + {6:Do you really want to write to it (y/n)?}u | + {6:Do you really want to write to it (y/n)?}^ | ]]) feed('\005') screen:expect([[ foobar | {1:~ }| - {4: }| + {3: }| "Xtest-overwrite" | - {2:WARNING: The file has been changed since reading it!!!} | - {3:Do you really want to write to it (y/n)?}u | - {3:Do you really want to write to it (y/n)?} | - {3:Do you really want to write to it (y/n)?}^ | + {9:WARNING: The file has been changed since reading it!!!} | + {6:Do you really want to write to it (y/n)?}u | + {6:Do you really want to write to it (y/n)?} | + {6:Do you really want to write to it (y/n)?}^ | ]]) feed('n') screen:expect([[ foobar | - {4: }| + {3: }| "Xtest-overwrite" | - {2:WARNING: The file has been changed since reading it!!!} | - {3:Do you really want to write to it (y/n)?}u | - {3:Do you really want to write to it (y/n)?} | - {3:Do you really want to write to it (y/n)?}n | - {3:Press ENTER or type command to continue}^ | + {9:WARNING: The file has been changed since reading it!!!} | + {6:Do you really want to write to it (y/n)?}u | + {6:Do you really want to write to it (y/n)?} | + {6:Do you really want to write to it (y/n)?}n | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') @@ -437,10 +428,6 @@ describe('display is updated', function() local screen before_each(function() screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText - [2] = { bold = true }, -- ModeMsg - }) screen:attach() end) @@ -452,7 +439,7 @@ describe('display is updated', function() abc | ^ | {1:~ }|*5 - {2:-- INSERT --} | + {5:-- INSERT --} | ]]) end) @@ -464,7 +451,7 @@ describe('display is updated', function() abc | ^ | {1:~ }|*5 - {2:-- INSERT --} | + {5:-- INSERT --} | ]]) end) end) diff --git a/test/functional/ui/linematch_spec.lua b/test/functional/ui/linematch_spec.lua index 40df5cadf1..03eed5a49c 100644 --- a/test/functional/ui/linematch_spec.lua +++ b/test/functional/ui/linematch_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed = helpers.feed -local clear = helpers.clear -local write_file = helpers.write_file +local feed = n.feed +local clear = n.clear +local write_file = t.write_file describe('Diff mode screen with 3 diffs open', function() local fname = 'Xtest-functional-diff-screen-1' @@ -38,18 +39,6 @@ describe('Diff mode screen with 3 diffs open', function() screen = Screen.new(100, 16) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, - [2] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1 }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray }, - [6] = { foreground = Screen.colors.Blue1, bold = true }, - [7] = { reverse = true, bold = true }, - [8] = { background = Screen.colors.Red1, bold = true }, - [10] = { foreground = Screen.colors.Brown }, - [9] = { background = Screen.colors.Plum1 }, - }) feed('<c-w>=') feed(':windo set nu!<cr>') end) @@ -96,20 +85,20 @@ describe('Diff mode screen with 3 diffs open', function() feed('1<c-w>w') feed(':2,6diffget screen-1.2<cr>') screen:expect([[ - {1: }{10: 1 }^ │{1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }{9:<<<<<<< HEAD }│{1: }{10: 3 }{9:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}| - {1: }{10: 4 } AAA │{1: }{10: 4 } AAA │{1: }{10: 3 } AAA | - {1: }{10: 5 } AAA │{1: }{10: 5 } AAA │{1: }{10: 4 } AAA | - {1: }{10: 6 } AAA │{1: }{10: 6 } AAA │{1: }{10: 5 } AAA | - {1: }{10: 7 }{9:======= }│{1: }{10: 7 }{9:======= }│{1: }{10: }{2:---------------------------}| - {1: }{10: 8 }{9: BBB }│{1: }{10: 8 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 9 }{9: BBB }│{1: }{10: 9 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 10 }{9: BBB }│{1: }{10: 10 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}| - {1: }{10: 12 } │{1: }{10: 12 } │{1: }{10: 6 } | - {6:~ }│{6:~ }│{6:~ }|*2 - {7:<-functional-diff-screen-1.3 [+] }{3:<est-functional-diff-screen-1.2 Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^ │{7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }{4:<<<<<<< HEAD }│{7: }{8: 3 }{4:<<<<<<< HEAD }│{7: }{8: }{23:---------------------------}| + {7: }{8: 4 } AAA │{7: }{8: 4 } AAA │{7: }{8: 3 } AAA | + {7: }{8: 5 } AAA │{7: }{8: 5 } AAA │{7: }{8: 4 } AAA | + {7: }{8: 6 } AAA │{7: }{8: 6 } AAA │{7: }{8: 5 } AAA | + {7: }{8: 7 }{4:======= }│{7: }{8: 7 }{4:======= }│{7: }{8: }{23:---------------------------}| + {7: }{8: 8 }{4: BBB }│{7: }{8: 8 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 9 }{4: BBB }│{7: }{8: 9 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 10 }{4: BBB }│{7: }{8: 10 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}| + {7: }{8: 12 } │{7: }{8: 12 } │{7: }{8: 6 } | + {1:~ }│{1:~ }│{1:~ }|*2 + {3:<-functional-diff-screen-1.3 [+] }{2:<est-functional-diff-screen-1.2 Xtest-functional-diff-screen-1 }| :2,6diffget screen-1.2 | ]]) end) @@ -118,17 +107,17 @@ describe('Diff mode screen with 3 diffs open', function() feed('2<c-w>w') feed(':5,7diffget screen-1.3<cr>') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}| - {1: }{10: }{2:---------------------------}│{1: }{10: 4 }{9: AAA }│{1: }{10: 3 }{9: AAA }| - {1: }{10: 3 }{9: BBB }│{1: }{10: 5 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 4 }{9: }{8:BBB}{9: }│{1: }{10: 6 }{9: }{8:BBB}{9: }│{1: }{10: 4 }{9: }{8:AAA}{9: }| - {1: }{10: 5 }{9: }{8:BBB}{9: }│{1: }{10: 7 }{9: }{8:BBB}{9: }│{1: }{10: 5 }{9: }{8:AAA}{9: }| - {1: }{10: }{2:---------------------------}│{1: }{10: 8 }{4:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}| - {1: }{10: 6 } │{1: }{10: 9 } │{1: }{10: 6 } | - {6:~ }│{6:~ }│{6:~ }|*5 - {3:<test-functional-diff-screen-1.3 }{7:<functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 }^ │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: }{23:---------------------------}│{7: }{8: 3 }{22:<<<<<<< HEAD }│{7: }{8: }{23:---------------------------}| + {7: }{8: }{23:---------------------------}│{7: }{8: 4 }{4: AAA }│{7: }{8: 3 }{4: AAA }| + {7: }{8: 3 }{4: BBB }│{7: }{8: 5 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 4 }{4: }{27:BBB}{4: }│{7: }{8: 6 }{4: }{27:BBB}{4: }│{7: }{8: 4 }{4: }{27:AAA}{4: }| + {7: }{8: 5 }{4: }{27:BBB}{4: }│{7: }{8: 7 }{4: }{27:BBB}{4: }│{7: }{8: 5 }{4: }{27:AAA}{4: }| + {7: }{8: }{23:---------------------------}│{7: }{8: 8 }{22:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}| + {7: }{8: 6 } │{7: }{8: 9 } │{7: }{8: 6 } | + {1:~ }│{1:~ }│{1:~ }|*5 + {2:<test-functional-diff-screen-1.3 }{3:<functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :5,7diffget screen-1.3 | ]]) end) @@ -137,20 +126,20 @@ describe('Diff mode screen with 3 diffs open', function() feed('3<c-w>w') feed(':5,6diffget screen-1.2<cr>') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } │{1: }{10: 1 }^ | - {1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}| - {1: }{10: }{2:---------------------------}│{1: }{10: 4 }{9: AAA }│{1: }{10: 3 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 5 }{9: AAA }│{1: }{10: 4 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 6 }{9: AAA }│{1: }{10: 5 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 7 }{9:======= }│{1: }{10: 6 }{9:======= }| - {1: }{10: 3 } BBB │{1: }{10: 8 } BBB │{1: }{10: 7 } BBB | - {1: }{10: 4 } BBB │{1: }{10: 9 } BBB │{1: }{10: 8 } BBB | - {1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 9 } BBB | - {1: }{10: }{2:---------------------------}│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 10 }{9:>>>>>>> branch1 }| - {1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 11 } | - {6:~ }│{6:~ }│{6:~ }|*2 - {3:<test-functional-diff-screen-1.3 <est-functional-diff-screen-1.2 }{7:<st-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } │{7: }{8: 1 }^ | + {7: }{8: 2 }common line │{7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: }{23:---------------------------}│{7: }{8: 3 }{22:<<<<<<< HEAD }│{7: }{8: }{23:---------------------------}| + {7: }{8: }{23:---------------------------}│{7: }{8: 4 }{4: AAA }│{7: }{8: 3 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 5 }{4: AAA }│{7: }{8: 4 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 6 }{4: AAA }│{7: }{8: 5 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 7 }{4:======= }│{7: }{8: 6 }{4:======= }| + {7: }{8: 3 } BBB │{7: }{8: 8 } BBB │{7: }{8: 7 } BBB | + {7: }{8: 4 } BBB │{7: }{8: 9 } BBB │{7: }{8: 8 } BBB | + {7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 9 } BBB | + {7: }{8: }{23:---------------------------}│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 10 }{4:>>>>>>> branch1 }| + {7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 11 } | + {1:~ }│{1:~ }│{1:~ }|*2 + {2:<test-functional-diff-screen-1.3 <est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }| :5,6diffget screen-1.2 | ]]) end) @@ -159,20 +148,20 @@ describe('Diff mode screen with 3 diffs open', function() feed('2<c-w>w') feed(':6,8diffput screen-1<cr>') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}| - {1: }{10: }{2:---------------------------}│{1: }{10: 4 }{9: AAA }│{1: }{10: 3 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 5 }{9: AAA }│{1: }{10: 4 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 6 }{9: AAA }│{1: }{10: 5 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 7 }{9:======= }│{1: }{10: 6 }{9:======= }| - {1: }{10: 3 }{9: BBB }│{1: }{10: 8 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 4 }{9: BBB }│{1: }{10: 9 }{9: BBB }│{1: }{10: }{2:---------------------------}| - {1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 7 } BBB | - {1: }{10: }{2:---------------------------}│{1: }{10: 11 }{4:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}| - {1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 8 } | - {6:~ }│{6:~ }│{6:~ }|*2 - {3:<test-functional-diff-screen-1.3 }{7:<est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 }^ │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: }{23:---------------------------}│{7: }{8: 3 }{22:<<<<<<< HEAD }│{7: }{8: }{23:---------------------------}| + {7: }{8: }{23:---------------------------}│{7: }{8: 4 }{4: AAA }│{7: }{8: 3 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 5 }{4: AAA }│{7: }{8: 4 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 6 }{4: AAA }│{7: }{8: 5 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 7 }{4:======= }│{7: }{8: 6 }{4:======= }| + {7: }{8: 3 }{4: BBB }│{7: }{8: 8 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 4 }{4: BBB }│{7: }{8: 9 }{4: BBB }│{7: }{8: }{23:---------------------------}| + {7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 7 } BBB | + {7: }{8: }{23:---------------------------}│{7: }{8: 11 }{22:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}| + {7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 8 } | + {1:~ }│{1:~ }│{1:~ }|*2 + {2:<test-functional-diff-screen-1.3 }{3:<est-functional-diff-screen-1.2 }{2:<st-functional-diff-screen-1 [+] }| :6,8diffput screen-1 | ]]) end) @@ -180,20 +169,20 @@ describe('Diff mode screen with 3 diffs open', function() feed('2<c-w>w') feed(':6,11diffput screen-1<cr>') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}| - {1: }{10: }{2:---------------------------}│{1: }{10: 4 }{9: AAA }│{1: }{10: 3 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 5 }{9: AAA }│{1: }{10: 4 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 6 }{9: AAA }│{1: }{10: 5 }{9: AAA }| - {1: }{10: }{2:---------------------------}│{1: }{10: 7 }{9:======= }│{1: }{10: 6 }{9:======= }| - {1: }{10: 3 } BBB │{1: }{10: 8 } BBB │{1: }{10: 7 } BBB | - {1: }{10: 4 } BBB │{1: }{10: 9 } BBB │{1: }{10: 8 } BBB | - {1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 9 } BBB | - {1: }{10: }{2:---------------------------}│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 10 }{9:>>>>>>> branch1 }| - {1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 11 } | - {6:~ }│{6:~ }│{6:~ }|*2 - {3:<test-functional-diff-screen-1.3 }{7:<est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 }^ │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: }{23:---------------------------}│{7: }{8: 3 }{22:<<<<<<< HEAD }│{7: }{8: }{23:---------------------------}| + {7: }{8: }{23:---------------------------}│{7: }{8: 4 }{4: AAA }│{7: }{8: 3 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 5 }{4: AAA }│{7: }{8: 4 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 6 }{4: AAA }│{7: }{8: 5 }{4: AAA }| + {7: }{8: }{23:---------------------------}│{7: }{8: 7 }{4:======= }│{7: }{8: 6 }{4:======= }| + {7: }{8: 3 } BBB │{7: }{8: 8 } BBB │{7: }{8: 7 } BBB | + {7: }{8: 4 } BBB │{7: }{8: 9 } BBB │{7: }{8: 8 } BBB | + {7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 9 } BBB | + {7: }{8: }{23:---------------------------}│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 10 }{4:>>>>>>> branch1 }| + {7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 11 } | + {1:~ }│{1:~ }│{1:~ }|*2 + {2:<test-functional-diff-screen-1.3 }{3:<est-functional-diff-screen-1.2 }{2:<st-functional-diff-screen-1 [+] }| :6,11diffput screen-1 | ]]) end) @@ -229,18 +218,6 @@ describe('Diff mode screen with 2 diffs open', function() screen = Screen.new(100, 20) screen:attach() - screen:set_default_attr_ids({ - [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, - [2] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1 }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray }, - [6] = { foreground = Screen.colors.Blue1, bold = true }, - [7] = { reverse = true, bold = true }, - [8] = { background = Screen.colors.Red1, bold = true }, - [10] = { foreground = Screen.colors.Brown }, - [9] = { background = Screen.colors.Plum1 }, - }) feed('<c-w>=') feed(':windo set nu!<cr>') end) @@ -290,20 +267,20 @@ something feed('1<c-w>w') feed(':5,9diffget<cr>') screen:expect([[ - {1:+ }{10: 1 }{5:^+-- 7 lines: common line··················}│{1:+ }{10: 1 }{5:+-- 7 lines: common line···················}| - {1: }{10: 8 }xyz │{1: }{10: 8 }xyz | - {1: }{10: 9 }DEFabc │{1: }{10: 9 }DEFabc | - {1: }{10: 10 }DEFabc │{1: }{10: 10 }DEFabc | - {1: }{10: 11 }DEFabc │{1: }{10: 11 }DEFabc | - {1: }{10: 12 }common line │{1: }{10: 12 }common line | - {1: }{10: 13 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 14 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 15 }something │{1: }{10: 17 }something | - {1: }{10: 16 } │{1: }{10: 18 } | - {6:~ }│{6:~ }|*6 - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7:+ }{8: 1 }{13:^+-- 7 lines: common line··················}│{7:+ }{8: 1 }{13:+-- 7 lines: common line···················}| + {7: }{8: 8 }xyz │{7: }{8: 8 }xyz | + {7: }{8: 9 }DEFabc │{7: }{8: 9 }DEFabc | + {7: }{8: 10 }DEFabc │{7: }{8: 10 }DEFabc | + {7: }{8: 11 }DEFabc │{7: }{8: 11 }DEFabc | + {7: }{8: 12 }common line │{7: }{8: 12 }common line | + {7: }{8: 13 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 14 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 15 }something │{7: }{8: 17 }something | + {7: }{8: 16 } │{7: }{8: 18 } | + {1:~ }│{1:~ }|*6 + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :5,9diffget | ]]) end) @@ -311,23 +288,23 @@ something feed('2<c-w>w') feed(':5,10diffget<cr>') screen:expect([[ - {1:- }{10: 1 } │{1:- }{10: 1 }^ | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }ABCabc │{1: }{10: 5 }ABCabc | - {1: }{10: 6 }ABCabc │{1: }{10: 6 }ABCabc | - {1: }{10: 7 }ABCabc │{1: }{10: 7 }ABCabc | - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 8 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 9 }common line | - {1: }{10: 10 }common line │{1: }{10: 10 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 11 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 12 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 13 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 14 }something | - {1: }{10: 13 } │{1: }{10: 15 } | - {6:~ }│{6:~ }|*3 - {3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }| + {7:- }{8: 1 } │{7:- }{8: 1 }^ | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }ABCabc │{7: }{8: 5 }ABCabc | + {7: }{8: 6 }ABCabc │{7: }{8: 6 }ABCabc | + {7: }{8: 7 }ABCabc │{7: }{8: 7 }ABCabc | + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 8 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 9 }common line | + {7: }{8: 10 }common line │{7: }{8: 10 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 11 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 12 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 13 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 14 }something | + {7: }{8: 13 } │{7: }{8: 15 } | + {1:~ }│{1:~ }|*3 + {2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| :5,10diffget | ]]) end) @@ -335,21 +312,21 @@ something feed('2<c-w>w') feed(':4,17diffget<cr>') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 }^ | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }ABCabc │{1: }{10: 5 }ABCabc | - {1: }{10: 6 }ABCabc │{1: }{10: 6 }ABCabc | - {1: }{10: 7 }ABCabc │{1: }{10: 7 }ABCabc | - {1: }{10: 8 }ABCabc │{1: }{10: 8 }ABCabc | - {1: }{10: 9 }common line │{1: }{10: 9 }common line | - {1: }{10: 10 }common line │{1: }{10: 10 }common line | - {1: }{10: 11 }common line │{1: }{10: 11 }common line | - {1: }{10: 12 }something │{1: }{10: 12 }something | - {1: }{10: 13 } │{1: }{10: 13 } | - {6:~ }│{6:~ }|*5 - {3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 }^ | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }ABCabc │{7: }{8: 5 }ABCabc | + {7: }{8: 6 }ABCabc │{7: }{8: 6 }ABCabc | + {7: }{8: 7 }ABCabc │{7: }{8: 7 }ABCabc | + {7: }{8: 8 }ABCabc │{7: }{8: 8 }ABCabc | + {7: }{8: 9 }common line │{7: }{8: 9 }common line | + {7: }{8: 10 }common line │{7: }{8: 10 }common line | + {7: }{8: 11 }common line │{7: }{8: 11 }common line | + {7: }{8: 12 }something │{7: }{8: 12 }something | + {7: }{8: 13 } │{7: }{8: 13 } | + {1:~ }│{1:~ }|*5 + {2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| :4,17diffget | ]]) end) @@ -357,25 +334,25 @@ something feed('1<c-w>w') feed(':4,12diffget<cr>') screen:expect([[ - {1: }{10: 1 }^ │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }DEFabc │{1: }{10: 5 }DEFabc | - {1: }{10: 6 }xyz │{1: }{10: 6 }xyz | - {1: }{10: 7 }xyz │{1: }{10: 7 }xyz | - {1: }{10: 8 }xyz │{1: }{10: 8 }xyz | - {1: }{10: 9 }DEFabc │{1: }{10: 9 }DEFabc | - {1: }{10: 10 }DEFabc │{1: }{10: 10 }DEFabc | - {1: }{10: 11 }DEFabc │{1: }{10: 11 }DEFabc | - {1: }{10: 12 }common line │{1: }{10: 12 }common line | - {1: }{10: 13 }common line │{1: }{10: 13 }common line | - {1: }{10: 14 }DEF │{1: }{10: 14 }DEF | - {1: }{10: 15 }common line │{1: }{10: 15 }common line | - {1: }{10: 16 }DEF │{1: }{10: 16 }DEF | - {1: }{10: 17 }something │{1: }{10: 17 }something | - {1: }{10: 18 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^ │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }DEFabc │{7: }{8: 5 }DEFabc | + {7: }{8: 6 }xyz │{7: }{8: 6 }xyz | + {7: }{8: 7 }xyz │{7: }{8: 7 }xyz | + {7: }{8: 8 }xyz │{7: }{8: 8 }xyz | + {7: }{8: 9 }DEFabc │{7: }{8: 9 }DEFabc | + {7: }{8: 10 }DEFabc │{7: }{8: 10 }DEFabc | + {7: }{8: 11 }DEFabc │{7: }{8: 11 }DEFabc | + {7: }{8: 12 }common line │{7: }{8: 12 }common line | + {7: }{8: 13 }common line │{7: }{8: 13 }common line | + {7: }{8: 14 }DEF │{7: }{8: 14 }DEF | + {7: }{8: 15 }common line │{7: }{8: 15 }common line | + {7: }{8: 16 }DEF │{7: }{8: 16 }DEF | + {7: }{8: 17 }something │{7: }{8: 17 }something | + {7: }{8: 18 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :4,12diffget | ]]) end) @@ -384,25 +361,25 @@ something feed('5gg') feed('do') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }^DEFabc │{1: }{10: 5 }DEFabc | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }^DEFabc │{7: }{8: 5 }DEFabc | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -411,25 +388,25 @@ something feed('6gg') feed('do') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }^DEFabc │{1: }{10: 9 }DEFabc | - {1: }{10: 7 }DEFabc │{1: }{10: 10 }DEFabc | - {1: }{10: 8 }DEFabc │{1: }{10: 11 }DEFabc | - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }^DEFabc │{7: }{8: 9 }DEFabc | + {7: }{8: 7 }DEFabc │{7: }{8: 10 }DEFabc | + {7: }{8: 8 }DEFabc │{7: }{8: 11 }DEFabc | + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -438,25 +415,25 @@ something feed('7gg') feed('do') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }DEFabc │{1: }{10: 9 }DEFabc | - {1: }{10: 7 }^DEFabc │{1: }{10: 10 }DEFabc | - {1: }{10: 8 }DEFabc │{1: }{10: 11 }DEFabc | - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }DEFabc │{7: }{8: 9 }DEFabc | + {7: }{8: 7 }^DEFabc │{7: }{8: 10 }DEFabc | + {7: }{8: 8 }DEFabc │{7: }{8: 11 }DEFabc | + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -465,25 +442,25 @@ something feed('11gg') feed('do') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: 11 }DEF │{1: }{10: 14 }DEF | - {1: }{10: 12 }^common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 13 }something │{1: }{10: 17 }something | - {1: }{10: 14 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: 11 }DEF │{7: }{8: 14 }DEF | + {7: }{8: 12 }^common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 13 }something │{7: }{8: 17 }something | + {7: }{8: 14 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -492,25 +469,25 @@ something feed('12gg') feed('do') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: 12 }DEF │{1: }{10: 16 }DEF | - {1: }{10: 13 }^something │{1: }{10: 17 }something | - {1: }{10: 14 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: 12 }DEF │{7: }{8: 16 }DEF | + {7: }{8: 13 }^something │{7: }{8: 17 }something | + {7: }{8: 14 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -519,25 +496,25 @@ something feed('5gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }^ABCabc │{1: }{10: 5 }ABCabc | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }^ABCabc │{7: }{8: 5 }ABCabc | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }| :e | ]]) end) @@ -546,25 +523,25 @@ something feed('6gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }^ABCabc │{1: }{10: 9 }ABCabc | - {1: }{10: 7 }ABCabc │{1: }{10: 10 }ABCabc | - {1: }{10: 8 }ABCabc │{1: }{10: 11 }ABCabc | - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }^ABCabc │{7: }{8: 9 }ABCabc | + {7: }{8: 7 }ABCabc │{7: }{8: 10 }ABCabc | + {7: }{8: 8 }ABCabc │{7: }{8: 11 }ABCabc | + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }| :e | ]]) end) @@ -573,25 +550,25 @@ something feed('7gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }ABCabc │{1: }{10: 9 }ABCabc | - {1: }{10: 7 }^ABCabc │{1: }{10: 10 }ABCabc | - {1: }{10: 8 }ABCabc │{1: }{10: 11 }ABCabc | - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }ABCabc │{7: }{8: 9 }ABCabc | + {7: }{8: 7 }^ABCabc │{7: }{8: 10 }ABCabc | + {7: }{8: 8 }ABCabc │{7: }{8: 11 }ABCabc | + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }| :e | ]]) end) @@ -600,25 +577,25 @@ something feed('11gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: 11 }^common line │{1: }{10: 14 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 15 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 16 }something | - {1: }{10: 13 } │{1: }{10: 17 } | - {6:~ }│{6:~ }| - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: 11 }^common line │{7: }{8: 14 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 15 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 16 }something | + {7: }{8: 13 } │{7: }{8: 17 } | + {1:~ }│{1:~ }| + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }| :e | ]]) end) @@ -627,25 +604,25 @@ something feed('12gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: 12 }^something │{1: }{10: 16 }something | - {1: }{10: 13 } │{1: }{10: 17 } | - {6:~ }│{6:~ }| - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: 12 }^something │{7: }{8: 16 }something | + {7: }{8: 13 } │{7: }{8: 17 } | + {1:~ }│{1:~ }| + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }| :e | ]]) end) @@ -654,25 +631,25 @@ something feed('6gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: 6 }xyz │{1: }{10: 6 }^xyz | - {1: }{10: 7 }xyz │{1: }{10: 7 }xyz | - {1: }{10: 8 }xyz │{1: }{10: 8 }xyz | - {1: }{10: 9 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 10 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 11 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 12 }common line │{1: }{10: 12 }common line | - {1: }{10: 13 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 14 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 15 }something │{1: }{10: 17 }something | - {1: }{10: 16 } │{1: }{10: 18 } | - {3:Xtest-functional-diff-screen-1.2 [+] }{7:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: 6 }xyz │{7: }{8: 6 }^xyz | + {7: }{8: 7 }xyz │{7: }{8: 7 }xyz | + {7: }{8: 8 }xyz │{7: }{8: 8 }xyz | + {7: }{8: 9 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 10 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 11 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 12 }common line │{7: }{8: 12 }common line | + {7: }{8: 13 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 14 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 15 }something │{7: }{8: 17 }something | + {7: }{8: 16 } │{7: }{8: 18 } | + {2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -681,25 +658,25 @@ something feed('8gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: 6 }xyz │{1: }{10: 6 }xyz | - {1: }{10: 7 }xyz │{1: }{10: 7 }xyz | - {1: }{10: 8 }xyz │{1: }{10: 8 }^xyz | - {1: }{10: 9 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 10 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 11 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 12 }common line │{1: }{10: 12 }common line | - {1: }{10: 13 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 14 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 15 }something │{1: }{10: 17 }something | - {1: }{10: 16 } │{1: }{10: 18 } | - {3:Xtest-functional-diff-screen-1.2 [+] }{7:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: 6 }xyz │{7: }{8: 6 }xyz | + {7: }{8: 7 }xyz │{7: }{8: 7 }xyz | + {7: }{8: 8 }xyz │{7: }{8: 8 }^xyz | + {7: }{8: 9 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 10 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 11 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 12 }common line │{7: }{8: 12 }common line | + {7: }{8: 13 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 14 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 15 }something │{7: }{8: 17 }something | + {7: }{8: 16 } │{7: }{8: 18 } | + {2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -708,25 +685,25 @@ something feed('9gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }DEFabc │{1: }{10: 9 }^DEFabc | - {1: }{10: 7 }DEFabc │{1: }{10: 10 }DEFabc | - {1: }{10: 8 }DEFabc │{1: }{10: 11 }DEFabc | - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }| - {1: }{10: 12 }something │{1: }{10: 17 }something | - {1: }{10: 13 } │{1: }{10: 18 } | - {3:Xtest-functional-diff-screen-1.2 [+] }{7:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }DEFabc │{7: }{8: 9 }^DEFabc | + {7: }{8: 7 }DEFabc │{7: }{8: 10 }DEFabc | + {7: }{8: 8 }DEFabc │{7: }{8: 11 }DEFabc | + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }| + {7: }{8: 12 }something │{7: }{8: 17 }something | + {7: }{8: 13 } │{7: }{8: 18 } | + {2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -735,25 +712,25 @@ something feed('17gg') feed('dp') screen:expect([[ - {1: }{10: 1 } │{1: }{10: 1 } | - {1: }{10: 2 }common line │{1: }{10: 2 }common line | - {1: }{10: 3 }common line │{1: }{10: 3 }common line | - {1: }{10: 4 } │{1: }{10: 4 } | - {1: }{10: 5 }{8:ABC}{9:abc }│{1: }{10: 5 }{8:DEF}{9:abc }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 6 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 7 }{4:xyz }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 8 }{4:xyz }| - {1: }{10: 6 }{8:ABC}{9:abc }│{1: }{10: 9 }{8:DEF}{9:abc }| - {1: }{10: 7 }{8:ABC}{9:abc }│{1: }{10: 10 }{8:DEF}{9:abc }| - {1: }{10: 8 }{8:ABC}{9:abc }│{1: }{10: 11 }{8:DEF}{9:abc }| - {1: }{10: 9 }common line │{1: }{10: 12 }common line | - {1: }{10: 10 }common line │{1: }{10: 13 }common line | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 14 }{4:DEF }| - {1: }{10: 11 }common line │{1: }{10: 15 }common line | - {1: }{10: 12 }DEF │{1: }{10: 16 }DEF | - {1: }{10: 13 }something │{1: }{10: 17 }^something | - {1: }{10: 14 } │{1: }{10: 18 } | - {3:Xtest-functional-diff-screen-1.2 [+] }{7:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 } │{7: }{8: 1 } | + {7: }{8: 2 }common line │{7: }{8: 2 }common line | + {7: }{8: 3 }common line │{7: }{8: 3 }common line | + {7: }{8: 4 } │{7: }{8: 4 } | + {7: }{8: 5 }{27:ABC}{4:abc }│{7: }{8: 5 }{27:DEF}{4:abc }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 6 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 7 }{22:xyz }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 8 }{22:xyz }| + {7: }{8: 6 }{27:ABC}{4:abc }│{7: }{8: 9 }{27:DEF}{4:abc }| + {7: }{8: 7 }{27:ABC}{4:abc }│{7: }{8: 10 }{27:DEF}{4:abc }| + {7: }{8: 8 }{27:ABC}{4:abc }│{7: }{8: 11 }{27:DEF}{4:abc }| + {7: }{8: 9 }common line │{7: }{8: 12 }common line | + {7: }{8: 10 }common line │{7: }{8: 13 }common line | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }| + {7: }{8: 11 }common line │{7: }{8: 15 }common line | + {7: }{8: 12 }DEF │{7: }{8: 16 }DEF | + {7: }{8: 13 }something │{7: }{8: 17 }^something | + {7: }{8: 14 } │{7: }{8: 18 } | + {2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -778,13 +755,13 @@ d it('display results', function() screen:expect([[ - {1: }{10: 1 }{4:^ }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 2 }{9:abc d }│{1: }{10: 1 }{8:// }{9:abc d }| - {1: }{10: 3 }{9:d }│{1: }{10: 2 }{8:// }{9:d }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 3 }{4:// d }| - {1: }{10: 4 } │{1: }{10: 4 } | - {6:~ }│{6:~ }|*13 - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }{22:^ }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 2 }{4:abc d }│{7: }{8: 1 }{27:// }{4:abc d }| + {7: }{8: 3 }{4:d }│{7: }{8: 2 }{27:// }{4:d }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 3 }{22:// d }| + {7: }{8: 4 } │{7: }{8: 4 } | + {1:~ }│{1:~ }|*13 + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -813,15 +790,15 @@ void testFunction () { it('display results', function() screen:expect([[ - {1: }{10: 1 }^void testFunction () { │{1: }{10: 1 }void testFunction () { | - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 2 }{4: for (int i = 0; i < 10; i++) { }| - {1: }{10: 2 }{9: }{8:// for (int j = 0; j < 10; i}{9:++) { }│{1: }{10: 3 }{9: }{8:for (int j = 0; j < 10; j}{9:++) { }| - {1: }{10: 3 }{9: }{8:// }{9:} }│{1: }{10: 4 }{9: } }| - {1: }{10: }{2:-------------------------------------------}│{1: }{10: 5 }{4: } }| - {1: }{10: 4 }} │{1: }{10: 6 }} | - {1: }{10: 5 } │{1: }{10: 7 } | - {6:~ }│{6:~ }|*11 - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^void testFunction () { │{7: }{8: 1 }void testFunction () { | + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 2 }{22: for (int i = 0; i < 10; i++) { }| + {7: }{8: 2 }{4: }{27:// for (int j = 0; j < 10; i}{4:++) { }│{7: }{8: 3 }{4: }{27:for (int j = 0; j < 10; j}{4:++) { }| + {7: }{8: 3 }{4: }{27:// }{4:} }│{7: }{8: 4 }{4: } }| + {7: }{8: }{23:-------------------------------------------}│{7: }{8: 5 }{22: } }| + {7: }{8: 4 }} │{7: }{8: 6 }} | + {7: }{8: 5 } │{7: }{8: 7 } | + {1:~ }│{1:~ }|*11 + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -851,17 +828,17 @@ void testFunction () { it('display results', function() screen:expect([[ - {1: }{10: 1 }{4:^?Z }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 2 }{8:?}{9:A }│{1: }{10: 1 }{8:!}{9:A }| - {1: }{10: 3 }{8:?}{9:B }│{1: }{10: 2 }{8:!}{9:B }| - {1: }{10: 4 }{8:?}{9:C }│{1: }{10: 3 }{8:!}{9:C }| - {1: }{10: 5 }{4:?A }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 6 }{4:?B }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 7 }{4:?B }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 8 }{4:?C }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 9 } │{1: }{10: 4 } | - {6:~ }│{6:~ }|*9 - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }{22:^?Z }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 2 }{27:?}{4:A }│{7: }{8: 1 }{27:!}{4:A }| + {7: }{8: 3 }{27:?}{4:B }│{7: }{8: 2 }{27:!}{4:B }| + {7: }{8: 4 }{27:?}{4:C }│{7: }{8: 3 }{27:!}{4:C }| + {7: }{8: 5 }{22:?A }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 6 }{22:?B }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 7 }{22:?B }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 8 }{22:?C }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 9 } │{7: }{8: 4 } | + {1:~ }│{1:~ }|*9 + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -891,17 +868,17 @@ void testFunction () { it('display results', function() screen:expect([[ - {1: }{10: 1 }{4:^?A }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 2 }{4:?Z }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 3 }{4:?B }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 4 }{4:?C }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 5 }{8:?}{9:A }│{1: }{10: 1 }{8:!}{9:A }| - {1: }{10: 6 }{8:?}{9:B }│{1: }{10: 2 }{8:!}{9:B }| - {1: }{10: 7 }{8:?}{9:C }│{1: }{10: 3 }{8:!}{9:C }| - {1: }{10: 8 }{4:?C }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 9 } │{1: }{10: 4 } | - {6:~ }│{6:~ }|*9 - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }{22:^?A }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 2 }{22:?Z }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 3 }{22:?B }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 4 }{22:?C }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 5 }{27:?}{4:A }│{7: }{8: 1 }{27:!}{4:A }| + {7: }{8: 6 }{27:?}{4:B }│{7: }{8: 2 }{27:!}{4:B }| + {7: }{8: 7 }{27:?}{4:C }│{7: }{8: 3 }{27:!}{4:C }| + {7: }{8: 8 }{22:?C }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 9 } │{7: }{8: 4 } | + {1:~ }│{1:~ }|*9 + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :e | ]]) end) @@ -953,50 +930,50 @@ something feed('1<c-w>w') -- linematch is disabled for the longest diff because it's combined line length is over 10 screen:expect([[ - {1: }{10: 1 }^common line │{1: }{10: 1 }common line | - {1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }| - {1: }{10: 4 }{4:something }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 5 } │{1: }{10: 3 } | - {1: }{10: 6 }{9:a}{8:DEF}{9:abc }│{1: }{10: 4 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 7 }{8:xyz}{9: }│{1: }{10: 5 }{8:aABCabc}{9: }| - {1: }{10: 8 }{8:xyz}{9: }│{1: }{10: 6 }{8:aABCabc}{9: }| - {1: }{10: 9 }{8:xyz}{9: }│{1: }{10: 7 }{8:aABCabc}{9: }| - {1: }{10: 10 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 11 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 12 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 13 }common line │{1: }{10: 8 }common line | - {1: }{10: 14 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 15 }{8:GHI}{9: }│{1: }{10: 9 }{8:HIL}{9: }| - {1: }{10: 16 }{4:something else }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 17 }common line │{1: }{10: 10 }common line | - {1: }{10: 18 }something │{1: }{10: 11 }something | - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^common line │{7: }{8: 1 }common line | + {7: }{8: 2 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 3 }{27:GHI}{4: }│{7: }{8: 2 }{27:HIL}{4: }| + {7: }{8: 4 }{22:something }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 5 } │{7: }{8: 3 } | + {7: }{8: 6 }{4:a}{27:DEF}{4:abc }│{7: }{8: 4 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 7 }{27:xyz}{4: }│{7: }{8: 5 }{27:aABCabc}{4: }| + {7: }{8: 8 }{27:xyz}{4: }│{7: }{8: 6 }{27:aABCabc}{4: }| + {7: }{8: 9 }{27:xyz}{4: }│{7: }{8: 7 }{27:aABCabc}{4: }| + {7: }{8: 10 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 11 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 12 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 13 }common line │{7: }{8: 8 }common line | + {7: }{8: 14 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 15 }{27:GHI}{4: }│{7: }{8: 9 }{27:HIL}{4: }| + {7: }{8: 16 }{22:something else }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 17 }common line │{7: }{8: 10 }common line | + {7: }{8: 18 }something │{7: }{8: 11 }something | + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :e | ]]) -- enable it by increasing the number feed(':set diffopt-=linematch:10<cr>') feed(':set diffopt+=linematch:30<cr>') screen:expect([[ - {1: }{10: 1 }^common line │{1: }{10: 1 }common line | - {1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }| - {1: }{10: 4 }{4:something }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 5 } │{1: }{10: 3 } | - {1: }{10: 6 }{9:a}{8:DEF}{9:abc }│{1: }{10: 4 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 7 }{4:xyz }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 8 }{4:xyz }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 9 }{4:xyz }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 10 }{9:a}{8:DEF}{9:abc }│{1: }{10: 5 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 11 }{9:a}{8:DEF}{9:abc }│{1: }{10: 6 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 12 }{9:a}{8:DEF}{9:abc }│{1: }{10: 7 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 13 }common line │{1: }{10: 8 }common line | - {1: }{10: 14 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 15 }{8:GHI}{9: }│{1: }{10: 9 }{8:HIL}{9: }| - {1: }{10: 16 }{4:something else }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 17 }common line │{1: }{10: 10 }common line | - {1: }{10: 18 }something │{1: }{10: 11 }something | - {7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^common line │{7: }{8: 1 }common line | + {7: }{8: 2 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 3 }{27:GHI}{4: }│{7: }{8: 2 }{27:HIL}{4: }| + {7: }{8: 4 }{22:something }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 5 } │{7: }{8: 3 } | + {7: }{8: 6 }{4:a}{27:DEF}{4:abc }│{7: }{8: 4 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 7 }{22:xyz }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 8 }{22:xyz }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 9 }{22:xyz }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 10 }{4:a}{27:DEF}{4:abc }│{7: }{8: 5 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 11 }{4:a}{27:DEF}{4:abc }│{7: }{8: 6 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 12 }{4:a}{27:DEF}{4:abc }│{7: }{8: 7 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 13 }common line │{7: }{8: 8 }common line | + {7: }{8: 14 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 15 }{27:GHI}{4: }│{7: }{8: 9 }{27:HIL}{4: }| + {7: }{8: 16 }{22:something else }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 17 }common line │{7: }{8: 10 }common line | + {7: }{8: 18 }something │{7: }{8: 11 }something | + {3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }| :set diffopt+=linematch:30 | ]]) end @@ -1005,25 +982,25 @@ something feed('2<c-w>w') feed(':1,12diffget<cr>') screen:expect([[ - {1: }{10: 1 }common line │{1: }{10: 1 }^common line | - {1: }{10: 2 }DEF │{1: }{10: 2 }DEF | - {1: }{10: 3 }GHI │{1: }{10: 3 }GHI | - {1: }{10: 4 }something │{1: }{10: 4 }something | - {1: }{10: 5 } │{1: }{10: 5 } | - {1: }{10: 6 }aDEFabc │{1: }{10: 6 }aDEFabc | - {1: }{10: 7 }xyz │{1: }{10: 7 }xyz | - {1: }{10: 8 }xyz │{1: }{10: 8 }xyz | - {1: }{10: 9 }xyz │{1: }{10: 9 }xyz | - {1: }{10: 10 }aDEFabc │{1: }{10: 10 }aDEFabc | - {1: }{10: 11 }aDEFabc │{1: }{10: 11 }aDEFabc | - {1: }{10: 12 }aDEFabc │{1: }{10: 12 }aDEFabc | - {1: }{10: 13 }common line │{1: }{10: 13 }common line | - {1: }{10: 14 }DEF │{1: }{10: 14 }DEF | - {1: }{10: 15 }GHI │{1: }{10: 15 }GHI | - {1: }{10: 16 }something else │{1: }{10: 16 }something else | - {1: }{10: 17 }common line │{1: }{10: 17 }common line | - {1: }{10: 18 }something │{1: }{10: 18 }something | - {3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 }common line │{7: }{8: 1 }^common line | + {7: }{8: 2 }DEF │{7: }{8: 2 }DEF | + {7: }{8: 3 }GHI │{7: }{8: 3 }GHI | + {7: }{8: 4 }something │{7: }{8: 4 }something | + {7: }{8: 5 } │{7: }{8: 5 } | + {7: }{8: 6 }aDEFabc │{7: }{8: 6 }aDEFabc | + {7: }{8: 7 }xyz │{7: }{8: 7 }xyz | + {7: }{8: 8 }xyz │{7: }{8: 8 }xyz | + {7: }{8: 9 }xyz │{7: }{8: 9 }xyz | + {7: }{8: 10 }aDEFabc │{7: }{8: 10 }aDEFabc | + {7: }{8: 11 }aDEFabc │{7: }{8: 11 }aDEFabc | + {7: }{8: 12 }aDEFabc │{7: }{8: 12 }aDEFabc | + {7: }{8: 13 }common line │{7: }{8: 13 }common line | + {7: }{8: 14 }DEF │{7: }{8: 14 }DEF | + {7: }{8: 15 }GHI │{7: }{8: 15 }GHI | + {7: }{8: 16 }something else │{7: }{8: 16 }something else | + {7: }{8: 17 }common line │{7: }{8: 17 }common line | + {7: }{8: 18 }something │{7: }{8: 18 }something | + {2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| :1,12diffget | ]]) end) @@ -1031,20 +1008,20 @@ something feed('1<c-w>w') feed(':1,19diffget<cr>') screen:expect([[ - {1: }{10: 1 }^common line │{1: }{10: 1 }common line | - {1: }{10: 2 }HIL │{1: }{10: 2 }HIL | - {1: }{10: 3 } │{1: }{10: 3 } | - {1: }{10: 4 }aABCabc │{1: }{10: 4 }aABCabc | - {1: }{10: 5 }aABCabc │{1: }{10: 5 }aABCabc | - {1: }{10: 6 }aABCabc │{1: }{10: 6 }aABCabc | - {1: }{10: 7 }aABCabc │{1: }{10: 7 }aABCabc | - {1: }{10: 8 }common line │{1: }{10: 8 }common line | - {1: }{10: 9 }HIL │{1: }{10: 9 }HIL | - {1: }{10: 10 }common line │{1: }{10: 10 }common line | - {1: }{10: 11 }something │{1: }{10: 11 }something | - {1: }{10: 12 } │{1: }{10: 12 } | - {6:~ }│{6:~ }|*6 - {7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }| + {7: }{8: 1 }^common line │{7: }{8: 1 }common line | + {7: }{8: 2 }HIL │{7: }{8: 2 }HIL | + {7: }{8: 3 } │{7: }{8: 3 } | + {7: }{8: 4 }aABCabc │{7: }{8: 4 }aABCabc | + {7: }{8: 5 }aABCabc │{7: }{8: 5 }aABCabc | + {7: }{8: 6 }aABCabc │{7: }{8: 6 }aABCabc | + {7: }{8: 7 }aABCabc │{7: }{8: 7 }aABCabc | + {7: }{8: 8 }common line │{7: }{8: 8 }common line | + {7: }{8: 9 }HIL │{7: }{8: 9 }HIL | + {7: }{8: 10 }common line │{7: }{8: 10 }common line | + {7: }{8: 11 }something │{7: }{8: 11 }something | + {7: }{8: 12 } │{7: }{8: 12 } | + {1:~ }│{1:~ }|*6 + {3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }| :1,19diffget | ]]) end) @@ -1054,25 +1031,25 @@ something feed('2<c-w>w') feed(':7,8diffget<cr>') screen:expect([[ - {1: }{10: 1 }common line │{1: }{10: 1 }^common line | - {1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }| - {1: }{10: 4 }{4:something }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 5 } │{1: }{10: 3 } | - {1: }{10: 6 }{9:a}{8:DEF}{9:abc }│{1: }{10: 4 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 7 }{8:xyz}{9: }│{1: }{10: 5 }{8:aABCabc}{9: }| - {1: }{10: 8 }{8:xyz}{9: }│{1: }{10: 6 }{8:aABCabc}{9: }| - {1: }{10: 9 }xyz │{1: }{10: 7 }xyz | - {1: }{10: 10 }aDEFabc │{1: }{10: 8 }aDEFabc | - {1: }{10: 11 }aDEFabc │{1: }{10: 9 }aDEFabc | - {1: }{10: 12 }aDEFabc │{1: }{10: 10 }aDEFabc | - {1: }{10: 13 }common line │{1: }{10: 11 }common line | - {1: }{10: 14 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 15 }{8:GHI}{9: }│{1: }{10: 12 }{8:HIL}{9: }| - {1: }{10: 16 }{4:something else }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 17 }common line │{1: }{10: 13 }common line | - {1: }{10: 18 }something │{1: }{10: 14 }something | - {3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 }common line │{7: }{8: 1 }^common line | + {7: }{8: 2 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 3 }{27:GHI}{4: }│{7: }{8: 2 }{27:HIL}{4: }| + {7: }{8: 4 }{22:something }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 5 } │{7: }{8: 3 } | + {7: }{8: 6 }{4:a}{27:DEF}{4:abc }│{7: }{8: 4 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 7 }{27:xyz}{4: }│{7: }{8: 5 }{27:aABCabc}{4: }| + {7: }{8: 8 }{27:xyz}{4: }│{7: }{8: 6 }{27:aABCabc}{4: }| + {7: }{8: 9 }xyz │{7: }{8: 7 }xyz | + {7: }{8: 10 }aDEFabc │{7: }{8: 8 }aDEFabc | + {7: }{8: 11 }aDEFabc │{7: }{8: 9 }aDEFabc | + {7: }{8: 12 }aDEFabc │{7: }{8: 10 }aDEFabc | + {7: }{8: 13 }common line │{7: }{8: 11 }common line | + {7: }{8: 14 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 15 }{27:GHI}{4: }│{7: }{8: 12 }{27:HIL}{4: }| + {7: }{8: 16 }{22:something else }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 17 }common line │{7: }{8: 13 }common line | + {7: }{8: 18 }something │{7: }{8: 14 }something | + {2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| :7,8diffget | ]]) end @@ -1083,25 +1060,25 @@ something feed('2<c-w>w') feed(':8,10diffget<cr>') screen:expect([[ - {1: }{10: 1 }common line │{1: }{10: 1 }^common line | - {1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }| - {1: }{10: 4 }{4:something }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 5 } │{1: }{10: 3 } | - {1: }{10: 6 }{9:a}{8:DEF}{9:abc }│{1: }{10: 4 }{9:a}{8:ABC}{9:abc }| - {1: }{10: 7 }{8:xyz}{9: }│{1: }{10: 5 }{8:aABCabc}{9: }| - {1: }{10: 8 }{8:xyz}{9: }│{1: }{10: 6 }{8:aABCabc}{9: }| - {1: }{10: 9 }{8:xyz}{9: }│{1: }{10: 7 }{8:aABCabc}{9: }| - {1: }{10: 10 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 11 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 12 }{4:aDEFabc }│{1: }{10: }{2:--------------------------------------------}| - {1: }{10: 13 }common line │{1: }{10: 8 }common line | - {1: }{10: 14 }DEF │{1: }{10: 9 }DEF | - {1: }{10: 15 }GHI │{1: }{10: 10 }GHI | - {1: }{10: 16 }something else │{1: }{10: 11 }something else | - {1: }{10: 17 }common line │{1: }{10: 12 }common line | - {1: }{10: 18 }something │{1: }{10: 13 }something | - {3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }| + {7: }{8: 1 }common line │{7: }{8: 1 }^common line | + {7: }{8: 2 }{22:DEF }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 3 }{27:GHI}{4: }│{7: }{8: 2 }{27:HIL}{4: }| + {7: }{8: 4 }{22:something }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 5 } │{7: }{8: 3 } | + {7: }{8: 6 }{4:a}{27:DEF}{4:abc }│{7: }{8: 4 }{4:a}{27:ABC}{4:abc }| + {7: }{8: 7 }{27:xyz}{4: }│{7: }{8: 5 }{27:aABCabc}{4: }| + {7: }{8: 8 }{27:xyz}{4: }│{7: }{8: 6 }{27:aABCabc}{4: }| + {7: }{8: 9 }{27:xyz}{4: }│{7: }{8: 7 }{27:aABCabc}{4: }| + {7: }{8: 10 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 11 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 12 }{22:aDEFabc }│{7: }{8: }{23:--------------------------------------------}| + {7: }{8: 13 }common line │{7: }{8: 8 }common line | + {7: }{8: 14 }DEF │{7: }{8: 9 }DEF | + {7: }{8: 15 }GHI │{7: }{8: 10 }GHI | + {7: }{8: 16 }something else │{7: }{8: 11 }something else | + {7: }{8: 17 }common line │{7: }{8: 12 }common line | + {7: }{8: 18 }something │{7: }{8: 13 }something | + {2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }| :8,10diffget | ]]) end @@ -1118,10 +1095,10 @@ describe('regressions', function() screen = Screen.new(100, 20) screen:attach() -- line must be greater than MATCH_CHAR_MAX_LEN - helpers.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1000) .. 'hello' }) - helpers.exec 'vnew' - helpers.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1010) .. 'world' }) - helpers.exec 'windo diffthis' + n.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1000) .. 'hello' }) + n.exec 'vnew' + n.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1010) .. 'world' }) + n.exec 'windo diffthis' end) it('properly computes filler lines for hunks bigger than linematch limit', function() @@ -1133,10 +1110,10 @@ describe('regressions', function() for i = 0, 29 do lines[#lines + 1] = tostring(i) end - helpers.api.nvim_buf_set_lines(0, 0, -1, false, lines) - helpers.exec 'vnew' - helpers.api.nvim_buf_set_lines(0, 0, -1, false, { '00', '29' }) - helpers.exec 'windo diffthis' + n.api.nvim_buf_set_lines(0, 0, -1, false, lines) + n.exec 'vnew' + n.api.nvim_buf_set_lines(0, 0, -1, false, { '00', '29' }) + n.exec 'windo diffthis' feed('<C-e>') screen:expect { grid = [[ diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 31b1464589..ca52a265fa 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -1,24 +1,28 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed = helpers.clear, helpers.feed -local eval = helpers.eval -local eq = helpers.eq -local command = helpers.command -local set_method_error = helpers.set_method_error -local api = helpers.api -local async_meths = helpers.async_meths -local test_build_dir = helpers.paths.test_build_dir -local nvim_prog = helpers.nvim_prog -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local poke_eventloop = helpers.poke_eventloop -local assert_alive = helpers.assert_alive -local is_os = helpers.is_os -local is_ci = helpers.is_ci -local fn = helpers.fn -local skip = helpers.skip + +local clear, feed = n.clear, n.feed +local eval = n.eval +local eq = t.eq +local neq = t.neq +local command = n.command +local set_method_error = n.set_method_error +local api = n.api +local async_meths = n.async_meths +local test_build_dir = t.paths.test_build_dir +local nvim_prog = n.nvim_prog +local testprg = n.testprg +local exec = n.exec +local exec_capture = n.exec_capture +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local poke_eventloop = n.poke_eventloop +local assert_alive = n.assert_alive +local retry = t.retry +local is_os = t.is_os +local fn = n.fn +local skip = t.skip describe('ui/ext_messages', function() local screen @@ -28,18 +32,9 @@ describe('ui/ext_messages', function() clear() screen = Screen.new(25, 5) screen:attach({ rgb = true, ext_messages = true, ext_popupmenu = true }) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [5] = { foreground = Screen.colors.Blue1 }, - [6] = { bold = true, reverse = true }, - [7] = { background = Screen.colors.Yellow }, - [8] = { foreground = Screen.colors.Red }, - [9] = { special = Screen.colors.Red, undercurl = true }, - [10] = { foreground = Screen.colors.Brown }, - }) + screen:add_extra_attr_ids { + [100] = { undercurl = true, special = Screen.colors.Red }, + } end) after_each(function() os.remove(fname) @@ -55,7 +50,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 4 } }, + content = { { '\ntest\n[O]k: ', 6 } }, kind = 'confirm', }, }, @@ -83,7 +78,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 4 } }, + content = { { '\ntest\n[O]k: ', 6 } }, kind = 'confirm', }, }, @@ -97,7 +92,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 4 } }, + content = { { '\ntest\n[O]k: ', 6 } }, kind = 'confirm', }, { @@ -105,7 +100,7 @@ describe('ui/ext_messages', function() kind = 'echo', }, { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -116,23 +111,13 @@ describe('ui/ext_messages', function() feed(':%s/i/X/gc<cr>') screen:expect { grid = [[ - l{7:i}ne 1 | - l{8:i}ne ^2 | + l{2:i}ne 1 | + l{10:i}ne ^2 | {1:~ }|*3 ]], - attr_ids = { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [5] = { foreground = Screen.colors.Blue1 }, - [6] = { bold = true, reverse = true }, - [7] = { reverse = true }, - [8] = { background = Screen.colors.Yellow }, - }, messages = { { - content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 4 } }, + content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6 } }, kind = 'confirm_sub', }, }, @@ -146,16 +131,12 @@ describe('ui/ext_messages', function() screen:expect { grid = [[ line 1 | - {MATCH:.*}| + line ^2 | {1:~ }|*3 ]], - attr_ids = { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [7] = { foreground = Screen.colors.Red }, - }, messages = { { - content = { { 'W10: Warning: Changing a readonly file', 7 } }, + content = { { 'W10: Warning: Changing a readonly file', 19 } }, kind = 'wmsg', }, }, @@ -169,18 +150,9 @@ describe('ui/ext_messages', function() line 2 | {1:~ }|*3 ]], - attr_ids = { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [5] = { foreground = Screen.colors.Blue1 }, - [6] = { bold = true, reverse = true }, - [7] = { foreground = Screen.colors.Red }, - }, messages = { { - content = { { 'search hit BOTTOM, continuing at TOP', 7 } }, + content = { { 'search hit BOTTOM, continuing at TOP', 19 } }, kind = 'wmsg', }, }, @@ -196,15 +168,15 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'Error detected while processing :', 2 } }, + content = { { 'Error detected while processing :', 9 } }, kind = 'emsg', }, { - content = { { 'E605: Exception not caught: foo', 2 } }, + content = { { 'E605: Exception not caught: foo', 9 } }, kind = '', }, { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -237,7 +209,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'raa', 2 } }, + content = { { 'raa', 9 } }, kind = 'echoerr', } }, } @@ -264,15 +236,15 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'bork', 2 } }, + content = { { 'bork', 9 } }, kind = 'echoerr', }, { - content = { { 'fail', 2 } }, + content = { { 'fail', 9 } }, kind = 'echoerr', }, { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -286,19 +258,19 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'bork', 2 } }, + content = { { 'bork', 9 } }, kind = 'echoerr', }, { - content = { { 'fail', 2 } }, + content = { { 'fail', 9 } }, kind = 'echoerr', }, { - content = { { 'extrafail', 2 } }, + content = { { 'extrafail', 9 } }, kind = 'echoerr', }, { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -320,7 +292,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'problem', 2 } }, + content = { { 'problem', 9 } }, kind = 'echoerr', } }, cmdline = { @@ -348,15 +320,15 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], msg_history = { - { kind = 'echoerr', content = { { 'raa', 2 } } }, - { kind = 'echoerr', content = { { 'bork', 2 } } }, - { kind = 'echoerr', content = { { 'fail', 2 } } }, - { kind = 'echoerr', content = { { 'extrafail', 2 } } }, - { kind = 'echoerr', content = { { 'problem', 2 } } }, + { kind = 'echoerr', content = { { 'raa', 9 } } }, + { kind = 'echoerr', content = { { 'bork', 9 } } }, + { kind = 'echoerr', content = { { 'fail', 9 } } }, + { kind = 'echoerr', content = { { 'extrafail', 9 } } }, + { kind = 'echoerr', content = { { 'problem', 9 } } }, }, messages = { { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -380,7 +352,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'bork\nfail', 2 } }, + content = { { 'bork\nfail', 9 } }, kind = 'echoerr', } }, } @@ -393,13 +365,13 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, msg_history = { { - content = { { 'bork\nfail', 2 } }, + content = { { 'bork\nfail', 9 } }, kind = 'echoerr', }, }, @@ -413,8 +385,8 @@ describe('ui/ext_messages', function() feed('/line<cr>') screen:expect { grid = [[ - {7:^line} 1 | - {7:line} 2 | + {10:^line} 1 | + {10:line} 2 | {1:~ }|*3 ]], messages = { @@ -425,8 +397,8 @@ describe('ui/ext_messages', function() feed('n') screen:expect { grid = [[ - {7:line} 1 | - {7:^line} 2 | + {10:line} 1 | + {10:^line} 2 | {1:~ }|*3 ]], messages = { @@ -446,15 +418,15 @@ describe('ui/ext_messages', function() { content = { { '\nErrorMsg ' }, - { 'xxx', 2 }, + { 'xxx', 9 }, { ' ' }, - { 'ctermfg=', 5 }, + { 'ctermfg=', 18 }, { '15 ' }, - { 'ctermbg=', 5 }, + { 'ctermbg=', 18 }, { '1 ' }, - { 'guifg=', 5 }, + { 'guifg=', 18 }, { 'White ' }, - { 'guibg=', 5 }, + { 'guibg=', 18 }, { 'Red' }, }, kind = '', @@ -474,7 +446,7 @@ describe('ui/ext_messages', function() messages = { { content = { { 'x #1' } }, kind = '' }, { content = { { 'y #2' } }, kind = '' }, - { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' }, + { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, }, } end) @@ -487,7 +459,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --', 3 } }, + showmode = { { '-- INSERT --', 5 } }, } feed('alphpabet<cr>alphanum<cr>') @@ -498,7 +470,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*2 ]], - showmode = { { '-- INSERT --', 3 } }, + showmode = { { '-- INSERT --', 5 } }, } feed('<c-x>') @@ -509,7 +481,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*2 ]], - showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 3 } }, + showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5 } }, } feed('<c-p>') @@ -525,7 +497,7 @@ describe('ui/ext_messages', function() items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } }, pos = 1, }, - showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 1 of 2', 4 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 1 of 2', 6 } }, } -- echomsg and showmode don't overwrite each other, this is the same @@ -547,7 +519,7 @@ describe('ui/ext_messages', function() content = { { 'stuff' } }, kind = 'echomsg', } }, - showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 1 of 2', 4 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 1 of 2', 6 } }, } feed('<c-p>') @@ -567,7 +539,7 @@ describe('ui/ext_messages', function() content = { { 'stuff' } }, kind = 'echomsg', } }, - showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 2 of 2', 4 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 2 of 2', 6 } }, } feed('<esc>:messages<cr>') @@ -584,7 +556,7 @@ describe('ui/ext_messages', function() } }, messages = { { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, @@ -598,7 +570,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 3 } }, + showmode = { { 'recording @q', 5 } }, } feed('i') @@ -607,7 +579,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --recording @q', 3 } }, + showmode = { { '-- INSERT --recording @q', 5 } }, } feed('<esc>') @@ -616,7 +588,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 3 } }, + showmode = { { 'recording @q', 5 } }, } feed('q') @@ -635,7 +607,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 3 } }, + showmode = { { 'recording @q', 5 } }, mode = 'normal', } @@ -645,7 +617,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 3 } }, + showmode = { { 'recording @q', 5 } }, mode = 'insert', } @@ -655,7 +627,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 3 } }, + showmode = { { 'recording @q', 5 } }, mode = 'normal', } @@ -684,7 +656,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --', 3 } }, + showmode = { { '-- INSERT --', 5 } }, ruler = { { '0,1 All' } }, } feed('abcde<cr>12345<esc>') @@ -715,7 +687,18 @@ describe('ui/ext_messages', function() ]], ruler = { { '2,1 All' } }, } - feed('d') + feed('<c-v>k2l') + screen:expect({ + grid = [[ + {17:ab}^cde | + {17:123}45 | + {1:~ }|*3 + ]], + showmode = { { '-- VISUAL BLOCK --', 5 } }, + showcmd = { { '2x3' } }, + ruler = { { '1,3 All' } }, + }) + feed('o<esc>d') screen:expect { grid = [[ abcde | @@ -752,7 +735,7 @@ describe('ui/ext_messages', function() abcde | ^ | {1:~ }|*2 - {6:<o Name] [+] 2,0-1 All}| + {3:<o Name] [+] 2,0-1 All}| ]]) end) @@ -792,7 +775,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'bork', 2 } }, + content = { { 'bork', 9 } }, kind = 'echoerr', } }, } @@ -817,7 +800,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'E117: Unknown function: nosuchfunction', 2 } }, + content = { { 'E117: Unknown function: nosuchfunction', 9 } }, kind = 'emsg', }, }, @@ -832,19 +815,19 @@ describe('ui/ext_messages', function() msg_history = { { kind = 'echomsg', content = { { 'howdy' } } }, { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } }, - { kind = 'echoerr', content = { { 'bork', 2 } } }, - { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 2 } } }, + { kind = 'echoerr', content = { { 'bork', 9 } } }, + { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9 } } }, }, messages = { { - content = { { 'Press ENTER or type command to continue', 4 } }, + content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt', }, }, } end) - it('implies ext_cmdline and ignores cmdheight', function() + it("implies ext_cmdline but allows changing 'cmdheight'", function() eq(0, eval('&cmdheight')) feed(':set cmdheight=1') screen:expect { @@ -864,15 +847,17 @@ describe('ui/ext_messages', function() feed('<cr>') screen:expect([[ ^ | - {1:~ }|*4 + {1:~ }|*3 + | ]]) - eq(0, eval('&cmdheight')) + eq(1, eval('&cmdheight')) feed(':set cmdheight=0') screen:expect { grid = [[ ^ | - {1:~ }|*4 + {1:~ }|*3 + | ]], cmdline = { { @@ -907,7 +892,7 @@ error stack traceback: [C]: in function 'error' [string ":lua"]:1: in main chunk]], - 2, + 9, }, }, kind = 'lua_error', @@ -927,7 +912,7 @@ stack traceback: messages = { { content = { - { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 2 }, + { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9 }, }, kind = 'rpc_error', }, @@ -952,7 +937,7 @@ stack traceback: { content = { { '\nn Q @@\nn Y y$\nn j ' }, - { '*', 5 }, + { '*', 18 }, { ' k' }, }, kind = '', @@ -993,7 +978,7 @@ stack traceback: feed('z=') screen:expect { grid = [[ - {9:helllo} | + {100:helllo} | {1:~ }|*3 {1:^~ }| ]], @@ -1012,7 +997,7 @@ stack traceback: feed('1') screen:expect { grid = [[ - {9:helllo} | + {100:helllo} | {1:~ }|*3 {1:^~ }| ]], @@ -1050,7 +1035,7 @@ stack traceback: {1:~ }|*4 ]], messages = { - { content = { { 'wow, ', 7 }, { 'such\n\nvery ', 2 }, { 'color', 10 } }, kind = 'echomsg' }, + { content = { { 'wow, ', 10 }, { 'such\n\nvery ', 9 }, { 'color', 8 } }, kind = 'echomsg' }, }, } @@ -1072,10 +1057,10 @@ stack traceback: {1:~ }|*4 ]], messages = { - { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' }, + { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, }, msg_history = { - { content = { { 'wow, ', 7 }, { 'such\n\nvery ', 2 }, { 'color', 10 } }, kind = 'echomsg' }, + { content = { { 'wow, ', 10 }, { 'such\n\nvery ', 9 }, { 'color', 8 } }, kind = 'echomsg' }, }, } @@ -1104,18 +1089,10 @@ describe('ui/builtin messages', function() clear() screen = Screen.new(60, 7) screen:attach({ rgb = true, ext_popupmenu = true }) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true, reverse = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [5] = { foreground = Screen.colors.Blue1 }, - [6] = { bold = true, foreground = Screen.colors.Magenta }, - [7] = { background = Screen.colors.Grey20 }, - [8] = { reverse = true }, - [9] = { background = Screen.colors.LightRed }, - [10] = { background = Screen.colors.Yellow }, - [11] = { foreground = Screen.colors.Brown }, + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.LightRed }, + [101] = { background = Screen.colors.Grey20 }, + [102] = { foreground = Screen.colors.Magenta1, bold = true }, } end) @@ -1125,12 +1102,12 @@ describe('ui/builtin messages', function() screen:expect { grid = [[ {3: }| - {2:Error invoking 'test_method' on channel 1:} | - {2:complete} | - {2:error} | + {9:Error invoking 'test_method' on channel 1:} | + {9:complete} | + {9:error} | | - {2:message} | - {4:Press ENTER or type command to continue}^ | + {9:message} | + {6:Press ENTER or type command to continue}^ | ]], request_cb = function(name) if name == 'test_method' then @@ -1148,8 +1125,8 @@ describe('ui/builtin messages', function() {1:~ }|*2 {3: }| :hi ErrorMsg | - ErrorMsg {2:xxx} {5:ctermfg=}15 {5:ctermbg=}1 {5:guifg=}White {5:guibg=}Red | - {4:Press ENTER or type command to continue}^ | + ErrorMsg {9:xxx} {18:ctermfg=}15 {18:ctermbg=}1 {18:guifg=}White {18:guibg=}Red | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') @@ -1157,12 +1134,12 @@ describe('ui/builtin messages', function() feed(':hi ErrorMsg<cr>') screen:expect([[ :hi ErrorMsg | - ErrorMsg {2:xxx} {5:ctermfg=}15 | - {5:ctermbg=}1 | - {5:guifg=}White| - {5:guibg=}Red | - {4:Press ENTER or type command to}| - {4: continue}^ | + ErrorMsg {9:xxx} {18:ctermfg=}15 | + {18:ctermbg=}1 | + {18:guifg=}White| + {18:guibg=}Red | + {6:Press ENTER or type command to}| + {6: continue}^ | ]]) feed('<cr>') @@ -1176,13 +1153,13 @@ describe('ui/builtin messages', function() screen:try_resize(110, 7) feed(':syntax list vimComment<cr>') screen:expect([[ - {6:--- Syntax items ---} | - vimComment {5:xxx} {5:match} /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 {5:excludenl} {5:contains}=@vimCommentGroup,vimCommentString | + {102:--- Syntax items ---} | + vimComment {18:xxx} {18:match} /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 {18:excludenl} {18:contains}=@vimCommentGroup,vimCommentString | | - {5:match} /\<endif\s\+".*$/ms=s+5,lc=5 {5:contains}=@vimCommentGroup,vimCommentString | - {5:match} /\<else\s\+".*$/ms=s+4,lc=4 {5:contains}=@vimCommentGroup,vimCommentString | - {5:links to} Comment | - {4:Press ENTER or type command to continue}^ | + {18:match} /\<endif\s\+".*$/ms=s+5,lc=5 {18:contains}=@vimCommentGroup,vimCommentString | + {18:match} /\<else\s\+".*$/ms=s+4,lc=4 {18:contains}=@vimCommentGroup,vimCommentString | + {18:links to} Comment | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') @@ -1190,12 +1167,12 @@ describe('ui/builtin messages', function() feed(':syntax list vimComment<cr>') screen:expect([[ | - {5:match} /\<endif\s\+".*$/ms=s+5,lc=5 | - {5:contains}=@vimCommentGroup,vimCommentString | - {5:match} /\<else\s\+".*$/ms=s+4,lc=4 {5:c}| - {5:ontains}=@vimCommentGroup,vimCommentString | - {5:links to} Comment | - {4:Press ENTER or type command to continue}^ | + {18:match} /\<endif\s\+".*$/ms=s+5,lc=5 | + {18:contains}=@vimCommentGroup,vimCommentString | + {18:match} /\<else\s\+".*$/ms=s+4,lc=4 {18:c}| + {18:ontains}=@vimCommentGroup,vimCommentString | + {18:links to} Comment | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') @@ -1268,7 +1245,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim grid = [[ ^ | {1:~ }|*5 - {7: 0,0-1 All }| + {101: 0,0-1 All }| ]], } @@ -1277,7 +1254,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim grid = [[ ^ | {1:~ }|*5 - {7: 0,0-1 100% }| + {101: 0,0-1 100% }| ]], } end) @@ -1291,7 +1268,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim {3: }| line 1 | line 2 | - {4:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } @@ -1315,7 +1292,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim grid = [[ | {1:~ }| - {8:[No Name] }| + {2:[No Name] }| ^ | {1:~ }| {3:[No Name] }| @@ -1327,12 +1304,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim screen:expect { grid = [[ :set colorcolumn=10 | digraphs | - NU {5:^@} 10 SH {5:^A} 1 SX {5:^B} 2 EX {5:^C} 3 | - ET {5:^D} 4 EQ {5:^E} 5 AK {5:^F} 6 BL {5:^G} 7 | - BS {5:^H} 8 HT {5:^I} 9 LF {5:^@} 10 VT {5:^K} 11 | - FF {5:^L} 12 CR {5:^M} 13 SO {5:^N} 14 SI {5:^O} 15 | - DL {5:^P} 16 D1 {5:^Q} 17 D2 {5:^R} 18 D3 {5:^S} 19 | - {4:-- More --}^ | + NU {18:^@} 10 SH {18:^A} 1 SX {18:^B} 2 EX {18:^C} 3 | + ET {18:^D} 4 EQ {18:^E} 5 AK {18:^F} 6 BL {18:^G} 7 | + BS {18:^H} 8 HT {18:^I} 9 LF {18:^@} 10 VT {18:^K} 11 | + FF {18:^L} 12 CR {18:^M} 13 SO {18:^N} 14 SI {18:^O} 15 | + DL {18:^P} 16 D1 {18:^Q} 17 D2 {18:^R} 18 D3 {18:^S} 19 | + {6:-- More --}^ | ]], } @@ -1341,8 +1318,8 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim grid = [[ | {1:~ }| - {8:[No Name] }| - ^ {9: } | + {2:[No Name] }| + ^ {100: } | {1:~ }| {3:[No Name] }| | @@ -1353,13 +1330,13 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>') screen:expect { grid = [[ - {2:E5108: Error executing lua [string ":lua"]:1: x} | + {9:E5108: Error executing lua [string ":lua"]:1: x} | | - {2:x} | - {2:stack traceback:} | - {2: [C]: in function 'error'} | - {2: [string ":lua"]:1: in main chunk} | - {4:Press ENTER or type command to continue}^ | + {9:x} | + {9:stack traceback:} | + {9: [C]: in function 'error'} | + {9: [string ":lua"]:1: in main chunk} | + {6:Press ENTER or type command to continue}^ | ]], } @@ -1368,8 +1345,8 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim grid = [[ | {1:~ }| - {8:[No Name] }| - ^ {9: } | + {2:[No Name] }| + ^ {100: } | {1:~ }| {3:[No Name] }| | @@ -1380,12 +1357,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>') screen:expect { grid = [[ - {2:E5108: Error executing lua [string ":lua"]:1: x} | + {9:E5108: Error executing lua [string ":lua"]:1: x} | |*2 - {2:x} | - {2:stack traceback:} | - {2: [C]: in function 'error'} | - {4:-- More --}^ | + {9:x} | + {9:stack traceback:} | + {9: [C]: in function 'error'} | + {6:-- More --}^ | ]], } @@ -1393,11 +1370,11 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim screen:expect { grid = [[ |*2 - {2:x} | - {2:stack traceback:} | - {2: [C]: in function 'error'} | - {2: [string ":lua"]:1: in main chunk} | - {4:Press ENTER or type command to continue}^ | + {9:x} | + {9:stack traceback:} | + {9: [C]: in function 'error'} | + {9: [string ":lua"]:1: in main chunk} | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -1413,10 +1390,10 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim | {1:~ }| {3: }| - {10:wow, }{2:such} | + {10:wow, }{9:such} | | - {2:very }{11:color} | - {4:Press ENTER or type command to continue}^ | + {9:very }{8:color} | + {6:Press ENTER or type command to continue}^ | ]], } @@ -1435,10 +1412,10 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim | {1:~ }| {3: }| - {10:wow, }{2:such} | + {10:wow, }{9:such} | | - {2:very }{11:color} | - {4:Press ENTER or type command to continue}^ | + {9:very }{8:color} | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -1449,19 +1426,19 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim feed('gggQ<CR><CR>1<CR><CR>vi') screen:expect([[ Entering Ex mode. Type "visual" to go to Normal mode. | - {11: 2 }bbb | - {11: 3 }ccc | + {8: 2 }bbb | + {8: 3 }ccc | :1 | - {11: 1 }aaa | - {11: 2 }bbb | + {8: 1 }aaa | + {8: 2 }bbb | :vi^ | ]]) feed('<CR>') screen:expect([[ - {11: 1 }aaa | - {11: 2 }^bbb | - {11: 3 }ccc | - {11: 4 } | + {8: 1 }aaa | + {8: 2 }^bbb | + {8: 3 }ccc | + {8: 4 } | {1:~ }|*2 | ]]) @@ -1502,7 +1479,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim aaa | bbb | ccc | - {4:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } end @@ -1534,7 +1511,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim {1:~ }|*3 {3: }| | - {4:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed('<CR>') screen:expect([[ @@ -1572,6 +1549,35 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim |*4 ]]) end) + + it('supports :intro with cmdheight=0 #26505', function() + screen:try_resize(80, 24) + command('set cmdheight=0') + feed(':intro<CR>') + screen:expect([[ + |*5 + {MATCH:.*}| + | + Nvim is open source and freely distributable | + https://neovim.io/#chat | + | + type :help nvim{18:<Enter>} if you are new! | + type :checkhealth{18:<Enter>} to optimize Nvim | + type :q{18:<Enter>} to exit | + type :help{18:<Enter>} for help | + | + {MATCH: +}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}| + | + Help poor children in Uganda! | + type :help iccf{18:<Enter>} for information | + |*2 + {3: }| + | + {6:Press ENTER or type command to continue}^ | + ]]) + feed('<CR>') + assert_alive() + end) end) it('calling screenstring() after redrawing between messages without UI #20999', function() @@ -1592,21 +1598,12 @@ describe('ui/ext_messages', function() clear { args_rm = { '--headless' }, args = { '--cmd', 'set shortmess-=I' } } screen = Screen.new(80, 24) screen:attach({ rgb = true, ext_messages = true, ext_popupmenu = true }) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [5] = { foreground = Screen.colors.Blue1 }, - [6] = { reverse = true }, - [7] = { bold = true, reverse = true }, - }) end) it('supports intro screen', function() -- intro message is not externalized. But check that it still works. -- Note parts of it depends on version or is indeterministic. We ignore those parts. - screen:expect([[ + local introscreen = [[ ^ | {1:~ }|*4 {MATCH:.*}| @@ -1614,24 +1611,70 @@ describe('ui/ext_messages', function() {1:~ }Nvim is open source and freely distributable{1: }| {1:~ }https://neovim.io/#chat{1: }| {1:~ }| - {1:~ }type :help nvim{5:<Enter>} if you are new! {1: }| - {1:~ }type :checkhealth{5:<Enter>} to optimize Nvim{1: }| - {1:~ }type :q{5:<Enter>} to exit {1: }| - {1:~ }type :help{5:<Enter>} for help {1: }| + {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }| + {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }| + {1:~ }type :q{18:<Enter>} to exit {1: }| + {1:~ }type :help{18:<Enter>} for help {1: }| {1:~ }| - {1:~{MATCH: +}}type :help news{5:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}| + {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}| {1:~ }| - {MATCH:.*}|*2 + {1:~ }Help poor children in Uganda!{1: }| + {1:~ }type :help iccf{18:<Enter>} for information {1: }| {1:~ }|*5 - ]]) - - feed('<c-l>') - screen:expect([[ + ]] + local showmode = { { '-- INSERT --', 5 } } + screen:expect(introscreen) + + -- <c-l> (same as :mode) does _not_ clear intro message + feed('<c-l>i') + screen:expect { grid = introscreen, showmode = showmode } + + -- opening a float without focus also does not + local win = api.nvim_open_win(api.nvim_create_buf(false, false), false, { + relative = 'editor', + height = 1, + width = 5, + row = 1, + col = 5, + }) + screen:expect { + grid = [[ ^ | + {1:~ }{4: }{1: }| + {1:~ }|*3 + {MATCH:.*}| + {1:~ }| + {1:~ }Nvim is open source and freely distributable{1: }| + {1:~ }https://neovim.io/#chat{1: }| + {1:~ }| + {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }| + {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }| + {1:~ }type :q{18:<Enter>} to exit {1: }| + {1:~ }type :help{18:<Enter>} for help {1: }| + {1:~ }| + {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}| + {1:~ }| + {1:~ }Help poor children in Uganda!{1: }| + {1:~ }type :help iccf{18:<Enter>} for information {1: }| + {1:~ }|*5 + ]], + showmode = showmode, + } + + api.nvim_win_close(win, true) + screen:expect { grid = introscreen, showmode = showmode } + + -- but editing text does.. + feed('x') + screen:expect { + grid = [[ + x^ | {1:~ }|*23 - ]]) + ]], + showmode = showmode, + } - feed(':intro<cr>') + feed('<esc>:intro<cr>') screen:expect { grid = [[ ^ | @@ -1641,20 +1684,81 @@ describe('ui/ext_messages', function() Nvim is open source and freely distributable | https://neovim.io/#chat | | - type :help nvim{5:<Enter>} if you are new! | - type :checkhealth{5:<Enter>} to optimize Nvim | - type :q{5:<Enter>} to exit | - type :help{5:<Enter>} for help | + type :help nvim{18:<Enter>} if you are new! | + type :checkhealth{18:<Enter>} to optimize Nvim | + type :q{18:<Enter>} to exit | + type :help{18:<Enter>} for help | | - {MATCH: +}type :help news{5:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}| + {MATCH: +}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}| | - {MATCH:.*}|*2 + Help poor children in Uganda! | + type :help iccf{18:<Enter>} for information | |*5 ]], messages = { - { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' }, + { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, }, } + + feed('<cr>') + screen:expect { + grid = [[ + ^x | + {1:~ }|*23 + ]], + } + end) + + it('clears intro screen when new buffer is active', function() + api.nvim_set_current_buf(api.nvim_create_buf(true, false)) + screen:expect { + grid = [[ + ^ | + {1:~ }|*23 + ]], + } + end) + + it('clears intro screen when new buffer is active in floating window', function() + local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 } + api.nvim_open_win(api.nvim_create_buf(false, false), true, win_opts) + screen:expect { + grid = [[ + | + {1:~ }{4:^ }{1: }| + {1:~ }|*22 + ]], + } + end) + + it('clears intro screen when initial buffer is active in floating window', function() + local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 } + api.nvim_open_win(api.nvim_get_current_buf(), true, win_opts) + screen:expect { + grid = [[ + | + {1:~ }{4:^ }{1: }| + {1:~ }|*22 + ]], + } + end) + + it('clears intro screen when initial window is converted to be floating', function() + exec_lua([[ + local init_win_id = vim.api.nvim_get_current_win() + vim.cmd('split') + local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 } + vim.api.nvim_win_set_config(init_win_id, win_opts) + vim.api.nvim_set_current_win(init_win_id) + ]]) + screen:expect { + grid = [[ + | + {1:~ }{4:^ }{1: }| + {1:~ }|*21 + {2:[No Name] }| + ]], + } end) it('supports global statusline', function() @@ -1668,7 +1772,7 @@ describe('ui/ext_messages', function() ────────────────────────────────────────────────────────────────────────────────| | {1:~ }|*10 - {7:[No Name] }| + {3:[No Name] }| ]], messages = { { content = { { ' cmdheight=0' } }, kind = '' }, @@ -1684,7 +1788,7 @@ describe('ui/ext_messages', function() ────────────────────────────────────────────────────────────────────────────────| | {1:~ }|*9 - {7:[No Name] }| + {3:[No Name] }| ]], messages = { { content = { { ' laststatus=3' } }, kind = '' }, @@ -1704,7 +1808,7 @@ describe('ui/ext_messages', function() ────────────────────────────────────────────────────────────────────────────────| | {1:~ }|*10 - {7:[No Name] }| + {3:[No Name] }| ]], messages = { { content = { { ' cmdheight=0' } }, kind = '' }, @@ -1713,6 +1817,76 @@ describe('ui/ext_messages', function() end) end) +it('ui/ext_multigrid supports intro screen', function() + clear { args_rm = { '--headless' }, args = { '--cmd', 'set shortmess-=I' } } + local screen = Screen.new(80, 24) + screen:attach({ rgb = true, ext_multigrid = true }) + + screen:expect { + grid = [[ + ## grid 1 + [2:--------------------------------------------------------------------------------]|*23 + [3:--------------------------------------------------------------------------------]| + ## grid 2 + ^ | + {1:~ }|*4 + {MATCH:.*}| + {1:~ }| + {1:~ }Nvim is open source and freely distributable{1: }| + {1:~ }https://neovim.io/#chat{1: }| + {1:~ }| + {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }| + {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }| + {1:~ }type :q{18:<Enter>} to exit {1: }| + {1:~ }type :help{18:<Enter>} for help {1: }| + {1:~ }| + {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}| + {1:~ }| + {1:~ }Help poor children in Uganda!{1: }| + {1:~ }type :help iccf{18:<Enter>} for information {1: }| + {1:~ }|*4 + ## grid 3 + | + ]], + win_viewport = { + [2] = { + win = 1000, + topline = 0, + botline = 2, + curline = 0, + curcol = 0, + linecount = 1, + sum_scroll_delta = 0, + }, + }, + } + + feed 'ix' + screen:expect { + grid = [[ + ## grid 1 + [2:--------------------------------------------------------------------------------]|*23 + [3:--------------------------------------------------------------------------------]| + ## grid 2 + x^ | + {1:~ }|*22 + ## grid 3 + {5:-- INSERT --} | + ]], + win_viewport = { + [2] = { + win = 1000, + topline = 0, + botline = 2, + curline = 0, + curcol = 1, + linecount = 1, + sum_scroll_delta = 0, + }, + }, + } +end) + describe('ui/msg_puts_printf', function() it('output multibyte characters correctly', function() local screen @@ -1728,16 +1902,12 @@ describe('ui/msg_puts_printf', function() pending('missing japanese language features', function() end) return else - cmd = 'chcp 932 > NULL & ' + cmd = 'chcp 932 > NUL & ' end else if exc_exec('lang ja_JP.UTF-8') ~= 0 then pending('Locale ja_JP.UTF-8 not supported', function() end) return - elseif is_ci() then - -- Fails non--Windows CI. Message catalog directory issue? - pending('fails on unix CI', function() end) - return end end @@ -1749,9 +1919,9 @@ describe('ui/msg_puts_printf', function() cmd = cmd .. '"' .. nvim_prog .. '" -u NONE -i NONE -Es -V1' command([[call termopen(']] .. cmd .. [[')]]) screen:expect([[ - ^Exモードに入ります. ノー | - マルモードに戻るには"visu| - al"と入力してください. | + ^Exモードに入ります。ノー | + マルモードに戻るには "vis| + ual" と入力してください。| : | | ]]) @@ -2378,4 +2548,221 @@ aliquip ex ea commodo consequat.]] ]], } end) + + it('g< shows blank line from :echo properly', function() + screen:try_resize(60, 8) + feed([[:echo 1 | echo "\n" | echo 2<CR>]]) + screen:expect([[ + | + {1:~ }|*2 + {12: }| + 1 | + | + 2 | + {4:Press ENTER or type command to continue}^ | + ]]) + + feed('<CR>') + screen:expect([[ + ^ | + {1:~ }|*6 + | + ]]) + + feed('g<lt>') + screen:expect([[ + | + {1:~ }| + {12: }| + :echo 1 | echo "\n" | echo 2 | + 1 | + | + 2 | + {4:Press ENTER or type command to continue}^ | + ]]) + + feed('<CR>') + screen:expect([[ + ^ | + {1:~ }|*6 + | + ]]) + end) + + it('scrolling works properly when :echo output ends with newline', function() + screen:try_resize(60, 6) + feed([[:echo range(100)->join("\n") .. "\n"<CR>]]) + screen:expect([[ + 0 | + 1 | + 2 | + 3 | + 4 | + {4:-- More --}^ | + ]]) + feed('G') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:Press ENTER or type command to continue}^ | + ]]) + for _ = 1, 3 do + feed('k') + screen:expect([[ + 95 | + 96 | + 97 | + 98 | + 99 | + {4:-- More --}^ | + ]]) + feed('k') + screen:expect([[ + 94 | + 95 | + 96 | + 97 | + 98 | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 95 | + 96 | + 97 | + 98 | + 99 | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:Press ENTER or type command to continue}^ | + ]]) + end + end) + + it('scrolling works properly when :!cmd output ends with newline #27902', function() + screen:try_resize(60, 6) + api.nvim_set_option_value('shell', testprg('shell-test'), {}) + api.nvim_set_option_value('shellcmdflag', 'REP 100', {}) + api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes + feed([[:!foo<CR>]]) + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:Press ENTER or type command to continue}^ | + ]]) + for _ = 1, 3 do + feed('k') + screen:expect([[ + 95: foo | + 96: foo | + 97: foo | + 98: foo | + 99: foo | + {4:-- More --}^ | + ]]) + feed('k') + screen:expect([[ + 94: foo | + 95: foo | + 96: foo | + 97: foo | + 98: foo | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 95: foo | + 96: foo | + 97: foo | + 98: foo | + 99: foo | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:Press ENTER or type command to continue}^ | + ]]) + end + end) +end) + +it('pager works in headless mode with UI attached', function() + skip(is_os('win')) + clear() + local child_server = assert(n.new_pipename()) + fn.jobstart({ nvim_prog, '--clean', '--headless', '--listen', child_server }) + retry(nil, nil, function() + neq(nil, vim.uv.fs_stat(child_server)) + end) + + local child_session = n.connect(child_server) + local child_screen = Screen.new(40, 6) + child_screen:attach(nil, child_session) + child_screen._default_attr_ids = nil -- TODO: unskip with new color scheme + + child_session:notify('nvim_command', [[echo range(100)->join("\n")]]) + child_screen:expect([[ + 0 | + 1 | + 2 | + 3 | + 4 | + -- More --^ | + ]]) + + child_session:request('nvim_input', 'G') + child_screen:expect([[ + 95 | + 96 | + 97 | + 98 | + 99 | + Press ENTER or type command to continue^ | + ]]) + + child_session:request('nvim_input', 'g') + child_screen:expect([[ + 0 | + 1 | + 2 | + 3 | + 4 | + -- More --^ | + ]]) end) diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua index 8d7fae3e91..f623cfda06 100644 --- a/test/functional/ui/mode_spec.lua +++ b/test/functional/ui/mode_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command = helpers.command -local retry = helpers.retry +local clear, feed, insert = n.clear, n.feed, n.insert +local command = n.command +local retry = t.retry describe('ui mode_change event', function() local screen @@ -12,20 +13,13 @@ describe('ui mode_change event', function() clear() screen = Screen.new(25, 4) screen:attach({ rgb = true }) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = 255 }, - [1] = { bold = true, reverse = true }, - [2] = { bold = true }, - [3] = { reverse = true }, - [4] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg - }) end) it('works in normal mode', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -35,7 +29,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'operator', @@ -45,7 +39,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -61,7 +55,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'operator', @@ -71,8 +65,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 - {4:E21: Cannot make changes, 'modifiable' is off} | + {1:~ }|*2 + {9:E21: Cannot make changes, 'modifiable' is off} | ]], mode = 'normal', } @@ -84,7 +78,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'replace', @@ -94,7 +88,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -106,8 +100,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 - {2:-- INSERT --} | + {1:~ }|*2 + {5:-- INSERT --} | ]], mode = 'insert', } @@ -116,7 +110,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ wor^d | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -133,8 +127,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ word(stuff^ | - {0:~ }|*2 - {2:-- INSERT --} | + {1:~ }|*2 + {5:-- INSERT --} | ]], mode = 'insert', timeout = screen_timeout, @@ -144,8 +138,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ word^(stuff) | - {0:~ }|*2 - {2:-- INSERT --} | + {1:~ }|*2 + {5:-- INSERT --} | ]], mode = 'showmatch', timeout = screen_timeout, @@ -154,8 +148,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ word(stuff)^ | - {0:~ }|*2 - {2:-- INSERT --} | + {1:~ }|*2 + {5:-- INSERT --} | ]], mode = 'insert', timeout = screen_timeout, @@ -168,8 +162,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 - {2:-- REPLACE --} | + {1:~ }|*2 + {5:-- REPLACE --} | ]], mode = 'replace', } @@ -178,7 +172,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ wor^d | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -190,7 +184,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ | - {0:~ }|*2 + {1:~ }|*2 :^ | ]], mode = 'cmdline_normal', @@ -200,7 +194,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ | - {0:~ }|*2 + {1:~ }|*2 :^x | ]], mode = 'cmdline_insert', @@ -210,7 +204,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ | - {0:~ }|*2 + {1:~ }|*2 :^x | ]], mode = 'cmdline_replace', @@ -220,7 +214,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ | - {0:~ }|*2 + {1:~ }|*2 :x^ | ]], mode = 'cmdline_normal', @@ -230,7 +224,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -243,8 +237,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ tex^t | - {0:~ }|*2 - {2:-- VISUAL --} | + {1:~ }|*2 + {5:-- VISUAL --} | ]], mode = 'visual', } @@ -253,7 +247,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ tex^t | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', @@ -264,8 +258,8 @@ describe('ui mode_change event', function() screen:expect { grid = [[ tex^t | - {0:~ }|*2 - {2:-- VISUAL --} | + {1:~ }|*2 + {5:-- VISUAL --} | ]], mode = 'visual_select', } @@ -274,7 +268,7 @@ describe('ui mode_change event', function() screen:expect { grid = [[ tex^t | - {0:~ }|*2 + {1:~ }|*2 | ]], mode = 'normal', diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 0f30bf4471..42c877fd92 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, api = helpers.clear, helpers.feed, helpers.api -local insert, feed_command = helpers.insert, helpers.feed_command -local eq, fn = helpers.eq, helpers.fn -local poke_eventloop = helpers.poke_eventloop -local command = helpers.command -local exec = helpers.exec + +local clear, feed, api = n.clear, n.feed, n.api +local insert, feed_command = n.insert, n.feed_command +local eq, fn = t.eq, n.fn +local poke_eventloop = n.poke_eventloop +local command = n.command +local exec = n.exec describe('ui/mouse/input', function() local screen @@ -34,6 +36,7 @@ describe('ui/mouse/input', function() [6] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, [7] = { bold = true, foreground = Screen.colors.SeaGreen4 }, [8] = { foreground = Screen.colors.Brown }, + [9] = { background = Screen.colors.DarkGrey, foreground = Screen.colors.LightGrey }, }) command('set mousemodel=extend') feed('itesting<cr>mouse<cr>support and selection<esc>') @@ -574,7 +577,7 @@ describe('ui/mouse/input', function() :tabprevious | ]]) feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab - helpers.poke_eventloop() + n.poke_eventloop() feed('<LeftMouse><0,1>') screen:expect([[ {tab: + foo }{sel: + bar }{fill: }{tab:X}| @@ -1638,6 +1641,59 @@ describe('ui/mouse/input', function() end) end) + it('virtual text does not change cursor placement on concealed line', function() + command('%delete') + insert('aaaaaaaaaa|hidden|bbbbbbbbbb|hidden|cccccccccc') + command('syntax match test /|hidden|/ conceal cchar=X') + command('set conceallevel=2 concealcursor=n virtualedit=all') + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbbb | + bbb{9:X}ccccccccc^c | + {0:~ }|*2 + | + ]]) + api.nvim_input_mouse('left', 'press', '', 0, 0, 22) + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbb^b | + bbb{9:X}cccccccccc | + {0:~ }|*2 + | + ]]) + api.nvim_input_mouse('left', 'press', '', 0, 1, 16) + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbbb | + bbb{9:X}cccccccccc ^ | + {0:~ }|*2 + | + ]]) + + api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 0, 0, { + virt_text = { { '?', 'ErrorMsg' } }, + virt_text_pos = 'right_align', + virt_text_repeat_linebreak = true, + }) + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbbb {6:?}| + bbb{9:X}cccccccccc ^ {6:?}| + {0:~ }|*2 + | + ]]) + api.nvim_input_mouse('left', 'press', '', 0, 0, 22) + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbb^b {6:?}| + bbb{9:X}cccccccccc {6:?}| + {0:~ }|*2 + | + ]]) + api.nvim_input_mouse('left', 'press', '', 0, 1, 16) + screen:expect([[ + aaaaaaaaaa{9:X}bbbbbbb {6:?}| + bbb{9:X}cccccccccc ^ {6:?}| + {0:~ }|*2 + | + ]]) + end) + it('getmousepos() works correctly', function() local winwidth = api.nvim_get_option_value('winwidth', {}) -- Set winwidth=1 so that window sizes don't change. @@ -1802,8 +1858,8 @@ describe('ui/mouse/input', function() it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function() feed('<MouseMove>') - helpers.poke_eventloop() - helpers.assert_alive() + n.poke_eventloop() + n.assert_alive() end) it('mousemodel=popup_setpos', function() diff --git a/test/functional/ui/multibyte_spec.lua b/test/functional/ui/multibyte_spec.lua index c2fc763401..dc25a09d0d 100644 --- a/test/functional/ui/multibyte_spec.lua +++ b/test/functional/ui/multibyte_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local feed_command = helpers.feed_command -local insert = helpers.insert -local fn = helpers.fn -local api = helpers.api + +local clear = n.clear +local command = n.command +local feed = n.feed +local feed_command = n.feed_command +local insert = n.insert +local fn = n.fn +local api = n.api local split = vim.split -local dedent = helpers.dedent +local dedent = t.dedent describe('multibyte rendering', function() local screen @@ -16,15 +18,6 @@ describe('multibyte rendering', function() clear() screen = Screen.new(60, 6) screen:attach({ rgb = true }) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, - [2] = { background = Screen.colors.WebGray }, - [3] = { background = Screen.colors.LightMagenta }, - [4] = { bold = true }, - [5] = { foreground = Screen.colors.Blue }, - [6] = { reverse = true, bold = true }, - [7] = { reverse = true }, - }) end) it('works with composed char at start of line', function() @@ -83,17 +76,17 @@ describe('multibyte rendering', function() ab ^ | -馬 | {1:~ }|*3 - {4:-- INSERT --} | + {5:-- INSERT --} | ]]) -- check double-width char is temporarily hidden when overlapped fn.complete(4, { 'xx', 'yy' }) screen:expect([[ ab xx^ | - - {2: xx } | - {1:~ }{3: yy }{1: }| + - {12: xx } | + {1:~ }{4: yy }{1: }| {1:~ }|*2 - {4:-- INSERT --} | + {5:-- INSERT --} | ]]) -- check it is properly restored @@ -102,7 +95,7 @@ describe('multibyte rendering', function() ab xxz^ | -馬 | {1:~ }|*3 - {4:-- INSERT --} | + {5:-- INSERT --} | ]]) end) @@ -129,7 +122,7 @@ describe('multibyte rendering', function() {1:~ }│a口口口口口口口口口口口口口口口口 | {1:~ }│aa口口口口口口口口口口口口口口口口 | {1:~ }│aaa口口口口口口口口口口口口口口口口 | - {6:[No Name] }{7:[No Name] [+] }| + {3:[No Name] }{2:[No Name] [+] }| | ]]) end) @@ -139,7 +132,7 @@ describe('multibyte rendering', function() feed('$') screen:expect { grid = [[ - {5:<ffff>}!!^! | + {18:<ffff>}!!^! | {1:~ }|*4 | ]], @@ -204,6 +197,32 @@ describe('multibyte rendering', function() } end) + it('works with even huger zalgo chars', function() + screen:try_resize(100, 20) + api.nvim_command 'color default' + api.nvim_set_hl(0, 'MyHighlight', { bg = '#53246b', fg = '#a4d844' }) + screen:add_extra_attr_ids { + [100] = { background = tonumber('0x53246b'), foreground = Screen.colors.NvimLightGrey4 }, + [101] = { background = tonumber('0x53246b'), foreground = tonumber('0xa4d844') }, + } + api.nvim_set_option_value('winhl', 'Normal:MyHighlight', {}) + api.nvim_set_option_value('number', true, {}) + local text = + 'c̯̥̳̮̫̳͔̱̀ͦͩ̄͋̓͘c̯̥̳̮̫̳͔̱̀ͦͩ̄͋̓͘l̶̴̴̨̛͓͚͎̥ͦͤ̑͆͛͢l̶̴̴̨̛͓͚͎̥ͦͤ̑͆͛͢ô̷̤̩ͯͧ͆ͪ̈́́͒̒̐͐̕ô̷̤̩ͯͧ͆ͪ̈́́͒̒̐͐̕s̶̷̢̩̱̠̀ͦ̽ͮ͒ͨ̚͟͠s̶̷̢̩̱̠̀ͦ̽ͮ͒ͨ̚͟͠e͉̯̱̖͕̳̼̽̊̒ͣ̊ͥ̚̚e͉̯̱̖͕̳̼̽̊̒ͣ̊ͥ̚̚ ͇͌̈̄ͬͧͧ͝͠͏̷ͪ̎͟͠ ͇͌̈̄ͬͧͧ͝͠͏̷ͪ̎͟͠t̵̳̅̽͏̵̡̥̲͍͙̹̯ͩ̐t̵̳̅̽͏̵̡̥̲͍͙̹̯ͩ̐o͋͏̬̞̣ͬ́ͬ̎̋̓̽͘͠͡o͋͏̬̞̣ͬ́ͬ̎̋̓̽͘͠͡ ͏̛͙̮̈ͬ̌͐ͤ͒ͧ̎ͤ͜͠ ͏̛͙̮̈ͬ̌͐ͤ͒ͧ̎ͤ͜͠ǫ̛̳͕̦͖̪̀͂͛̅̔ͪ͒͜ǫ̛̳͕̦͖̪̀͂͛̅̔ͪ͒͜v̸̡͖̗̣ͯ̿̔͊̅ͯ̈̓̇ͅv̸̡͖̗̣ͯ̿̔͊̅ͯ̈̓̇ͅe̴̶̢̜̭̠̰̞ͪͨ͂ͤ͆́͗e̴̶̢̜̭̠̰̞ͪͨ͂ͤ͆́͗r̨̖̼̳̳͚̖̒ͯ̊̋̂̑̚͞r̨̖̼̳̳͚̖̒ͯ̊̋̂̑̚͞f̵̮̣̬̾͛̌ͧͦ͘͢͜͜͠ͅf̵̮̣̬̾͛̌ͧͦ͘͢͜͜͠ͅl̡͉̬̳͈̠̏͂ͤ̈ͨ̀ͩ̔͏l̡͉̬̳͈̠̏͂ͤ̈ͨ̀ͩ̔͏ỏ̶̢̻̠͎͇͈̜̈̆ͯ̔ͩ̾ỏ̶̢̻̠͎͇͈̜̈̆ͯ̔ͩ̾ẉ̦̞̼̩̣͙̅̿́̓̉̎̈ͪẉ̦̞̼̩̣͙̅̿́̓̉̎̈ͪi̷̡͍͓͔̝͙͖͖̍ͯͤͬͦ͝i̷̡͍͓͔̝͙͖͖̍ͯͤͬͦ͝n̠̪̰͋ͩ̆͏̶̖̯ͭ̀̿͛͘n̠̪̰͋ͩ̆͏̶̖̯ͭ̀̿͛͘g̴̭͎̞͙̗̯͙͖ͬ́ͧͧ͝ͅg̴̭͎̞͙̗̯͙͖ͬ́ͧͧ͝ͅ ̢͎̬͓̮̹̰̙͍̓̐͋͂͐̚ ̢͎̬͓̮̹̰̙͍̓̐͋͂͐̚ť̴̼̝̗ͩ̍͋̿͏͇ͧ̑̏̚ť̴̼̝̗ͩ̍͋̿͏͇ͧ̑̏̚h̨̨̢͓̲͚͕̦ͨ͛̓ͩ̚͟͠h̨̨̢͓̲͚͕̦ͨ͛̓ͩ̚͟͠ȩ͕̜̥̃̑͋̏͐̎̒͛͊͏͙ȩ͕̜̥̃̑͋̏͐̎̒͛͊͏͙ ̵̨̜̜̠͉̱͎͑ͥ̌͐̽͢͡ ̵̨̜̜̠͉̱͎͑ͥ̌͐̽͢͡r̢̫͓͎̙̭̽ͥͭ͐̂̀̕͟͝r̢̫͓͎̙̭̽ͥͭ͐̂̀̕͟͝e̴̷͓̹̩ͧ́̉̑̈̿ͥ̕͡͝e̴̷͓̹̩ͧ́̉̑̈̿ͥ̕͡͝d̵̡̼̩̠̜͈̯̬͚͛̋̀̆͟d̵̡̼̩̠̜͈̯̬͚͛̋̀̆͟ŕ̻̳̬͏̨̮͚̲ͥ̌͆͗͠ͅŕ̻̳̬͏̨̮͚̲ͥ̌͆͗͠ͅā̸͙̥̤͍͈̣ͪͨ̈͋̈́̈́͜ā̸͙̥̤͍͈̣ͪͨ̈͋̈́̈́͜w̶̦̪͚̤̃ͬ̓͒ͤ̇̇ͮ͢͡w̶̦̪͚̤̃ͬ̓͒ͤ̇̇ͮ͢͡ ̷̡̦̻̻̪͚̳͎ͥ̓ͩͪ͠͝ ̷̡̦̻̻̪͚̳͎ͥ̓ͩͪ͠͝b̳ͮ̒̊̆̒́̈́̏̓͋ͭ̔ͤ̚b̳ͮ̒̊̆̒́̈́̏̓͋ͭ̔ͤ̚u̧̟̫͎͚̭̠͕͂̄̀̒̈̇͜u̧̟̫͎͚̭̠͕͂̄̀̒̈̇͜f̶̸̢͍̑̂̊ͥͫ̈́ͥ͛̈́̃͝f̶̸̢͍̑̂̊ͥͫ̈́ͥ͛̈́̃͝f̵̼̭̮͎ͧ̒̆͊̀ͤ͊̇̕͡f̵̼̭̮͎ͧ̒̆͊̀ͤ͊̇̕͡e̮̪̲̣̞̖͎ͥͤ̐̌̓̐͟͢e̮̪̲̣̞̖͎ͥͤ̐̌̓̐͟͢ŗ̭̘̮̹̖̎̄̆́ͫͭ͢ͅͅŗ̭̘̮̹̖̎̄̆́ͫͭ͢ͅͅ.̪̖͉͚̹̾̉ͮ̔̊ͪ̾̎͟͞.̪̖͉͚̹̾̉ͮ̔̊ͪ̾̎͟͞ ̷̧̺̰͎̣̃͒͗ͮ͑ͪͮ͞ͅ ̷̧̺̰͎̣̃͒͗ͮ͑ͪͮ͞ͅf̛̫͚͚͍̜͎̗̳̂ͬͭ͜͢͝f̛̫͚͚͍̜͎̗̳̂ͬͭ͜͢͝i̴̵̡̛̛͎̤̳̮ͩ̐ͩ͑̇̚i̴̵̡̛̛͎̤̳̮ͩ̐ͩ͑̇̚n̵͇͍͚̖̥̣ͨ̄ͧ̌̂͗͘͝n̵͇͍͚̖̥̣ͨ̄ͧ̌̂͗͘͝ȉ̼̱̫̜̋̓̐͌͆ͨ͘͝͡ͅȉ̼̱̫̜̋̓̐͌͆ͨ͘͝͡ͅs̴̸̝̺̬͚̲̹̘ͪ̆̊ͥ͞͝s̴̸̝̺̬͚̲̹̘ͪ̆̊ͥ͞͝h̴̜̠͇ͦͥ̔̅ͭͭ͋ͩ͟͡͞h̴̜̠͇ͦͥ̔̅ͭͭ͋ͩ͟͡͞ ̶̧̛̻͙̤̘̺̣̻̗͍̓͑͠ ̶̧̛̻͙̤̘̺̣̻̗͍̓͑͠t̠͉̼̬̩͛́ͨ͐̀͛̂ͨ̾͞t̠͉̼̬̩͛́ͨ͐̀͛̂ͨ̾͞h̻̹̝̹̾ͩ̍ͧ͆ͥ̔͘͏̉ͯh̻̹̝̹̾ͩ̍ͧ͆ͥ̔͘͏̉ͯì̷̢̛̺̭͇̟̦̄̓́̓ͪ͟ì̷̢̛̺̭͇̟̦̄̓́̓ͪ͟s̴̡̗͍͕͖̮̟̱̫̎ͣ̀̎̿s̴̡̗͍͕͖̮̟̱̫̎ͣ̀̎̿ ̶͇̟̜̗̗͇͇͐̑̈͋̋̽͟ ̶͇̟̜̗̗͇͇͐̑̈͋̋̽͟e̷̥͙͈̖̤̯̹̯͗̉̈́̽ͨ̕e̷̥͙͈̖̤̯̹̯͗̉̈́̽ͨ̕v̛̝͕̱͙̞̖̒̂̔͆̊̎́ͫv̛̝͕̱͙̞̖̒̂̔͆̊̎́ͫę̴̤̭͖̈̐̿͂ͣ͒̃ͭ̕͟ę̴̤̭͖̈̐̿͂ͣ͒̃ͭ̕͟ṇ̳̭͓̟̠͕̯͑̉ͦ̀ͯ͜͡ṇ̳̭͓̟̠͕̯͑̉ͦ̀ͯ͜͡t̢̞͔̣̄̀͆̂̃ͨͦ͜͜͝͠t̢̞͔̣̄̀͆̂̃ͨͦ͜͜͝͠,̬̳̮͓͉̟͉͓̦͔̑̄ͨ̎͜,̬̳̮͓͉̟͉͓̦͔̑̄ͨ̎͜ ͕͈̠̰̬̬̌͂̏ͥ̀̕̚͢͠ ͕͈̠̰̬̬̌͂̏ͥ̀̕̚͢͠f̺̮̞̈́̏̋͏̺̖̝̓̑̂̚͢f̺̮̞̈́̏̋͏̺̖̝̓̑̂̚͢l̜̪͍̩̩̟͉͓̊̓ͤ̆ͣͫ̌l̜̪͍̩̩̟͉͓̊̓ͤ̆ͣͫ̌u̷̧̞̳̱̜̟̲͑̐͂ͪ͛͘͟u̷̧̞̳̱̜̟̲͑̐͂ͪ͛͘͟s͔͍̽ͣͮ̏̓͛̄ͯ̽͂̐ͯ͜s͔͍̽ͣͮ̏̓͛̄ͯ̽͂̐ͯ͜ḩ̼͕̦͖̼͚̗̃̃ͥ̅̂̈͟ḩ̼͕̦͖̼͚̗̃̃ͥ̅̂̈͟,̵͍̮̮̟͚̝̃ͨ̿ͭ̌ͤ̋̊,̵͍̮̮̟͚̝̃ͨ̿ͭ̌ͤ̋̊ ̷̨̨͈̝̦͂ͦ̒̋̇ͧ̒͟͝ ̷̨̨͈̝̦͂ͦ̒̋̇ͧ̒͟͝a̡̨̲̖̾̂͗̚͢͡͏͈ͤ̉͡a̡̨̲̖̾̂͗̚͢͡͏͈ͤ̉͡nͫͤ̚͜͏̧̛̣̻ͩ̔̍ͦ̕͝nͫͤ̚͜͏̧̛̣̻ͩ̔̍ͦ̕͝d͈̻̗̼̀͡͏̶̵̟̹̻̎̾ͯd͈̻̗̼̀͡͏̶̵̟̹̻̎̾ͯ ̶͙͈̠̜̬̺͛̀̊̂ͪ̔ͮ͑ ̶͙͈̠̜̬̺͛̀̊̂ͪ̔ͮ͑ş̧̡̢͓̠͋ͫ͑͒͊̅̔͜͞ş̧̡̢͓̠͋ͫ͑͒͊̅̔͜͞t̤̭͓̰̣̉̔̎ͫ͛ͦ̑̕͟͞t̤̭͓̰̣̉̔̎ͫ͛ͦ̑̕͟͞a̠͇͇̯̥͍͚̳̒́͐͐̏͋̓a̠͇͇̯̥͍͚̳̒́͐͐̏͋̓r͉͈̻̻͕̩̩̃̅͋͆ͮ͢͢͡r͉͈̻̻͕̩̩̃̅͋͆ͮ͢͢͡t̵̛̝̗̥̙̟̆ͮ̽̏ͧ͜͠ͅt̵̛̝̗̥̙̟̆ͮ̽̏ͧ͜͠ͅ ̷̼͎̦ͫ̈͑̃̽͏̲̪ͣͯ̽ ̷̼͎̦ͫ̈͑̃̽͏̲̪ͣͯ̽á̸̷̴̟̣́̔̌͏̶͕͋ͭͭá̸̷̴̟̣́̔̌͏̶͕͋ͭͭ ̧̧̲͍̘̘͚͔͇͙ͨͬ́̊ͅ ̧̧̲͍̘̘͚͔͇͙ͨͬ́̊ͅn̸̸̩͖͔͚͚̖͗ͦ̓̀̀̈́̈́n̸̸̩͖͔͚͚̖͗ͦ̓̀̀̈́̈́ę̵̧̬̣̦̖̝̹̱͌̃̑ͣ̚ę̵̧̬̣̦̖̝̹̱͌̃̑ͣ̚w͍̥͚̺ͮ̓̈̈́̾̊̆́̚͜͝w͍̥͚̺ͮ̓̈̈́̾̊̆́̚͜͝ ̛̹̲̥̝͙̾ͨ̆̎̃̋͂̓̕ ̛̹̲̥̝͙̾ͨ̆̎̃̋͂̓̕"̴̜̰̰̱̖̙̘̈́͌ͨͪ̐̕͠"̴̜̰̰̱̖̙̘̈́͌ͨͪ̐̕͠g̸̛͇̐͊͂̽͢͏͖̣ͫ͊ͯͅg̸̛͇̐͊͂̽͢͏͖̣ͫ͊ͯͅr̴̨̲͎̹͇̠̐ͤ̇̒ͬ̆ͧ͞r̴̨̲͎̹͇̠̐ͤ̇̒ͬ̆ͧ͞į̝̱̩͔̈ͨ̉͌̋̍̂͜͟͞į̝̱̩͔̈ͨ̉͌̋̍̂͜͟͞d̷̴̷̟̎͌͑͛̈́ͭͨͯ̋ͭ̕d̷̴̷̟̎͌͑͛̈́ͭͨͯ̋ͭ̕_̢̭̙̦̪͇̾̔̆ͬͦ́ͥ͢͡_̢̭̙̦̪͇̾̔̆ͬͦ́ͥ͢͡l̡̢̨̧͔̱̥̹̬̆ͮ̈́̏̅͜l̡̢̨̧͔̱̥̹̬̆ͮ̈́̏̅͜ĩ̢͖̠̩̞͚̰̰̉̋̌͛ͪ͠ĩ̢͖̠̩̞͚̰̰̉̋̌͛ͪ͠n̢̬̜̘̲͉ͮ͆͏̯͕ͭͦ̉̅n̢̬̜̘̲͉ͮ͆͏̯͕ͭͦ̉̅ē̡͈̮̭̰̜͍̗̮͔͌͐͆ͫē̡͈̮̭̰̜͍̗̮͔͌͐͆ͫ"̦̠̟ͣ̽͋͐ͧ̓̂̆̎͒͝ͅ"̦̠̟ͣ̽͋͐ͧ̓̂̆̎͒͝ͅ ̴̡̺̹̖̰̀ͤ͊̊͗̊́͜͠ ̴̡̺̹̖̰̀ͤ͊̊͗̊́͜͠ẻ͎̳̻̯̹͓͊̌̄͑͂̉͜͢ẻ͎̳̻̯̹͓͊̌̄͑͂̉͜͢v̞̬̪̥͖ͤ͐̍́ͤ̇̀̕̕ͅv̞̬̪̥͖ͤ͐̍́ͤ̇̀̕̕ͅȇ̶̱̗̩̠͚͎͊ͤͪͦͫ̂̚ȇ̶̱̗̩̠͚͎͊ͤͪͦͫ̂̚n̢̮̜͉̎ͨͩ̒̓ͬͨ̓ͦ͘͜n̢̮̜͉̎ͨͩ̒̓ͬͨ̓ͦ͘͜t̢͚͉̹͇̺̭ͪ̄̉ͨ̄͐̕ͅt̢͚͉̹͇̺̭ͪ̄̉ͨ̄͐̕ͅ ̵̛̳̱͍̩͓ͣ͋̈́͐ͭͧ̿ͅ ̵̛̳̱͍̩͓ͣ͋̈́͐ͭͧ̿ͅã̰̪̙͉̪͇ͣ͋ͤ̓͋͑̕͘ã̰̪̙͉̪͇ͣ͋ͤ̓͋͑̕͘t̴̴̡̡̛̳̼̻̳̂̽͒̇̚͠t̴̴̡̡̛̳̼̻̳̂̽͒̇̚͠ ̴̙̤̹͔̳̟̽̀̆ͥ̂̕͘͝ ̴̙̤̹͔̳̟̽̀̆ͥ̂̕͘͝t̴͖̼͔̬̦̏ͩ̄́̓̊̔̇͡t̴͖̼͔̬̦̏ͩ̄́̓̊̔̇͡ḫ̷͚͇̫̫̠͒ͮ̍ͣ̃͐͐̍ḫ̷͚͇̫̫̠͒ͮ̍ͣ̃͐͐̍e̳͉̮͖̳̣̎͌̂ͣ͋ͯ̆͜͞e̳͉̮͖̳̣̎͌̂ͣ͋ͯ̆͜͞ ̪̖̉̌̀̽̄̍̓̀̂̋͐̈̚ ̪̖̉̌̀̽̄̍̓̀̂̋͐̈̚c̶̫̜͚̊̿̂̿ͥͭ̓̂̈́͘͡c̶̫̜͚̊̿̂̿ͥͭ̓̂̈́͘͡ṷ̵̷͉̯̜̬̝̑͛ͤ̋ͧͯ̉ṷ̵̷͉̯̜̬̝̑͛ͤ̋ͧͯ̉ŗ̙̬̺̬ͥͤ̓͐̈́ͬ̽̌͡͡ŗ̙̬̺̬ͥͤ̓͐̈́ͬ̽̌͡͡r̛͖̼̣͙̋̇̀̅͒̽ͥ̑ͅͅr̛͖̼̣͙̋̇̀̅͒̽ͥ̑ͅͅě̢̪̦̼͘͏̴̠̞͍̓̐ͭ̇ě̢̪̦̼͘͏̴̠̞͍̓̐ͭ̇ǹ̨̨̛̛̯̍ͭͫ̎̍̃̄̐̍ǹ̨̨̛̛̯̍ͭͫ̎̍̃̄̐̍t̵̳͔̭̮̭̱̰ͤ͐̉̾͗̅͢t̵̳͔̭̮̭̱̰ͤ͐̉̾͗̅͢ ̩͕ͧ̌͂͂́ͫͥ̍͏̬̙͗ͅ ̩͕ͧ̌͂͂́ͫͥ̍͏̬̙͗ͅp̞̞͇͇̯̩̬̜ͥ̃͐̑͋́͗p̞̞͇͇̯̩̬̜ͥ̃͐̑͋́͗o̵͖͈̩̪̥̝̊̒̉̿͋ͩ̆͠o̵͖͈̩̪̥̝̊̒̉̿͋ͩ̆͠s̶͇̺̩̟̺͋̆̒ͫͥ̆͏͔͜s̶͇̺̩̟̺͋̆̒ͫͥ̆͏͔͜i̞̝̭̲͈̝̮̫͚͑̓ͤ̎ͮ̀i̞̝̭̲͈̝̮̫͚͑̓ͤ̎ͮ̀t̷̬͇̗̥̳͔̮͔̎̀ͣ̊̕͢t̷̬͇̗̥̳͔̮͔̎̀ͣ̊̕͢i̶̧̗̠̗̲͑̋ͣͪͦͣ͆̕͢i̶̧̗̠̗̲͑̋ͣͪͦͣ͆̕͢ǫ̰̟̙ͯ͏̬̦͚̝̀̈́ͣ͘͜ǫ̰̟̙ͯ͏̬̦͚̝̀̈́ͣ͘͜n̸̻̩͖͓̠̲̮̐̄̌̇́́͠n̸̻̩͖͓̠̲̮̐̄̌̇́́͠.̧̛͈̙̭̉ͥ̋͛̏͋̂̿͛͞.̧̛͈̙̭̉ͥ̋͛̏͋̂̿͛͞ ̡̲͇̳͔̦̤̹̥ͣ̍ͪͮ̎͡ ̡̲͇̳͔̦̤̹̥ͣ̍ͪͮ̎͡F̼̣͙̳̞͑͒ͧͣ̔̊̇̓̈́͠F̼̣͙̳̞͑͒ͧͣ̔̊̇̓̈́͠ŏ̸̶͎̘̟͙̤̑̒̿͗͛̐̚ŏ̸̶͎̘̟͙̤̑̒̿͗͛̐̚r̵̰͇͚̥̻͚̈́̌̽ͨͥ̕͘͞r̵̰͇͚̥̻͚̈́̌̽ͨͥ̕͘͞ ̵̶̧͖̙̝̻̭̤̒̿͌͗͑͡ ̵̶̧͖̙̝̻̭̤̒̿͌͗͑͡ś̸̬̘̭̼͓̹ͥ͛ͪ̐̈́͆͝ś̸̬̘̭̼͓̹ͥ͛ͪ̐̈́͆͝i͎̺̪̖̻ͫ̀ͤ̾ͦ̽ͭ͒̒͘i͎̺̪̖̻ͫ̀ͤ̾ͦ̽ͭ͒̒͘m̨̩͎̫̫̙̃̈͆ͬ̊͠͏̽͞m̨̩͎̫̫̙̃̈͆ͬ̊͠͏̽͞p̴̢̨͖̼͍̲͍̲ͩ̊̒̌̃ͤp̴̢̨͖̼͍̲͍̲ͩ̊̒̌̃ͤļ͔̱͙̝̟̜͚͎͕̮̹ͣ̀͘ļ͔̱͙̝̟̜͚͎͕̮̹ͣ̀͘ḭ̢̛͈͍̠̟̪̑̎̈́̑̽͜͡ḭ̢̛͈͍̠̟̪̑̎̈́̑̽͜͡c̖̠̥͔̪̼̑̃̆̓ͫ͗ͩͩ̋c̖̠̥͔̪̼̑̃̆̓ͫ͗ͩͩ̋i̴̸̡̘͇͔̹͂̍̐̀ͬͩ̈͘i̴̸̡̘͇͔̹͂̍̐̀ͬͩ̈͘t̵̵̖̫͙͎̒ͭ̔̃̔ͧͫ̽͝t̵̵̖̫͙͎̒ͭ̔̃̔ͧͫ̽͝y̴̘̱͈̳ͯ̈́̍ͮ̔͊͊̚̚͞y̴̘̱͈̳ͯ̈́̍ͮ̔͊͊̚̚͞ ̛̩̤̪͇̬͕̯̞̙̪̮̀̂̕ ̛̩̤̪͇̬͕̯̞̙̪̮̀̂̕ļ̲̰̞̈̌̿͐̉́̋ͬ͟͟͡ļ̲̰̞̈̌̿͐̉́̋ͬ͟͟͡e̡̧̛̬̣̗̣̰͂̐̂͗͛̋̇e̡̧̛̬̣̗̣̰͂̐̂͗͛̋̇a̡̯͉̠̞ͩͮ̉̓́ͮ̔̆̒͘a̡̯͉̠̞ͩͮ̉̓́ͮ̔̆̒͘v͔ͦ͏͎̪̮̝̟̤́̀͊̈̎͟v͔ͦ͏͎̪̮̝̟̤́̀͊̈̎͟ȩ̪͔̤̺͗ͦ̅̓ͭͤͫ̆ͣ͒ȩ̪͔̤̺͗ͦ̅̓ͭͤͫ̆ͣ͒ ̶̢̤͎̰̝̤͂̔͒ͦͦ͂̊̀ ̶̢̤͎̰̝̤͂̔͒ͦͦ͂̊̀p̛̝̪͚͖̫͕̅̍̊́̓͒̂̃p̛̝̪͚͖̫͕̅̍̊́̓͒̂̃l̴̸͉͎̖͕̦̥̾ͨ̌̑ͣ̕͝l̴̸͉͎̖͕̦̥̾ͨ̌̑ͣ̕͝a̰̩͔̼͔̦̩͒ͪͭ̐͡͏̗ͮa̰̩͔̼͔̦̩͒ͪͭ̐͡͏̗ͮč̵̱͇̲̞̉̆̌̄ͧͫ̑̈́͠č̵̱͇̲̞̉̆̌̄ͧͫ̑̈́͠e̶̛̜̬̯̤͔̓ͤͮͦ̂͐͜͜e̶̛̜̬̯̤͔̓ͤͮͦ̂͐͜͜ ̸̧̼̯͕̼̭ͣͣ̿̑̈̎̽͜ ̸̧̼̯͕̼̭ͣͣ̿̑̈̎̽͜f̴̼̞͇̺̊̎̓̑̔̈́͗̊͘͞f̴̼̞͇̺̊̎̓̑̔̈́͗̊͘͞ő̶̶̧̺̤̜̹̫͎̻̏̉̍ͩő̶̶̧̺̤̜̹̫͎̻̏̉̍ͩr̵̙̱̺̮͙̯̼͐̀͗̾͊͟͝r̵̙̱̺̮͙̯̼͐̀͗̾͊͟͝ ̵̪̥͍̩̱ͨ͗̓̎̓͒̚͜͞ ̵̪̥͍̩̱ͨ͗̓̎̓͒̚͜͞t̪̤͙̥̖̹̣̤͎̞̒́̒̽̃t̪̤͙̥̖̹̣̤͎̞̒́̒̽̃ḥ̵̷̷̭̘͙͓ͩ̓ͪͤ̓ͮ̍ḥ̵̷̷̭̘͙͓ͩ̓ͪͤ̓ͮ̍é̡̬̺͉̻̻̀̀͂̽ͬ̕̕͠é̡̬̺͉̻̻̀̀͂̽ͬ̕̕͠ ̵̱̻̣͙̌͊́ͯ́̐̀́͂̕ ̵̱̻̣͙̌͊́ͯ́̐̀́͂̕f̨̪͈̲̬̟̝͎̀̔̋ͨ̀͡ͅf̨̪͈̲̬̟̝͎̀̔̋ͨ̀͡ͅi̵̫̱̝͒̇̏̃ͭ̂̄̄̊̐͠i̵̫̱̝͒̇̏̃ͭ̂̄̄̊̐͠n̵̷͖̻̦͍̻̑̈́̎̓͑ͪͫ͟n̵̷͖̻̦͍̻̑̈́̎̓͑ͪͫ͟a̗̗̠̫̦̻̹͇ͯͦͫ͗̽ͥ̚a̗̗̠̫̦̻̹͇ͯͦͫ͗̽ͥ̚l̵̨̨͙̜͔̘̗̯͌̋͂̑̄͢l̵̨̨͙̜͔̘̗̯͌̋͂̑̄͢ ̵̷̛̺̳͙̲̥̬̊̌̽̓̇͝ ̵̷̛̺̳͙̲̥̬̊̌̽̓̇͝"̸̨̫̟̤̥͉̮̥̀ͤ̐͊̇̑"̸̨̫̟̤̥͉̮̥̀ͤ̐͊̇̑c̵̭̘͍͇̜ͨ̔̍̆͛͌͂͌͛c̵̭̘͍͇̜ͨ̔̍̆͛͌͂͌͛l̸̷̢̡̫̩̃́͐̆͒ͨ̔̄͟l̸̷̢̡̫̩̃́͐̆͒ͨ̔̄͟è̙͎̝̞̠̹͍́́̅͐͌͘ͅè̙͎̝̞̠̹͍́́̅͐͌͘ͅą̶̢̡̘̦͖̰̌̎͌ͩ́̓ͮą̶̢̡̘̦͖̰̌̎͌ͩ́̓ͮȑ̹̻̦͙̠͂̽͆ͫ͛͟͏̺͡ȑ̹̻̦͙̠͂̽͆ͫ͛͟͏̺͡"̣̞͕̇ͯ̓̽ͪ͑́̍̚͘͘ͅ"̣̞͕̇ͯ̓̽ͪ͑́̍̚͘͘ͅ ̛̩̘̗̜̗̥̂͊ͥ̀ͨͫ̾ͧ ̛̩̘̗̜̗̥̂͊ͥ̀ͨͫ̾ͧe̵̡͚͉̤̯̮͛̎̓ͪ̾̉̆͟e̵̡͚͉̤̯̮͛̎̓ͪ̾̉̆͟l̢̩͓̙͓͍̈̊ͫͣ́̅ͧ͛͞l̢̩͓̙͓͍̈̊ͫͣ́̅ͧ͛͞e̠̱͉̯͔̙͔̓ͩ̃͋͌ͬͭ͋e̠̱͉̯͔̙͔̓ͩ̃͋͌ͬͭ͋m̧̡̛̤͕̻̳̽͛̓̈́ͣ̊̚͟m̧̡̛̤͕̻̳̽͛̓̈́ͣ̊̚͟e̯͎̺͔̼̾͂͐̄ͮ͌̍͑̕ͅe̯͎̺͔̼̾͂͐̄ͮ͌̍͑̕ͅṉ̸͔̩̙̙̹͚̭ͩ͛͗̀̾ͅṉ̸͔̩̙̙̹͚̭ͩ͛͗̀̾ͅt̸̢̧̝͉̺͉̓́̇ͯ̕͠͠͝t̸̢̧̝͉̺͉̓́̇ͯ̕͠͠͝ ̳͔̜̹̘̪̅̋̎̉͆̑ͤ͡͞ ̳͔̜̹̘̪̅̋̎̉͆̑ͤ͡͞a̷̳͓̞̱͈̓́̒̔̆ͩͯ̊͠a̷̳͓̞̱͈̓́̒̔̆ͩͯ̊͠s̷̛͙̘̳͙͓̠̞̫̆̓̚̚͡s̷̛͙̘̳͙͓̠̞̫̆̓̚̚͡ ̷̢̦̘̮̰͕̏̀ͩ̓͂ͦ͟ͅ ̷̢̦̘̮̰͕̏̀ͩ̓͂ͦ͟ͅw̮͔͇͕̝͖ͪ͒̏̇ͪ̇̍ͦ͠w̮͔͇͕̝͖ͪ͒̏̇ͪ̇̍ͦ͠ẹ̗͚̮̭̓̍̐̃̍́̐͘̕͘ẹ̗͚̮̭̓̍̐̃̍́̐͘̕͘l̴̡̩̱̞͛ͤ͑͑͂̀ͣ̉̌̕l̴̡̩̱̞͛ͤ͑͑͂̀ͣ̉̌̕l̷̨̘̤̣̯͇̲̝ͨ̍ͦ͝͝ͅl̷̨̘̤̣̯͇̲̝ͨ̍ͦ͝͝ͅ,̷̻̙̖͔͚͋̇̂̑͗̕̕͢ͅ,̷̻̙̖͔͚͋̇̂̑͗̕̕͢ͅ ̴̶̮̣̪̣̟͚̅͊ͧͭ̂͂̓ ̴̶̮̣̪̣̟͚̅͊ͧͭ̂͂̓h̡͈̗̙͚̳͕̤͍̿̄͑ͥ͊̉h̡͈̗̙͚̳͕̤͍̿̄͑ͥ͊̉e̡̞͔̘͐̋͌̅̓̈͆̇̿͟͠e̡̞͔̘͐̋͌̅̓̈͆̇̿͟͠n̤͕͉̣̐͊́̽̍́͂͏̙̾ͅn̤͕͉̣̐͊́̽̍́͂͏̙̾ͅc̨̧̛̜͈͍͓̣̹ͮͧ̊͟͡ͅc̨̧̛̜͈͍͓̣̹ͮͧ̊͟͡ͅȩ̢̛͚̣͓͙ͣͮͩ̌̌́͟͠ȩ̢̛͚̣͓͙ͣͮͩ̌̌́͟͠ ̷̜̀ͪ̅͐͝͏̤̮̄͑̾ͬ͝ ̷̜̀ͪ̅͐͝͏̤̮̄͑̾ͬ͝t̙͔̳͕̝̝͔͐̊̓ͩ̈́ͪ̒͠t̙͔̳͕̝̝͔͐̊̓ͩ̈́ͪ̒͠h̩̖̪̠͂ͪ́͐̿͊ͨ̈̋̃͟h̩̖̪̠͂ͪ́͐̿͊ͨ̈̋̃͟e̋͆ͬ͞͏̵̘̹̙̂ͥ̐̀́ͅe̋͆ͬ͞͏̵̘̹̙̂ͥ̐̀́ͅ ̧̱͌̆̏͘͏̬̠̹̏ͦ̓͋̕ ̧̱͌̆̏͘͏̬̠̹̏ͦ̓͋̕f̸̧͎̣̪̯̻̗̟̎̎͂ͫ̕͝f̸̧͎̣̪̯̻̗̟̎̎͂ͫ̕͝a̟̓̃͒͏̸̧̣̱̎̽̏̐̓ͤa̟̓̃͒͏̸̧̣̱̎̽̏̐̓ͤć̯͚͕͡͏̴̛̜̺̣͙͉̀̍ć̯͚͕͡͏̴̛̜̺̣͙͉̀̍ț̢̹͇͈ͩ̋́̔̇̉ͤ̽͢ͅț̢̹͇͈ͩ̋́̔̇̉ͤ̽͢ͅo͈̥͊ͦ̔̃ͬ̎͛ͧ͌͌͟͟͝o͈̥͊ͦ̔̃ͬ̎͛ͧ͌͌͟͟͝r̸̨͕̙̟̟͈̼͔ͥͮ͋ͫ͒͝r̸̨͕̙̟̟͈̼͔ͥͮ͋ͫ͒͝ ̧̗̝̘͇͉̩̗̅̊̓͂̐͊͡ ̧̗̝̘͇͉̩̗̅̊̓͂̐͊͡o̬̻̪̹̘̥̳̲̫̳̫̳ͬͩ͊o̬̻̪̹̘̥̳̲̫̳̫̳ͬͩ͊f̡̣̜̗͚̙͇̓͑̍ͬ̅̚͞͞f̡̣̜̗͚̙͇̓͑̍ͬ̅̚͞͞ ̵̸͓̱̻̱̌̃ͫ̑̿͐͂ͨ̇ ̵̸͓̱̻̱̌̃ͫ̑̿͐͂ͨ̇2̡̝̥̯͚͔̖̫ͫ̽̔͑̅̚͞2̡̝̥̯͚͔̖̫ͫ̽̔͑̅̚͞ ̨̠̰̯̤͕̗̗̳͆̑͐͌̕͟ ̨̠̰̯̤͕̗̗̳͆̑͐͌̕͟i͇̫̲̲͓̖͙͖̱ͤ͊̎̃ͧ͢i͇̫̲̲͓̖͙͖̱ͤ͊̎̃ͧ͢n̵̢̻̦̭̏̓̂́͏̲̪̙̏͌n̵̢̻̦̭̏̓̂́͏̲̪̙̏͌ ̸̵̛̹͇͚̓̋̎̏̽̚̚͢͜ ̸̵̛̹͇͚̓̋̎̏̽̚̚͢͜t͈͔̤̲̬ͧͩ̔̀̂́͑̂ͭ͘t͈͔̤̲̬ͧͩ̔̀̂́͑̂ͭ͘h̡̻̙̖̪̱̍͗̍́͗́́̅͠h̡̻̙̖̪̱̍͗̍́͗́́̅͠e̶̖̩̜͐ͥͨͪͣ̆͋̋̉͢͡e̶̖̩̜͐ͥͨͪͣ̆͋̋̉͢͡ ̧͈̙̤͉͌ͩ̓͐̌̄ͦ͌ͥ͝ ̧͈̙̤͉͌ͩ̓͐̌̄ͦ͌ͥ͝c̨̨̹̗̬͕̩̈̑̉̃̑́̆͞c̨̨̹̗̬͕̩̈̑̉̃̑́̆͞h̭͚̦̻̘͈͆ͪ̿̌́̏̐͊͠h̭͚̦̻̘͈͆ͪ̿̌́̏̐͊͠ę̙͍͚ͮͦ́ͭͥ̈͑ͧ̕̕͢ę̙͍͚ͮͦ́ͭͥ̈͑ͧ̕̕͢c̝̭͓̹̙̠̄̍ͦ̌̏̉̇͛ͥc̝̭͓̹̙̠̄̍ͦ̌̏̉̇͛ͥk̶̡͚̦̰̣͖̔͌́̋͋̔ͥ̕k̶̡͚̦̰̣͖̔͌́̋͋̔ͥ̕.̛̱̖͓̼͚̲ͪ̆̈́̃̚͜͞ͅ.̛̱̖͓̼͚̲ͪ̆̈́̃̚͜͞ͅ ̶̴̺̹̜̺͇ͮ̉ͯ͋͗͝͝ͅ ̶̴̺̹̜̺͇ͮ̉ͯ͋͗͝͝ͅA͉̺̰̲̟̺͚͙̽́̀̌ͬͩ͠A͉̺̰̲̟̺͚͙̽́̀̌ͬͩ͠l̜͈̟͖̾͑̈́́̇ͮ̐ͦͮ͋̋l̜͈̟͖̾͑̈́́̇ͮ̐ͦͮ͋̋s̡̛̯̜̩̪̤̹̅͛̋̓͂̊͡s̡̛̯̜̩̪̤̹̅͛̋̓͂̊͡o̶͉̱͉̠̫̻ͤͣ̓ͭ͊͑͆ͅo̶͉̱͉̠̫̻ͤͣ̓ͭ͊͑͆ͅ ̢̗͉̝̞͗͛̊́ͦ͛̍̚͜͡ ̢̗͉̝̞͗͛̊́ͦ͛̍̚͜͡i̵̧͍̝̦̬̭̽̎̈̃̓̚͟͝i̵̧͍̝̦̬̭̽̎̈̃̓̚͟͝f̴̛̻̞̬̟͖̙̦̑́̀̍̇͝f̴̛̻̞̬̟͖̙̦̑́̀̍̇͝ ͓͚͇̺ͪ͛ͦͥ̓̎ͨ͒͊̚͟ ͓͚͇̺ͪ͛ͦͥ̓̎ͨ͒͊̚͟t̶̯͙̹̟͖̂̇͒̾ͭ͒͐͛̌t̶̯͙̹̟͖̂̇͒̾ͭ͒͐͛̌ḧ̠̬́͋̕͏̧̙̼͑͂̀̌̉̈ḧ̠̬́͋̕͏̧̙̼͑͂̀̌̉̈e̫̺͔̗̳͋̒͌ͤͬ̔͗̕̕͡e̫̺͔̗̳͋̒͌ͤͬ̔͗̕̕͡r̴̛̭͙͑́ͤ̓̒͊̈ͥ̑ͮ͞r̴̛̭͙͑́ͤ̓̒͊̈ͥ̑ͮ͞ȇ̷̛̝͓̜̮̩͙ͨ̎̎͛̌̽ȇ̷̛̝͓̜̮̩͙ͨ̎̎͛̌̽ ̸̩̤̘̖̳̻̋̈͛͑̈́̌̒͝ ̸̩̤̘̖̳̻̋̈͛͑̈́̌̒͝i̧͖͕̞̩̱̭̎̽̀͏̮ͬͨ͡i̧͖͕̞̩̱̭̎̽̀͏̮ͬͨ͡ś̶͍̞̉ͯ̊ͦͧ̀̆̌͂͞͝ś̶͍̞̉ͯ̊ͦͧ̀̆̌͂͞͝ ̡̛͙͈̜̗̻̮̞͍̝̝̓̅͋ ̡̛͙͈̜̗̻̮̞͍̝̝̓̅͋ȃ̢͍̟̬̳ͣ͏̝̔͑̎ͣ̕ͅȃ̢͍̟̬̳ͣ͏̝̔͑̎ͣ̕ͅ ̖̼͙̯͎̒͒ͩͣ̀̆͗̇͝ͅ ̖̼͙̯͎̒͒ͩͣ̀̆͗̇͝ͅļ̩̪͕͓͖͌̐͛̊ͫͪ̿͊ͤļ̩̪͕͓͖͌̐͛̊ͫͪ̿͊ͤȍ͍̜͓̣͈͍̳̄͊̄ͣ͢͝ͅȍ͍̜͓̣͈͍̳̄͊̄ͣ͢͝ͅt̵̷̛̤͎͕̖̹ͦ̇͒́͂ͮ͘t̵̷̛̤͎͕̖̹ͦ̇͒́͂ͮ͘ ̶̨̳̺̖̼̯͎̯̬̀̈̐ͦ͜ ̶̨̳̺̖̼̯͎̯̬̀̈̐ͦ͜o̷̡̯̼͇̻͙̙̙͒͂ͩ̉̀ͮo̷̡̯̼͇̻͙̙̙͒͂ͩ̉̀ͮf̻̺̖͉̊ͤ̇ͤ̍͌͛̐͟͟͝f̻̺̖͉̊ͤ̇ͤ̍͌͛̐͟͟͝ ̷̴̟̠̹͎̱̈́̈́̆̈́̇̃͘͞ ̷̴̟̠̹͎̱̈́̈́̆̈́̇̃͘͞p̸̸̧̨̦̪͕̮̀͒͒͌͌̑͢p̸̸̧̨̦̪͕̮̀͒͒͌͌̑͢a̯͙ͥͬ̊̓ͯ͌ͮ͊̎̂͒͢͠a̯͙ͥͬ̊̓ͯ͌ͮ͊̎̂͒͢͠ċ̛̫̱̥͕̳̲ͫͤ̎͐̄̕͠ċ̛̫̱̥͕̳̲ͫͤ̎͐̄̕͠k̵̡̹̲͓̾̉͏̶̻́ͩ̎̓̊k̵̡̹̲͓̾̉͏̶̻́ͩ̎̓̊e̵̡̢̢̪͍̲̣͒̒̍ͯͤ͊͑e̵̡̢̢̪͍̲̣͒̒̍ͯͤ͊͑ḑ̘͖̼̌ͭ̐͑ͯ͋ͬ̈́͆̓̚ḑ̘͖̼̌ͭ̐͑ͯ͋ͬ̈́͆̓̚ ̶̶̧̺̰͖̯͇̏̄̿ͤ̔͘͡ ̶̶̧̺̰͖̯͇̏̄̿ͤ̔͘͡c̩̝̯͂͆ͤ̈́͆̏̑̄ͦ͗̿͞c̩̝̯͂͆ͤ̈́͆̏̑̄ͦ͗̿͞e̥̫͌̓̚͏̵̧͙̣̻̞́̌̉e̥̫͌̓̚͏̵̧͙̣̻̞́̌̉l̵̪̣̪̘̙̟̘͊͒̿̏͗͝͠l̵̪̣̪̘̙̟̘͊͒̿̏͗͝͠l̨̮͚̟̺̹ͮ͊ͭ̊ͮ̿͘͘͟l̨̮͚̟̺̹ͮ͊ͭ̊ͮ̿͘͘͟s̩̯͌̊͒͝͏̥͑̈̎ͥ̀͟͞s̩̯͌̊͒͝͏̥͑̈̎ͥ̀͟͞,̡̙̻̭̪̭̖̀̇̒ͮ̈̒̇̕,̡̙̻̭̪̭̖̀̇̒ͮ̈̒̇̕ ̷̢̫̳̺͉̯̳̂̓ͨ͋͛͂͞ ̷̢̫̳̺͉̯̳̂̓ͨ͋͛͂͞p̟̰͖̹̦̲͙̉̑͐͑͗̀͟͢p̟̰͖̹̦̲͙̉̑͐͑͗̀͟͢á̳̜̈̓͛͠͏̢̄ͧ̉ͧͨͅá̳̜̈̓͛͠͏̢̄ͧ̉ͧͨͅs̵̢̥̖̰̥̼̯ͪͭ̿͗͌ͪ͊s̵̢̥̖̰̥̼̯ͪͭ̿͗͌ͪ͊s̘̱͕̓̅͛̆̅ͮ́̅ͧͣ̈̚s̘̱͕̓̅͛̆̅ͮ́̅ͧͣ̈̚ ̡̮̹̹̗͎̝ͣ̇́ͤ̾ͤ͞ͅ ̡̮̹̹̗͎̝ͣ̇́ͤ̾ͤ͞ͅt̡̛̝̯̱̖̠̱ͤ͒͆̍̚͘ͅt̡̛̝̯̱̖̠̱ͤ͒͆̍̚͘ͅh̛̯̻̩̘̤̳̿̓͂̐͐͡͡͠h̛̯̻̩̘̤̳̿̓͂̐͐͡͡͠ë́͏̩̣̗̺̟ͭ̃̾͂̀͘͢͝ë́͏̩̣̗̺̟ͭ̃̾͂̀͘͢͝m̸̜͔̮̥̹̲̖̲̄̈̊̎ͬ͠m̸̜͔̮̥̹̲̖̲̄̈̊̎ͬ͠ ̝͇̏͏̡̟̥͍ͦ̋̎ͤ̕͢͜ ̝͇̏͏̡̟̥͍ͦ̋̎ͤ̕͢͜ó͖̬̩̤̜̫͔͑̌ͫ̈́͡͏̇ó͖̬̩̤̜̫͔͑̌ͫ̈́͡͏̇f̴̶̴̥͔̗͖̬̆͒ͨ͊ͬͅͅf̴̶̴̥͔̗͖̬̆͒ͨ͊ͬͅͅ ̮̦̲̼̞̑ͨ͒̌ͤ̿́̌͐͒ ̮̦̲̼̞̑ͨ͒̌ͤ̿́̌͐͒t̛̮̰͔̋͂͗̓͋̇̅̆̒͊ͅt̛̮̰͔̋͂͗̓͋̇̅̆̒͊ͅo̴̢͚̮̳͙̟̳̐ͬ͑̃̓͡ͅo̴̢͚̮̳͙̟̳̐ͬ͑̃̓͡ͅ ̝̺͖͒ͯͭ̑ͤ͊ͮ͂̚̚͡ͅ ̝̺͖͒ͯͭ̑ͤ͊ͮ͂̚̚͡ͅt̶̨̲̦͉͖̲̤̗ͬ̋̋ͦ̂ͯt̶̨̲̦͉͖̲̤̗ͬ̋̋ͦ̂ͯh̶̨̤͍̜̯͈͇͛ͩ́̀͊ͮͩh̶̨̤͍̜̯͈͇͛ͩ́̀͊ͮͩe̡̢̤̰̰͙̭͈̓ͯͬ͑ͨ̃͢e̡̢̤̰̰͙̭͈̓ͯͬ͑ͨ̃͢ ̶̛̺̦̯̹̞͎̟̥̞̝̐̕ͅ ̶̛̺̦̯̹̞͎̟̥̞̝̐̕ͅU͙̓ͤ͏̟̗̟͕̥̰́͑̆ͧ͟U͙̓ͤ͏̟̗̟͕̥̰́͑̆ͧ͟I̪̩͕͕̼̎͐ͭͦ͐̋̐̅ͯ͢I̪̩͕͕̼̎͐ͭͦ͐̋̐̅ͯ͢ ̢̦͍̰̬͚ͯ́ͫ̿ͨ͘͘͝͡ ̢̦͍̰̬͚ͯ́ͫ̿ͨ͘͘͝͡t̴̨͉̟̥͛͐̇̀̎̒̄ͧ̀̇t̴̨͉̟̥͛͐̇̀̎̒̄ͧ̀̇o̸͇͏̷͍͉̠ͤ̈̾ͤ͛ͥ̚͝o̸͇͏̷͍͉̠ͤ̈̾ͤ͛ͥ̚͝ ̸̣͕̝̯̼́ͨͯ̏̋̂̑́͘ ̸̣͕̝̯̼́ͨͯ̏̋̂̑́͘l̵̨̛̬̱̣̬͚̺̫̳ͨ̽ͫͯl̵̨̛̬̱̣̬͚̺̫̳ͨ̽ͫͯḙ̳͕̝̥̄̆ͮ̄ͦͨ̓̚͏͢ḙ̳͕̝̥̄̆ͮ̄ͦͨ̓̚͏͢t̵̼̲̣̉̀̌ͭ̒̓͌̀͒̀ͅt̵̼̲̣̉̀̌ͭ̒̓͌̀͒̀ͅ ̺͈͙̘̣̩̙͕̋̇͆̀͊̇̂ ̺͈͙̘̣̩̙͕̋̇͆̀͊̇̂i̧̭̲̼̗̥̪̣̭ͬ͑ͨ̓̈̐i̧̭̲̼̗̥̪̣̭ͬ͑ͨ̓̈̐ṱ̴̯̲̱̫̲̥ͭ̀͋̂̚̕͟ṱ̴̯̲̱̫̲̥ͭ̀͋̂̚̕͟ ̖̗͔̦̲̻̌̀̏͆͊ͤ̑ͨ̉ ̖̗͔̦̲̻̌̀̏͆͊ͤ̑ͨ̉s̨̢͔̄̃ͯ̈́̑͐̚̕͢͝͝s̨̢͔̄̃ͯ̈́̑͐̚̕͢͝͝t͚͉͇̳̘̅̇̋͌̀̋́ͨ́͏t͚͉͇̳̘̅̇̋͌̀̋́ͨ́͏â͇͎̺ͨͭ͡͏͚̯ͤͩ͋ͧ͘â͇͎̺ͨͭ͡͏͚̯ͤͩ͋ͧ͘r̷̘̜͍̫̯ͭͪ͑͗̓͆͟͝ͅr̷̘̜͍̫̯ͭͪ͑͗̓͆͟͝ͅṭ̷̢̱͕̎ͬ̿́́͊̐͟͢͜ṭ̷̢̱͕̎ͬ̿́́͊̐͟͢͜ ̟̥̖͕̭͍̲ͩ̆̒̑͊̕̚͡ ̟̥̖͕̭͍̲ͩ̆̒̑͊̕̚͡p̶̴̨̧̜̰̜̘̉̽ͤ́͘͢͜p̶̴̨̧̜̰̜̘̉̽ͤ́͘͢͜ṙ̠̘̟̭͖̜̜͍ͦ̾͒͜͠͞ṙ̠̘̟̭͖̜̜͍ͦ̾͒͜͠͞ǒ̷̶̫͈̫̹ͬ͂ͧ̿̿̑͂͂ǒ̷̶̫͈̫̹ͬ͂ͧ̿̿̑͂͂c̵̸̮͕̮͈̞̼͎͉͍̑́ͭ̀c̵̸̮͕̮͈̞̼͎͉͍̑́ͭ̀e̸̡͔͓̳̞̟̘ͩ̍̽ͪͤͣ͢e̸̡͔͓̳̞̟̘ͩ̍̽ͪͤͣ͢s̨͍̬̖͂̏ͦ̀ͫ̐ͨͪ͡ͅͅs̨͍̬̖͂̏ͦ̀ͫ̐ͨͪ͡ͅͅs̡̻̹̜͍̺͌͛ͮ̓̀̈́̉̿͑s̡̻̹̜͍̺͌͛ͮ̓̀̈́̉̿͑í̤̜ͭ͢͏̶̶̹͍ͤͪ̉ͫ̋í̤̜ͭ͢͏̶̶̹͍ͤͪ̉ͫ̋ņ̵̼̪̭̲̤͙͖̒̑ͨ͂̌͘ņ̵̼̪̭̲̤͙͖̒̑ͨ͂̌͘g̷̢̢̭̘̙̥̖̲̭͛ͣ́̀̍g̷̢̢̭̘̙̥̖̲̭͛ͣ́̀̍ ̷̺̱̙̹͔̗͆ͪ̾ͬͬ̓͘͠ ̷̺̱̙̹͔̗͆ͪ̾ͬͬ̓͘͠t̛̤̻̲̓̓ͩ̇ͫͫ͆ͦ͛̕͞t̛̤̻̲̓̓ͩ̇ͫͫ͆ͦ͛̕͞ḣ̜̘̮̫͍̗͇ͥͯ̽̕͢͢͝ḣ̜̘̮̫͍̗͇ͥͯ̽̕͢͢͝ẹ̵̱̹͚͖̜̞̆̾͌ͬ̀̿͞ẹ̵̱̹͚͖̜̞̆̾͌ͬ̀̿͞m̶̢̧͉̝̜̝̍͑͂̽̌̉̈́ͩm̶̢̧͉̝̜̝̍͑͂̽̌̉̈́ͩ' + api.nvim_buf_set_lines(0, 0, -1, true, { text }) + + screen:try_resize(250, 10) + screen:expect({ + grid = [[ + {100: 1 }{101:^c̯̥̳̮̫̳͔̱̀ͦͩ̄͋̓͘c̯̥̳̮̫̳͔̱̀ͦͩ̄͋̓͘l̶̴̴̨̛͓͚͎̥ͦͤ̑͆͛͢l̶̴̴̨̛͓͚͎̥ͦͤ̑͆͛͢ô̷̤̩ͯͧ͆ͪ̈́́͒̒̐͐̕ô̷̤̩ͯͧ͆ͪ̈́́͒̒̐͐̕s̶̷̢̩̱̠̀ͦ̽ͮ͒ͨ̚͟͠s̶̷̢̩̱̠̀ͦ̽ͮ͒ͨ̚͟͠e͉̯̱̖͕̳̼̽̊̒ͣ̊ͥ̚̚e͉̯̱̖͕̳̼̽̊̒ͣ̊ͥ̚̚ ͇͌̈̄ͬͧͧ͝͠͏̷ͪ̎͟͠ ͇͌̈̄ͬͧͧ͝͠͏̷ͪ̎͟͠t̵̳̅̽͏̵̡̥̲͍͙̹̯ͩ̐t̵̳̅̽͏̵̡̥̲͍͙̹̯ͩ̐o͋͏̬̞̣ͬ́ͬ̎̋̓̽͘͠͡o͋͏̬̞̣ͬ́ͬ̎̋̓̽͘͠͡ ͏̛͙̮̈ͬ̌͐ͤ͒ͧ̎ͤ͜͠ ͏̛͙̮̈ͬ̌͐ͤ͒ͧ̎ͤ͜͠ǫ̛̳͕̦͖̪̀͂͛̅̔ͪ͒͜ǫ̛̳͕̦͖̪̀͂͛̅̔ͪ͒͜v̸̡͖̗̣ͯ̿̔͊̅ͯ̈̓̇ͅv̸̡͖̗̣ͯ̿̔͊̅ͯ̈̓̇ͅe̴̶̢̜̭̠̰̞ͪͨ͂ͤ͆́͗e̴̶̢̜̭̠̰̞ͪͨ͂ͤ͆́͗r̨̖̼̳̳͚̖̒ͯ̊̋̂̑̚͞r̨̖̼̳̳͚̖̒ͯ̊̋̂̑̚͞f̵̮̣̬̾͛̌ͧͦ͘͢͜͜͠ͅf̵̮̣̬̾͛̌ͧͦ͘͢͜͜͠ͅl̡͉̬̳͈̠̏͂ͤ̈ͨ̀ͩ̔͏l̡͉̬̳͈̠̏͂ͤ̈ͨ̀ͩ̔͏ỏ̶̢̻̠͎͇͈̜̈̆ͯ̔ͩ̾ỏ̶̢̻̠͎͇͈̜̈̆ͯ̔ͩ̾ẉ̦̞̼̩̣͙̅̿́̓̉̎̈ͪẉ̦̞̼̩̣͙̅̿́̓̉̎̈ͪi̷̡͍͓͔̝͙͖͖̍ͯͤͬͦ͝i̷̡͍͓͔̝͙͖͖̍ͯͤͬͦ͝n̠̪̰͋ͩ̆͏̶̖̯ͭ̀̿͛͘n̠̪̰͋ͩ̆͏̶̖̯ͭ̀̿͛͘g̴̭͎̞͙̗̯͙͖ͬ́ͧͧ͝ͅg̴̭͎̞͙̗̯͙͖ͬ́ͧͧ͝ͅ ̢͎̬͓̮̹̰̙͍̓̐͋͂͐̚ ̢͎̬͓̮̹̰̙͍̓̐͋͂͐̚ť̴̼̝̗ͩ̍͋̿͏͇ͧ̑̏̚ť̴̼̝̗ͩ̍͋̿͏͇ͧ̑̏̚h̨̨̢͓̲͚͕̦ͨ͛̓ͩ̚͟͠h̨̨̢͓̲͚͕̦ͨ͛̓ͩ̚͟͠ȩ͕̜̥̃̑͋̏͐̎̒͛͊͏͙ȩ͕̜̥̃̑͋̏͐̎̒͛͊͏͙ ̵̨̜̜̠͉̱͎͑ͥ̌͐̽͢͡ ̵̨̜̜̠͉̱͎͑ͥ̌͐̽͢͡r̢̫͓͎̙̭̽ͥͭ͐̂̀̕͟͝r̢̫͓͎̙̭̽ͥͭ͐̂̀̕͟͝e̴̷͓̹̩ͧ́̉̑̈̿ͥ̕͡͝e̴̷͓̹̩ͧ́̉̑̈̿ͥ̕͡͝d̵̡̼̩̠̜͈̯̬͚͛̋̀̆͟d̵̡̼̩̠̜͈̯̬͚͛̋̀̆͟ŕ̻̳̬͏̨̮͚̲ͥ̌͆͗͠ͅŕ̻̳̬͏̨̮͚̲ͥ̌͆͗͠ͅā̸͙̥̤͍͈̣ͪͨ̈͋̈́̈́͜ā̸͙̥̤͍͈̣ͪͨ̈͋̈́̈́͜w̶̦̪͚̤̃ͬ̓͒ͤ̇̇ͮ͢͡w̶̦̪͚̤̃ͬ̓͒ͤ̇̇ͮ͢͡ ̷̡̦̻̻̪͚̳͎ͥ̓ͩͪ͠͝ ̷̡̦̻̻̪͚̳͎ͥ̓ͩͪ͠͝b̳ͮ̒̊̆̒́̈́̏̓͋ͭ̔ͤ̚b̳ͮ̒̊̆̒́̈́̏̓͋ͭ̔ͤ̚u̧̟̫͎͚̭̠͕͂̄̀̒̈̇͜u̧̟̫͎͚̭̠͕͂̄̀̒̈̇͜f̶̸̢͍̑̂̊ͥͫ̈́ͥ͛̈́̃͝f̶̸̢͍̑̂̊ͥͫ̈́ͥ͛̈́̃͝f̵̼̭̮͎ͧ̒̆͊̀ͤ͊̇̕͡f̵̼̭̮͎ͧ̒̆͊̀ͤ͊̇̕͡e̮̪̲̣̞̖͎ͥͤ̐̌̓̐͟͢e̮̪̲̣̞̖͎ͥͤ̐̌̓̐͟͢ŗ̭̘̮̹̖̎̄̆́ͫͭ͢ͅͅŗ̭̘̮̹̖̎̄̆́ͫͭ͢ͅͅ.̪̖͉͚̹̾̉ͮ̔̊ͪ̾̎͟͞.̪̖͉͚̹̾̉ͮ̔̊ͪ̾̎͟͞ ̷̧̺̰͎̣̃͒͗ͮ͑ͪͮ͞ͅ ̷̧̺̰͎̣̃͒͗ͮ͑ͪͮ͞ͅf̛̫͚͚͍̜͎̗̳̂ͬͭ͜͢͝f̛̫͚͚͍̜͎̗̳̂ͬͭ͜͢͝i̴̵̡̛̛͎̤̳̮ͩ̐ͩ͑̇̚i̴̵̡̛̛͎̤̳̮ͩ̐ͩ͑̇̚n̵͇͍͚̖̥̣ͨ̄ͧ̌̂͗͘͝n̵͇͍͚̖̥̣ͨ̄ͧ̌̂͗͘͝ȉ̼̱̫̜̋̓̐͌͆ͨ͘͝͡ͅȉ̼̱̫̜̋̓̐͌͆ͨ͘͝͡ͅs̴̸̝̺̬͚̲̹̘ͪ̆̊ͥ͞͝s̴̸̝̺̬͚̲̹̘ͪ̆̊ͥ͞͝h̴̜̠͇ͦͥ̔̅ͭͭ͋ͩ͟͡͞h̴̜̠͇ͦͥ̔̅ͭͭ͋ͩ͟͡͞ ̶̧̛̻͙̤̘̺̣̻̗͍̓͑͠ ̶̧̛̻͙̤̘̺̣̻̗͍̓͑͠t̠͉̼̬̩͛́ͨ͐̀͛̂ͨ̾͞t̠͉̼̬̩͛́ͨ͐̀͛̂ͨ̾͞h̻̹̝̹̾ͩ̍ͧ͆ͥ̔͘͏̉ͯh̻̹̝̹̾ͩ̍ͧ͆ͥ̔͘͏̉ͯì̷̢̛̺̭͇̟̦̄̓́̓ͪ͟ì̷̢̛̺̭͇̟̦̄̓́̓ͪ͟s̴̡̗͍͕͖̮̟̱̫̎ͣ̀̎̿s̴̡̗͍͕͖̮̟̱̫̎ͣ̀̎̿ ̶͇̟̜̗̗͇͇͐̑̈͋̋̽͟ ̶͇̟̜̗̗͇͇͐̑̈͋̋̽͟e̷̥͙͈̖̤̯̹̯͗̉̈́̽ͨ̕e̷̥͙͈̖̤̯̹̯͗̉̈́̽ͨ̕v̛̝͕̱͙̞̖̒̂̔͆̊̎́ͫv̛̝͕̱͙̞̖̒̂̔͆̊̎́ͫę̴̤̭͖̈̐̿͂ͣ͒̃ͭ̕͟ę̴̤̭͖̈̐̿͂ͣ͒̃ͭ̕͟ṇ̳̭͓̟̠͕̯͑̉ͦ̀ͯ͜͡ṇ̳̭͓̟̠͕̯͑̉ͦ̀ͯ͜͡t̢̞͔̣̄̀͆̂̃ͨͦ͜͜͝͠t̢̞͔̣̄̀͆̂̃ͨͦ͜͜͝͠,̬̳̮͓͉̟͉͓̦͔̑̄ͨ̎͜,̬̳̮͓͉̟͉͓̦͔̑̄ͨ̎͜ ͕͈̠̰̬̬̌͂̏ͥ̀̕̚͢͠ ͕͈̠̰̬̬̌͂̏ͥ̀̕̚͢͠f̺̮̞̈́̏̋͏̺̖̝̓̑̂̚͢f̺̮̞̈́̏̋͏̺̖̝̓̑̂̚͢l̜̪͍̩̩̟͉͓̊̓ͤ̆ͣͫ̌l̜̪͍̩̩̟͉͓̊̓ͤ̆ͣͫ̌u̷̧̞̳̱̜̟̲͑̐͂ͪ͛͘͟u̷̧̞̳̱̜̟̲͑̐͂ͪ͛͘͟s͔͍̽ͣͮ̏̓͛̄ͯ̽͂̐ͯ͜s͔͍̽ͣͮ̏̓͛̄ͯ̽͂̐ͯ͜ḩ̼͕̦͖̼͚̗̃̃ͥ̅̂̈͟ḩ̼͕̦͖̼͚̗̃̃ͥ̅̂̈͟,̵͍̮̮̟͚̝̃ͨ̿ͭ̌ͤ̋̊,̵͍̮̮̟͚̝̃ͨ̿ͭ̌ͤ̋̊ ̷̨̨͈̝̦͂ͦ̒̋̇ͧ̒͟͝ ̷̨̨͈̝̦͂ͦ̒̋̇ͧ̒͟͝a̡̨̲̖̾̂͗̚͢͡͏͈ͤ̉͡a̡̨̲̖̾̂͗̚͢͡͏͈ͤ̉͡nͫͤ̚͜͏̧̛̣̻ͩ̔̍ͦ̕͝nͫͤ̚͜͏̧̛̣̻ͩ̔̍ͦ̕͝d͈̻̗̼̀͡͏̶̵̟̹̻̎̾ͯd͈̻̗̼̀͡͏̶̵̟̹̻̎̾ͯ ̶͙͈̠̜̬̺͛̀̊̂ͪ̔ͮ͑ ̶͙͈̠̜̬̺͛̀̊̂ͪ̔ͮ͑ş̧̡̢͓̠͋ͫ͑͒͊̅̔͜͞ş̧̡̢͓̠͋ͫ͑͒͊̅̔͜͞t̤̭͓̰̣̉̔̎ͫ͛ͦ̑̕͟͞t̤̭͓̰̣̉̔̎ͫ͛ͦ̑̕͟͞a̠͇͇̯̥͍͚̳̒́͐͐̏͋̓a̠͇͇̯̥͍͚̳̒́͐͐̏͋̓r͉͈̻̻͕̩̩̃̅͋͆ͮ͢͢͡r͉͈̻̻͕̩̩̃̅͋͆ͮ͢͢͡t̵̛̝̗̥̙̟̆ͮ̽̏ͧ͜͠ͅt̵̛̝̗̥̙̟̆ͮ̽̏ͧ͜͠ͅ ̷̼͎̦ͫ̈͑̃̽͏̲̪ͣͯ̽ ̷̼͎̦ͫ̈͑̃̽͏̲̪ͣͯ̽á̸̷̴̟̣́̔̌͏̶͕͋ͭͭá̸̷̴̟̣́̔̌͏̶͕͋ͭͭ ̧̧̲͍̘̘͚͔͇͙ͨͬ́̊ͅ ̧̧̲͍̘̘͚͔͇͙ͨͬ́̊ͅn̸̸̩͖͔͚͚̖͗ͦ̓̀̀̈́̈́n̸̸̩͖͔͚͚̖͗ͦ̓̀̀̈́̈́ę̵̧̬̣̦̖̝̹̱͌̃̑ͣ̚ę̵̧̬̣̦̖̝̹̱͌̃̑ͣ̚w͍̥͚̺ͮ̓̈̈́̾̊̆́̚͜͝w͍̥͚̺ͮ̓̈̈́̾̊̆́̚͜͝ ̛̹̲̥̝͙̾ͨ̆̎̃̋͂̓̕ ̛̹̲̥̝͙̾ͨ̆̎̃̋͂̓̕"̴̜̰̰̱̖̙̘̈́͌ͨͪ̐̕͠"̴̜̰̰̱̖̙̘̈́͌ͨͪ̐̕͠g̸̛͇̐͊͂̽͢͏͖̣ͫ͊ͯͅg̸̛͇̐͊͂̽͢͏͖̣ͫ͊ͯͅr̴̨̲͎̹͇̠̐ͤ̇̒ͬ̆ͧ͞r̴̨̲͎̹͇̠̐ͤ̇̒ͬ̆ͧ͞į̝̱̩͔̈ͨ̉͌̋̍̂͜͟͞į̝̱̩͔̈ͨ̉͌̋̍̂͜͟͞d̷̴̷̟̎͌͑͛̈́ͭͨͯ̋ͭ̕d̷̴̷̟̎͌͑͛̈́ͭͨͯ̋ͭ̕_̢̭̙̦̪͇̾̔̆ͬͦ́ͥ͢͡_̢̭̙̦̪͇̾̔̆ͬͦ́ͥ͢͡l̡̢̨̧͔̱̥̹̬̆ͮ̈́̏̅͜l̡̢̨̧͔̱̥̹̬̆ͮ̈́̏̅͜ĩ̢͖̠̩̞͚̰̰̉̋̌͛ͪ͠ĩ̢͖̠̩̞͚̰̰̉̋̌͛ͪ͠n̢̬̜̘̲͉ͮ͆͏̯͕ͭͦ̉̅n̢̬̜̘̲͉ͮ͆͏̯͕ͭͦ̉̅ē̡͈̮̭̰̜͍̗̮͔͌͐͆ͫē̡͈̮̭̰̜͍̗̮͔͌͐͆ͫ"̦̠̟ͣ̽͋͐ͧ̓̂̆̎͒͝ͅ"̦̠̟ͣ̽͋͐ͧ̓̂̆̎͒͝ͅ ̴̡̺̹̖̰̀ͤ͊̊͗̊́͜͠ ̴̡̺̹̖̰̀ͤ͊̊͗̊́͜͠ẻ͎̳̻̯̹͓͊̌̄͑͂̉͜͢ẻ͎̳̻̯̹͓͊̌̄͑͂̉͜͢v̞̬̪̥͖ͤ͐̍́ͤ̇̀̕̕ͅv̞̬̪̥͖ͤ͐̍́ͤ̇̀̕̕ͅȇ̶̱̗̩̠͚͎͊ͤͪͦͫ̂̚ȇ̶̱̗̩̠͚͎͊ͤͪͦͫ̂̚n̢̮̜͉̎ͨͩ̒̓ͬͨ̓ͦ͘͜n̢̮̜͉̎ͨͩ̒̓ͬͨ̓ͦ͘͜t̢͚͉̹͇̺̭ͪ̄̉ͨ̄͐̕ͅt̢͚͉̹͇̺̭ͪ̄̉ͨ̄͐̕ͅ ̵̛̳̱͍̩͓ͣ͋̈́͐ͭͧ̿ͅ ̵̛̳̱͍̩͓ͣ͋̈́͐ͭͧ̿ͅã̰̪̙͉̪͇ͣ͋ͤ̓͋͑̕͘ã̰̪̙͉̪͇ͣ͋ͤ̓͋͑̕͘t̴̴̡̡̛̳̼̻̳̂̽͒̇̚͠t̴̴̡̡̛̳̼̻̳̂̽͒̇̚͠ ̴̙̤̹͔̳̟̽̀̆ͥ̂̕͘͝ ̴̙̤̹͔̳̟̽̀̆ͥ̂̕͘͝t̴͖̼͔̬̦̏ͩ̄́̓̊̔̇͡t̴͖̼͔̬̦̏ͩ̄́̓̊̔̇͡ḫ̷͚͇̫̫̠͒ͮ̍ͣ̃͐͐̍ḫ̷͚͇̫̫̠͒ͮ̍ͣ̃͐͐̍e̳͉̮͖̳̣̎͌̂ͣ͋ͯ̆͜͞e̳͉̮͖̳̣̎͌̂ͣ͋ͯ̆͜͞ ̪̖̉̌̀̽̄̍̓̀̂̋͐̈̚ ̪̖̉̌̀̽̄̍̓̀̂̋͐̈̚c̶̫̜͚̊̿̂̿ͥͭ̓̂̈́͘͡c̶̫̜͚̊̿̂̿ͥͭ̓̂̈́͘͡ṷ̵̷͉̯̜̬̝̑͛ͤ̋ͧͯ̉ṷ̵̷͉̯̜̬̝̑͛ͤ̋ͧͯ̉ŗ̙̬̺̬ͥͤ̓͐̈́ͬ̽̌͡͡ŗ̙̬̺̬ͥͤ̓͐̈́ͬ̽̌͡͡r̛͖̼̣͙̋̇̀̅͒̽ͥ̑ͅͅr̛͖̼̣͙̋̇̀̅͒̽ͥ̑ͅͅě̢̪̦̼͘͏̴̠̞͍̓̐ͭ̇ě̢̪̦̼͘͏̴̠̞͍̓̐ͭ̇ǹ̨̨̛̛̯̍ͭͫ̎̍̃̄̐̍ǹ̨̨̛̛̯̍ͭͫ̎̍̃̄̐̍t̵̳͔̭̮̭̱̰ͤ͐̉̾͗̅͢t̵̳͔̭̮̭̱̰ͤ͐̉̾͗̅͢ ̩͕ͧ̌͂͂́ͫͥ̍͏̬̙͗ͅ ̩͕ͧ̌͂͂́ͫͥ̍͏̬̙͗ͅp̞̞͇͇̯̩̬̜ͥ̃͐̑͋́͗p̞̞͇͇̯̩̬̜ͥ̃͐̑͋́͗o̵͖͈̩̪̥̝̊̒̉̿͋ͩ̆͠o̵͖͈̩̪̥̝̊̒̉̿͋ͩ̆͠s̶͇̺̩̟̺͋̆̒ͫͥ̆͏͔͜s̶͇̺̩̟̺͋̆̒ͫͥ̆͏͔͜i̞̝̭̲͈̝̮̫͚͑̓ͤ̎ͮ̀i̞̝̭̲͈̝̮̫͚͑̓ͤ̎ͮ̀t̷̬͇̗̥̳͔̮͔̎̀ͣ̊̕͢t̷̬͇̗̥̳͔̮͔̎̀ͣ̊̕͢i̶̧̗̠̗̲͑̋ͣͪͦͣ͆̕͢i̶̧̗̠̗̲͑̋ͣͪͦͣ͆̕͢ǫ̰̟̙ͯ͏̬̦͚̝̀̈́ͣ͘͜ǫ̰̟̙ͯ͏̬̦͚̝̀̈́ͣ͘͜n̸̻̩͖͓̠̲̮̐̄̌̇́́͠n̸̻̩͖͓̠̲̮̐̄̌̇́́͠}| + {100: }{101:.̧̛͈̙̭̉ͥ̋͛̏͋̂̿͛͞.̧̛͈̙̭̉ͥ̋͛̏͋̂̿͛͞ ̡̲͇̳͔̦̤̹̥ͣ̍ͪͮ̎͡ ̡̲͇̳͔̦̤̹̥ͣ̍ͪͮ̎͡F̼̣͙̳̞͑͒ͧͣ̔̊̇̓̈́͠F̼̣͙̳̞͑͒ͧͣ̔̊̇̓̈́͠ŏ̸̶͎̘̟͙̤̑̒̿͗͛̐̚ŏ̸̶͎̘̟͙̤̑̒̿͗͛̐̚r̵̰͇͚̥̻͚̈́̌̽ͨͥ̕͘͞r̵̰͇͚̥̻͚̈́̌̽ͨͥ̕͘͞ ̵̶̧͖̙̝̻̭̤̒̿͌͗͑͡ ̵̶̧͖̙̝̻̭̤̒̿͌͗͑͡ś̸̬̘̭̼͓̹ͥ͛ͪ̐̈́͆͝ś̸̬̘̭̼͓̹ͥ͛ͪ̐̈́͆͝i͎̺̪̖̻ͫ̀ͤ̾ͦ̽ͭ͒̒͘i͎̺̪̖̻ͫ̀ͤ̾ͦ̽ͭ͒̒͘m̨̩͎̫̫̙̃̈͆ͬ̊͠͏̽͞m̨̩͎̫̫̙̃̈͆ͬ̊͠͏̽͞p̴̢̨͖̼͍̲͍̲ͩ̊̒̌̃ͤp̴̢̨͖̼͍̲͍̲ͩ̊̒̌̃ͤļ͔̱͙̝̟̜͚͎͕̮̹ͣ̀͘ļ͔̱͙̝̟̜͚͎͕̮̹ͣ̀͘ḭ̢̛͈͍̠̟̪̑̎̈́̑̽͜͡ḭ̢̛͈͍̠̟̪̑̎̈́̑̽͜͡c̖̠̥͔̪̼̑̃̆̓ͫ͗ͩͩ̋c̖̠̥͔̪̼̑̃̆̓ͫ͗ͩͩ̋i̴̸̡̘͇͔̹͂̍̐̀ͬͩ̈͘i̴̸̡̘͇͔̹͂̍̐̀ͬͩ̈͘t̵̵̖̫͙͎̒ͭ̔̃̔ͧͫ̽͝t̵̵̖̫͙͎̒ͭ̔̃̔ͧͫ̽͝y̴̘̱͈̳ͯ̈́̍ͮ̔͊͊̚̚͞y̴̘̱͈̳ͯ̈́̍ͮ̔͊͊̚̚͞ ̛̩̤̪͇̬͕̯̞̙̪̮̀̂̕ ̛̩̤̪͇̬͕̯̞̙̪̮̀̂̕ļ̲̰̞̈̌̿͐̉́̋ͬ͟͟͡ļ̲̰̞̈̌̿͐̉́̋ͬ͟͟͡e̡̧̛̬̣̗̣̰͂̐̂͗͛̋̇e̡̧̛̬̣̗̣̰͂̐̂͗͛̋̇a̡̯͉̠̞ͩͮ̉̓́ͮ̔̆̒͘a̡̯͉̠̞ͩͮ̉̓́ͮ̔̆̒͘v͔ͦ͏͎̪̮̝̟̤́̀͊̈̎͟v͔ͦ͏͎̪̮̝̟̤́̀͊̈̎͟ȩ̪͔̤̺͗ͦ̅̓ͭͤͫ̆ͣ͒ȩ̪͔̤̺͗ͦ̅̓ͭͤͫ̆ͣ͒ ̶̢̤͎̰̝̤͂̔͒ͦͦ͂̊̀ ̶̢̤͎̰̝̤͂̔͒ͦͦ͂̊̀p̛̝̪͚͖̫͕̅̍̊́̓͒̂̃p̛̝̪͚͖̫͕̅̍̊́̓͒̂̃l̴̸͉͎̖͕̦̥̾ͨ̌̑ͣ̕͝l̴̸͉͎̖͕̦̥̾ͨ̌̑ͣ̕͝a̰̩͔̼͔̦̩͒ͪͭ̐͡͏̗ͮa̰̩͔̼͔̦̩͒ͪͭ̐͡͏̗ͮč̵̱͇̲̞̉̆̌̄ͧͫ̑̈́͠č̵̱͇̲̞̉̆̌̄ͧͫ̑̈́͠e̶̛̜̬̯̤͔̓ͤͮͦ̂͐͜͜e̶̛̜̬̯̤͔̓ͤͮͦ̂͐͜͜ ̸̧̼̯͕̼̭ͣͣ̿̑̈̎̽͜ ̸̧̼̯͕̼̭ͣͣ̿̑̈̎̽͜f̴̼̞͇̺̊̎̓̑̔̈́͗̊͘͞f̴̼̞͇̺̊̎̓̑̔̈́͗̊͘͞ő̶̶̧̺̤̜̹̫͎̻̏̉̍ͩő̶̶̧̺̤̜̹̫͎̻̏̉̍ͩr̵̙̱̺̮͙̯̼͐̀͗̾͊͟͝r̵̙̱̺̮͙̯̼͐̀͗̾͊͟͝ ̵̪̥͍̩̱ͨ͗̓̎̓͒̚͜͞ ̵̪̥͍̩̱ͨ͗̓̎̓͒̚͜͞t̪̤͙̥̖̹̣̤͎̞̒́̒̽̃t̪̤͙̥̖̹̣̤͎̞̒́̒̽̃ḥ̵̷̷̭̘͙͓ͩ̓ͪͤ̓ͮ̍ḥ̵̷̷̭̘͙͓ͩ̓ͪͤ̓ͮ̍é̡̬̺͉̻̻̀̀͂̽ͬ̕̕͠é̡̬̺͉̻̻̀̀͂̽ͬ̕̕͠ ̵̱̻̣͙̌͊́ͯ́̐̀́͂̕ ̵̱̻̣͙̌͊́ͯ́̐̀́͂̕f̨̪͈̲̬̟̝͎̀̔̋ͨ̀͡ͅf̨̪͈̲̬̟̝͎̀̔̋ͨ̀͡ͅi̵̫̱̝͒̇̏̃ͭ̂̄̄̊̐͠i̵̫̱̝͒̇̏̃ͭ̂̄̄̊̐͠n̵̷͖̻̦͍̻̑̈́̎̓͑ͪͫ͟n̵̷͖̻̦͍̻̑̈́̎̓͑ͪͫ͟a̗̗̠̫̦̻̹͇ͯͦͫ͗̽ͥ̚a̗̗̠̫̦̻̹͇ͯͦͫ͗̽ͥ̚l̵̨̨͙̜͔̘̗̯͌̋͂̑̄͢l̵̨̨͙̜͔̘̗̯͌̋͂̑̄͢ ̵̷̛̺̳͙̲̥̬̊̌̽̓̇͝ ̵̷̛̺̳͙̲̥̬̊̌̽̓̇͝"̸̨̫̟̤̥͉̮̥̀ͤ̐͊̇̑"̸̨̫̟̤̥͉̮̥̀ͤ̐͊̇̑c̵̭̘͍͇̜ͨ̔̍̆͛͌͂͌͛c̵̭̘͍͇̜ͨ̔̍̆͛͌͂͌͛l̸̷̢̡̫̩̃́͐̆͒ͨ̔̄͟l̸̷̢̡̫̩̃́͐̆͒ͨ̔̄͟è̙͎̝̞̠̹͍́́̅͐͌͘ͅè̙͎̝̞̠̹͍́́̅͐͌͘ͅą̶̢̡̘̦͖̰̌̎͌ͩ́̓ͮą̶̢̡̘̦͖̰̌̎͌ͩ́̓ͮȑ̹̻̦͙̠͂̽͆ͫ͛͟͏̺͡ȑ̹̻̦͙̠͂̽͆ͫ͛͟͏̺͡"̣̞͕̇ͯ̓̽ͪ͑́̍̚͘͘ͅ"̣̞͕̇ͯ̓̽ͪ͑́̍̚͘͘ͅ ̛̩̘̗̜̗̥̂͊ͥ̀ͨͫ̾ͧ ̛̩̘̗̜̗̥̂͊ͥ̀ͨͫ̾ͧe̵̡͚͉̤̯̮͛̎̓ͪ̾̉̆͟e̵̡͚͉̤̯̮͛̎̓ͪ̾̉̆͟l̢̩͓̙͓͍̈̊ͫͣ́̅ͧ͛͞l̢̩͓̙͓͍̈̊ͫͣ́̅ͧ͛͞e̠̱͉̯͔̙͔̓ͩ̃͋͌ͬͭ͋e̠̱͉̯͔̙͔̓ͩ̃͋͌ͬͭ͋m̧̡̛̤͕̻̳̽͛̓̈́ͣ̊̚͟m̧̡̛̤͕̻̳̽͛̓̈́ͣ̊̚͟e̯͎̺͔̼̾͂͐̄ͮ͌̍͑̕ͅe̯͎̺͔̼̾͂͐̄ͮ͌̍͑̕ͅṉ̸͔̩̙̙̹͚̭ͩ͛͗̀̾ͅṉ̸͔̩̙̙̹͚̭ͩ͛͗̀̾ͅt̸̢̧̝͉̺͉̓́̇ͯ̕͠͠͝t̸̢̧̝͉̺͉̓́̇ͯ̕͠͠͝ ̳͔̜̹̘̪̅̋̎̉͆̑ͤ͡͞ ̳͔̜̹̘̪̅̋̎̉͆̑ͤ͡͞a̷̳͓̞̱͈̓́̒̔̆ͩͯ̊͠a̷̳͓̞̱͈̓́̒̔̆ͩͯ̊͠s̷̛͙̘̳͙͓̠̞̫̆̓̚̚͡s̷̛͙̘̳͙͓̠̞̫̆̓̚̚͡ ̷̢̦̘̮̰͕̏̀ͩ̓͂ͦ͟ͅ ̷̢̦̘̮̰͕̏̀ͩ̓͂ͦ͟ͅw̮͔͇͕̝͖ͪ͒̏̇ͪ̇̍ͦ͠w̮͔͇͕̝͖ͪ͒̏̇ͪ̇̍ͦ͠ẹ̗͚̮̭̓̍̐̃̍́̐͘̕͘ẹ̗͚̮̭̓̍̐̃̍́̐͘̕͘l̴̡̩̱̞͛ͤ͑͑͂̀ͣ̉̌̕l̴̡̩̱̞͛ͤ͑͑͂̀ͣ̉̌̕l̷̨̘̤̣̯͇̲̝ͨ̍ͦ͝͝ͅl̷̨̘̤̣̯͇̲̝ͨ̍ͦ͝͝ͅ,̷̻̙̖͔͚͋̇̂̑͗̕̕͢ͅ,̷̻̙̖͔͚͋̇̂̑͗̕̕͢ͅ ̴̶̮̣̪̣̟͚̅͊ͧͭ̂͂̓ ̴̶̮̣̪̣̟͚̅͊ͧͭ̂͂̓h̡͈̗̙͚̳͕̤͍̿̄͑ͥ͊̉h̡͈̗̙͚̳͕̤͍̿̄͑ͥ͊̉e̡̞͔̘͐̋͌̅̓̈͆̇̿͟͠e̡̞͔̘͐̋͌̅̓̈͆̇̿͟͠n̤͕͉̣̐͊́̽̍́͂͏̙̾ͅn̤͕͉̣̐͊́̽̍́͂͏̙̾ͅc̨̧̛̜͈͍͓̣̹ͮͧ̊͟͡ͅc̨̧̛̜͈͍͓̣̹ͮͧ̊͟͡ͅȩ̢̛͚̣͓͙ͣͮͩ̌̌́͟͠ȩ̢̛͚̣͓͙ͣͮͩ̌̌́͟͠ ̷̜̀ͪ̅͐͝͏̤̮̄͑̾ͬ͝ ̷̜̀ͪ̅͐͝͏̤̮̄͑̾ͬ͝t̙͔̳͕̝̝͔͐̊̓ͩ̈́ͪ̒͠t̙͔̳͕̝̝͔͐̊̓ͩ̈́ͪ̒͠h̩̖̪̠͂ͪ́͐̿͊ͨ̈̋̃͟h̩̖̪̠͂ͪ́͐̿͊ͨ̈̋̃͟e̋͆ͬ͞͏̵̘̹̙̂ͥ̐̀́ͅe̋͆ͬ͞͏̵̘̹̙̂ͥ̐̀́ͅ ̧̱͌̆̏͘͏̬̠̹̏ͦ̓͋̕ ̧̱͌̆̏͘͏̬̠̹̏ͦ̓͋̕f̸̧͎̣̪̯̻̗̟̎̎͂ͫ̕͝f̸̧͎̣̪̯̻̗̟̎̎͂ͫ̕͝a̟̓̃͒͏̸̧̣̱̎̽̏̐̓ͤa̟̓̃͒͏̸̧̣̱̎̽̏̐̓ͤć̯͚͕͡͏̴̛̜̺̣͙͉̀̍ć̯͚͕͡͏̴̛̜̺̣͙͉̀̍ț̢̹͇͈ͩ̋́̔̇̉ͤ̽͢ͅț̢̹͇͈ͩ̋́̔̇̉ͤ̽͢ͅo͈̥͊ͦ̔̃ͬ̎͛ͧ͌͌͟͟͝o͈̥͊ͦ̔̃ͬ̎͛ͧ͌͌͟͟͝r̸̨͕̙̟̟͈̼͔ͥͮ͋ͫ͒͝r̸̨͕̙̟̟͈̼͔ͥͮ͋ͫ͒͝ ̧̗̝̘͇͉̩̗̅̊̓͂̐͊͡ ̧̗̝̘͇͉̩̗̅̊̓͂̐͊͡o̬̻̪̹̘̥̳̲̫̳̫̳ͬͩ͊o̬̻̪̹̘̥̳̲̫̳̫̳ͬͩ͊f̡̣̜̗͚̙͇̓͑̍ͬ̅̚͞͞f̡̣̜̗͚̙͇̓͑̍ͬ̅̚͞͞ ̵̸͓̱̻̱̌̃ͫ̑̿͐͂ͨ̇ ̵̸͓̱̻̱̌̃ͫ̑̿͐͂ͨ̇2̡̝̥̯͚͔̖̫ͫ̽̔͑̅̚͞2̡̝̥̯͚͔̖̫ͫ̽̔͑̅̚͞ ̨̠̰̯̤͕̗̗̳͆̑͐͌̕͟ ̨̠̰̯̤͕̗̗̳͆̑͐͌̕͟i͇̫̲̲͓̖͙͖̱ͤ͊̎̃ͧ͢i͇̫̲̲͓̖͙͖̱ͤ͊̎̃ͧ͢n̵̢̻̦̭̏̓̂́͏̲̪̙̏͌n̵̢̻̦̭̏̓̂́͏̲̪̙̏͌ ̸̵̛̹͇͚̓̋̎̏̽̚̚͢͜ ̸̵̛̹͇͚̓̋̎̏̽̚̚͢͜t͈͔̤̲̬ͧͩ̔̀̂́͑̂ͭ͘t͈͔̤̲̬ͧͩ̔̀̂́͑̂ͭ͘h̡̻̙̖̪̱̍͗̍́͗́́̅͠h̡̻̙̖̪̱̍͗̍́͗́́̅͠e̶̖̩̜͐ͥͨͪͣ̆͋̋̉͢͡e̶̖̩̜͐ͥͨͪͣ̆͋̋̉͢͡ ̧͈̙̤͉͌ͩ̓͐̌̄ͦ͌ͥ͝ ̧͈̙̤͉͌ͩ̓͐̌̄ͦ͌ͥ͝c̨̨̹̗̬͕̩̈̑̉̃̑́̆͞c̨̨̹̗̬͕̩̈̑̉̃̑́̆͞h̭͚̦̻̘͈͆ͪ̿̌́̏̐͊͠h̭͚̦̻̘͈͆ͪ̿̌́̏̐͊͠ę̙͍͚ͮͦ́ͭͥ̈͑ͧ̕̕͢ę̙͍͚ͮͦ́ͭͥ̈͑ͧ̕̕͢c̝̭͓̹̙̠̄̍ͦ̌̏̉̇͛ͥc̝̭͓̹̙̠̄̍ͦ̌̏̉̇͛ͥk̶̡͚̦̰̣͖̔͌́̋͋̔ͥ̕k̶̡͚̦̰̣͖̔͌́̋͋̔ͥ̕.̛̱̖͓̼͚̲ͪ̆̈́̃̚͜͞ͅ.̛̱̖͓̼͚̲ͪ̆̈́̃̚͜͞ͅ ̶̴̺̹̜̺͇ͮ̉ͯ͋͗͝͝ͅ ̶̴̺̹̜̺͇ͮ̉ͯ͋͗͝͝ͅA͉̺̰̲̟̺͚͙̽́̀̌ͬͩ͠A͉̺̰̲̟̺͚͙̽́̀̌ͬͩ͠l̜͈̟͖̾͑̈́́̇ͮ̐ͦͮ͋̋l̜͈̟͖̾͑̈́́̇ͮ̐ͦͮ͋̋s̡̛̯̜̩̪̤̹̅͛̋̓͂̊͡s̡̛̯̜̩̪̤̹̅͛̋̓͂̊͡o̶͉̱͉̠̫̻ͤͣ̓ͭ͊͑͆ͅo̶͉̱͉̠̫̻ͤͣ̓ͭ͊͑͆ͅ ̢̗͉̝̞͗͛̊́ͦ͛̍̚͜͡ ̢̗͉̝̞͗͛̊́ͦ͛̍̚͜͡i̵̧͍̝̦̬̭̽̎̈̃̓̚͟͝i̵̧͍̝̦̬̭̽̎̈̃̓̚͟͝f̴̛̻̞̬̟͖̙̦̑́̀̍̇͝f̴̛̻̞̬̟͖̙̦̑́̀̍̇͝ ͓͚͇̺ͪ͛ͦͥ̓̎ͨ͒͊̚͟ ͓͚͇̺ͪ͛ͦͥ̓̎ͨ͒͊̚͟t̶̯͙̹̟͖̂̇͒̾ͭ͒͐͛̌t̶̯͙̹̟͖̂̇͒̾ͭ͒͐͛̌ḧ̠̬́͋̕͏̧̙̼͑͂̀̌̉̈ḧ̠̬́͋̕͏̧̙̼͑͂̀̌̉̈e̫̺͔̗̳͋̒͌ͤͬ̔͗̕̕͡e̫̺͔̗̳͋̒͌ͤͬ̔͗̕̕͡r̴̛̭͙͑́ͤ̓̒͊̈ͥ̑ͮ͞r̴̛̭͙͑́ͤ̓̒͊̈ͥ̑ͮ͞ȇ̷̛̝͓̜̮̩͙ͨ̎̎͛̌̽ȇ̷̛̝͓̜̮̩͙ͨ̎̎͛̌̽ ̸̩̤̘̖̳̻̋̈͛͑̈́̌̒͝ ̸̩̤̘̖̳̻̋̈͛͑̈́̌̒͝i̧͖͕̞̩̱̭̎̽̀͏̮ͬͨ͡i̧͖͕̞̩̱̭̎̽̀͏̮ͬͨ͡ś̶͍̞̉ͯ̊ͦͧ̀̆̌͂͞͝ś̶͍̞̉ͯ̊ͦͧ̀̆̌͂͞͝ ̡̛͙͈̜̗̻̮̞͍̝̝̓̅͋ ̡̛͙͈̜̗̻̮̞͍̝̝̓̅͋ȃ̢͍̟̬̳ͣ͏̝̔͑̎ͣ̕ͅȃ̢͍̟̬̳ͣ͏̝̔͑̎ͣ̕ͅ ̖̼͙̯͎̒͒ͩͣ̀̆͗̇͝ͅ ̖̼͙̯͎̒͒ͩͣ̀̆͗̇͝ͅ}| + {100: }{101:ļ̩̪͕͓͖͌̐͛̊ͫͪ̿͊ͤļ̩̪͕͓͖͌̐͛̊ͫͪ̿͊ͤȍ͍̜͓̣͈͍̳̄͊̄ͣ͢͝ͅȍ͍̜͓̣͈͍̳̄͊̄ͣ͢͝ͅt̵̷̛̤͎͕̖̹ͦ̇͒́͂ͮ͘t̵̷̛̤͎͕̖̹ͦ̇͒́͂ͮ͘ ̶̨̳̺̖̼̯͎̯̬̀̈̐ͦ͜ ̶̨̳̺̖̼̯͎̯̬̀̈̐ͦ͜o̷̡̯̼͇̻͙̙̙͒͂ͩ̉̀ͮo̷̡̯̼͇̻͙̙̙͒͂ͩ̉̀ͮf̻̺̖͉̊ͤ̇ͤ̍͌͛̐͟͟͝f̻̺̖͉̊ͤ̇ͤ̍͌͛̐͟͟͝ ̷̴̟̠̹͎̱̈́̈́̆̈́̇̃͘͞ ̷̴̟̠̹͎̱̈́̈́̆̈́̇̃͘͞p̸̸̧̨̦̪͕̮̀͒͒͌͌̑͢p̸̸̧̨̦̪͕̮̀͒͒͌͌̑͢a̯͙ͥͬ̊̓ͯ͌ͮ͊̎̂͒͢͠a̯͙ͥͬ̊̓ͯ͌ͮ͊̎̂͒͢͠ċ̛̫̱̥͕̳̲ͫͤ̎͐̄̕͠ċ̛̫̱̥͕̳̲ͫͤ̎͐̄̕͠k̵̡̹̲͓̾̉͏̶̻́ͩ̎̓̊k̵̡̹̲͓̾̉͏̶̻́ͩ̎̓̊e̵̡̢̢̪͍̲̣͒̒̍ͯͤ͊͑e̵̡̢̢̪͍̲̣͒̒̍ͯͤ͊͑ḑ̘͖̼̌ͭ̐͑ͯ͋ͬ̈́͆̓̚ḑ̘͖̼̌ͭ̐͑ͯ͋ͬ̈́͆̓̚ ̶̶̧̺̰͖̯͇̏̄̿ͤ̔͘͡ ̶̶̧̺̰͖̯͇̏̄̿ͤ̔͘͡c̩̝̯͂͆ͤ̈́͆̏̑̄ͦ͗̿͞c̩̝̯͂͆ͤ̈́͆̏̑̄ͦ͗̿͞e̥̫͌̓̚͏̵̧͙̣̻̞́̌̉e̥̫͌̓̚͏̵̧͙̣̻̞́̌̉l̵̪̣̪̘̙̟̘͊͒̿̏͗͝͠l̵̪̣̪̘̙̟̘͊͒̿̏͗͝͠l̨̮͚̟̺̹ͮ͊ͭ̊ͮ̿͘͘͟l̨̮͚̟̺̹ͮ͊ͭ̊ͮ̿͘͘͟s̩̯͌̊͒͝͏̥͑̈̎ͥ̀͟͞s̩̯͌̊͒͝͏̥͑̈̎ͥ̀͟͞,̡̙̻̭̪̭̖̀̇̒ͮ̈̒̇̕,̡̙̻̭̪̭̖̀̇̒ͮ̈̒̇̕ ̷̢̫̳̺͉̯̳̂̓ͨ͋͛͂͞ ̷̢̫̳̺͉̯̳̂̓ͨ͋͛͂͞p̟̰͖̹̦̲͙̉̑͐͑͗̀͟͢p̟̰͖̹̦̲͙̉̑͐͑͗̀͟͢á̳̜̈̓͛͠͏̢̄ͧ̉ͧͨͅá̳̜̈̓͛͠͏̢̄ͧ̉ͧͨͅs̵̢̥̖̰̥̼̯ͪͭ̿͗͌ͪ͊s̵̢̥̖̰̥̼̯ͪͭ̿͗͌ͪ͊s̘̱͕̓̅͛̆̅ͮ́̅ͧͣ̈̚s̘̱͕̓̅͛̆̅ͮ́̅ͧͣ̈̚ ̡̮̹̹̗͎̝ͣ̇́ͤ̾ͤ͞ͅ ̡̮̹̹̗͎̝ͣ̇́ͤ̾ͤ͞ͅt̡̛̝̯̱̖̠̱ͤ͒͆̍̚͘ͅt̡̛̝̯̱̖̠̱ͤ͒͆̍̚͘ͅh̛̯̻̩̘̤̳̿̓͂̐͐͡͡͠h̛̯̻̩̘̤̳̿̓͂̐͐͡͡͠ë́͏̩̣̗̺̟ͭ̃̾͂̀͘͢͝ë́͏̩̣̗̺̟ͭ̃̾͂̀͘͢͝m̸̜͔̮̥̹̲̖̲̄̈̊̎ͬ͠m̸̜͔̮̥̹̲̖̲̄̈̊̎ͬ͠ ̝͇̏͏̡̟̥͍ͦ̋̎ͤ̕͢͜ ̝͇̏͏̡̟̥͍ͦ̋̎ͤ̕͢͜ó͖̬̩̤̜̫͔͑̌ͫ̈́͡͏̇ó͖̬̩̤̜̫͔͑̌ͫ̈́͡͏̇f̴̶̴̥͔̗͖̬̆͒ͨ͊ͬͅͅf̴̶̴̥͔̗͖̬̆͒ͨ͊ͬͅͅ ̮̦̲̼̞̑ͨ͒̌ͤ̿́̌͐͒ ̮̦̲̼̞̑ͨ͒̌ͤ̿́̌͐͒t̛̮̰͔̋͂͗̓͋̇̅̆̒͊ͅt̛̮̰͔̋͂͗̓͋̇̅̆̒͊ͅo̴̢͚̮̳͙̟̳̐ͬ͑̃̓͡ͅo̴̢͚̮̳͙̟̳̐ͬ͑̃̓͡ͅ ̝̺͖͒ͯͭ̑ͤ͊ͮ͂̚̚͡ͅ ̝̺͖͒ͯͭ̑ͤ͊ͮ͂̚̚͡ͅt̶̨̲̦͉͖̲̤̗ͬ̋̋ͦ̂ͯt̶̨̲̦͉͖̲̤̗ͬ̋̋ͦ̂ͯh̶̨̤͍̜̯͈͇͛ͩ́̀͊ͮͩh̶̨̤͍̜̯͈͇͛ͩ́̀͊ͮͩe̡̢̤̰̰͙̭͈̓ͯͬ͑ͨ̃͢e̡̢̤̰̰͙̭͈̓ͯͬ͑ͨ̃͢ ̶̛̺̦̯̹̞͎̟̥̞̝̐̕ͅ ̶̛̺̦̯̹̞͎̟̥̞̝̐̕ͅU͙̓ͤ͏̟̗̟͕̥̰́͑̆ͧ͟U͙̓ͤ͏̟̗̟͕̥̰́͑̆ͧ͟I̪̩͕͕̼̎͐ͭͦ͐̋̐̅ͯ͢I̪̩͕͕̼̎͐ͭͦ͐̋̐̅ͯ͢ ̢̦͍̰̬͚ͯ́ͫ̿ͨ͘͘͝͡ ̢̦͍̰̬͚ͯ́ͫ̿ͨ͘͘͝͡t̴̨͉̟̥͛͐̇̀̎̒̄ͧ̀̇t̴̨͉̟̥͛͐̇̀̎̒̄ͧ̀̇o̸͇͏̷͍͉̠ͤ̈̾ͤ͛ͥ̚͝o̸͇͏̷͍͉̠ͤ̈̾ͤ͛ͥ̚͝ ̸̣͕̝̯̼́ͨͯ̏̋̂̑́͘ ̸̣͕̝̯̼́ͨͯ̏̋̂̑́͘l̵̨̛̬̱̣̬͚̺̫̳ͨ̽ͫͯl̵̨̛̬̱̣̬͚̺̫̳ͨ̽ͫͯḙ̳͕̝̥̄̆ͮ̄ͦͨ̓̚͏͢ḙ̳͕̝̥̄̆ͮ̄ͦͨ̓̚͏͢t̵̼̲̣̉̀̌ͭ̒̓͌̀͒̀ͅt̵̼̲̣̉̀̌ͭ̒̓͌̀͒̀ͅ ̺͈͙̘̣̩̙͕̋̇͆̀͊̇̂ ̺͈͙̘̣̩̙͕̋̇͆̀͊̇̂i̧̭̲̼̗̥̪̣̭ͬ͑ͨ̓̈̐i̧̭̲̼̗̥̪̣̭ͬ͑ͨ̓̈̐ṱ̴̯̲̱̫̲̥ͭ̀͋̂̚̕͟ṱ̴̯̲̱̫̲̥ͭ̀͋̂̚̕͟ ̖̗͔̦̲̻̌̀̏͆͊ͤ̑ͨ̉ ̖̗͔̦̲̻̌̀̏͆͊ͤ̑ͨ̉s̨̢͔̄̃ͯ̈́̑͐̚̕͢͝͝s̨̢͔̄̃ͯ̈́̑͐̚̕͢͝͝t͚͉͇̳̘̅̇̋͌̀̋́ͨ́͏t͚͉͇̳̘̅̇̋͌̀̋́ͨ́͏â͇͎̺ͨͭ͡͏͚̯ͤͩ͋ͧ͘â͇͎̺ͨͭ͡͏͚̯ͤͩ͋ͧ͘r̷̘̜͍̫̯ͭͪ͑͗̓͆͟͝ͅr̷̘̜͍̫̯ͭͪ͑͗̓͆͟͝ͅṭ̷̢̱͕̎ͬ̿́́͊̐͟͢͜ṭ̷̢̱͕̎ͬ̿́́͊̐͟͢͜ ̟̥̖͕̭͍̲ͩ̆̒̑͊̕̚͡ ̟̥̖͕̭͍̲ͩ̆̒̑͊̕̚͡p̶̴̨̧̜̰̜̘̉̽ͤ́͘͢͜p̶̴̨̧̜̰̜̘̉̽ͤ́͘͢͜ṙ̠̘̟̭͖̜̜͍ͦ̾͒͜͠͞ṙ̠̘̟̭͖̜̜͍ͦ̾͒͜͠͞ǒ̷̶̫͈̫̹ͬ͂ͧ̿̿̑͂͂ǒ̷̶̫͈̫̹ͬ͂ͧ̿̿̑͂͂c̵̸̮͕̮͈̞̼͎͉͍̑́ͭ̀c̵̸̮͕̮͈̞̼͎͉͍̑́ͭ̀e̸̡͔͓̳̞̟̘ͩ̍̽ͪͤͣ͢e̸̡͔͓̳̞̟̘ͩ̍̽ͪͤͣ͢s̨͍̬̖͂̏ͦ̀ͫ̐ͨͪ͡ͅͅs̨͍̬̖͂̏ͦ̀ͫ̐ͨͪ͡ͅͅs̡̻̹̜͍̺͌͛ͮ̓̀̈́̉̿͑s̡̻̹̜͍̺͌͛ͮ̓̀̈́̉̿͑í̤̜ͭ͢͏̶̶̹͍ͤͪ̉ͫ̋í̤̜ͭ͢͏̶̶̹͍ͤͪ̉ͫ̋ņ̵̼̪̭̲̤͙͖̒̑ͨ͂̌͘ņ̵̼̪̭̲̤͙͖̒̑ͨ͂̌͘g̷̢̢̭̘̙̥̖̲̭͛ͣ́̀̍g̷̢̢̭̘̙̥̖̲̭͛ͣ́̀̍ ̷̺̱̙̹͔̗͆ͪ̾ͬͬ̓͘͠ ̷̺̱̙̹͔̗͆ͪ̾ͬͬ̓͘͠t̛̤̻̲̓̓ͩ̇ͫͫ͆ͦ͛̕͞t̛̤̻̲̓̓ͩ̇ͫͫ͆ͦ͛̕͞ḣ̜̘̮̫͍̗͇ͥͯ̽̕͢͢͝ḣ̜̘̮̫͍̗͇ͥͯ̽̕͢͢͝ẹ̵̱̹͚͖̜̞̆̾͌ͬ̀̿͞ẹ̵̱̹͚͖̜̞̆̾͌ͬ̀̿͞m̶̢̧͉̝̜̝̍͑͂̽̌̉̈́ͩm̶̢̧͉̝̜̝̍͑͂̽̌̉̈́ͩ }| + {100:~ }|*6 + | + ]], + }) + end) + it('works with arabic input and arabicshape', function() command('set arabic') @@ -285,11 +304,6 @@ describe('multibyte rendering: statusline', function() before_each(function() clear() screen = Screen.new(40, 4) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { bold = true, reverse = true }, - [3] = { background = Screen.colors.Red, foreground = Screen.colors.Gray100 }, - }) screen:attach() command('set laststatus=2') end) @@ -299,7 +313,7 @@ describe('multibyte rendering: statusline', function() screen:expect([[ ^ | {1:~ }| - {2:你好 }| + {3:你好 }| | ]]) end) @@ -308,7 +322,7 @@ describe('multibyte rendering: statusline', function() screen:expect([[ ^ | {1:~ }| - {2:abc }| + {3:abc }| | ]]) end) @@ -317,7 +331,7 @@ describe('multibyte rendering: statusline', function() screen:expect([[ ^ | {1:~ }| - {2:<9f> }| + {3:<9f> }| | ]]) end) @@ -327,7 +341,7 @@ describe('multibyte rendering: statusline', function() screen:expect([[ ^ | {1:~ }| - {2:o̸⃯ᷰ⃐⃧⃝ }| + {3:o̸⃯ᷰ⃐⃧⃝ }| | ]]) end) @@ -337,7 +351,7 @@ describe('multibyte rendering: statusline', function() screen:expect([[ ^ | {1:~ }| - {2:<9f><1df0><20ef><0338><20d0><20e7><20dd>}| + {3:<9f><1df0><20ef><0338><20d0><20e7><20dd>}| | ]]) end) @@ -348,7 +362,7 @@ describe('multibyte rendering: statusline', function() grid = [[ ^ | {1:~ }| - {2: Q≡ }| + {3: Q≡ }| | ]], } @@ -361,7 +375,7 @@ describe('multibyte rendering: statusline', function() grid = [[ ^ | {1:~ }| - {2:🧑�💻 }| + {3:🧑�💻 }| | ]], } @@ -375,7 +389,7 @@ describe('multibyte rendering: statusline', function() grid = [[ ^ | {1:~ }| - {2:xx}{3:🧑<200d>💻}{2:yy }| + {3:xx}{9:🧑<200d>💻}{3:yy }| | ]], } diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index c1d3af085f..dc48061a6c 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local feed, command, insert = helpers.feed, helpers.command, helpers.insert -local eq = helpers.eq -local fn = helpers.fn -local api = helpers.api -local curwin = helpers.api.nvim_get_current_win -local poke_eventloop = helpers.poke_eventloop + +local clear = n.clear +local feed, command, insert = n.feed, n.command, n.insert +local eq = t.eq +local fn = n.fn +local api = n.api +local curwin = n.api.nvim_get_current_win +local poke_eventloop = n.poke_eventloop describe('ext_multigrid', function() @@ -412,9 +414,23 @@ describe('ext_multigrid', function() end) describe('grid of smaller inner size', function() + before_each(function() + screen:try_resize_grid(2, 20, 5) + end) + it('is rendered correctly', function() + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + ^ | + {1:~ }|*4 + ## grid 3 + | + ]]} screen:try_resize_grid(2, 8, 5) - screen:expect{grid=[[ ## grid 1 [2:-----------------------------------------------------]|*12 @@ -427,12 +443,43 @@ describe('ext_multigrid', function() | ]]} end) + + it("cursor draws correctly with double-width char and 'showbreak'", function() + insert(('a'):rep(19) .. '哦bbbb') + command('setlocal showbreak=++') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + aaaaaaaaaaaaaaaaaaa{1:>}| + {1:++}哦bbb^b | + {1:~ }|*3 + ## grid 3 + | + ]]} + end) end) describe('grid of bigger inner size', function() + before_each(function() + screen:try_resize_grid(2, 60, 20) + end) + it('is rendered correctly', function() + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + ^ | + {1:~ }|*19 + ## grid 3 + | + ]]} screen:try_resize_grid(2, 80, 20) - screen:expect{grid=[[ ## grid 1 [2:-----------------------------------------------------]|*12 @@ -445,13 +492,6 @@ describe('ext_multigrid', function() | ]]} end) - end) - - - describe('with resized grid', function() - before_each(function() - screen:try_resize_grid(2, 60, 20) - end) it('winwidth() winheight() getwininfo() return inner width and height #19743', function() eq(60, fn.winwidth(0)) @@ -483,7 +523,7 @@ describe('ext_multigrid', function() ]]} end) - it('"g$" works correctly with double-width characters and no wrapping', function() + it('g$ works correctly with double-width chars and no wrapping', function() command('set nowrap') insert(('a'):rep(58) .. ('哦'):rep(3)) feed('0') @@ -543,6 +583,22 @@ describe('ext_multigrid', function() ## grid 3 | ]]} + command('setlocal breakindent breakindentopt=shift:8') + feed('g$') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| + {23:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b}| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + | + {1:~ }|*16 + ## grid 3 + | + ]]} end) it('displays messages with default grid width', function() @@ -685,6 +741,75 @@ describe('ext_multigrid', function() [4] = {-1, "SW", 1, 13, 5, false, 250}; }} end) + + it('half-page scrolling stops at end of buffer', function() + command('set number') + insert(('foobar\n'):rep(100)) + feed('7<C-Y>') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 75 }foobar | + {19: 76 }foobar | + {19: 77 }foobar | + {19: 78 }foobar | + {19: 79 }foobar | + {19: 80 }foobar | + {19: 81 }foobar | + {19: 82 }foobar | + {19: 83 }foobar | + {19: 84 }foobar | + {19: 85 }foobar | + {19: 86 }foobar | + {19: 87 }foobar | + {19: 88 }foobar | + {19: 89 }foobar | + {19: 90 }foobar | + {19: 91 }foobar | + {19: 92 }foobar | + {19: 93 }foobar | + {19: 94 }^foobar | + ## grid 3 + | + ]], + }) + feed('<C-D>') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 82 }foobar | + {19: 83 }foobar | + {19: 84 }foobar | + {19: 85 }foobar | + {19: 86 }foobar | + {19: 87 }foobar | + {19: 88 }foobar | + {19: 89 }foobar | + {19: 90 }foobar | + {19: 91 }foobar | + {19: 92 }foobar | + {19: 93 }foobar | + {19: 94 }foobar | + {19: 95 }foobar | + {19: 96 }foobar | + {19: 97 }foobar | + {19: 98 }foobar | + {19: 99 }foobar | + {19:100 }foobar | + {19:101 }^ | + ## grid 3 + | + ]], + }) + end) end) it('multiline messages scroll over windows', function() @@ -2300,6 +2425,9 @@ describe('ext_multigrid', function() ]], win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 0, bottom = 0, left = 0, right = 0}; }} -- XXX: hack to get notifications. Could use next_msg() also. @@ -2330,6 +2458,9 @@ describe('ext_multigrid', function() ]], win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 1, bottom = 0, left = 0, right = 0}; }} eq({}, win_pos) @@ -2352,6 +2483,9 @@ describe('ext_multigrid', function() ]], win_viewport={ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = {win = 1000, top = 0, bottom = 0, left = 0, right = 0}; + [4] = {win = 1001, top = 0, bottom = 0, left = 0, right = 0}; }} eq({}, win_pos) end) diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 98af82a7c5..b40ff29dec 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local shallowcopy = helpers.shallowcopy -local eval = helpers.eval + +local clear = n.clear +local command = n.command +local eq = t.eq +local shallowcopy = t.shallowcopy +local eval = n.eval describe('UI receives option updates', function() local screen diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 5e340af89c..4f6454a0fb 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -1,19 +1,21 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers')(after_each) -local child_session = require('test.functional.terminal.helpers') -local assert_alive = helpers.assert_alive -local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir -local eq = helpers.eq -local feed = helpers.feed -local feed_command = helpers.feed_command -local clear = helpers.clear -local command = helpers.command -local testprg = helpers.testprg -local nvim_dir = helpers.nvim_dir -local has_powershell = helpers.has_powershell -local set_shell_powershell = helpers.set_shell_powershell -local skip = helpers.skip -local is_os = helpers.is_os +local tt = require('test.functional.terminal.testutil') + +local assert_alive = n.assert_alive +local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir +local eq = t.eq +local feed = n.feed +local feed_command = n.feed_command +local clear = n.clear +local command = n.command +local testprg = n.testprg +local nvim_dir = n.nvim_dir +local has_powershell = n.has_powershell +local set_shell_powershell = n.set_shell_powershell +local skip = t.skip +local is_os = t.is_os clear() -- for has_powershell() @@ -21,7 +23,7 @@ describe('shell command :!', function() local screen before_each(function() clear() - screen = child_session.setup_child_nvim({ + screen = tt.setup_child_nvim({ '-u', 'NONE', '-i', @@ -29,7 +31,7 @@ describe('shell command :!', function() '--cmd', 'colorscheme vim', '--cmd', - helpers.nvim_set .. ' notermguicolors', + n.nvim_set .. ' notermguicolors', }) screen:expect([[ {1: } | @@ -40,14 +42,14 @@ describe('shell command :!', function() end) after_each(function() - child_session.feed_data('\3') -- Ctrl-C + tt.feed_data('\3') -- Ctrl-C end) it('displays output without LF/EOF. #4646 #4569 #3772', function() skip(is_os('win')) -- NOTE: We use a child nvim (within a :term buffer) -- to avoid triggering a UI flush. - child_session.feed_data(':!printf foo; sleep 200\n') + tt.feed_data(':!printf foo; sleep 200\n') screen:expect([[ | {4:~ }|*2 @@ -61,7 +63,7 @@ describe('shell command :!', function() it('throttles shell-command output greater than ~10KB', function() skip(is_os('openbsd'), 'FIXME #10804') skip(is_os('win')) - child_session.feed_data((':!%s REP 30001 foo\n'):format(testprg('shell-test'))) + tt.feed_data((':!%s REP 30001 foo\n'):format(testprg('shell-test'))) -- If we observe any line starting with a dot, then throttling occurred. -- Avoid false failure on slow systems. @@ -80,7 +82,7 @@ describe('shell command :!', function() {3:-- TERMINAL --} | ]], { - -- test/functional/helpers.lua defaults to background=light. + -- test/functional/testnvim.lua defaults to background=light. [1] = { reverse = true }, [3] = { bold = true }, [10] = { foreground = 2 }, @@ -107,20 +109,15 @@ describe('shell command :!', function() it('handles control codes', function() skip(is_os('win'), 'missing printf') local screen = Screen.new(50, 4) - screen:set_default_attr_ids { - [1] = { bold = true, reverse = true }, - [2] = { bold = true, foreground = Screen.colors.SeaGreen }, - [3] = { foreground = Screen.colors.Blue }, - } screen:attach() -- Print TAB chars. #2958 feed([[:!printf '1\t2\t3'<CR>]]) screen:expect { grid = [[ - {1: }| + {3: }| :!printf '1\t2\t3' | 1 2 3 | - {2:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } feed([[<CR>]]) @@ -130,10 +127,10 @@ describe('shell command :!', function() feed([[:!printf '\007\007\007\007text'<CR>]]) screen:expect { grid = [[ - {1: }| + {3: }| :!printf '\007\007\007\007text' | text | - {2:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], condition = function() eq(true, screen.bell) @@ -144,10 +141,10 @@ describe('shell command :!', function() -- Print BS control code. feed([[:echo system('printf ''\010\n''')<CR>]]) screen:expect([[ - {1: }| - {3:^H} | + {3: }| + {18:^H} | | - {2:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed([[<CR>]]) @@ -156,7 +153,7 @@ describe('shell command :!', function() screen:expect([[ :!printf '\n' | |*2 - {2:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) feed([[<CR>]]) end) @@ -170,12 +167,6 @@ describe('shell command :!', function() write_file('bang_filter_spec/f2', 'f2') write_file('bang_filter_spec/f3', 'f3') screen = Screen.new(53, 10) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Blue1 }, - [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - [4] = { bold = true, reverse = true }, - }) screen:attach() end) @@ -195,13 +186,13 @@ describe('shell command :!', function() screen:expect([[ | {1:~ }|*2 - {4: }| + {3: }| ]] .. result .. [[ | f1 | f2 | f3 | | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) end) @@ -212,14 +203,14 @@ describe('shell command :!', function() grid = [[ | {1:~ }| - {4: }| + {3: }| :!cat test/functional/fixtures/shell_data.txt | - {2:^@^A^B^C^D^E^F^H} | - {2:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} | - ö 한글 {2:<a5><c3>} | - t {2:<ff>} | + {18:^@^A^B^C^D^E^F^H} | + {18:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} | + ö 한글 {18:<a5><c3>} | + t {18:<ff>} | | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], condition = function() eq(true, screen.bell) @@ -234,7 +225,7 @@ describe('shell command :!', function() -- Note: only the first example of split composed char works screen:expect([[ | - {4: }| + {3: }| :]] .. cmd .. [[ | å | ref: å̲ | @@ -242,7 +233,7 @@ describe('shell command :!', function() 2: å ̲ | 3: å ̲ | | - {3:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]]) end) end) @@ -256,28 +247,28 @@ describe('shell command :!', function() :!'Write-Output $a' | Write-Output $a | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) feed_command([[!$a = 1; Write-Output '$a']]) screen:expect([[ :!$a = 1; Write-Output '$a' | $a | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) feed_command([[!"Write-Output $a"]]) screen:expect([[ :!"Write-Output $a" | Write-Output | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) feed_command([[!$a = 1; Write-Output "$a"]]) screen:expect([[ :!$a = 1; Write-Output "$a" | 1 | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) if is_os('win') then feed_command([[!& 'cmd.exe' /c 'echo $a']]) @@ -285,7 +276,7 @@ describe('shell command :!', function() :!& 'cmd.exe' /c 'echo $a' | $a | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) else feed_command([[!& '/bin/sh' -c 'echo ''$a''']]) @@ -293,7 +284,7 @@ describe('shell command :!', function() :!& '/bin/sh' -c 'echo ''$a''' | $a | | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) end end) diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 1f0d20f66d..8f8604eecb 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -1,17 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local clear, feed = helpers.clear, helpers.feed -local source = helpers.source -local insert = helpers.insert -local api = helpers.api -local async_meths = helpers.async_meths -local command = helpers.command -local fn = helpers.fn -local eq = helpers.eq -local pcall_err = helpers.pcall_err -local exec_lua = helpers.exec_lua -local exec = helpers.exec + +local assert_alive = n.assert_alive +local clear, feed = n.clear, n.feed +local source = n.source +local insert = n.insert +local api = n.api +local async_meths = n.async_meths +local command = n.command +local fn = n.fn +local eq = t.eq +local pcall_err = t.pcall_err +local exec_lua = n.exec_lua +local exec = n.exec describe('ui/ext_popupmenu', function() local screen @@ -1171,6 +1173,10 @@ describe('builtin popupmenu', function() [6] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, [7] = { background = Screen.colors.Yellow }, -- Search [8] = { foreground = Screen.colors.Red }, + kn = { foreground = Screen.colors.Red, background = Screen.colors.Magenta }, + ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey }, + xn = { foreground = Screen.colors.White, background = Screen.colors.Magenta }, + xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey }, }) screen:attach({ ext_multigrid = multigrid }) end) @@ -1588,13 +1594,13 @@ describe('builtin popupmenu', function() describe('floating window preview #popup', function() it('pum popup preview', function() --row must > 10 - screen:try_resize(30, 11) + screen:try_resize(40, 11) exec([[ funct Omni_test(findstart, base) if a:findstart return col(".") - 1 endif - return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three"}] + return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "looooooooooooooong"}] endfunc set omnifunc=Omni_test set completeopt=menu,popup @@ -1602,94 +1608,185 @@ describe('builtin popupmenu', function() funct Set_info() let comp_info = complete_info() if comp_info['selected'] == 2 - call nvim_complete_set(comp_info['selected'], {"info": "3info"}) + call nvim__complete_set(comp_info['selected'], {"info": "3info"}) endif endfunc autocmd CompleteChanged * call Set_info() ]]) feed('Gi<C-x><C-o>') - --floating preview in right if multigrid then screen:expect { grid = [[ ## grid 1 - [2:------------------------------]|*10 - [3:------------------------------]| + [2:----------------------------------------]|*10 + [3:----------------------------------------]| ## grid 2 - one^ | - {1:~ }|*9 + one^ | + {1:~ }|*9 ## grid 3 - {2:-- }{5:match 1 of 3} | + {2:-- }{5:match 1 of 3} | ## grid 4 {n:1info}| {n: }| ## grid 5 - {s:one }| - {n:two }| - {n:three }| + {s:one }| + {n:two }| + {n:looooooooooooooong }| ]], float_pos = { [5] = { -1, 'NW', 2, 1, 0, false, 100 }, - [4] = { 1001, 'NW', 1, 1, 15, true, 50 }, + [4] = { 1001, 'NW', 1, 1, 19, false, 50 }, + }, + win_viewport = { + [2] = { + win = 1000, + topline = 0, + botline = 2, + curline = 0, + curcol = 3, + linecount = 1, + sum_scroll_delta = 0, + }, + [4] = { + win = 1001, + topline = 0, + botline = 2, + curline = 0, + curcol = 0, + linecount = 1, + sum_scroll_delta = 0, + }, }, } else screen:expect { grid = [[ - one^ | - {s:one }{n:1info}{1: }| - {n:two }{1: }| - {n:three }{1: }| - {1:~ }|*6 - {2:-- }{5:match 1 of 3} | + one^ | + {s:one }{n:1info}{1: }| + {n:two }{1: }| + {n:looooooooooooooong }{1: }| + {1:~ }|*6 + {2:-- }{5:match 1 of 3} | ]], - unchanged = true, } end - -- test nvim_complete_set_info - feed('<C-N><C-N>') - vim.uv.sleep(10) + -- info window position should be adjusted when new leader add + feed('<C-P>o') if multigrid then screen:expect { grid = [[ ## grid 1 - [2:------------------------------]|*10 - [3:------------------------------]| + [2:----------------------------------------]|*10 + [3:----------------------------------------]| ## grid 2 - three^ | - {1:~ }|*9 + o^ | + {1:~ }|*9 ## grid 3 - {2:-- }{5:match 3 of 3} | + {2:-- }{8:Back at original} | ## grid 4 - {n:3info}| + {n:1info}| {n: }| ## grid 5 {n:one }| - {n:two }| - {s:three }| ]], float_pos = { [5] = { -1, 'NW', 2, 1, 0, false, 100 }, - [4] = { 1001, 'NW', 1, 1, 15, true, 50 }, + [4] = { 1001, 'NW', 1, 1, 15, false, 50 }, + }, + win_viewport = { + [2] = { + win = 1000, + topline = 0, + botline = 2, + curline = 0, + curcol = 1, + linecount = 1, + sum_scroll_delta = 0, + }, + [4] = { + win = 1001, + topline = 0, + botline = 2, + curline = 0, + curcol = 0, + linecount = 1, + sum_scroll_delta = 0, + }, }, } else screen:expect { grid = [[ - three^ | - {n:one 3info}{1: }| - {n:two }{1: }| - {s:three }{1: }| - {1:~ }|*6 - {2:-- }{5:match 3 of 3} | + o^ | + {n:one 1info}{1: }| + {1:~ }{n: }{1: }| + {1:~ }|*7 + {2:-- }{8:Back at original} | + ]], + } + end + + -- test nvim__complete_set_info + feed('<ESC>cc<C-X><C-O><C-N><C-N>') + vim.uv.sleep(10) + if multigrid then + screen:expect { + grid = [[ + ## grid 1 + [2:----------------------------------------]|*10 + [3:----------------------------------------]| + ## grid 2 + looooooooooooooong^ | + {1:~ }|*9 + ## grid 3 + {2:-- }{5:match 3 of 3} | + ## grid 5 + {n:one }| + {n:two }| + {s:looooooooooooooong }| + ## grid 6 + {n:3info}| + {n: }| + ]], + float_pos = { + [5] = { -1, 'NW', 2, 1, 0, false, 100 }, + [6] = { 1002, 'NW', 1, 1, 19, false, 50 }, + }, + win_viewport = { + [2] = { + win = 1000, + topline = 0, + botline = 2, + curline = 0, + curcol = 18, + linecount = 1, + sum_scroll_delta = 0, + }, + [6] = { + win = 1002, + topline = 0, + botline = 2, + curline = 0, + curcol = 0, + linecount = 1, + sum_scroll_delta = 0, + }, + }, + } + else + screen:expect { + grid = [[ + looooooooooooooong^ | + {n:one 3info}{1: }| + {n:two }{1: }| + {s:looooooooooooooong }{1: }| + {1:~ }|*6 + {2:-- }{5:match 3 of 3} | ]], } end - -- make sure info has set - feed('<C-y>') - eq('3info', exec_lua('return vim.v.completed_item.info')) -- preview in left feed('<ESC>cc') @@ -1699,24 +1796,24 @@ describe('builtin popupmenu', function() screen:expect { grid = [[ ## grid 1 - [2:------------------------------]|*10 - [3:------------------------------]| + [2:----------------------------------------]|*10 + [3:----------------------------------------]| ## grid 2 - itesttesttesttesttesone^t | - {1:~ }|*9 + itesttesttesttesttesone^t | + {1:~ }|*9 ## grid 3 - {2:-- }{5:match 1 of 3} | + {2:-- }{5:match 1 of 3} | ## grid 5 - {s: one }| - {n: two }| - {n: three }| - ## grid 6 + {s: one }| + {n: two }| + {n: looooooooooooooong }| + ## grid 7 {n:1info}| {n: }| ]], float_pos = { + [7] = { 1003, 'NW', 1, 1, 14, false, 50 }, [5] = { -1, 'NW', 2, 1, 19, false, 100 }, - [6] = { 1002, 'NW', 1, 1, 1, true, 50 }, }, win_viewport = { [2] = { @@ -1728,8 +1825,8 @@ describe('builtin popupmenu', function() linecount = 1, sum_scroll_delta = 0, }, - [6] = { - win = 1002, + [7] = { + win = 1003, topline = 0, botline = 2, curline = 0, @@ -1742,12 +1839,12 @@ describe('builtin popupmenu', function() else screen:expect { grid = [[ - itesttesttesttesttesone^t | - {1:~}{n:1info}{1: }{s: one }{1: }| - {1:~}{n: }{1: }{n: two }{1: }| - {1:~ }{n: three }{1: }| - {1:~ }|*6 - {2:-- }{5:match 1 of 3} | + itesttesttesttesttesone^t | + {1:~ }{n:1info}{s: one }{1: }| + {1:~ }{n: two }{1: }| + {1:~ }{n: looooooooooooooong }{1: }| + {1:~ }|*6 + {2:-- }{5:match 1 of 3} | ]], } end @@ -2942,7 +3039,7 @@ describe('builtin popupmenu', function() | {3:[No Name] }| {1::}sign define | - {1::}sign defin^e | + {1::}sign define^ | {1:~ }|*4 {4:[Command Line] }| :sign define | @@ -4477,23 +4574,15 @@ describe('builtin popupmenu', function() hi PmenuExtra guifg=White guibg=Magenta hi PmenuExtraSel guifg=Black guibg=Grey ]]) - local attrs = screen:get_default_attr_ids() - attrs.kn = { foreground = Screen.colors.Red, background = Screen.colors.Magenta } - attrs.ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey } - attrs.xn = { foreground = Screen.colors.White, background = Screen.colors.Magenta } - attrs.xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey } feed('iaw<C-X><C-u>') - screen:expect( - [[ + screen:expect([[ aword1^ | {s:aword1 }{ks:W }{xs:extra text 1 }{1: }| {n:aword2 }{kn:W }{xn:extra text 2 }{1: }| {n:aword3 }{kn:W }{xn:extra text 3 }{1: }| {1:~ }|*3 {2:-- }{5:match 1 of 3} | - ]], - attrs - ) + ]]) end) end) end diff --git a/test/functional/ui/quickfix_spec.lua b/test/functional/ui/quickfix_spec.lua index 40f8ef353a..73923a153a 100644 --- a/test/functional/ui/quickfix_spec.lua +++ b/test/functional/ui/quickfix_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, api = helpers.clear, helpers.feed, helpers.api -local insert, command = helpers.insert, helpers.command + +local clear, feed, api = n.clear, n.feed, n.api +local insert, command = n.insert, n.command describe('quickfix selection highlight', function() local screen diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index e8d7d5c72d..4625ce8553 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -70,17 +70,19 @@ -- To help write screen tests, see Screen:snapshot_util(). -- To debug screen tests, see Screen:redraw_debug(). -local helpers = require('test.functional.helpers')(nil) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local busted = require('busted') + local deepcopy = vim.deepcopy -local shallowcopy = helpers.shallowcopy -local concat_tables = helpers.concat_tables +local shallowcopy = t.shallowcopy +local concat_tables = t.concat_tables local pesc = vim.pesc -local run_session = helpers.run_session -local eq = helpers.eq -local dedent = helpers.dedent -local get_session = helpers.get_session -local create_callindex = helpers.create_callindex +local run_session = n.run_session +local eq = t.eq +local dedent = t.dedent +local get_session = n.get_session +local create_callindex = n.create_callindex local inspect = vim.inspect @@ -139,6 +141,43 @@ local function _init_colors() end Screen.colors = colors Screen.colornames = colornames + + Screen._global_default_attr_ids = { + [1] = { foreground = Screen.colors.Blue1, bold = true }, + [2] = { reverse = true }, + [3] = { bold = true, reverse = true }, + [4] = { background = Screen.colors.LightMagenta }, + [5] = { bold = true }, + [6] = { foreground = Screen.colors.SeaGreen, bold = true }, + [7] = { background = Screen.colors.Gray, foreground = Screen.colors.DarkBlue }, + [8] = { foreground = Screen.colors.Brown }, + [9] = { background = Screen.colors.Red, foreground = Screen.colors.Grey100 }, + [10] = { background = Screen.colors.Yellow }, + [11] = { + foreground = Screen.colors.Blue1, + background = Screen.colors.LightMagenta, + bold = true, + }, + [12] = { background = Screen.colors.Gray }, + [13] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, + [14] = { background = Screen.colors.DarkGray, foreground = Screen.colors.LightGrey }, + [15] = { foreground = Screen.colors.Brown, bold = true }, + [16] = { foreground = Screen.colors.SlateBlue }, + [17] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, + [18] = { foreground = Screen.colors.Blue1 }, + [19] = { foreground = Screen.colors.Red }, + [20] = { background = Screen.colors.Yellow, foreground = Screen.colors.Red }, + [21] = { background = Screen.colors.Grey90 }, + [22] = { background = Screen.colors.LightBlue }, + [23] = { foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan, bold = true }, + [24] = { background = Screen.colors.LightGrey, underline = true }, + [25] = { foreground = Screen.colors.Cyan4 }, + [26] = { foreground = Screen.colors.Fuchsia }, + [27] = { background = Screen.colors.Red, bold = true }, + [28] = { foreground = Screen.colors.SlateBlue, underline = true }, + [29] = { foreground = Screen.colors.SlateBlue, bold = true }, + [30] = { background = Screen.colors.Red }, + } end --- @param width? integer @@ -167,6 +206,7 @@ function Screen.new(width, height) wildmenu_selected = nil, win_position = {}, win_viewport = {}, + win_viewport_margins = {}, float_pos = {}, msg_grid = nil, msg_grid_pos = nil, @@ -217,6 +257,17 @@ function Screen:set_default_attr_ids(attr_ids) self._default_attr_ids = attr_ids end +function Screen:add_extra_attr_ids(extra_attr_ids) + local attr_ids = vim.deepcopy(Screen._global_default_attr_ids) + for id, attr in pairs(extra_attr_ids) do + if type(id) == 'number' and id < 100 then + error('extra attr ids should be at least 100 or be strings') + end + attr_ids[id] = attr + end + self._default_attr_ids = attr_ids +end + function Screen:get_default_attr_ids() return deepcopy(self._default_attr_ids) end @@ -234,7 +285,7 @@ end --- @field rgb? boolean --- @field _debug_float? boolean ---- @param options test.functional.ui.screen.Opts +--- @param options? test.functional.ui.screen.Opts --- @param session? test.Session function Screen:attach(options, session) session = session or get_session() @@ -257,6 +308,10 @@ function Screen:attach(options, session) if self._options.ext_multigrid then self._options.ext_linegrid = true end + + if self._default_attr_ids == nil then + self._default_attr_ids = Screen._global_default_attr_ids + end end function Screen:detach() @@ -296,6 +351,7 @@ local ext_keys = { 'ruler', 'float_pos', 'win_viewport', + 'win_viewport_margins', } local expect_keys = { @@ -480,7 +536,10 @@ function Screen:expect(expected, attr_ids, ...) attr_state.id_to_index = self:linegrid_check_attrs(attr_state.ids or {}) end - local actual_rows = self:render(not expected.any, attr_state) + local actual_rows + if expected.any or grid then + actual_rows = self:render(not expected.any, attr_state) + end if expected.any then -- Search for `any` anywhere in the screen lines. @@ -577,6 +636,9 @@ screen:redraw_debug() to show all intermediate screen states.]] if expected.win_viewport == nil then extstate.win_viewport = nil end + if expected.win_viewport_margins == nil then + extstate.win_viewport_margins = nil + end if expected.float_pos then expected.float_pos = deepcopy(expected.float_pos) @@ -949,6 +1011,7 @@ function Screen:_handle_grid_destroy(grid) if self._options.ext_multigrid then self.win_position[grid] = nil self.win_viewport[grid] = nil + self.win_viewport_margins[grid] = nil end end @@ -1004,6 +1067,16 @@ function Screen:_handle_win_viewport( } end +function Screen:_handle_win_viewport_margins(grid, win, top, bottom, left, right) + self.win_viewport_margins[grid] = { + win = win, + top = top, + bottom = bottom, + left = left, + right = right, + } +end + function Screen:_handle_win_float_pos(grid, ...) self.win_position[grid] = nil self.float_pos[grid] = { ... } @@ -1422,6 +1495,8 @@ function Screen:_extstate_repr(attr_state) end local win_viewport = (next(self.win_viewport) and self.win_viewport) or nil + local win_viewport_margins = (next(self.win_viewport_margins) and self.win_viewport_margins) + or nil return { popupmenu = self.popupmenu, @@ -1436,6 +1511,7 @@ function Screen:_extstate_repr(attr_state) msg_history = msg_history, float_pos = self.float_pos, win_viewport = win_viewport, + win_viewport_margins = win_viewport_margins, } end @@ -1642,23 +1718,26 @@ function Screen:_print_snapshot(attrs, ignore) if self._options.ext_linegrid then dict = self:_pprint_hlitem(a) else - dict = '{' .. self:_pprint_attrs(a) .. '}' + dict = '{ ' .. self:_pprint_attrs(a) .. ' }' end local keyval = (type(i) == 'number') and '[' .. tostring(i) .. ']' or i - table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ';') + table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ',') end - attrstr = (', attr_ids={\n' .. table.concat(attrstrs, '\n') .. '\n}') + attrstr = (',\n attr_ids = {\n ' .. table.concat(attrstrs, '\n ') .. '\n },') elseif isempty(attrs) then - attrstr = ', attr_ids={}' + attrstr = ',\n attr_ids = {},' end - local result = 'screen:expect{grid=[[\n' .. kwargs.grid .. '\n]]' .. attrstr + local result = ('screen:expect({\n grid = [[\n %s\n ]]%s'):format( + kwargs.grid:gsub('\n', '\n '), + attrstr + ) for _, k in ipairs(ext_keys) do if ext_state[k] ~= nil and not (k == 'win_viewport' and not self.options.ext_multigrid) then result = result .. ', ' .. k .. '=' .. fmt_ext_state(k, ext_state[k]) end end - result = result .. '}' + result = result .. '\n})' return result end @@ -1764,20 +1843,20 @@ function Screen:_pprint_hlitem(item) -- print(inspect(item)) local multi = self._rgb_cterm or self._options.ext_hlstate local cterm = (not self._rgb_cterm and not self._options.rgb) - local attrdict = '{' .. self:_pprint_attrs(multi and item[1] or item, cterm) .. '}' + local attrdict = '{ ' .. self:_pprint_attrs(multi and item[1] or item, cterm) .. ' }' local attrdict2, hlinfo local descdict = '' if self._rgb_cterm then - attrdict2 = ', {' .. self:_pprint_attrs(item[2], true) .. '}' + attrdict2 = ', { ' .. self:_pprint_attrs(item[2], true) .. ' }' hlinfo = item[3] else attrdict2 = '' hlinfo = item[2] end if self._options.ext_hlstate then - descdict = ', {' .. self:_pprint_hlinfo(hlinfo) .. '}' + descdict = ', { ' .. self:_pprint_hlinfo(hlinfo) .. ' }' end - return (multi and '{' or '') .. attrdict .. attrdict2 .. descdict .. (multi and '}' or '') + return (multi and '{ ' or '') .. attrdict .. attrdict2 .. descdict .. (multi and ' }' or '') end function Screen:_pprint_hlinfo(states) diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 42e2b4d4b5..54580bf47c 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.clear -local feed, command = helpers.feed, helpers.command -local insert = helpers.insert -local eq = helpers.eq -local fn, api = helpers.fn, helpers.api + +local spawn, set_session, clear = n.spawn, n.set_session, n.clear +local feed, command = n.feed, n.command +local insert = n.insert +local eq = t.eq +local fn, api = n.fn, n.api describe('screen', function() local screen local nvim_argv = { - helpers.nvim_prog, + n.nvim_prog, '-u', 'NONE', '-i', @@ -27,17 +29,13 @@ describe('screen', function() set_session(screen_nvim) screen = Screen.new() screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = 255 }, - [1] = { bold = true, reverse = true }, - }) end) it('default initial screen', function() screen:expect([[ ^ | - {0:~ }|*11 - {1:[No Name] }| + {1:~ }|*11 + {3:[No Name] }| | ]]) end) @@ -704,7 +702,7 @@ describe('Screen default colors', function() local extra = (light and ' background=light') or '' local nvim_argv = { - helpers.nvim_prog, + n.nvim_prog, '-u', 'NONE', '-i', @@ -811,9 +809,6 @@ end) it("showcmd doesn't cause empty grid_line with redrawdebug=compositor #22593", function() clear() local screen = Screen.new(30, 2) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - }) screen:attach() command('set showcmd redrawdebug=compositor') feed('d') diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index a05436cf55..8bdf528412 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command = helpers.command -local feed_command = helpers.feed_command -local eq = helpers.eq -local eval = helpers.eval -local fn = helpers.fn -local testprg = helpers.testprg + +local clear, feed, insert = n.clear, n.feed, n.insert +local command = n.command +local feed_command = n.feed_command +local eq = t.eq +local eval = n.eval +local fn = n.fn +local testprg = n.testprg describe('search highlighting', function() local screen @@ -53,7 +55,7 @@ describe('search highlighting', function() topline = 0, botline = 3, curline = 0, - curcol = 8, + curcol = 9, linecount = 2, sum_scroll_delta = 0, }, @@ -674,4 +676,18 @@ describe('search highlighting', function() :%g@a/b^ | ]]) end) + + it('incsearch is still visible after :redraw from K_EVENT', function() + fn.setline(1, { 'foo', 'bar' }) + feed('/foo<CR>/bar') + screen:expect([[ + foo | + {3:bar} | + {1:~ }|*4 + /bar^ | + ]]) + command('redraw!') + -- There is an intermediate state where :redraw! removes 'incsearch' highlight. + screen:expect_unchanged(true) + end) end) diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index 847a918dc9..b353b3738a 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local api, clear, eq = helpers.api, helpers.clear, helpers.eq -local eval, exec, feed = helpers.eval, helpers.exec, helpers.feed + +local api, clear, eq = n.api, n.clear, t.eq +local eval, exec, feed = n.eval, n.exec, n.feed describe('Signs', function() local screen @@ -205,7 +207,7 @@ describe('Signs', function() screen:expect([[ {2: }{6: 1 }a | {2: }{6: 2 }b | - {1:>>}WW{6: 3 }c | + WW{1:>>}{6: 3 }c | {2: }{6: 4 }^ | {0:~ }|*9 | @@ -218,9 +220,9 @@ describe('Signs', function() sign place 3 line=2 name=pietError buffer=1 ]]) screen:expect([[ - {1:>>}{8:XX}{6: 1 }a | - {8:XX}{1:>>}{6: 2 }b | - {1:>>}WW{6: 3 }c | + {8:XX}{1:>>}{6: 1 }a | + {1:>>}{8:XX}{6: 2 }b | + WW{1:>>}{6: 3 }c | {2: }{6: 4 }^ | {0:~ }|*9 | @@ -238,9 +240,9 @@ describe('Signs', function() -- "auto:3" accommodates all the signs we defined so far. exec('set signcolumn=auto:3') local s3 = [[ - {1:>>}{8:XX}{2: }{6: 1 }a | - {8:XX}{1:>>}{2: }{6: 2 }b | - {8:XX}{1:>>}WW{6: 3 }c | + {8:XX}{1:>>}{2: }{6: 1 }a | + {1:>>}{8:XX}{2: }{6: 2 }b | + WW{1:>>}{8:XX}{6: 3 }c | {2: }{6: 4 }^ | {0:~ }|*9 | @@ -249,9 +251,9 @@ describe('Signs', function() -- Check "yes:9". exec('set signcolumn=yes:9') screen:expect([[ - {1:>>}{8:XX}{2: }{6: 1 }a | - {8:XX}{1:>>}{2: }{6: 2 }b | - {8:XX}{1:>>}WW{2: }{6: 3 }c | + {8:XX}{1:>>}{2: }{6: 1 }a | + {1:>>}{8:XX}{2: }{6: 2 }b | + WW{1:>>}{8:XX}{2: }{6: 3 }c | {2: }{6: 4 }^ | {0:~ }|*9 | @@ -264,8 +266,8 @@ describe('Signs', function() exec('3move1') exec('2d') screen:expect([[ - {1:>>}{8:XX}{6: 1 }a | - {8:XX}{1:>>}{6: 2 }^b | + {8:XX}{1:>>}{6: 1 }a | + {1:>>}{8:XX}{6: 2 }^b | {2: }{6: 3 } | {0:~ }|*10 | @@ -273,8 +275,8 @@ describe('Signs', function() -- character deletion does not delete signs. feed('x') screen:expect([[ - {1:>>}{8:XX}{6: 1 }a | - {8:XX}{1:>>}{6: 2 }^ | + {8:XX}{1:>>}{6: 1 }a | + {1:>>}{8:XX}{6: 2 }^ | {2: }{6: 3 } | {0:~ }|*10 | diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua index 8b5644ee42..da112148cd 100644 --- a/test/functional/ui/spell_spec.lua +++ b/test/functional/ui/spell_spec.lua @@ -1,13 +1,15 @@ -- Test for scenarios involving 'spell' -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local exec = helpers.exec -local feed = helpers.feed -local insert = helpers.insert -local api = helpers.api -local is_os = helpers.is_os + +local clear = n.clear +local exec = n.exec +local feed = n.feed +local insert = n.insert +local api = n.api +local is_os = t.is_os describe("'spell'", function() local screen diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index 41406a5860..faf94bccbe 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local exec = helpers.exec -local eval = helpers.eval -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local api = helpers.api -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive + +local clear = n.clear +local command = n.command +local eq = t.eq +local exec = n.exec +local eval = n.eval +local exec_lua = n.exec_lua +local feed = n.feed +local api = n.api +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive local mousemodels = { 'extend', 'popup', 'popup_setpos' } @@ -27,38 +29,38 @@ describe('statuscolumn', function() [[set stc=%{v:relnum?v:relnum:(v:lnum==5?'truncate':v:lnum)}%{!v:relnum&&v:lnum==5?invalid:''}\ ]] ) screen:expect([[ - 4 aaaaa | - 3 aaaaa | - 2 aaaaa | - 1 aaaaa | - 8 ^aaaaa | - 1 aaaaa | - 2 aaaaa | - 3 aaaaa | - 4 aaaaa | - 5 aaaaa | - 6 aaaaa | - 7 aaaaa | - 8 aaaaa | + {8:4 }aaaaa | + {8:3 }aaaaa | + {8:2 }aaaaa | + {8:1 }aaaaa | + {8:8 }^aaaaa | + {8:1 }aaaaa | + {8:2 }aaaaa | + {8:3 }aaaaa | + {8:4 }aaaaa | + {8:5 }aaaaa | + {8:6 }aaaaa | + {8:7 }aaaaa | + {8:8 }aaaaa | | ]]) command('norm 5G') eq('Vim(redraw):E121: Undefined variable: invalid', pcall_err(command, 'redraw!')) eq('', eval('&statuscolumn')) screen:expect([[ - 4 aaaaa | - 5 ^aaaaa | - 6 aaaaa | - 7 aaaaa | - 8 aaaaa | - 9 aaaaa | - 10 aaaaa | - 11 aaaaa | - 12 aaaaa | - 13 aaaaa | - 14 aaaaa | - 15 aaaaa | - 16 aaaaa | + {8: 4 }aaaaa | + {8: 5 }^aaaaa | + {8: 6 }aaaaa | + {8: 7 }aaaaa | + {8: 8 }aaaaa | + {8: 9 }aaaaa | + {8:10 }aaaaa | + {8:11 }aaaaa | + {8:12 }aaaaa | + {8:13 }aaaaa | + {8:14 }aaaaa | + {8:15 }aaaaa | + {8:16 }aaaaa | | ]]) end) @@ -72,9 +74,9 @@ describe('statuscolumn', function() norm 5G | redraw! ]=]) screen:expect([[ - 1 aaaaa virt_text | - bbbbba^eaaa | - 1 aaaaa | + {8:1 }aaaaa virt_text | + {8:bbbbb}a^eaaa | + {8:1 }aaaaa | | ]]) -- Doesn't crash when trying to fill click defs that do not fit (#26845) @@ -84,9 +86,9 @@ describe('statuscolumn', function() norm 5Gzt | redraw! ]=]) screen:expect([[ - bbbbba^eaaa | - 1 aaaaa | - 2 aaaaa | + {8:bbbbb}a^eaaa | + {8:1 }aaaaa | + {8:2 }aaaaa | | ]]) end) @@ -94,19 +96,19 @@ describe('statuscolumn', function() it("works with 'number' and 'relativenumber'", function() command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]]) screen:expect([[ - 4 │aaaaa | - 5 │aaaaa | - 6 │aaaaa | - 7 │aaaaa | - 8 │^aaaaa | - 9 │aaaaa | - 10│aaaaa | - 11│aaaaa | - 12│aaaaa | - 13│aaaaa | - 14│aaaaa | - 15│aaaaa | - 16│aaaaa | + {8:4 │}aaaaa | + {8:5 │}aaaaa | + {8:6 │}aaaaa | + {8:7 │}aaaaa | + {8:8 │}^aaaaa | + {8:9 │}aaaaa | + {8:10│}aaaaa | + {8:11│}aaaaa | + {8:12│}aaaaa | + {8:13│}aaaaa | + {8:14│}aaaaa | + {8:15│}aaaaa | + {8:16│}aaaaa | | ]]) command([[set stc=%l%=%{&rnu?'\ ':''}%r│]]) @@ -114,39 +116,19 @@ describe('statuscolumn', function() command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]]) command('set relativenumber') screen:expect([[ - 4 4│aaaaa | - 5 3│aaaaa | - 6 2│aaaaa | - 7 1│aaaaa | - 8 0│^aaaaa | - 9 1│aaaaa | - 10 2│aaaaa | - 11 3│aaaaa | - 12 4│aaaaa | - 13 5│aaaaa | - 14 6│aaaaa | - 15 7│aaaaa | - 16 8│aaaaa | - | - ]]) - command([[set stc=%l%=%{&rnu?'\ ':''}%r│]]) - screen:expect_unchanged() - command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}│]]) - command('norm 12GH') - screen:expect([[ - 4 0│^aaaaa | - 5 1│aaaaa | - 6 2│aaaaa | - 7 3│aaaaa | - 8 4│aaaaa | - 9 5│aaaaa | - 10 6│aaaaa | - 11 7│aaaaa | - 12 8│aaaaa | - 13 9│aaaaa | - 14 10│aaaaa | - 15 11│aaaaa | - 16 12│aaaaa | + {8:4 4│}aaaaa | + {8:5 3│}aaaaa | + {8:6 2│}aaaaa | + {8:7 1│}aaaaa | + {8:8 0│}^aaaaa | + {8:9 1│}aaaaa | + {8:10 2│}aaaaa | + {8:11 3│}aaaaa | + {8:12 4│}aaaaa | + {8:13 5│}aaaaa | + {8:14 6│}aaaaa | + {8:15 7│}aaaaa | + {8:16 8│}aaaaa | | ]]) command([[set stc=%l%=%{&rnu?'\ ':''}%r│]]) @@ -160,58 +142,54 @@ describe('statuscolumn', function() .. [[%=%{&rnu&&(v:lnum%2)?'\ '.v:relnum:''}]] .. [[%#LineNr#%{&rnu&&!(v:lnum%2)?'\ '.v:relnum:''}│]] ) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { foreground = Screen.colors.Brown }, - }) screen:expect([[ - {0:4 }{1:│}aaaaa | - {0:5 }{1:│}aaaaa | - {0:6 }{1:│}aaaaa | - {0:7 }{1:│}aaaaa | - {0:8 }{1:│}^aaaaa | - {0:9 }{1:│}aaaaa | - {0:10}{1:│}aaaaa | - {0:11}{1:│}aaaaa | - {0:12}{1:│}aaaaa | - {0:13}{1:│}aaaaa | - {0:14}{1:│}aaaaa | - {0:15}{1:│}aaaaa | - {0:16}{1:│}aaaaa | + {1:4 }{8:│}aaaaa | + {1:5 }{8:│}aaaaa | + {1:6 }{8:│}aaaaa | + {1:7 }{8:│}aaaaa | + {1:8 }{8:│}^aaaaa | + {1:9 }{8:│}aaaaa | + {1:10}{8:│}aaaaa | + {1:11}{8:│}aaaaa | + {1:12}{8:│}aaaaa | + {1:13}{8:│}aaaaa | + {1:14}{8:│}aaaaa | + {1:15}{8:│}aaaaa | + {1:16}{8:│}aaaaa | | ]]) command('set relativenumber') screen:expect([[ - {0:4 }{1: 4│}aaaaa | - {0:5 3}{1:│}aaaaa | - {0:6 }{1: 2│}aaaaa | - {0:7 1}{1:│}aaaaa | - {0:8 }{1: 0│}^aaaaa | - {0:9 1}{1:│}aaaaa | - {0:10}{1: 2│}aaaaa | - {0:11 3}{1:│}aaaaa | - {0:12}{1: 4│}aaaaa | - {0:13 5}{1:│}aaaaa | - {0:14}{1: 6│}aaaaa | - {0:15 7}{1:│}aaaaa | - {0:16}{1: 8│}aaaaa | + {1:4 }{8: 4│}aaaaa | + {1:5 3}{8:│}aaaaa | + {1:6 }{8: 2│}aaaaa | + {1:7 1}{8:│}aaaaa | + {1:8 }{8: 0│}^aaaaa | + {1:9 1}{8:│}aaaaa | + {1:10}{8: 2│}aaaaa | + {1:11 3}{8:│}aaaaa | + {1:12}{8: 4│}aaaaa | + {1:13 5}{8:│}aaaaa | + {1:14}{8: 6│}aaaaa | + {1:15 7}{8:│}aaaaa | + {1:16}{8: 8│}aaaaa | | ]]) command('set nonumber') screen:expect([[ - {1:4│}aaaaa | - {0:3}{1:│}aaaaa | - {1:2│}aaaaa | - {0:1}{1:│}aaaaa | - {1:0│}^aaaaa | - {0:1}{1:│}aaaaa | - {1:2│}aaaaa | - {0:3}{1:│}aaaaa | - {1:4│}aaaaa | - {0:5}{1:│}aaaaa | - {1:6│}aaaaa | - {0:7}{1:│}aaaaa | - {1:8│}aaaaa | + {8:4│}aaaaa | + {1:3}{8:│}aaaaa | + {8:2│}aaaaa | + {1:1}{8:│}aaaaa | + {8:0│}^aaaaa | + {1:1}{8:│}aaaaa | + {8:2│}aaaaa | + {1:3}{8:│}aaaaa | + {8:4│}aaaaa | + {1:5}{8:│}aaaaa | + {8:6│}aaaaa | + {1:7}{8:│}aaaaa | + {8:8│}aaaaa | | ]]) end) @@ -259,7 +237,7 @@ describe('statuscolumn', function() {2: }{1: │ }aaaaa | {0:>!}{2: }{1: 5│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │ }aaaaa | - {1:>>}{0:>!}{1: 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {0:>!}{1:>> 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │ }aaaaa | {2: }{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │ }aaaaa | @@ -278,7 +256,7 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | - {2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | @@ -295,7 +273,7 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | - {2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | @@ -313,7 +291,7 @@ describe('statuscolumn', function() {2: }{1: 4│}{2: }{1: }aaaaaa | {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 5│}{2: }{1: }aaaaaa | - {2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 6│}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│}{2: }{1: }aaaaaa | @@ -331,7 +309,7 @@ describe('statuscolumn', function() {2: }{1: 4│}{2: }{1: }aaaaaa | {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 3│}{2: }{1: }aaaaaa | - {2: }{1: 2│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 2│}{2: }{1: }aaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 1│}{2: }{1: }aaaaaa | @@ -348,7 +326,7 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | - {2: }{1: 2│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | @@ -552,15 +530,11 @@ describe('statuscolumn', function() it('does not corrupt the screen with minwid sign item', function() screen:try_resize(screen._width, 3) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Brown }, - [1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Gray }, - }) command([[set stc=%6s\ %l]]) exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "𒀀"})') screen:expect([[ - {0: 𒀀 8 }^aaaaa | - {0: }{1: }{0: 9 }aaaaa | + {8: 𒀀 8 }^aaaaa | + {8: }{7: }{8: 9 }aaaaa | | ]]) end) @@ -735,19 +709,19 @@ describe('statuscolumn', function() virt_lines_leftcol = true, virt_lines = {{{"virt", ""}}} }) ]]) screen:expect([[ - 4 aaaaa | - 5 aaaaa | - 6 aaaaa | - 7 aaaaa | + {7: }{8: 4 }aaaaa | + {7: }{8: 5 }aaaaa | + {7: }{8: 6 }aaaaa | + {7: }{8: 7 }aaaaa | virt | - --------- 8 ^aaaaa | + {7:---------}{8: 8 }^aaaaa | virt | - 𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀 9 aaaaa | - 10 aaaaa | - 11 aaaaa | - 12 aaaaa | - 13 aaaaa | - 14 aaaaa | + {7:𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀𒀀}{8: 9 }aaaaa | + {7: }{8:10 }aaaaa | + {7: }{8:11 }aaaaa | + {7: }{8:12 }aaaaa | + {7: }{8:13 }aaaaa | + {7: }{8:14 }aaaaa | | ]]) command('set stc=') -- also for the default fold column @@ -756,18 +730,18 @@ describe('statuscolumn', function() command([[set stc=%{foldlevel(v:lnum)>0?repeat('-',foldlevel(v:lnum)):''}%=%l\ ]]) feed('Gd10Ggg<C-l>') screen:expect([[ - 1 ^aaaaa | - 2 aaaaa | - 3 aaaaa | - 4 aaaaa | - 5 aaaaa | - 6 aaaaa | - 7 aaaaa | + {8: 1 }^aaaaa | + {8: 2 }aaaaa | + {8: 3 }aaaaa | + {8: 4 }aaaaa | + {8: 5 }aaaaa | + {8: 6 }aaaaa | + {8: 7 }aaaaa | virt | - ---------8 aaaaa | + {8:---------8 }aaaaa | virt | - ---------9 aaaaa | - ~ |*2 + {8:---------9 }aaaaa | + {1:~ }|*2 | ]]) end) @@ -775,15 +749,15 @@ describe('statuscolumn', function() it('works with cmdwin', function() feed(':set stc=%l<CR>q:k$') screen:expect([[ - 7 aaaaa | - 8 aaaaa | - 9 aaaaa | - 10aaaaa | - [No Name] [+] | - :1set stc=%^l | - :2 | - ~ |*5 - [Command Line] | + {8:7 }aaaaa | + {8:8 }aaaaa | + {8:9 }aaaaa | + {8:10}aaaaa | + {2:[No Name] [+] }| + {1::}{8:1}set stc=%^l | + {1::}{8:2} | + {1:~ }|*5 + {3:[Command Line] }| : | ]]) end) @@ -794,11 +768,11 @@ describe('statuscolumn', function() command('set relativenumber') command([[set stc=%{!&nu&&!&rnu?'':&rnu?v:relnum?v:relnum:&nu?v:lnum:'0':v:lnum}]]) screen:expect([[ - 1 aaaaa | - 8 ^aaaaa | - 1 aaaaa | - 2 aaaaa | - 3 aaaaa | + {8:1 }aaaaa | + {8:8 }^aaaaa | + {8:1 }aaaaa | + {8:2 }aaaaa | + {8:3 }aaaaa | | ]]) -- width correctly estimated with "w_nrwidth_line_count" when setting 'stc' @@ -815,11 +789,11 @@ describe('statuscolumn', function() -- width correctly estimated with "w_nrwidth_line_count" when setting 'nu' command('set number') screen:expect([[ - 7 aaaaa | - 8 ^aaaaa | - 9 aaaaa | - 10 aaaaa | - 11 aaaaa | + {8:7 }aaaaa | + {8:8 }^aaaaa | + {8:9 }aaaaa | + {8:10 }aaaaa | + {8:11 }aaaaa | | ]]) end) @@ -846,59 +820,59 @@ describe('statuscolumn', function() ]]) command('sign place 1 line=2 name=sign') screen:expect([[ - 1 ^aaaaa | - 2 ssaaaaa | + {8:1 }^aaaaa | + {8:2 ss}aaaaa | | ]]) command('sign place 2 line=2 name=sign') screen:expect([[ - 1 ^aaaaa | - 2 ssssaaaaa | + {8:1 }^aaaaa | + {8:2 ssss}aaaaa | | ]]) command('sign unplace 2') screen:expect([[ - 1 ^aaaaa | - 2 ssaaaaa | + {8:1 }^aaaaa | + {8:2 ss}aaaaa | | ]]) command('sign unplace 1') screen:expect([[ - 1 ^aaaaa | - 2 aaaaa | + {8:1 }^aaaaa | + {8:2 }aaaaa | | ]]) -- Also for extmark signs exec_lua('id1 = vim.api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text = "ss"})') screen:expect([[ - 1 ^aaaaa | - 2 ssaaaaa | + {8:1 }^aaaaa | + {8:2 ss}aaaaa | | ]]) exec_lua('id2 = vim.api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text = "ss"})') screen:expect([[ - 1 ^aaaaa | - 2 ssssaaaaa | + {8:1 }^aaaaa | + {8:2 ssss}aaaaa | | ]]) exec_lua('vim.api.nvim_buf_del_extmark(0, ns, id1)') screen:expect([[ - 1 ^aaaaa | - 2 ssaaaaa | + {8:1 }^aaaaa | + {8:2 ss}aaaaa | | ]]) exec_lua('vim.api.nvim_buf_del_extmark(0, ns, id2)') screen:expect([[ - 1 ^aaaaa | - 2 aaaaa | + {8:1 }^aaaaa | + {8:2 }aaaaa | | ]]) -- In all windows command('wincmd v | set ls=0') command('sign place 1 line=2 name=sign') screen:expect([[ - 1 ^aaaaa │1 aaaaa | - 2 ssaaaaa │2 ssaaaaa | + {8:1 }^aaaaa │{8:1 }aaaaa | + {8:2 ss}aaaaa │{8:2 ss}aaaaa | | ]]) end) @@ -918,12 +892,16 @@ describe('statuscolumn', function() it('does not wrap multibyte characters at the end of a line', function() screen:try_resize(33, 4) + screen:set_default_attr_ids { + [8] = { foreground = Screen.colors.Brown }, + [31] = { undercurl = true, special = Screen.colors.Red }, + } command([[set spell stc=%l\ ]]) command('call setline(8, "This is a line that contains ᶏ multibyte character.")') screen:expect([[ - 8 ^This is a line that contains ᶏ| - multibyte character. | - 9 aaaaa | + {8:8 }^This is a line that contains {31:ᶏ}| + {8: } {31:multibyte} character. | + {8:9 }{31:aaaaa} | | ]]) end) @@ -934,10 +912,63 @@ describe('statuscolumn', function() command('call setline(1, range(1, 99))') feed('Gyyp') screen:expect([[ - 98 98 | - 99 99 | - 100 ^99 | + {8:98 }98 | + {8:99 }99 | + {8:100 }^99 | | ]]) end) + + it('forces a rebuild with nvim__redraw', function() + screen:try_resize(40, 4) + -- Current window + command([[ + let g:insert = v:false + set nonu stc=%{g:insert?'insert':''} + vsplit + au InsertEnter * let g:insert = v:true | call nvim__redraw(#{statuscolumn:1, win:0}) + au InsertLeave * let g:insert = v:false | call nvim__redraw(#{statuscolumn:1, win:0}) + ]]) + feed('i') + screen:expect({ + grid = [[ + {8:insert}^aaaaa │aaaaa | + {8:insert}aaaaa │aaaaa | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- INSERT --} | + ]], + }) + feed('<esc>') + screen:expect({ + grid = [[ + ^aaaaa │aaaaa | + aaaaa │aaaaa | + {3:[No Name] [+] }{2:[No Name] [+] }| + | + ]], + }) + -- All windows + command([[ + au! InsertEnter * let g:insert = v:true | call nvim__redraw(#{statuscolumn:1}) + au! InsertLeave * let g:insert = v:false | call nvim__redraw(#{statuscolumn:1}) + ]]) + feed('i') + screen:expect({ + grid = [[ + {8:insert}^aaaaa │{8:insert}aaaaa | + {8:insert}aaaaa │{8:insert}aaaaa | + {3:[No Name] [+] }{2:[No Name] [+] }| + {5:-- INSERT --} | + ]], + }) + feed('<esc>') + screen:expect({ + grid = [[ + ^aaaaa │aaaaa | + aaaaa │aaaaa | + {3:[No Name] [+] }{2:[No Name] [+] }| + | + ]], + }) + end) end) diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index fee4b64d44..3087a0cde1 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -1,16 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local clear = helpers.clear -local command = helpers.command -local feed = helpers.feed -local eq = helpers.eq -local fn = helpers.fn -local api = helpers.api -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local eval = helpers.eval + +local assert_alive = n.assert_alive +local clear = n.clear +local command = n.command +local feed = n.feed +local eq = t.eq +local fn = n.fn +local api = n.api +local exec = n.exec +local exec_lua = n.exec_lua +local eval = n.eval local sleep = vim.uv.sleep +local pcall_err = t.pcall_err local mousemodels = { 'extend', 'popup', 'popup_setpos' } @@ -474,6 +477,25 @@ describe('global statusline', function() | ]]) end) + + it('horizontal separators unchanged when failing to split-move window', function() + exec([[ + botright split + let &winwidth = &columns + let &winminwidth = &columns + ]]) + eq('Vim(wincmd):E36: Not enough room', pcall_err(command, 'wincmd L')) + command('mode') + screen:expect([[ + | + {1:~ }|*5 + ────────────────────────────────────────────────────────────| + ^ | + {1:~ }|*6 + {2:[No Name] 0,0-1 All}| + | + ]]) + end) end) it('statusline does not crash if it has Arabic characters #19447', function() @@ -576,57 +598,59 @@ it('statusline is redrawn on various state changes', function() command('set ls=2 stl=%{repeat(reg_recording(),5)}') screen:expect([[ ^ | - ~ | - |*2 + {1:~ }| + {3: }| + | ]]) feed('qQ') screen:expect([[ ^ | - ~ | - QQQQQ | - recording @Q | + {1:~ }| + {3:QQQQQ }| + {5:recording @Q} | ]]) feed('q') screen:expect([[ ^ | - ~ | - |*2 + {1:~ }| + {3: }| + | ]]) -- Visual mode change #23932 command('set ls=2 stl=%{mode(1)}') screen:expect([[ ^ | - ~ | - n | + {1:~ }| + {3:n }| | ]]) feed('v') screen:expect([[ ^ | - ~ | - v | - -- VISUAL -- | + {1:~ }| + {3:v }| + {5:-- VISUAL --} | ]]) feed('V') screen:expect([[ ^ | - ~ | - V | - -- VISUAL LINE -- | + {1:~ }| + {3:V }| + {5:-- VISUAL LINE --} | ]]) feed('<C-V>') screen:expect([[ ^ | - ~ | - ^V | - -- VISUAL BLOCK -- | + {1:~ }| + {3:^V }| + {5:-- VISUAL BLOCK --} | ]]) feed('<Esc>') screen:expect([[ ^ | - ~ | - n | + {1:~ }| + {3:n }| | ]]) end) diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index 5afc7dfe6c..be35e9bf4f 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -1,10 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, command = helpers.clear, helpers.feed, helpers.command -local eq = helpers.eq -local insert = helpers.insert -local poke_eventloop = helpers.poke_eventloop -local exec = helpers.exec + +local clear, feed, command = n.clear, n.feed, n.command +local eq = t.eq +local insert = n.insert +local poke_eventloop = n.poke_eventloop +local exec = n.exec describe('Screen', function() local screen @@ -435,6 +437,18 @@ describe('Screen', function() {0:~ }|*3 | ]]) + + feed('r') + screen:expect_unchanged() + + feed('m') + screen:expect([[ + ^moo {1:b} bar {1:b} eggs | + foo {1:b} bar {1:b} eggs |*4 + | + {0:~ }|*3 + | + ]]) end) it('and open line', function() diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua index 1c90b17e57..5cda70df21 100644 --- a/test/functional/ui/tabline_spec.lua +++ b/test/functional/ui/tabline_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, command, eq = helpers.clear, helpers.command, helpers.eq -local insert = helpers.insert -local api = helpers.api -local assert_alive = helpers.assert_alive + +local clear, command, eq = n.clear, n.command, t.eq +local insert = n.insert +local api = n.api +local assert_alive = n.assert_alive describe('ui/ext_tabline', function() local screen @@ -31,7 +33,7 @@ describe('ui/ext_tabline', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 | ]], condition = function() @@ -44,7 +46,7 @@ describe('ui/ext_tabline', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 | ]], condition = function() @@ -62,7 +64,7 @@ describe('ui/ext_tabline', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 | ]], condition = function() @@ -81,7 +83,7 @@ describe('ui/ext_tabline', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 | ]], condition = function() @@ -99,10 +101,6 @@ describe('tabline', function() clear() screen = Screen.new(42, 5) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { reverse = true }, -- TabLineFill - }) end) it('redraws when tabline option is set', function() @@ -110,18 +108,18 @@ describe('tabline', function() command('set showtabline=2') screen:expect { grid = [[ - {1:asdf }| + {2:asdf }| ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], } command('set tabline=jkl') screen:expect { grid = [[ - {1:jkl }| + {2:jkl }| ^ | - {0:~ }|*2 + {1:~ }|*2 | ]], } @@ -141,9 +139,9 @@ describe('tabline', function() api.nvim_set_option_value('tabline', '%1T口口%2Ta' .. ('b'):rep(38) .. '%999Xc', {}) screen:expect { grid = [[ - {1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| + {2:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| tab^1 | - {0:~ }|*2 + {1:~ }|*2 | ]], } @@ -151,27 +149,27 @@ describe('tabline', function() api.nvim_input_mouse('left', 'press', '', 0, 0, 1) screen:expect { grid = [[ - {1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| + {2:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| tab^2 | - {0:~ }|*2 + {1:~ }|*2 | ]], } api.nvim_input_mouse('left', 'press', '', 0, 0, 0) screen:expect { grid = [[ - {1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| + {2:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| tab^1 | - {0:~ }|*2 + {1:~ }|*2 | ]], } api.nvim_input_mouse('left', 'press', '', 0, 0, 39) screen:expect { grid = [[ - {1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| + {2:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }| tab^2 | - {0:~ }|*2 + {1:~ }|*2 | ]], } @@ -179,7 +177,7 @@ describe('tabline', function() screen:expect { grid = [[ tab^1 | - {0:~ }|*3 + {1:~ }|*3 | ]], } diff --git a/test/functional/ui/title_spec.lua b/test/functional/ui/title_spec.lua index 8060d3a460..e86fdbe5a3 100644 --- a/test/functional/ui/title_spec.lua +++ b/test/functional/ui/title_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local curwin = helpers.api.nvim_get_current_win -local eq = helpers.eq -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local fn = helpers.fn -local api = helpers.api -local is_os = helpers.is_os + +local clear = n.clear +local command = n.command +local curwin = n.api.nvim_get_current_win +local eq = t.eq +local exec_lua = n.exec_lua +local feed = n.feed +local fn = n.fn +local api = n.api +local is_os = t.is_os describe('title', function() local screen diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 667dd64d62..0feec6bd03 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -1,19 +1,28 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear, feed, command = helpers.clear, helpers.feed, helpers.command -local fn = helpers.fn -local api = helpers.api -local eq = helpers.eq -local eval = helpers.eval -local retry = helpers.retry -local testprg = helpers.testprg -local is_os = helpers.is_os + +local clear, feed, command = n.clear, n.feed, n.command +local fn = n.fn +local api = n.api +local eq = t.eq +local eval = n.eval +local retry = t.retry +local testprg = n.testprg +local is_os = t.is_os describe("'wildmenu'", function() local screen before_each(function() clear() screen = Screen.new(25, 5) + screen:set_default_attr_ids { + [1] = { foreground = Screen.colors.Blue, bold = true }, + [2] = { reverse = true }, + [3] = { bold = true, reverse = true }, + [5] = { bold = true }, + [31] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, + } screen:attach() end) @@ -105,14 +114,14 @@ describe("'wildmenu'", function() feed(':sign <tab>') screen:expect([[ | - ~ |*2 - define jump list > | + {1:~ }|*2 + {31:define}{3: jump list > }| :sign define^ | ]]) feed('<C-E>') screen:expect([[ | - ~ |*3 + {1:~ }|*3 :sign ^ | ]]) end) @@ -121,14 +130,14 @@ describe("'wildmenu'", function() feed(':sign <tab>') screen:expect([[ | - ~ |*2 - define jump list > | + {1:~ }|*2 + {31:define}{3: jump list > }| :sign define^ | ]]) feed('<tab><C-Y>') screen:expect([[ | - ~ |*3 + {1:~ }|*3 :sign jump^ | ]]) end) @@ -138,8 +147,8 @@ describe("'wildmenu'", function() feed(':sign <tab>') screen:expect([[ | - ~ |*2 - define jump list > | + {1:~ }|*2 + {31:define}{3: jump list > }| :sign define^ | ]]) end) @@ -152,15 +161,15 @@ describe("'wildmenu'", function() feed(':sign <tab>') screen:expect([[ | - ~ |*2 - define jump list > | + {1:~ }|*2 + {31:define}{3: jump list > }| :sign define^ | ]]) feed('<space>') screen:expect([[ | - ~ |*2 - [No Name] | + {1:~ }|*2 + {3:[No Name] }| :sign define ^ | ]]) end) @@ -170,16 +179,16 @@ describe("'wildmenu'", function() feed(':j<Tab><Tab><Tab>') screen:expect([[ | - ~ |*2 - join jumps | + {1:~ }|*2 + {3:join jumps }| :j^ | ]]) -- This would cause nvim to crash before #6650 feed('<BS><Tab>') screen:expect([[ | - ~ |*2 - ! # & < = > @ > | + {1:~ }|*2 + {31:!}{3: # & < = > @ > }| :!^ | ]]) end) @@ -192,7 +201,7 @@ describe("'wildmenu'", function() feed([[:sign <Tab>]]) -- Invoke wildmenu. -- NB: in earlier versions terminal output was redrawn during cmdline mode. -- For now just assert that the screen remains unchanged. - screen:expect { any = 'define jump list > |\n:sign define^ |' } + screen:expect { any = '{31:define}{3: jump list > }|\n:sign define^ |' } screen:expect_unchanged() -- cmdline CTRL-D display should also be preserved. @@ -222,8 +231,8 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - ~ |*2 - define jump list > | + {1:~ }|*2 + {31:define}{3: jump list > }| :sign define^ | ]], } @@ -252,7 +261,7 @@ describe("'wildmenu'", function() feed([[:<Tab>]]) -- Invoke wildmenu. -- Check only the last 2 lines, because the shell output is -- system-dependent. - screen:expect { any = '! # & < = > @ > |\n:!^' } + screen:expect { any = '{31:!}{3: # & < = > @ > }|\n:!^' } -- Because this test verifies a _lack_ of activity, we must wait the full timeout. -- So make it reasonable. screen:expect_unchanged(false, 1000) @@ -266,27 +275,29 @@ describe("'wildmenu'", function() command('set showtabline=2') feed(':set wildm<tab>') screen:expect([[ - [No Name] | - | - ~ | + {5: [No Name] }{2: }| | + {1:~ }| + {3: }| :set wildm | wildmenu wildmode | :set wildm^ | ]]) feed('<tab>') -- trigger wildmode full screen:expect([[ - [No Name] | - |*2 + {5: [No Name] }{2: }| + | + {3: }| :set wildm | - wildmenu wildmode |*2 + wildmenu wildmode | + {31:wildmenu}{3: wildmode }| :set wildmenu^ | ]]) feed('<Esc>') screen:expect([[ - [No Name] | + {5: [No Name] }{2: }| ^ | - ~ |*4 + {1:~ }|*4 | ]]) end) @@ -301,14 +312,14 @@ describe("'wildmenu'", function() feed(':sign u<tab>') screen:expect([[ | - ~ |*5 + {1:~ }|*5 :sign un^ | ]]) feed('<tab>') -- trigger wildmode list screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| :sign un | undefine unplace | :sign un^ | @@ -316,7 +327,7 @@ describe("'wildmenu'", function() feed('<Esc>') screen:expect([[ ^ | - ~ |*5 + {1:~ }|*5 | ]]) @@ -324,8 +335,8 @@ describe("'wildmenu'", function() feed(':sign un<tab>') screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| :sign un | undefine unplace | :sign un^ | @@ -335,7 +346,7 @@ describe("'wildmenu'", function() feed('<Esc>') screen:expect([[ ^ | - ~ |*5 + {1:~ }|*5 | ]]) end) @@ -348,8 +359,8 @@ describe("'wildmenu'", function() feed(':sign u<tab>') screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| :sign u | undefine unplace | :sign u^ | @@ -357,8 +368,8 @@ describe("'wildmenu'", function() feed('<tab>') -- trigger wildmode longest screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| :sign u | undefine unplace | :sign un^ | @@ -366,7 +377,7 @@ describe("'wildmenu'", function() feed('<Esc>') screen:expect([[ ^ | - ~ |*5 + {1:~ }|*5 | ]]) end) @@ -379,15 +390,16 @@ describe("'wildmenu'", function() feed('<c-d>') screen:expect([[ | - ~ |*2 - | + {1:~ }|*2 + {3: }| :set wildm | wildmenu wildmode | :set wildm^ | ]]) feed('<c-d>') screen:expect([[ - |*2 + | + {3: }| :set wildm | wildmenu wildmode | :set wildm | @@ -397,8 +409,8 @@ describe("'wildmenu'", function() feed('<Esc>') screen:expect([[ ^ | - ~ |*4 - [No Name] | + {1:~ }|*4 + {3:[No Name] }| | ]]) end) @@ -594,7 +606,7 @@ describe('ui/ext_wildmenu', function() screen:expect { grid = [[ | - ~ |*3 + {1:~ }|*3 :sign define^ | ]], wildmenu_items = expected, @@ -605,7 +617,7 @@ describe('ui/ext_wildmenu', function() screen:expect { grid = [[ | - ~ |*3 + {1:~ }|*3 :sign jump^ | ]], wildmenu_items = expected, @@ -616,7 +628,7 @@ describe('ui/ext_wildmenu', function() screen:expect { grid = [[ | - ~ |*3 + {1:~ }|*3 :sign ^ | ]], wildmenu_items = expected, @@ -627,7 +639,7 @@ describe('ui/ext_wildmenu', function() screen:expect { grid = [[ | - ~ |*3 + {1:~ }|*3 :sign define^ | ]], wildmenu_items = expected, @@ -638,7 +650,7 @@ describe('ui/ext_wildmenu', function() screen:expect { grid = [[ | - ~ |*3 + {1:~ }|*3 :sign definea^ | ]], } diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua index c2a52c0f21..fb907026a5 100644 --- a/test/functional/ui/winbar_spec.lua +++ b/test/functional/ui/winbar_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local command = helpers.command -local insert = helpers.insert -local api = helpers.api -local eq = helpers.eq -local poke_eventloop = helpers.poke_eventloop -local feed = helpers.feed -local fn = helpers.fn -local pcall_err = helpers.pcall_err + +local clear = n.clear +local command = n.command +local insert = n.insert +local api = n.api +local eq = t.eq +local poke_eventloop = n.poke_eventloop +local feed = n.feed +local fn = n.fn +local pcall_err = t.pcall_err describe('winbar', function() local screen @@ -525,30 +527,24 @@ describe('local winbar with tabs', function() clear() screen = Screen.new(60, 10) screen:attach() - screen:set_default_attr_ids({ - [1] = { bold = true }, - [2] = { reverse = true }, - [3] = { bold = true, foreground = Screen.colors.Blue }, - [4] = { underline = true, background = Screen.colors.LightGray }, - }) api.nvim_set_option_value('winbar', 'foo', { scope = 'local', win = 0 }) end) it('works', function() command('tabnew') screen:expect([[ - {4: [No Name] }{1: [No Name] }{2: }{4:X}| + {24: [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {3:~ }|*7 + {1:~ }|*7 | ]]) command('tabnext') screen:expect { grid = [[ - {1: [No Name] }{4: [No Name] }{2: }{4:X}| - {1:foo }| + {5: [No Name] }{24: [No Name] }{2: }{24:X}| + {5:foo }| ^ | - {3:~ }|*6 + {1:~ }|*6 | ]], } @@ -561,11 +557,11 @@ describe('local winbar with tabs', function() text]] screen:expect { grid = [[ - {1:foo }| + {5:foo }| some | goofy | tex^t | - {3:~ }|*5 + {1:~ }|*5 | ]], } @@ -574,9 +570,9 @@ describe('local winbar with tabs', function() command 'tabedit' screen:expect { grid = [[ - {4: + [No Name] }{1: [No Name] }{2: }{4:X}| + {24: + [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {3:~ }|*7 + {1:~ }|*7 | ]], } @@ -584,12 +580,12 @@ describe('local winbar with tabs', function() command 'tabprev' screen:expect { grid = [[ - {1: + [No Name] }{4: [No Name] }{2: }{4:X}| - {1:foo }| + {5: + [No Name] }{24: [No Name] }{2: }{24:X}| + {5:foo }| some | goofy | tex^t | - {3:~ }|*4 + {1:~ }|*4 | ]], } @@ -609,16 +605,11 @@ it('winbar works properly when redrawing is postponed #23534', function() }) local screen = Screen.new(60, 6) screen:attach() - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue, bold = true }, - [1] = { bold = true }, - [2] = { bold = true, reverse = true }, - }) screen:expect([[ - {1:(winbar) }| + {5:(winbar) }| ^ | - {0:~ }|*2 - {2:(statusline) }| + {1:~ }|*2 + {3:(statusline) }| | ]]) end) diff --git a/test/functional/vimscript/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua index 4985768bb0..b2865d2b4c 100644 --- a/test/functional/vimscript/api_functions_spec.lua +++ b/test/functional/vimscript/api_functions_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local neq, eq, command = helpers.neq, helpers.eq, helpers.command -local clear = helpers.clear -local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval -local exec_lua = helpers.exec_lua -local insert, pcall_err = helpers.insert, helpers.pcall_err -local matches = helpers.matches -local api = helpers.api -local feed = helpers.feed + +local neq, eq, command = t.neq, t.eq, n.command +local clear = n.clear +local exc_exec, expect, eval = n.exc_exec, n.expect, n.eval +local exec_lua = n.exec_lua +local insert, pcall_err = n.insert, t.pcall_err +local matches = t.matches +local api = n.api +local feed = n.feed describe('eval-API', function() before_each(clear) @@ -179,8 +181,8 @@ describe('eval-API', function() eq('Vim(call):E117: Unknown function: buffer_get_line', err) -- some api functions are only useful from a msgpack-rpc channel - err = exc_exec('call nvim_subscribe("fancyevent")') - eq('Vim(call):E117: Unknown function: nvim_subscribe', err) + err = exc_exec('call nvim_set_client_info()') + eq('Vim(call):E117: Unknown function: nvim_set_client_info', err) end) it('have metadata accessible with api_info()', function() diff --git a/test/functional/vimscript/buf_functions_spec.lua b/test/functional/vimscript/buf_functions_spec.lua index 931fe640a9..625fbe7e03 100644 --- a/test/functional/vimscript/buf_functions_spec.lua +++ b/test/functional/vimscript/buf_functions_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local fn = helpers.fn -local api = helpers.api -local command = helpers.command -local exc_exec = helpers.exc_exec -local get_pathsep = helpers.get_pathsep -local rmdir = helpers.rmdir -local pcall_err = helpers.pcall_err -local mkdir = helpers.mkdir +local eq = t.eq +local clear = n.clear +local fn = n.fn +local api = n.api +local command = n.command +local exc_exec = n.exc_exec +local get_pathsep = n.get_pathsep +local rmdir = n.rmdir +local pcall_err = t.pcall_err +local mkdir = t.mkdir local fname = 'Xtest-functional-eval-buf_functions' local fname2 = fname .. '.2' diff --git a/test/functional/vimscript/changedtick_spec.lua b/test/functional/vimscript/changedtick_spec.lua index 85928921c5..baea53a700 100644 --- a/test/functional/vimscript/changedtick_spec.lua +++ b/test/functional/vimscript/changedtick_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed -local clear = helpers.clear -local fn = helpers.fn -local api = helpers.api -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err -local exec_capture = helpers.exec_capture +local eq = t.eq +local eval = n.eval +local feed = n.feed +local clear = n.clear +local fn = n.fn +local api = n.api +local command = n.command +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err +local exec_capture = n.exec_capture before_each(clear) diff --git a/test/functional/vimscript/container_functions_spec.lua b/test/functional/vimscript/container_functions_spec.lua index 1b34ea0165..1d95bf6470 100644 --- a/test/functional/vimscript/container_functions_spec.lua +++ b/test/functional/vimscript/container_functions_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local eval = helpers.eval -local api = helpers.api -local clear = helpers.clear +local eq = t.eq +local eval = n.eval +local api = n.api +local clear = n.clear before_each(clear) diff --git a/test/functional/vimscript/ctx_functions_spec.lua b/test/functional/vimscript/ctx_functions_spec.lua index dc60a474f3..5e9a803b5d 100644 --- a/test/functional/vimscript/ctx_functions_spec.lua +++ b/test/functional/vimscript/ctx_functions_spec.lua @@ -1,19 +1,20 @@ -local helpers = require('test.functional.helpers')(after_each) - -local call = helpers.call -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local eval = helpers.eval -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local call = n.call +local clear = n.clear +local command = n.command +local eq = t.eq +local eval = n.eval +local feed = n.feed local map = vim.tbl_map -local api = helpers.api -local parse_context = helpers.parse_context -local exec_capture = helpers.exec_capture -local source = helpers.source +local api = n.api +local parse_context = n.parse_context +local exec_capture = n.exec_capture +local source = n.source local trim = vim.trim -local write_file = helpers.write_file -local pcall_err = helpers.pcall_err +local write_file = t.write_file +local pcall_err = t.pcall_err describe('context functions', function() local fname1 = 'Xtest-functional-eval-ctx1' diff --git a/test/functional/vimscript/environ_spec.lua b/test/functional/vimscript/environ_spec.lua index 0763def84e..abb093a6c8 100644 --- a/test/functional/vimscript/environ_spec.lua +++ b/test/functional/vimscript/environ_spec.lua @@ -1,13 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local environ = helpers.fn.environ -local exists = helpers.fn.exists -local system = helpers.fn.system -local nvim_prog = helpers.nvim_prog -local command = helpers.command -local eval = helpers.eval -local setenv = helpers.fn.setenv +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local environ = n.fn.environ +local exists = n.fn.exists +local system = n.fn.system +local nvim_prog = n.nvim_prog +local command = n.command +local eval = n.eval +local setenv = n.fn.setenv describe('environment variables', function() it('environ() handles empty env variable', function() diff --git a/test/functional/vimscript/errorlist_spec.lua b/test/functional/vimscript/errorlist_spec.lua index 1e405e7e64..ef9111f788 100644 --- a/test/functional/vimscript/errorlist_spec.lua +++ b/test/functional/vimscript/errorlist_spec.lua @@ -1,13 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local command = helpers.command -local eq = helpers.eq -local exc_exec = helpers.exc_exec -local get_win_var = helpers.api.nvim_win_get_var +local clear = n.clear +local command = n.command +local eq = t.eq +local exc_exec = n.exc_exec +local get_win_var = n.api.nvim_win_get_var describe('setqflist()', function() - local setqflist = helpers.fn.setqflist + local setqflist = n.fn.setqflist before_each(clear) @@ -46,7 +47,7 @@ describe('setqflist()', function() end) describe('setloclist()', function() - local setloclist = helpers.fn.setloclist + local setloclist = n.fn.setloclist before_each(clear) @@ -73,7 +74,7 @@ describe('setloclist()', function() end) it("doesn't crash when when window is closed in the middle #13721", function() - helpers.insert([[ + n.insert([[ hello world]]) command('vsplit') @@ -82,6 +83,6 @@ describe('setloclist()', function() command('call setloclist(0, [])') command('lopen') - helpers.assert_alive() + n.assert_alive() end) end) diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua index e337959810..0c812d968e 100644 --- a/test/functional/vimscript/eval_spec.lua +++ b/test/functional/vimscript/eval_spec.lua @@ -9,37 +9,38 @@ -- test/functional/vimscript/<funcname>_spec.lua -- test/functional/vimscript/functions_spec.lua -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local mkdir = helpers.mkdir -local clear = helpers.clear -local eq = helpers.eq -local exec = helpers.exec -local exc_exec = helpers.exc_exec -local exec_lua = helpers.exec_lua -local exec_capture = helpers.exec_capture -local eval = helpers.eval -local command = helpers.command -local write_file = helpers.write_file -local api = helpers.api +local mkdir = t.mkdir +local clear = n.clear +local eq = t.eq +local exec = n.exec +local exc_exec = n.exc_exec +local exec_lua = n.exec_lua +local exec_capture = n.exec_capture +local eval = n.eval +local command = n.command +local write_file = t.write_file +local api = n.api local sleep = vim.uv.sleep -local matches = helpers.matches -local pcall_err = helpers.pcall_err -local assert_alive = helpers.assert_alive -local poke_eventloop = helpers.poke_eventloop -local feed = helpers.feed -local expect_exit = helpers.expect_exit +local matches = t.matches +local pcall_err = t.pcall_err +local assert_alive = n.assert_alive +local poke_eventloop = n.poke_eventloop +local feed = n.feed +local expect_exit = n.expect_exit describe('Up to MAX_FUNC_ARGS arguments are handled by', function() local max_func_args = 20 -- from eval.h - local range = helpers.fn.range + local range = n.fn.range before_each(clear) it('printf()', function() - local printf = helpers.fn.printf - local rep = helpers.fn['repeat'] + local printf = n.fn.printf + local rep = n.fn['repeat'] local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,' eq(expected, printf(rep('%d,', max_func_args - 1), unpack(range(2, max_func_args)))) local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') @@ -47,7 +48,7 @@ describe('Up to MAX_FUNC_ARGS arguments are handled by', function() end) it('rpcnotify()', function() - local rpcnotify = helpers.fn.rpcnotify + local rpcnotify = n.fn.rpcnotify local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args))) eq(1, ret) ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') @@ -69,17 +70,17 @@ describe('backtick expansion', function() end) teardown(function() - helpers.rmdir('test-backticks') + n.rmdir('test-backticks') end) it("with default 'shell'", function() - if helpers.is_os('win') then + if t.is_os('win') then command(':silent args `dir /b *2`') else command(':silent args `echo ***2`') end eq({ 'file2' }, eval('argv()')) - if helpers.is_os('win') then + if t.is_os('win') then command(':silent args `dir /s/b *4`') eq({ 'subdir\\file4' }, eval('map(argv(), \'fnamemodify(v:val, ":.")\')')) else diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua index 1d95f6088e..e5530926c4 100644 --- a/test/functional/vimscript/executable_spec.lua +++ b/test/functional/vimscript/executable_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, clear, call, write_file, command = - helpers.eq, helpers.clear, helpers.call, helpers.write_file, helpers.command -local exc_exec = helpers.exc_exec -local eval = helpers.eval -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear, call, write_file, command = t.eq, n.clear, n.call, t.write_file, n.command +local exc_exec = n.exc_exec +local eval = n.eval +local is_os = t.is_os describe('executable()', function() before_each(clear) diff --git a/test/functional/vimscript/execute_spec.lua b/test/functional/vimscript/execute_spec.lua index 29488ed31c..8caaea39a7 100644 --- a/test/functional/vimscript/execute_spec.lua +++ b/test/functional/vimscript/execute_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local eval = helpers.eval -local clear = helpers.clear -local source = helpers.source -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local command = helpers.command -local feed = helpers.feed -local is_os = helpers.is_os + +local eq = t.eq +local eval = n.eval +local clear = n.clear +local source = n.source +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err +local fn = n.fn +local command = n.command +local feed = n.feed +local is_os = t.is_os describe('execute()', function() before_each(clear) @@ -191,21 +193,21 @@ describe('execute()', function() feed([[:call Test1()<cr>]]) screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 ABCD | ]]) feed([[:call Test2()<cr>]]) screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 1234ABCD | ]]) feed([[:call Test3()<cr>]]) screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 1234ABCDXZYZ | ]]) @@ -215,39 +217,39 @@ describe('execute()', function() -- "ef" was overwritten since msg_col was recovered wrongly screen:expect([[ 1234 | - Error detected while processing function| - Test4: | - line 2: | - abcdABCD | - Press ENTER or type command to continue^ | + {9:Error detected while processing function}| + {9: Test4:} | + {8:line 2:} | + {9:abcd}ABCD | + {6:Press ENTER or type command to continue}^ | ]]) feed([[<cr>]]) -- to clear screen feed([[:call Test5()<cr>]]) screen:expect([[ ^ | - ~ |*4 + {1:~ }|*4 1234ABCD | ]]) feed([[:call Test6()<cr>]]) screen:expect([[ | - Error detected while processing function| - Test6: | - line 2: | - E121ABCD | - Press ENTER or type command to continue^ | + {9:Error detected while processing function}| + {9: Test6:} | + {8:line 2:} | + {9:E121}ABCD | + {6:Press ENTER or type command to continue}^ | ]]) feed([[:call Test7()<cr>]]) screen:expect([[ - Error detected while processing function| - Test6: | - line 2: | - E121ABCD | + {9:Error detected while processing function}| + {9: Test6:} | + {8:line 2:} | + {9:E121}ABCD | ABCD | - Press ENTER or type command to continue^ | + {6:Press ENTER or type command to continue}^ | ]]) end) @@ -265,7 +267,7 @@ describe('execute()', function() command('let g:mes = execute("echon 42", "")') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 42 | ]]) eq('42', eval('g:mes')) @@ -289,7 +291,7 @@ describe('execute()', function() command('let g:mes = execute("echon 42")') screen:expect([[ ^ | - ~ |*3 + {1:~ }|*3 | ]]) eq('42', eval('g:mes')) @@ -298,7 +300,7 @@ describe('execute()', function() screen:expect { grid = [[ ^ | - ~ |*3 + {1:~ }|*3 | ]], unchanged = true, diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua index 01033a2140..97747619ad 100644 --- a/test/functional/vimscript/exepath_spec.lua +++ b/test/functional/vimscript/exepath_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq, clear, call = helpers.eq, helpers.clear, helpers.call -local command = helpers.command -local exc_exec = helpers.exc_exec -local matches = helpers.matches -local is_os = helpers.is_os -local set_shell_powershell = helpers.set_shell_powershell -local eval = helpers.eval +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq, clear, call = t.eq, n.clear, n.call +local command = n.command +local exc_exec = n.exc_exec +local matches = t.matches +local is_os = t.is_os +local set_shell_powershell = n.set_shell_powershell +local eval = n.eval local find_dummies = function(ext_pat) local tmp_path = eval('$PATH') diff --git a/test/functional/vimscript/fnamemodify_spec.lua b/test/functional/vimscript/fnamemodify_spec.lua index 4a134fe23c..51b1e8489a 100644 --- a/test/functional/vimscript/fnamemodify_spec.lua +++ b/test/functional/vimscript/fnamemodify_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local fnamemodify = helpers.fn.fnamemodify -local getcwd = helpers.fn.getcwd -local command = helpers.command -local write_file = helpers.write_file -local alter_slashes = helpers.alter_slashes -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local fnamemodify = n.fn.fnamemodify +local getcwd = n.fn.getcwd +local command = n.command +local write_file = t.write_file +local alter_slashes = n.alter_slashes +local is_os = t.is_os local function eq_slashconvert(expected, got) eq(alter_slashes(expected), alter_slashes(got)) @@ -24,7 +26,7 @@ describe('fnamemodify()', function() end) it('handles the root path', function() - local root = helpers.pathroot() + local root = n.pathroot() eq(root, fnamemodify([[/]], ':p:h')) eq(root, fnamemodify([[/]], ':p')) if is_os('win') then diff --git a/test/functional/vimscript/functions_spec.lua b/test/functional/vimscript/functions_spec.lua index 09b3334989..7d9e80a32b 100644 --- a/test/functional/vimscript/functions_spec.lua +++ b/test/functional/vimscript/functions_spec.lua @@ -5,12 +5,13 @@ -- -- Core "eval" tests live in eval_spec.lua. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eval = helpers.eval -local matches = helpers.matches -local is_os = helpers.is_os +local clear = n.clear +local eval = n.eval +local matches = t.matches +local is_os = t.is_os before_each(clear) diff --git a/test/functional/vimscript/getline_spec.lua b/test/functional/vimscript/getline_spec.lua index 08e7711b8c..32be6b5702 100644 --- a/test/functional/vimscript/getline_spec.lua +++ b/test/functional/vimscript/getline_spec.lua @@ -1,9 +1,10 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local call = helpers.call -local clear = helpers.clear -local eq = helpers.eq -local expect = helpers.expect +local call = n.call +local clear = n.clear +local eq = t.eq +local expect = n.expect describe('getline()', function() before_each(function() diff --git a/test/functional/vimscript/glob_spec.lua b/test/functional/vimscript/glob_spec.lua index 77351f95fa..754381231e 100644 --- a/test/functional/vimscript/glob_spec.lua +++ b/test/functional/vimscript/glob_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, command, eval, eq = helpers.clear, helpers.command, helpers.eval, helpers.eq -local mkdir = helpers.mkdir +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, command, eval, eq = n.clear, n.command, n.eval, t.eq +local mkdir = t.mkdir before_each(function() clear() diff --git a/test/functional/vimscript/has_spec.lua b/test/functional/vimscript/has_spec.lua index 82b3db5b67..1d2187be6b 100644 --- a/test/functional/vimscript/has_spec.lua +++ b/test/functional/vimscript/has_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local clear = helpers.clear -local connect = helpers.connect -local eq = helpers.eq -local fn = helpers.fn -local is_os = helpers.is_os -local nvim_prog = helpers.nvim_prog + +local clear = n.clear +local connect = n.connect +local eq = t.eq +local fn = n.fn +local is_os = t.is_os +local nvim_prog = n.nvim_prog describe('has()', function() before_each(clear) diff --git a/test/functional/vimscript/hostname_spec.lua b/test/functional/vimscript/hostname_spec.lua index 62520e8222..e6b2499775 100644 --- a/test/functional/vimscript/hostname_spec.lua +++ b/test/functional/vimscript/hostname_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local ok = helpers.ok -local call = helpers.call -local clear = helpers.clear -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local ok = t.ok +local call = n.call +local clear = n.clear +local is_os = t.is_os describe('hostname()', function() before_each(clear) diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua index b749d5a7f0..552ae6d5cc 100644 --- a/test/functional/vimscript/input_spec.lua +++ b/test/functional/vimscript/input_spec.lua @@ -1,15 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local feed = helpers.feed -local api = helpers.api -local clear = helpers.clear -local source = helpers.source -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err -local async_meths = helpers.async_meths +local eq = t.eq +local feed = n.feed +local api = n.api +local clear = n.clear +local source = n.source +local command = n.command +local exc_exec = n.exc_exec +local async_meths = n.async_meths local NIL = vim.NIL local screen @@ -407,7 +407,6 @@ describe('inputdialog()', function() end) describe('confirm()', function() - -- oldtest: Test_confirm() it('works', function() api.nvim_set_option_value('more', false, {}) -- Avoid hit-enter prompt api.nvim_set_option_value('laststatus', 2, {}) @@ -470,20 +469,6 @@ describe('confirm()', function() screen:expect({ any = '%[No Name%]' }) eq(1, api.nvim_get_var('a')) end - - eq('Vim(call):E730: Using a List as a String', pcall_err(command, 'call confirm([])')) - eq( - 'Vim(call):E730: Using a List as a String', - pcall_err(command, 'call confirm("Are you sure?", [])') - ) - eq( - 'Vim(call):E745: Using a List as a Number', - pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])') - ) - eq( - 'Vim(call):E730: Using a List as a String', - pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])') - ) end) it('shows dialog even if :silent #8788', function() diff --git a/test/functional/vimscript/json_functions_spec.lua b/test/functional/vimscript/json_functions_spec.lua index ef0359263e..ae56e8873d 100644 --- a/test/functional/vimscript/json_functions_spec.lua +++ b/test/functional/vimscript/json_functions_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local fn = helpers.fn -local api = helpers.api -local eq = helpers.eq -local eval = helpers.eval -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local fn = n.fn +local api = n.api +local eq = t.eq +local eval = n.eval +local command = n.command +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err local NIL = vim.NIL -local source = helpers.source +local source = n.source describe('json_decode() function', function() local restart = function(...) diff --git a/test/functional/vimscript/lang_spec.lua b/test/functional/vimscript/lang_spec.lua index 2dde90e334..923c8c215d 100644 --- a/test/functional/vimscript/lang_spec.lua +++ b/test/functional/vimscript/lang_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local exc_exec, source = helpers.exc_exec, helpers.source +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval, eq = n.clear, n.eval, t.eq +local exc_exec, source = n.exc_exec, n.source describe('vimscript', function() before_each(clear) diff --git a/test/functional/vimscript/let_spec.lua b/test/functional/vimscript/let_spec.lua index 15d4b189b8..412e06df20 100644 --- a/test/functional/vimscript/let_spec.lua +++ b/test/functional/vimscript/let_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local command = helpers.command -local eval = helpers.eval -local api = helpers.api -local exec = helpers.exec -local exec_capture = helpers.exec_capture -local expect_exit = helpers.expect_exit -local source = helpers.source -local testprg = helpers.testprg +local eq = t.eq +local clear = n.clear +local command = n.command +local eval = n.eval +local api = n.api +local exec = n.exec +local exec_capture = n.exec_capture +local expect_exit = n.expect_exit +local source = n.source +local testprg = n.testprg before_each(clear) diff --git a/test/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua index 59d427ca90..44be5b3185 100644 --- a/test/functional/vimscript/map_functions_spec.lua +++ b/test/functional/vimscript/map_functions_spec.lua @@ -1,18 +1,19 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local expect = helpers.expect -local feed = helpers.feed -local fn = helpers.fn -local api = helpers.api -local source = helpers.source -local command = helpers.command -local exec_capture = helpers.exec_capture -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local eval = n.eval +local exec = n.exec +local exec_lua = n.exec_lua +local expect = n.expect +local feed = n.feed +local fn = n.fn +local api = n.api +local source = n.source +local command = n.command +local exec_capture = n.exec_capture +local pcall_err = t.pcall_err describe('maparg()', function() before_each(clear) @@ -233,7 +234,9 @@ describe('mapset()', function() 0, exec_lua([[ GlobalCount = 0 - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 1 end, + }) return GlobalCount ]]) ) @@ -242,7 +245,9 @@ describe('mapset()', function() exec_lua([[ _G.saved_asdf_map = vim.fn.maparg('asdf', 'n', false, true) - vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end }) + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 10 end, + }) ]]) feed('asdf') eq(11, exec_lua([[return GlobalCount]])) @@ -253,7 +258,10 @@ describe('mapset()', function() exec([[ let g:saved_asdf_map = maparg('asdf', 'n', v:false, v:true) - lua vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end }) + lua << + vim.api.nvim_set_keymap('n', 'asdf', '', { + callback = function() GlobalCount = GlobalCount + 10 end, + }) ]]) feed('asdf') eq(22, exec_lua([[return GlobalCount]])) diff --git a/test/functional/vimscript/match_functions_spec.lua b/test/functional/vimscript/match_functions_spec.lua index 3db612e472..87c57f1c15 100644 --- a/test/functional/vimscript/match_functions_spec.lua +++ b/test/functional/vimscript/match_functions_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local eq = helpers.eq -local clear = helpers.clear -local fn = helpers.fn -local command = helpers.command -local exc_exec = helpers.exc_exec +local eq = t.eq +local clear = n.clear +local fn = n.fn +local command = n.command +local exc_exec = n.exc_exec before_each(clear) diff --git a/test/functional/vimscript/minmax_functions_spec.lua b/test/functional/vimscript/minmax_functions_spec.lua index c4a986bc8c..bf223c436e 100644 --- a/test/functional/vimscript/minmax_functions_spec.lua +++ b/test/functional/vimscript/minmax_functions_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local eval = helpers.eval -local command = helpers.command -local clear = helpers.clear -local fn = helpers.fn -local pcall_err = helpers.pcall_err +local eq = t.eq +local eval = n.eval +local command = n.command +local clear = n.clear +local fn = n.fn +local pcall_err = t.pcall_err before_each(clear) for _, func in ipairs({ 'min', 'max' }) do diff --git a/test/functional/vimscript/modeline_spec.lua b/test/functional/vimscript/modeline_spec.lua index ae63a66f43..53a5e9b692 100644 --- a/test/functional/vimscript/modeline_spec.lua +++ b/test/functional/vimscript/modeline_spec.lua @@ -1,9 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_alive = helpers.assert_alive -local clear, command, write_file = helpers.clear, helpers.command, helpers.write_file +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_alive = n.assert_alive +local clear, command, write_file = n.clear, n.command, t.write_file describe('modeline', function() - local tempfile = helpers.tmpname() + local tempfile = t.tmpname() before_each(clear) after_each(function() diff --git a/test/functional/vimscript/msgpack_functions_spec.lua b/test/functional/vimscript/msgpack_functions_spec.lua index 609a706155..d59dceef31 100644 --- a/test/functional/vimscript/msgpack_functions_spec.lua +++ b/test/functional/vimscript/msgpack_functions_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local fn = helpers.fn -local eval, eq = helpers.eval, helpers.eq -local command = helpers.command -local api = helpers.api -local exc_exec = helpers.exc_exec -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local fn = n.fn +local eval, eq = n.eval, t.eq +local command = n.command +local api = n.api +local exc_exec = n.exc_exec +local is_os = t.is_os describe('msgpack*() functions', function() before_each(clear) @@ -469,12 +471,12 @@ describe('msgpackparse() function', function() end) it('msgpackparse(systemlist(...)) does not segfault. #3135', function() - local cmd = "sort(keys(msgpackparse(systemlist('" .. helpers.nvim_prog .. " --api-info'))[0]))" + local cmd = "sort(keys(msgpackparse(systemlist('" .. n.nvim_prog .. " --api-info'))[0]))" eval(cmd) eval(cmd) -- do it again (try to force segfault) local api_info = eval(cmd) -- do it again if is_os('win') then - helpers.assert_alive() + n.assert_alive() pending('msgpackparse() has a bug on windows') return end diff --git a/test/functional/vimscript/null_spec.lua b/test/functional/vimscript/null_spec.lua index 805cd13844..9a27239a6d 100644 --- a/test/functional/vimscript/null_spec.lua +++ b/test/functional/vimscript/null_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local exc_exec = helpers.exc_exec -local command = helpers.command -local clear = helpers.clear -local api = helpers.api -local fn = helpers.fn -local eq = helpers.eq +local exc_exec = n.exc_exec +local command = n.command +local clear = n.clear +local api = n.api +local fn = n.fn +local eq = t.eq local function redir_exec(cmd) api.nvim_set_var('__redir_exec_cmd', cmd) diff --git a/test/functional/vimscript/operators_spec.lua b/test/functional/vimscript/operators_spec.lua index 64f6b60238..9c4a91d655 100644 --- a/test/functional/vimscript/operators_spec.lua +++ b/test/functional/vimscript/operators_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local eq = helpers.eq -local eval = helpers.eval -local clear = helpers.clear +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local eq = t.eq +local eval = n.eval +local clear = n.clear describe('Division operator', function() before_each(clear) diff --git a/test/functional/vimscript/printf_spec.lua b/test/functional/vimscript/printf_spec.lua index 4fa4ea7f4c..3c66e07618 100644 --- a/test/functional/vimscript/printf_spec.lua +++ b/test/functional/vimscript/printf_spec.lua @@ -1,11 +1,12 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local clear = helpers.clear -local eq = helpers.eq -local eval = helpers.eval -local fn = helpers.fn -local api = helpers.api -local exc_exec = helpers.exc_exec +local clear = n.clear +local eq = t.eq +local eval = n.eval +local fn = n.fn +local api = n.api +local exc_exec = n.exc_exec describe('printf()', function() before_each(clear) diff --git a/test/functional/vimscript/reltime_spec.lua b/test/functional/vimscript/reltime_spec.lua index 7cdb78e4ce..fa110d602a 100644 --- a/test/functional/vimscript/reltime_spec.lua +++ b/test/functional/vimscript/reltime_spec.lua @@ -1,6 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok -local neq, command, fn = helpers.neq, helpers.command, helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, ok = n.clear, t.eq, t.ok +local neq, command, fn = t.neq, n.command, n.fn +local matches = t.matches local reltime, reltimestr, reltimefloat = fn.reltime, fn.reltimestr, fn.reltimefloat describe('reltimestr(), reltimefloat()', function() @@ -15,7 +18,7 @@ describe('reltimestr(), reltimefloat()', function() neq('0.0', reltimestr(elapsed)) ok(reltimefloat(elapsed) > 0.0) -- original vim test for < 0.1, but easily fails on travis - ok(nil ~= string.match(reltimestr(elapsed), '0%.')) + matches('0%.', reltimestr(elapsed)) ok(reltimefloat(elapsed) < 1.0) local same = reltime(now, now) @@ -29,7 +32,7 @@ describe('reltimestr(), reltimefloat()', function() neq('0.0', reltimestr(differs)) ok(reltimefloat(differs) > 0.0) -- original vim test for < 0.1, but easily fails on travis - ok(nil ~= string.match(reltimestr(differs), '0%.')) + matches('0%.', reltimestr(differs)) ok(reltimefloat(differs) < 1.0) end) diff --git a/test/functional/vimscript/screenchar_spec.lua b/test/functional/vimscript/screenchar_spec.lua index 48b6893865..b6137d7741 100644 --- a/test/functional/vimscript/screenchar_spec.lua +++ b/test/functional/vimscript/screenchar_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq -local command, api, fn = helpers.command, helpers.api, helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, neq = n.clear, t.eq, t.neq +local command, api, fn = n.command, n.api, n.fn local tbl_deep_extend = vim.tbl_deep_extend -- Set up two overlapping floating windows diff --git a/test/functional/vimscript/screenpos_spec.lua b/test/functional/vimscript/screenpos_spec.lua index b951d830a6..630e19b841 100644 --- a/test/functional/vimscript/screenpos_spec.lua +++ b/test/functional/vimscript/screenpos_spec.lua @@ -1,7 +1,9 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eq, api = helpers.clear, helpers.eq, helpers.api -local command, fn = helpers.command, helpers.fn -local feed = helpers.feed +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eq, api = n.clear, t.eq, n.api +local command, fn = n.command, n.fn +local feed = n.feed before_each(clear) diff --git a/test/functional/vimscript/server_spec.lua b/test/functional/vimscript/server_spec.lua index 360fcf0dfe..4b0dc087f6 100644 --- a/test/functional/vimscript/server_spec.lua +++ b/test/functional/vimscript/server_spec.lua @@ -1,12 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local assert_log = helpers.assert_log -local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval -local clear, fn, api = helpers.clear, helpers.fn, helpers.api -local ok = helpers.ok -local matches = helpers.matches -local pcall_err = helpers.pcall_err -local mkdir = helpers.mkdir -local is_os = helpers.is_os +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local assert_log = t.assert_log +local eq, neq, eval = t.eq, t.neq, n.eval +local clear, fn, api = n.clear, n.fn, n.api +local ok = t.ok +local matches = t.matches +local pcall_err = t.pcall_err +local check_close = n.check_close +local mkdir = t.mkdir +local rmdir = n.rmdir +local is_os = t.is_os local testlog = 'Xtest-server-log' @@ -18,12 +22,16 @@ end describe('server', function() after_each(function() + check_close() os.remove(testlog) end) it('serverstart() stores sockets in $XDG_RUNTIME_DIR', function() local dir = 'Xtest_xdg_run' mkdir(dir) + finally(function() + rmdir(dir) + end) clear({ env = { XDG_RUNTIME_DIR = dir } }) matches(dir, fn.stdpath('run')) if not is_os('win') then @@ -100,14 +108,14 @@ describe('server', function() local s = fn.serverstart('127.0.0.1:0') -- assign random port if #s > 0 then - assert(string.match(s, '127.0.0.1:%d+')) + matches('127.0.0.1:%d+', s) eq(s, fn.serverlist()[1]) clear_serverlist() end s = fn.serverstart('127.0.0.1:') -- assign random port if #s > 0 then - assert(string.match(s, '127.0.0.1:%d+')) + matches('127.0.0.1:%d+', s) eq(s, fn.serverlist()[1]) clear_serverlist() end @@ -142,7 +150,7 @@ describe('server', function() it('serverlist() returns the list of servers', function() clear() -- There should already be at least one server. - local n = eval('len(serverlist())') + local _n = eval('len(serverlist())') -- Add some servers. local servs = ( @@ -156,25 +164,25 @@ describe('server', function() local new_servs = eval('serverlist()') -- Exactly #servs servers should be added. - eq(n + #servs, #new_servs) + eq(_n + #servs, #new_servs) -- The new servers should be at the end of the list. for i = 1, #servs do - eq(servs[i], new_servs[i + n]) + eq(servs[i], new_servs[i + _n]) eq(1, eval("serverstop('" .. servs[i] .. "')")) end -- After serverstop() the servers should NOT be in the list. - eq(n, eval('len(serverlist())')) + eq(_n, eval('len(serverlist())')) end) end) describe('startup --listen', function() it('validates', function() clear() - local cmd = { unpack(helpers.nvim_argv) } + local cmd = { unpack(n.nvim_argv) } table.insert(cmd, '--listen') matches('nvim.*: Argument missing after: "%-%-listen"', fn.system(cmd)) - cmd = { unpack(helpers.nvim_argv) } + cmd = { unpack(n.nvim_argv) } table.insert(cmd, '--listen2') matches('nvim.*: Garbage after option argument: "%-%-listen2"', fn.system(cmd)) end) diff --git a/test/functional/vimscript/setpos_spec.lua b/test/functional/vimscript/setpos_spec.lua index a26e48f469..968da4d8f4 100644 --- a/test/functional/vimscript/setpos_spec.lua +++ b/test/functional/vimscript/setpos_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) -local setpos = helpers.fn.setpos -local getpos = helpers.fn.getpos -local insert = helpers.insert -local clear = helpers.clear -local command = helpers.command -local eval = helpers.eval -local eq = helpers.eq -local exc_exec = helpers.exc_exec +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local setpos = n.fn.setpos +local getpos = n.fn.getpos +local insert = n.insert +local clear = n.clear +local command = n.command +local eval = n.eval +local eq = t.eq +local exc_exec = n.exc_exec describe('setpos() function', function() before_each(function() diff --git a/test/functional/vimscript/sort_spec.lua b/test/functional/vimscript/sort_spec.lua index bd3d0da146..c8c1651ed8 100644 --- a/test/functional/vimscript/sort_spec.lua +++ b/test/functional/vimscript/sort_spec.lua @@ -1,14 +1,15 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq +local eq = t.eq local NIL = vim.NIL -local eval = helpers.eval -local clear = helpers.clear -local api = helpers.api -local fn = helpers.fn -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err +local eval = n.eval +local clear = n.clear +local api = n.api +local fn = n.fn +local command = n.command +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err before_each(clear) diff --git a/test/functional/vimscript/special_vars_spec.lua b/test/functional/vimscript/special_vars_spec.lua index 590d409141..70e195ba0b 100644 --- a/test/functional/vimscript/special_vars_spec.lua +++ b/test/functional/vimscript/special_vars_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local exc_exec = helpers.exc_exec -local command = helpers.command -local fn = helpers.fn -local clear = helpers.clear -local eval = helpers.eval -local eq = helpers.eq -local api = helpers.api +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local exc_exec = n.exc_exec +local command = n.command +local fn = n.fn +local clear = n.clear +local eval = n.eval +local eq = t.eq +local api = n.api local NIL = vim.NIL describe('Special values', function() diff --git a/test/functional/vimscript/state_spec.lua b/test/functional/vimscript/state_spec.lua index 7179806e36..211d79928a 100644 --- a/test/functional/vimscript/state_spec.lua +++ b/test/functional/vimscript/state_spec.lua @@ -1,11 +1,13 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local exec = helpers.exec -local exec_lua = helpers.exec_lua -local feed = helpers.feed -local api = helpers.api -local poke_eventloop = helpers.poke_eventloop +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local exec = n.exec +local exec_lua = n.exec_lua +local feed = n.feed +local api = n.api +local poke_eventloop = n.poke_eventloop before_each(clear) diff --git a/test/functional/vimscript/string_spec.lua b/test/functional/vimscript/string_spec.lua index 6a7fe1bad9..32aa04c0d0 100644 --- a/test/functional/vimscript/string_spec.lua +++ b/test/functional/vimscript/string_spec.lua @@ -1,14 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear -local eq = helpers.eq -local command = helpers.command -local api = helpers.api -local eval = helpers.eval -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err -local fn = helpers.fn +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear = n.clear +local eq = t.eq +local command = n.command +local api = n.api +local eval = n.eval +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err +local fn = n.fn local NIL = vim.NIL -local source = helpers.source +local source = n.source describe('string() function', function() before_each(clear) @@ -190,7 +192,7 @@ describe('string() function', function() eval('add(l, l)') -- Regression: the below line used to crash (add returns original list and -- there was error in dumping partials). Tested explicitly in - -- test/unit/api/private_helpers_spec.lua. + -- test/unit/api/private_t_spec.lua. eval('add(l, function("Test1", l))') eq( [=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=], diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua index d44f68e152..792e4c46c3 100644 --- a/test/functional/vimscript/system_spec.lua +++ b/test/functional/vimscript/system_spec.lua @@ -1,26 +1,20 @@ -- Tests for system() and :! shell. -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') -local assert_alive = helpers.assert_alive -local testprg = helpers.testprg +local assert_alive = n.assert_alive +local testprg = n.testprg local eq, call, clear, eval, feed_command, feed, api = - helpers.eq, - helpers.call, - helpers.clear, - helpers.eval, - helpers.feed_command, - helpers.feed, - helpers.api -local command = helpers.command -local insert = helpers.insert -local expect = helpers.expect -local exc_exec = helpers.exc_exec -local os_kill = helpers.os_kill -local pcall_err = helpers.pcall_err -local is_os = helpers.is_os - -local Screen = require('test.functional.ui.screen') + t.eq, n.call, n.clear, n.eval, n.feed_command, n.feed, n.api +local command = n.command +local insert = n.insert +local expect = n.expect +local exc_exec = n.exc_exec +local os_kill = n.os_kill +local pcall_err = t.pcall_err +local is_os = t.is_os local function create_file_with_nuls(name) return function() @@ -189,7 +183,7 @@ describe('system()', function() end) it('with powershell', function() - helpers.set_shell_powershell() + n.set_shell_powershell() eq('a\nb\n', eval([[system('Write-Output a b')]])) eq('C:\\\n', eval([[system('cd c:\; (Get-Location).Path')]])) eq('a b\n', eval([[system('Write-Output "a b"')]])) @@ -197,11 +191,11 @@ describe('system()', function() end it('powershell w/ UTF-8 text #13713', function() - if not helpers.has_powershell() then + if not n.has_powershell() then pending('powershell not found', function() end) return end - helpers.set_shell_powershell() + n.set_shell_powershell() eq('ああ\n', eval([[system('Write-Output "ああ"')]])) -- Sanity test w/ default encoding -- * on Windows, expected to default to Western European enc @@ -214,7 +208,7 @@ describe('system()', function() feed(':call system("echo")<cr>') screen:expect([[ ^ | - ~ |*12 + {1:~ }|*12 :call system("echo") | ]]) end) @@ -234,7 +228,7 @@ describe('system()', function() end) it('self and total time recorded separately', function() - local tempfile = helpers.tmpname() + local tempfile = t.tmpname() feed(':function! AlmostNoSelfTime()<cr>') feed('echo system("echo hi")<cr>') @@ -247,11 +241,11 @@ describe('system()', function() feed(':edit ' .. tempfile .. '<cr>') - local command_total_time = tonumber(helpers.fn.split(helpers.fn.getline(7))[2]) - local command_self_time = tonumber(helpers.fn.split(helpers.fn.getline(7))[3]) + local command_total_time = tonumber(n.fn.split(n.fn.getline(7))[2]) + local command_self_time = tonumber(n.fn.split(n.fn.getline(7))[3]) - helpers.neq(nil, command_total_time) - helpers.neq(nil, command_self_time) + t.neq(nil, command_total_time) + t.neq(nil, command_self_time) end) it('`yes` interrupted with CTRL-C', function() @@ -262,14 +256,14 @@ describe('system()', function() ) screen:expect([[ | - ~ |*12 + {1:~ }|*12 ]] .. (is_os('win') and [[ :call system("for /L %I in (1,0,2) do @echo y") |]] or [[ :call system("yes") |]])) feed('foo<c-c>') screen:expect([[ ^ | - ~ |*12 + {1:~ }|*12 Type :qa and press <Enter> to exit Nvim | ]]) end) @@ -283,15 +277,15 @@ describe('system()', function() ) screen:expect([[ | - ~ |*12 + {1:~ }|*12 ]] .. (is_os('win') and [[ :call system("for /L %I in (1,0,2) do @echo y") |]] or [[ :call system("yes") |]])) feed('foo<c-c>') screen:expect([[ ^ | - ~ |*12 - -- INSERT -- | + {1:~ }|*12 + {5:-- INSERT --} | ]]) end) end) @@ -447,7 +441,7 @@ describe('systemlist()', function() feed(':call systemlist("echo")<cr>') screen:expect([[ ^ | - ~ |*12 + {1:~ }|*12 :call systemlist("echo") | ]]) end) @@ -456,13 +450,13 @@ describe('systemlist()', function() feed(':call systemlist("yes | xargs")<cr>') screen:expect([[ | - ~ |*12 + {1:~ }|*12 :call systemlist("yes | xargs") | ]]) feed('<c-c>') screen:expect([[ ^ | - ~ |*12 + {1:~ }|*12 Type :qa and press <Enter> to exit Nvim | ]]) end) @@ -554,11 +548,11 @@ describe('systemlist()', function() end) it('powershell w/ UTF-8 text #13713', function() - if not helpers.has_powershell() then + if not n.has_powershell() then pending('powershell not found', function() end) return end - helpers.set_shell_powershell() + n.set_shell_powershell() eq({ is_os('win') and 'あ\r' or 'あ' }, eval([[systemlist('Write-Output あ')]])) -- Sanity test w/ default encoding -- * on Windows, expected to default to Western European enc @@ -574,7 +568,7 @@ describe('shell :!', function() it(':{range}! with powershell filter/redirect #16271 #19250', function() local screen = Screen.new(500, 8) screen:attach() - local found = helpers.set_shell_powershell(true) + local found = n.set_shell_powershell(true) insert([[ 3 1 @@ -621,12 +615,12 @@ describe('shell :!', function() } end feed('<CR>') - helpers.set_shell_powershell(true) + n.set_shell_powershell(true) feed(':4verbose %w !sort<cr>') screen:expect { any = [[Executing command: .?& { Get%-Content .* | & sort }]], } feed('<CR>') - helpers.expect_exit(command, 'qall!') + n.expect_exit(command, 'qall!') end) end) diff --git a/test/functional/vimscript/timer_spec.lua b/test/functional/vimscript/timer_spec.lua index 046d451888..f075e382bc 100644 --- a/test/functional/vimscript/timer_spec.lua +++ b/test/functional/vimscript/timer_spec.lua @@ -1,12 +1,14 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local feed, eq, eval, ok = helpers.feed, helpers.eq, helpers.eval, helpers.ok -local source, async_meths, run = helpers.source, helpers.async_meths, helpers.run -local clear, command, fn = helpers.clear, helpers.command, helpers.fn -local exc_exec = helpers.exc_exec -local api = helpers.api -local load_adjust = helpers.load_adjust -local retry = helpers.retry + +local feed, eq, eval, ok = n.feed, t.eq, n.eval, t.ok +local source, async_meths, run = n.source, n.async_meths, n.run +local clear, command, fn = n.clear, n.command, n.fn +local exc_exec = n.exc_exec +local api = n.api +local load_adjust = n.load_adjust +local retry = t.retry describe('timers', function() before_each(function() diff --git a/test/functional/vimscript/uniq_spec.lua b/test/functional/vimscript/uniq_spec.lua index 8fd4004be4..4e1ef699a4 100644 --- a/test/functional/vimscript/uniq_spec.lua +++ b/test/functional/vimscript/uniq_spec.lua @@ -1,10 +1,11 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local eq = helpers.eq -local clear = helpers.clear -local command = helpers.command -local exc_exec = helpers.exc_exec -local pcall_err = helpers.pcall_err +local eq = t.eq +local clear = n.clear +local command = n.command +local exc_exec = n.exc_exec +local pcall_err = t.pcall_err before_each(clear) diff --git a/test/functional/vimscript/vvar_event_spec.lua b/test/functional/vimscript/vvar_event_spec.lua index 68eda05363..16fa2c9f9f 100644 --- a/test/functional/vimscript/vvar_event_spec.lua +++ b/test/functional/vimscript/vvar_event_spec.lua @@ -1,6 +1,8 @@ -local helpers = require('test.functional.helpers')(after_each) -local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq -local command = helpers.command +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local clear, eval, eq = n.clear, n.eval, t.eq +local command = n.command describe('v:event', function() before_each(clear) it('is empty before any autocommand', function() diff --git a/test/functional/vimscript/wait_spec.lua b/test/functional/vimscript/wait_spec.lua index 50cdb2cfb4..0932bd3593 100644 --- a/test/functional/vimscript/wait_spec.lua +++ b/test/functional/vimscript/wait_spec.lua @@ -1,15 +1,17 @@ -local helpers = require('test.functional.helpers')(after_each) -local call = helpers.call -local clear = helpers.clear -local command = helpers.command -local eval = helpers.eval -local eq = helpers.eq -local feed = helpers.feed -local feed_command = helpers.feed_command -local next_msg = helpers.next_msg -local api = helpers.api -local source = helpers.source -local pcall_err = helpers.pcall_err +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local call = n.call +local clear = n.clear +local command = n.command +local eval = n.eval +local eq = t.eq +local feed = n.feed +local feed_command = n.feed_command +local next_msg = n.next_msg +local api = n.api +local source = n.source +local pcall_err = t.pcall_err before_each(function() clear() @@ -60,7 +62,7 @@ describe('wait()', function() ]]) -- XXX: flaky (#11137) - helpers.retry(nil, nil, function() + t.retry(nil, nil, function() api.nvim_set_var('counter', 0) eq(-1, call('wait', 20, 'Count() >= 5', 99999)) end) diff --git a/test/functional/vimscript/writefile_spec.lua b/test/functional/vimscript/writefile_spec.lua index 051e3794a3..404aceb92b 100644 --- a/test/functional/vimscript/writefile_spec.lua +++ b/test/functional/vimscript/writefile_spec.lua @@ -1,15 +1,16 @@ -local helpers = require('test.functional.helpers')(after_each) +local t = require('test.testutil') +local n = require('test.functional.testnvim')() -local mkdir = helpers.mkdir -local clear = helpers.clear -local eq = helpers.eq -local fn = helpers.fn -local api = helpers.api -local exc_exec = helpers.exc_exec -local read_file = helpers.read_file -local write_file = helpers.write_file -local pcall_err = helpers.pcall_err -local command = helpers.command +local mkdir = t.mkdir +local clear = n.clear +local eq = t.eq +local fn = n.fn +local api = n.api +local exc_exec = n.exc_exec +local read_file = t.read_file +local write_file = t.write_file +local pcall_err = t.pcall_err +local command = n.command local fname = 'Xtest-functional-eval-writefile' local dname = fname .. '.d' diff --git a/test/old/testdir/load.vim b/test/old/testdir/load.vim index 5697ee7304..58ec0b1356 100644 --- a/test/old/testdir/load.vim +++ b/test/old/testdir/load.vim @@ -1,4 +1,4 @@ -" Also used by: test/functional/helpers.lua +" Also used by: test/functional/testnvim.lua function! s:load_factor() abort let timeout = 200 diff --git a/test/old/testdir/setup.vim b/test/old/testdir/setup.vim index 091fb95806..7313a0a162 100644 --- a/test/old/testdir/setup.vim +++ b/test/old/testdir/setup.vim @@ -44,12 +44,16 @@ if exists('s:did_load') endif let s:did_load = 1 -" Clear Nvim default mappings and menus. +" Clear Nvim default user commands, mappings and menus. +comclear mapclear mapclear! aunmenu * tlunmenu * +" Undo the 'grepprg' and 'grepformat' setting in _defaults.lua. +set grepprg& grepformat& + " roughly equivalent to test_setmouse() in Vim func Ntest_setmouse(row, col) call nvim_input_mouse('move', '', '', 0, a:row - 1, a:col - 1) diff --git a/test/old/testdir/test.sh b/test/old/testdir/test.sh index 6e7fa9db18..cb6feb4e68 100644 --- a/test/old/testdir/test.sh +++ b/test/old/testdir/test.sh @@ -58,7 +58,7 @@ check_core_dumps() { } check_logs() { - # Iterate through each log to remove an useless warning. + # Iterate through each log to remove a useless warning. # shellcheck disable=SC2044 for log in $(find "${1}" -type f -name "${2}"); do sed -i "${log}" \ diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index 4d88573a1f..cdcd68f3d6 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -740,6 +740,27 @@ func Test_WinClosed_switch_tab() %bwipe! endfunc +" This used to trigger WinClosed twice for the same window, and the window's +" buffer was NULL in the second autocommand. +func Test_WinClosed_BufUnload_close_other() + tabnew + let g:tab = tabpagenr() + let g:buf = bufnr() + new + setlocal bufhidden=wipe + augroup test-WinClosed + autocmd BufUnload * ++once exe g:buf .. 'bwipe!' + autocmd WinClosed * call tabpagebuflist(g:tab) + augroup END + close + + unlet g:tab + unlet g:buf + autocmd! test-WinClosed + augroup! test-WinClosed + %bwipe! +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' @@ -3476,74 +3497,6 @@ func Test_autocmd_vimgrep() augroup END endfunc -" Test TextChangedI and TextChanged -func Test_Changed_ChangedI() - throw 'Skipped: use test/functional/autocmd/textchanged_spec.lua' - new - call test_override("char_avail", 1) - let [g:autocmd_i, g:autocmd_n] = ['',''] - - func! TextChangedAutocmdI(char) - let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick - endfunc - - augroup Test_TextChanged - au! - au TextChanged <buffer> :call TextChangedAutocmdI('N') - au TextChangedI <buffer> :call TextChangedAutocmdI('I') - augroup END - - call feedkeys("ifoo\<esc>", 'tnix') - " TODO: Test test does not seem to trigger TextChanged autocommand, this - " requires running Vim in a terminal window. - " call assert_equal('N3', g:autocmd_n) - call assert_equal('I3', g:autocmd_i) - - call feedkeys("yyp", 'tnix') - " TODO: Test test does not seem to trigger TextChanged autocommand. - " call assert_equal('N4', g:autocmd_n) - call assert_equal('I3', g:autocmd_i) - - " TextChangedI should only trigger if change was done in Insert mode - let g:autocmd_i = '' - call feedkeys("yypi\<esc>", 'tnix') - call assert_equal('', g:autocmd_i) - - " TextChanged should only trigger if change was done in Normal mode - let g:autocmd_n = '' - call feedkeys("ibar\<esc>", 'tnix') - call assert_equal('', g:autocmd_n) - - " If change is a mix of Normal and Insert modes, TextChangedI should trigger - func s:validate_mixed_textchangedi(keys) - call feedkeys("ifoo\<esc>", 'tnix') - let g:autocmd_i = '' - let g:autocmd_n = '' - call feedkeys(a:keys, 'tnix') - call assert_notequal('', g:autocmd_i) - call assert_equal('', g:autocmd_n) - endfunc - - call s:validate_mixed_textchangedi("o\<esc>") - call s:validate_mixed_textchangedi("O\<esc>") - call s:validate_mixed_textchangedi("ciw\<esc>") - call s:validate_mixed_textchangedi("cc\<esc>") - call s:validate_mixed_textchangedi("C\<esc>") - call s:validate_mixed_textchangedi("s\<esc>") - call s:validate_mixed_textchangedi("S\<esc>") - - - " CleanUp - call test_override("char_avail", 0) - au! TextChanged <buffer> - au! TextChangedI <buffer> - augroup! Test_TextChanged - delfu TextChangedAutocmdI - unlet! g:autocmd_i g:autocmd_n - - bw! -endfunc - func Test_closing_autocmd_window() let lines =<< trim END edit Xa.txt @@ -3569,6 +3522,49 @@ func Test_switch_window_in_autocmd_window() call assert_false(bufexists('Xb.txt')) endfunc +" Test that using the autocommand window doesn't change current directory. +func Test_autocmd_window_cwd() + let saveddir = getcwd() + call mkdir('Xcwd/a/b/c/d', 'pR') + + new Xa.txt + tabnew + new Xb.txt + + tabprev + cd Xcwd + call assert_match('/Xcwd$', getcwd()) + call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) + + autocmd BufEnter Xb.txt lcd ./a/b/c/d + doautoall BufEnter + au! BufEnter + call assert_match('/Xcwd$', getcwd()) + call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) + + tabnext + cd ./a + tcd ./b + lcd ./c + call assert_match('/Xcwd/a/b/c$', getcwd()) + call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) + + autocmd BufEnter Xa.txt call assert_match('Xcwd/a/b/c$', getcwd()) + doautoall BufEnter + au! BufEnter + call assert_match('/Xcwd/a/b/c$', getcwd()) + call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) + bwipe! + call assert_match('/Xcwd/a/b$', getcwd()) + call assert_match('\[tabpage\] .*/Xcwd/a/b$', trim(execute('verbose pwd'))) + bwipe! + call assert_match('/Xcwd/a$', getcwd()) + call assert_match('\[global\] .*/Xcwd/a$', trim(execute('verbose pwd'))) + bwipe! + + call chdir(saveddir) +endfunc + func Test_bufwipeout_changes_window() " This should not crash, but we don't have any expectations about what " happens, changing window in BufWipeout has unpredictable results. @@ -3880,4 +3876,248 @@ func Test_autocmd_creates_new_buffer_on_bufleave() bw c.txt endfunc +" Ensure `expected` was just recently written as a Vim session +func s:assert_session_path(expected) + call assert_equal(a:expected, v:this_session) +endfunc + +" Check for `expected` after a session is written to-disk. +func s:watch_for_session_path(expected) + execute 'autocmd SessionWritePost * ++once execute "call s:assert_session_path(\"' + \ . a:expected + \ . '\")"' +endfunc + +" Ensure v:this_session gets the full session path, if explicitly stated +func Test_explicit_session_absolute_path() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let name = "some_file.vim" + let expected = fnamemodify(name, ":p") + call s:watch_for_session_path(expected) + execute "mksession! " .. expected + + call delete(expected) +endfunc + +" Ensure v:this_session gets the full session path, if explicitly stated +func Test_explicit_session_relative_path() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let name = "some_file.vim" + let expected = fnamemodify(name, ":p") + call s:watch_for_session_path(expected) + execute "mksession! " .. name + + call delete(expected) +endfunc + +" Ensure v:this_session gets the full session path, if not specified +func Test_implicit_session() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let expected = fnamemodify("Session.vim", ":p") + call s:watch_for_session_path(expected) + mksession! + + call delete(expected) +endfunc + +" Test TextChangedI and TextChanged +func Test_Changed_ChangedI() + " Run this test in a terminal because it requires running the main loop. + " Don't use CheckRunVimInTerminal as that will skip the test on Windows. + CheckFeature terminal + CheckNotGui + " Starting a terminal to run Vim is always considered flaky. + let g:test_is_flaky = 1 + + call writefile(['one', 'two', 'three'], 'XTextChangedI2', 'D') + let before =<< trim END + set ttimeout ttimeoutlen=10 + let [g:autocmd_n, g:autocmd_i] = ['',''] + + func TextChangedAutocmd(char) + let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick + call writefile([$'{g:autocmd_n},{g:autocmd_i}'], 'XTextChangedI3') + endfunc + + au TextChanged <buffer> :call TextChangedAutocmd('N') + au TextChangedI <buffer> :call TextChangedAutocmd('I') + + nnoremap <CR> o<Esc> + autocmd SafeState * ++once call writefile([''], 'XTextChangedI3') + END + + call writefile(before, 'Xinit', 'D') + let buf = term_start( + \ GetVimCommandCleanTerm() .. '-n -S Xinit XTextChangedI2', + \ {'term_rows': 10}) + call assert_equal('running', term_getstatus(buf)) + call WaitForAssert({-> assert_true(filereadable('XTextChangedI3'))}) + defer delete('XTextChangedI3') + call WaitForAssert({-> assert_equal([''], readfile('XTextChangedI3'))}) + + " TextChanged should trigger if a mapping enters and leaves Insert mode. + call term_sendkeys(buf, "\<CR>") + call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) + + call term_sendkeys(buf, "i") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) + " TextChangedI should trigger if change is done in Insert mode. + call term_sendkeys(buf, "f") + call WaitForAssert({-> assert_equal('N4,I5', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "o") + call WaitForAssert({-> assert_equal('N4,I6', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "o") + call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) + " TextChanged shouldn't trigger when leaving Insert mode and TextChangedI + " has been triggered. + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChanged should trigger if change is done in Normal mode. + call term_sendkeys(buf, "yyp") + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChangedI shouldn't trigger if change isn't done in Insert mode. + call term_sendkeys(buf, "i") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChangedI should trigger if change is a mix of Normal and Insert modes. + func! s:validate_mixed_textchangedi(buf, keys) + let buf = a:buf + call term_sendkeys(buf, "ifoo") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call term_sendkeys(buf, ":let [g:autocmd_n, g:autocmd_i] = ['', '']\<CR>") + call writefile([], 'XTextChangedI3') + call term_sendkeys(buf, a:keys) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) + endfunc + + call s:validate_mixed_textchangedi(buf, "o") + call s:validate_mixed_textchangedi(buf, "O") + call s:validate_mixed_textchangedi(buf, "ciw") + call s:validate_mixed_textchangedi(buf, "cc") + call s:validate_mixed_textchangedi(buf, "C") + call s:validate_mixed_textchangedi(buf, "s") + call s:validate_mixed_textchangedi(buf, "S") + + " clean up + bwipe! +endfunc + +" Test that filetype detection still works when SwapExists autocommand sets +" filetype in another buffer. +func Test_SwapExists_set_other_buf_filetype() + let lines =<< trim END + set nocompatible directory=. + filetype on + + let g:buf = bufnr() + new + + func SwapExists() + let v:swapchoice = 'o' + call setbufvar(g:buf, '&filetype', 'text') + endfunc + + func SafeState() + edit <script> + redir! > XftSwapExists.out + set readonly? filetype? + redir END + qall! + endfunc + + autocmd SwapExists * ++nested call SwapExists() + autocmd SafeState * ++nested ++once call SafeState() + END + call writefile(lines, 'XftSwapExists.vim', 'D') + + new XftSwapExists.vim + if RunVim('', '', ' -S XftSwapExists.vim') + call assert_equal( + \ ['', ' readonly', ' filetype=vim'], + \ readfile('XftSwapExists.out')) + call delete('XftSwapExists.out') + endif + + bwipe! +endfunc + +" Test that file is not marked as modified when SwapExists autocommand sets +" 'modified' in another buffer. +func Test_SwapExists_set_other_buf_modified() + let lines =<< trim END + set nocompatible directory=. + + let g:buf = bufnr() + new + + func SwapExists() + let v:swapchoice = 'o' + call setbufvar(g:buf, '&modified', 1) + endfunc + + func SafeState() + edit <script> + redir! > XmodSwapExists.out + set readonly? modified? + redir END + qall! + endfunc + + autocmd SwapExists * ++nested call SwapExists() + autocmd SafeState * ++nested ++once call SafeState() + END + call writefile(lines, 'XmodSwapExists.vim', 'D') + + new XmodSwapExists.vim + if RunVim('', '', ' -S XmodSwapExists.vim') + call assert_equal( + \ ['', ' readonly', 'nomodified'], + \ readfile('XmodSwapExists.out')) + call delete('XmodSwapExists.out') + endif + + bwipe! +endfunc + +func Test_BufEnter_botline() + set hidden + call writefile(range(10), 'Xxx1', 'D') + call writefile(range(20), 'Xxx2', 'D') + edit Xxx1 + edit Xxx2 + au BufEnter Xxx1 call assert_true(line('w$') > 1) + edit Xxx1 + + bwipe! Xxx1 + bwipe! Xxx2 + au! BufEnter Xxx1 + set hidden&vim +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_buffer.vim b/test/old/testdir/test_buffer.vim index b0b9f4f24b..bc8e5eaf7b 100644 --- a/test/old/testdir/test_buffer.vim +++ b/test/old/testdir/test_buffer.vim @@ -133,7 +133,7 @@ func Test_bdelete_cmd() call assert_fails('1,1bdelete 1 2', 'E488:') call assert_fails('bdelete \)', 'E55:') - " Deleting a unlisted and unloaded buffer + " Deleting an unlisted and unloaded buffer edit Xbdelfile1 let bnr = bufnr() set nobuflisted @@ -232,8 +232,6 @@ endfunc " Test for deleting a modified buffer with :confirm func Test_bdel_with_confirm() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/buffer_spec.lua' CheckUnix CheckNotGui CheckFeature dialog_con @@ -251,26 +249,33 @@ endfunc " Test for editing another buffer from a modified buffer with :confirm func Test_goto_buf_with_confirm() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/buffer_spec.lua' CheckUnix CheckNotGui CheckFeature dialog_con + " When dialog_con_gui is defined, Vim is compiled with GUI support + " and FEAT_BROWSE will be defined, which causes :confirm :b to + " call do_browse(), which will try to use a GUI file browser, + " which aborts if a GUI is not available. + CheckNotFeature dialog_con_gui new XgotoConf enew call setline(1, 'test') call assert_fails('b XgotoConf', 'E37:') call feedkeys('c', 'L') call assert_fails('confirm b XgotoConf', 'E37:') - call assert_equal(1, &modified) - call assert_equal('', @%) + call assert_true(&modified) + call assert_true(empty(bufname('%'))) call feedkeys('y', 'L') - call assert_fails('confirm b XgotoConf', ['', 'E37:']) - call assert_equal(1, &modified) - call assert_equal('', @%) + confirm b XgotoConf + call assert_equal('XgotoConf', bufname('%')) + call assert_equal(['test'], readfile('Untitled')) + e Untitled + call setline(2, 'test2') call feedkeys('n', 'L') confirm b XgotoConf - call assert_equal('XgotoConf', @%) + call assert_equal('XgotoConf', bufname('%')) + call assert_equal(['test'], readfile('Untitled')) + call delete('Untitled') close! endfunc diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim index b8eb9a2b8b..443539fbfd 100644 --- a/test/old/testdir/test_cmdline.vim +++ b/test/old/testdir/test_cmdline.vim @@ -3907,9 +3907,9 @@ func Test_custom_completion() call assert_fails("call getcompletion('', 'custom')", 'E475:') call assert_fails("call getcompletion('', 'customlist')", 'E475:') - call assert_equal(getcompletion('', 'custom,CustomComplete1'), ['a', 'b', 'c']) - call assert_equal(getcompletion('', 'customlist,CustomComplete2'), ['a', 'b']) - call assert_equal(getcompletion('b', 'customlist,CustomComplete2'), ['b']) + call assert_equal(['a', 'b', 'c'], getcompletion('', 'custom,CustomComplete1')) + call assert_equal(['a', 'b'], getcompletion('', 'customlist,CustomComplete2')) + call assert_equal(['b'], getcompletion('b', 'customlist,CustomComplete2')) delcom Test1 delcom Test2 @@ -3966,4 +3966,22 @@ func Test_buffer_completion() call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:) endfunc +" :set t_?? +func Test_term_option() + throw 'Skipped: Nvim does not support termcap options' + set wildoptions& + let _cpo = &cpo + set cpo-=C + " There may be more, test only until t_xo + let expected='"set t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm' + \ .. ' t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe' + \ .. ' t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC' + \ .. ' t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr' + \ .. ' t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi' + \ .. ' t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u t_xo .*' + call feedkeys(":set t_\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match(expected, @:) + let &cpo = _cpo +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_comments.vim b/test/old/testdir/test_comments.vim index c34b85c42d..67454f477e 100644 --- a/test/old/testdir/test_comments.vim +++ b/test/old/testdir/test_comments.vim @@ -237,6 +237,12 @@ func Test_comment_autoformat() call feedkeys("aone\ntwo\n", 'xt') call assert_equal(['one', 'two', ''], getline(1, '$')) + set backspace=indent,eol,start + %d + call feedkeys("aone \n\<BS>", 'xt') + call assert_equal(['one'], getline(1, '$')) + set backspace& + close! endfunc diff --git a/test/old/testdir/test_compiler.vim b/test/old/testdir/test_compiler.vim index 0b22bafabb..69420b4b7f 100644 --- a/test/old/testdir/test_compiler.vim +++ b/test/old/testdir/test_compiler.vim @@ -62,10 +62,10 @@ func Test_compiler_completion() call assert_match('^"compiler ' .. clist .. '$', @:) call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('"compiler pbx perl\( p[a-z]\+\)\+ pylint pyunit', @:) + call assert_match('"compiler pandoc pbx perl\( p[a-z_]\+\)\+ pylint pyunit', @:) call feedkeys(":compiler! p\<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('"compiler! pbx perl\( p[a-z]\+\)\+ pylint pyunit', @:) + call assert_match('"compiler! pandoc pbx perl\( p[a-z_]\+\)\+ pylint pyunit', @:) endfunc func Test_compiler_error() diff --git a/test/old/testdir/test_conceal.vim b/test/old/testdir/test_conceal.vim index a679061544..df20654f12 100644 --- a/test/old/testdir/test_conceal.vim +++ b/test/old/testdir/test_conceal.vim @@ -169,6 +169,58 @@ func Test_conceal_with_cursorcolumn() call StopVimInTerminal(buf) endfunc +" Check that 'cursorline' and 'wincolor' apply to the whole line in presence +" of wrapped lines containing concealed text. +func Test_conceal_wrapped_cursorline_wincolor() + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline + normal! g$ + [CODE] + + call writefile(code, 'XTest_conceal_cul_wcr', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr', {'rows': 4, 'cols': 40}) + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_01', {}) + + call term_sendkeys(buf, ":set wincolor=ErrorMsg\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_02', {}) + + call term_sendkeys(buf, ":set nocursorline\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_03', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +" Same as Test_conceal_wrapped_cursorline_wincolor(), but with 'rightleft'. +func Test_conceal_wrapped_cursorline_wincolor_rightleft() + CheckFeature rightleft + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline rightleft + normal! g$ + [CODE] + + call writefile(code, 'XTest_conceal_cul_wcr_rl', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr_rl', {'rows': 4, 'cols': 40}) + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_01', {}) + + call term_sendkeys(buf, ":set wincolor=ErrorMsg\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_02', {}) + + call term_sendkeys(buf, ":set nocursorline\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_03', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + func Test_conceal_resize_term() CheckScreendump @@ -336,77 +388,290 @@ func Test_conceal_eol() endfunc func Test_conceal_mouse_click() - enew! + call NewWindow(10, 40) set mouse=a setlocal conceallevel=2 concealcursor=nc syn match Concealed "this" conceal hi link Concealed Search - call setline(1, 'conceal this click here') - redraw - call assert_equal(['conceal click here '], ScreenLines(1, 20)) - - " click on the space between "this" and "click" puts cursor there - call Ntest_setmouse(1, 9) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 13, 0, 13], getcurpos()) - " click on 'h' of "here" puts cursor there - call Ntest_setmouse(1, 16) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 20, 0, 20], getcurpos()) - " click on 'e' of "here" puts cursor there - call Ntest_setmouse(1, 19) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 23], getcurpos()) - " click after end of line puts cursor on 'e' without 'virtualedit' - call Ntest_setmouse(1, 20) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 24], getcurpos()) - call Ntest_setmouse(1, 21) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 25], getcurpos()) - call Ntest_setmouse(1, 22) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 26], getcurpos()) - call Ntest_setmouse(1, 31) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 35], getcurpos()) - call Ntest_setmouse(1, 32) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 36], getcurpos()) - - set virtualedit=all - redraw - " click on the space between "this" and "click" puts cursor there - call Ntest_setmouse(1, 9) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 13, 0, 13], getcurpos()) - " click on 'h' of "here" puts cursor there - call Ntest_setmouse(1, 16) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 20, 0, 20], getcurpos()) - " click on 'e' of "here" puts cursor there - call Ntest_setmouse(1, 19) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 23], getcurpos()) - " click after end of line puts cursor there without 'virtualedit' - call Ntest_setmouse(1, 20) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 0, 24], getcurpos()) - call Ntest_setmouse(1, 21) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 1, 25], getcurpos()) - call Ntest_setmouse(1, 22) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 2, 26], getcurpos()) - call Ntest_setmouse(1, 31) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 11, 35], getcurpos()) - call Ntest_setmouse(1, 32) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 12, 36], getcurpos()) - - bwipe! - set mouse& virtualedit& + + " Test with both 'nocursorline' and 'cursorline', as they use two different + " code paths to set virtual columns for the cells to clear. + for cul in [v:false, v:true] + let &l:cursorline = cul + + call setline(1, 'conceal this click here') + call assert_equal([ + \ 'conceal click here ', + \ ], ScreenLines(1, 40)) + + " Click on the space between "this" and "click" puts cursor there. + call Ntest_setmouse(1, 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call Ntest_setmouse(1, 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call Ntest_setmouse(1, 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor on 'e' without 'virtualedit'. + call Ntest_setmouse(1, 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 24], getcurpos()) + call Ntest_setmouse(1, 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 25], getcurpos()) + call Ntest_setmouse(1, 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 26], getcurpos()) + call Ntest_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 35], getcurpos()) + call Ntest_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 36], getcurpos()) + + set virtualedit=all + redraw + " Click on the space between "this" and "click" puts cursor there. + call Ntest_setmouse(1, 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call Ntest_setmouse(1, 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call Ntest_setmouse(1, 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor there with 'virtualedit'. + call Ntest_setmouse(1, 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 0, 24], getcurpos()) + call Ntest_setmouse(1, 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 1, 25], getcurpos()) + call Ntest_setmouse(1, 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 2, 26], getcurpos()) + call Ntest_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call Ntest_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + " Behavior should also be the same with 'colorcolumn'. + setlocal colorcolumn=30 + redraw + call Ntest_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call Ntest_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + setlocal colorcolumn& + + if has('rightleft') + setlocal rightleft + call assert_equal([ + \ ' ereh kcilc laecnoc', + \ ], ScreenLines(1, 40)) + " Click on the space between "this" and "click" puts cursor there. + call Ntest_setmouse(1, 41 - 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call Ntest_setmouse(1, 41 - 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call Ntest_setmouse(1, 41 - 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor there with 'virtualedit'. + call Ntest_setmouse(1, 41 - 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 0, 24], getcurpos()) + call Ntest_setmouse(1, 41 - 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 1, 25], getcurpos()) + call Ntest_setmouse(1, 41 - 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 2, 26], getcurpos()) + call Ntest_setmouse(1, 41 - 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call Ntest_setmouse(1, 41 - 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + setlocal rightleft& + endif + + set virtualedit& + + " Test with a wrapped line. + call setline(1, ['conceal this click here']->repeat(3)->join()) + call assert_equal([ + \ 'conceal click here conceal cli ', + \ 'ck here conceal click here ', + \ ], ScreenLines([1, 2], 40)) + " Click on boguscols puts cursor on the last char of a screen line. + for col in range(33, 40) + call Ntest_setmouse(1, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 40, 0, 40], getcurpos()) + endfor + + " Also test with the last char of a screen line concealed. + setlocal number signcolumn=yes + call assert_equal([ + \ ' 1 conceal click here conceal ', + \ ' click here conceal click h ', + \ ' ere ', + \ ], ScreenLines([1, 3], 40)) + call Ntest_setmouse(1, 34) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 32, 0, 32], getcurpos()) + call Ntest_setmouse(2, 7) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 37, 0, 37], getcurpos()) + " Click on boguscols puts cursor on the last char of a screen line. + for col in range(35, 40) + call Ntest_setmouse(1, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 34, 0, 34], getcurpos()) + call Ntest_setmouse(2, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 68, 0, 68], getcurpos()) + endfor + setlocal number& signcolumn& + endfor + + call CloseWindow() + set mouse& +endfunc + +" Test that cursor is drawn at the correct column when it is after end of the +" line with 'virtualedit' and concealing. +func Run_test_conceal_virtualedit_after_eol(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_ve_after_eol', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol', {'rows': 3}) + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_1', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_2', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_3', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_4', {}) + call term_sendkeys(buf, "rr") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_5', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_virtualedit_after_eol() + CheckScreendump + + call Run_test_conceal_virtualedit_after_eol(1) + call Run_test_conceal_virtualedit_after_eol(0) +endfunc + +" Same as Run_test_conceal_virtualedit_after_eol(), but with 'rightleft'. +func Run_test_conceal_virtualedit_after_eol_rightleft(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all rightleft + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_ve_after_eol_rl', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol_rl', {'rows': 3}) + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_1', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_2', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_3', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_4', {}) + call term_sendkeys(buf, "rr") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_5', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_virtualedit_after_eol_rightleft() + CheckFeature rightleft + CheckScreendump + + call Run_test_conceal_virtualedit_after_eol_rightleft(1) + call Run_test_conceal_virtualedit_after_eol_rightleft(0) +endfunc + +" Test that cursor position is correct when double-width chars are concealed. +func Run_test_conceal_double_width(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, ['aaaaa口=口bbbbb口=口ccccc', 'foobar']) + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n colorcolumn=30 + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_double_width', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_double_width', {'rows': 4}) + call VerifyScreenDump(buf, 'Test_conceal_double_width_1', {}) + call term_sendkeys(buf, "gM") + call VerifyScreenDump(buf, 'Test_conceal_double_width_2', {}) + call term_sendkeys(buf, ":set conceallevel=3\<CR>") + call VerifyScreenDump(buf, 'Test_conceal_double_width_3', {}) + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_conceal_double_width_4', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_double_width() + CheckScreendump + + call Run_test_conceal_double_width(1) + call Run_test_conceal_double_width(0) +endfunc + +" Test that line wrapping is correct when double-width chars are concealed. +func Test_conceal_double_width_wrap() + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'aaaaaaaaaa口=口bbbbbbbbbb口=口cccccccccc') + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_double_width_wrap', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_double_width_wrap', {'rows': 4, 'cols': 20}) + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_1', {}) + call term_sendkeys(buf, "gM") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_2', {}) + call term_sendkeys(buf, ":set conceallevel=3\<CR>") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_3', {}) + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_4', {}) + + " clean up + call StopVimInTerminal(buf) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim index 9a3e006430..71483b7469 100644 --- a/test/old/testdir/test_diffmode.vim +++ b/test/old/testdir/test_diffmode.vim @@ -3,6 +3,7 @@ source shared.vim source screendump.vim source check.vim +source view_util.vim func Test_diff_fold_sync() enew! @@ -1631,36 +1632,39 @@ endfunc func Test_diff_scroll_many_filler() 20new vnew - call setline(1, ['^^^', '^^^', '$$$', '$$$']) + call setline(1, range(1, 40)) diffthis setlocal scrolloff=0 wincmd p - call setline(1, ['^^^', '^^^'] + repeat(['###'], 41) + ['$$$', '$$$']) + call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse()) diffthis setlocal scrolloff=0 wincmd p redraw " Note: need a redraw after each scroll, otherwise the test always passes. - normal! G - redraw - call assert_equal(3, winsaveview().topline) - call assert_equal(18, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(3, winsaveview().topline) - call assert_equal(19, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(2, winsaveview().topline) - call assert_equal(0, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(1, winsaveview().topline) - call assert_equal(0, winsaveview().topfill) + for _ in range(2) + normal! G + redraw + call assert_equal(40, winsaveview().topline) + call assert_equal(19, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(22, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(4, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(1, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + set smoothscroll + endfor - bwipe! - bwipe! + set smoothscroll& + %bwipe! endfunc " This was trying to update diffs for a buffer being closed @@ -1702,4 +1706,89 @@ func Test_diff_put_and_undo() endfunc +func Test_diff_toggle_wrap_skipcol_leftcol() + 61vnew + call setline(1, 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.') + 30vnew + call setline(1, 'ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.') + let win1 = win_getid() + setlocal smoothscroll + exe "normal! $\<C-E>" + wincmd l + let win2 = win_getid() + setlocal smoothscroll + exe "normal! $\<C-E>" + call assert_equal([ + \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|', + \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|', + \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|', + \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|', + \ '~ |ptua. |', + \ ], ScreenLines([1, 5], 62)) + call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + wincmd h + diffthis + wincmd l + diffthis + normal! 0 + call assert_equal([ + \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |', + \ '~ |~ |', + \ ], ScreenLines([1, 2], 62)) + call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + normal! $ + call assert_equal([ + \ ' voluptua. | diam voluptua. |', + \ '~ |~ |', + \ ], ScreenLines([1, 2], 62)) + call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + diffoff! + call assert_equal([ + \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|', + \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|', + \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|', + \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|', + \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|', + \ '~ |ptua. |', + \ ], ScreenLines([1, 6], 62)) + call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + bwipe! + bwipe! +endfunc + +" Ctrl-D reveals filler lines below the last line in the buffer. +func Test_diff_eob_halfpage() + new + call setline(1, ['']->repeat(10) + ['a']) + diffthis + new + call setline(1, ['']->repeat(3) + ['a', 'b']) + diffthis + resize 5 + wincmd j + resize 5 + norm G + call assert_equal(7, line('w0')) + exe "norm! \<C-D>" + call assert_equal(8, line('w0')) + + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_digraph.vim b/test/old/testdir/test_digraph.vim index 8229248f7f..8fbcd4d8ca 100644 --- a/test/old/testdir/test_digraph.vim +++ b/test/old/testdir/test_digraph.vim @@ -539,6 +539,8 @@ func Test_digraph_set_function() call assert_fails('call digraph_set("あ", "あ")', 'E1214: Digraph must be just two characters: あ') call assert_fails('call digraph_set("aa", "ああ")', 'E1215: Digraph must be one character: ああ') call assert_fails('call digraph_set("aa", "か" .. nr2char(0x3099))', 'E1215: Digraph must be one character: か' .. nr2char(0x3099)) + call assert_fails('call digraph_set(v:_null_string, "い")', 'E1214: Digraph must be just two characters') + call assert_fails('call digraph_set("aa", 0z10)', 'E976: Using a Blob as a String') bwipe! endfunc @@ -556,6 +558,8 @@ func Test_digraph_get_function() call assert_equal('う', digraph_get(' ')) call assert_fails('call digraph_get("aaa")', 'E1214: Digraph must be just two characters: aaa') call assert_fails('call digraph_get("b")', 'E1214: Digraph must be just two characters: b') + call assert_fails('call digraph_get(v:_null_string)', 'E1214: Digraph must be just two characters:') + call assert_fails('call digraph_get(0z10)', 'E976: Using a Blob as a String') endfunc func Test_digraph_get_function_encode() @@ -580,8 +584,12 @@ func Test_digraph_setlist_function() call assert_equal('く', digraph_get('bb')) call assert_fails('call digraph_setlist([[]])', 'E1216:') - call assert_fails('call digraph_setlist([["aa", "b", "cc"]])', '1216:') + call assert_fails('call digraph_setlist([["aa", "b", "cc"]])', 'E1216:') call assert_fails('call digraph_setlist([["あ", "あ"]])', 'E1214: Digraph must be just two characters: あ') + call assert_fails('call digraph_setlist([v:_null_list])', 'E1216:') + call assert_fails('call digraph_setlist({})', 'E1216:') + call assert_fails('call digraph_setlist([{}])', 'E1216:') + call assert_true(digraph_setlist(v:_null_list)) endfunc func Test_digraph_getlist_function() @@ -589,13 +597,15 @@ func Test_digraph_getlist_function() call digraph_setlist([['aa', 'き'], ['bb', 'く']]) for pair in digraph_getlist(1) - call assert_equal(digraph_get(pair[0]), pair[1]) + call assert_equal(pair[1], digraph_get(pair[0])) endfor " We don't know how many digraphs are registered before, so check the number " of digraphs returned. call assert_equal(digraph_getlist()->len(), digraph_getlist(0)->len()) - call assert_notequal((digraph_getlist()->len()), digraph_getlist(1)->len()) + call assert_notequal(digraph_getlist()->len(), digraph_getlist(1)->len()) + + call assert_fails('call digraph_getlist(0z12)', 'E974: Using a Blob as a Number') endfunc diff --git a/test/old/testdir/test_edit.vim b/test/old/testdir/test_edit.vim index 67143ab524..57ff63f26d 100644 --- a/test/old/testdir/test_edit.vim +++ b/test/old/testdir/test_edit.vim @@ -6,8 +6,6 @@ endif source check.vim source screendump.vim - -" Needed for testing basic rightleft: Test_edit_rightleft source view_util.vim " Needs to come first until the bug in getchar() is @@ -1320,9 +1318,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 1, 0], getpos('.')) + call assert_equal([0, 10, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) " <S-Up> is the same as <PageUp> " <S-Down> is the same as <PageDown> call cursor(1, 1) @@ -1343,9 +1341,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 1, 0], getpos('.')) + call assert_equal([0, 10, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) set nostartofline call cursor(30, 11) norm! zt @@ -1356,9 +1354,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) @@ -1381,9 +1379,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) @@ -1985,8 +1983,8 @@ func Test_edit_ctrl_r_failed() let buf = RunVimInTerminal('', #{rows: 6, cols: 60}) - " trying to insert a dictionary produces an error - call term_sendkeys(buf, "i\<C-R>={}\<CR>") + " trying to insert a blob produces an error + call term_sendkeys(buf, "i\<C-R>=0z\<CR>") " ending Insert mode should put the cursor back on the ':' call term_sendkeys(buf, ":\<Esc>") @@ -2067,7 +2065,10 @@ func Test_edit_revins() call setline(1, 'one two three') exe "normal! wi\nfour" call assert_equal(['one two three', 'ruof'], getline(1, '$')) - set revins& + set backspace=indent,eol,start + exe "normal! ggA\<BS>:" + call assert_equal(['one two three:ruof'], getline(1, '$')) + set revins& backspace& bw! endfunc @@ -2153,4 +2154,133 @@ func Test_edit_Ctrl_RSB() bwipe! endfunc +func s:check_backspace(expected) + let g:actual = [] + inoremap <buffer> <F2> <Cmd>let g:actual += [getline('.')]<CR> + set backspace=indent,eol,start + + exe "normal i" .. repeat("\<BS>\<F2>", len(a:expected)) + call assert_equal(a:expected, g:actual) + + set backspace& + iunmap <buffer> <F2> + unlet g:actual +endfunc + +" Test that backspace works with 'smarttab' and mixed Tabs and spaces. +func Test_edit_backspace_smarttab_mixed() + set smarttab + call NewWindow(1, 30) + setlocal tabstop=4 shiftwidth=4 + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and 'varsofttabstop'. +func Test_edit_backspace_smarttab_varsofttabstop() + CheckFeature vartabs + + set smarttab + call NewWindow(1, 30) + setlocal tabstop=8 varsofttabstop=6,2,5,3 + + call setline(1, "a\t \t a") + normal! $ + call s:check_backspace([ + \ "a\t \ta", + \ "a\t a", + \ "a\ta", + \ "a a", + \ "aa", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' when a Tab is shown as "^I". +func Test_edit_backspace_smarttab_list() + set smarttab + call NewWindow(1, 30) + setlocal tabstop=4 shiftwidth=4 list listchars= + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and 'breakindent'. +func Test_edit_backspace_smarttab_breakindent() + CheckFeature linebreak + + set smarttab + call NewWindow(3, 17) + setlocal tabstop=4 shiftwidth=4 breakindent breakindentopt=min:5 + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and virtual text. +func Test_edit_backspace_smarttab_virtual_text() + CheckFeature textprop + + set smarttab + call NewWindow(1, 50) + setlocal tabstop=4 shiftwidth=4 + + call setline(1, "\t \t \t a") + call prop_type_add('theprop', {}) + call prop_add(1, 3, {'type': 'theprop', 'text': 'text'}) + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + call prop_type_delete('theprop') + set smarttab& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_excmd.vim b/test/old/testdir/test_excmd.vim index b7356c22fa..4a780078fd 100644 --- a/test/old/testdir/test_excmd.vim +++ b/test/old/testdir/test_excmd.vim @@ -3,6 +3,7 @@ source check.vim source shared.vim source term_util.vim +source screendump.vim func Test_ex_delete() new @@ -758,4 +759,19 @@ func Test_ex_address_range_overflow() call assert_fails(':--+foobar', 'E492:') endfunc +func Test_drop_modified_file() + CheckScreendump + let lines =<< trim END + call setline(1, 'The quick brown fox jumped over the lazy dogs') + END + call writefile([''], 'Xdrop_modified.txt', 'D') + call writefile(lines, 'Xtest_drop_modified', 'D') + let buf = RunVimInTerminal('-S Xtest_drop_modified Xdrop_modified.txt', {'rows': 10,'columns': 40}) + call term_sendkeys(buf, ":drop Xdrop_modified.txt\<CR>") + call VerifyScreenDump(buf, 'Test_drop_modified_1', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_execute_func.vim b/test/old/testdir/test_execute_func.vim index 2edae39b8f..ec8ed160c3 100644 --- a/test/old/testdir/test_execute_func.vim +++ b/test/old/testdir/test_execute_func.vim @@ -3,6 +3,7 @@ source view_util.vim source check.vim source vim9.vim +source term_util.vim func NestedEval() let nested = execute('echo "nested\nlines"') @@ -177,6 +178,27 @@ func Test_win_execute_visual_redraw() bwipe! endfunc +func Test_win_execute_on_startup() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + [repeat('x', &columns)]->writefile('Xfile1') + silent tabedit Xfile2 + var id = win_getid() + silent tabedit Xfile3 + autocmd VimEnter * win_execute(id, 'close') + END + call writefile(lines, 'XwinExecute') + let buf = RunVimInTerminal('-p Xfile1 -Nu XwinExecute', {}) + + " this was crashing on exit with EXITFREE defined + call StopVimInTerminal(buf) + + call delete('XwinExecute') + call delete('Xfile1') +endfunc + func Test_execute_cmd_with_null() call assert_equal("", execute(v:_null_string)) call assert_equal("", execute(v:_null_list)) @@ -190,4 +212,28 @@ func Test_execute_cmd_with_null() endif endfunc +func Test_win_execute_tabpagewinnr() + belowright split + tab split + belowright split + call assert_equal(2, tabpagewinnr(1)) + + tabprevious + wincmd p + call assert_equal(1, tabpagenr()) + call assert_equal(1, tabpagewinnr(1)) + call assert_equal(2, tabpagewinnr(2)) + + call win_execute(win_getid(1, 2), + \ 'call assert_equal(2, tabpagenr())' + \ .. '| call assert_equal(1, tabpagewinnr(1))' + \ .. '| call assert_equal(1, tabpagewinnr(2))') + + call assert_equal(1, tabpagenr()) + call assert_equal(1, tabpagewinnr(1)) + call assert_equal(2, tabpagewinnr(2)) + + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_expand.vim b/test/old/testdir/test_expand.vim index cd537f4ea1..24df156386 100644 --- a/test/old/testdir/test_expand.vim +++ b/test/old/testdir/test_expand.vim @@ -45,12 +45,25 @@ endfunc func Test_expand_tilde_filename() split ~ - call assert_equal('~', expand('%')) + call assert_equal('~', expand('%')) call assert_notequal(expand('%:p'), expand('~/')) - call assert_match('\~', expand('%:p')) + call assert_match('\~', expand('%:p')) bwipe! endfunc +func Test_expand_env_pathsep() + let $FOO = './foo' + call assert_equal('./foo/bar', expand('$FOO/bar')) + let $FOO = './foo/' + call assert_equal('./foo/bar', expand('$FOO/bar')) + let $FOO = 'C:' + call assert_equal('C:/bar', expand('$FOO/bar')) + let $FOO = 'C:/' + call assert_equal('C:/bar', expand('$FOO/bar')) + + unlet $FOO +endfunc + func Test_expandcmd() let $FOO = 'Test' call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y')) diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim index d316e63818..8871e7e7d7 100644 --- a/test/old/testdir/test_expr.vim +++ b/test/old/testdir/test_expr.vim @@ -904,6 +904,22 @@ func Test_string_interp() endif call assert_equal(0, tmp) + #" Dict interpolation + VAR d = {'a': 10, 'b': [1, 2]} + call assert_equal("{'a': 10, 'b': [1, 2]}", $'{d}') + VAR emptydict = {} + call assert_equal("a{}b", $'a{emptydict}b') + VAR nulldict = v:_null_dict + call assert_equal("a{}b", $'a{nulldict}b') + + #" List interpolation + VAR l = ['a', 'b', 'c'] + call assert_equal("['a', 'b', 'c']", $'{l}') + VAR emptylist = [] + call assert_equal("a[]b", $'a{emptylist}b') + VAR nulllist = v:_null_list + call assert_equal("a[]b", $'a{nulllist}b') + #" Stray closing brace. call assert_fails('echo $"moo}"', 'E1278:') #" Undefined variable in expansion. diff --git a/test/old/testdir/test_filechanged.vim b/test/old/testdir/test_filechanged.vim index fef0eb732f..a8fc78ff90 100644 --- a/test/old/testdir/test_filechanged.vim +++ b/test/old/testdir/test_filechanged.vim @@ -11,8 +11,12 @@ func Test_FileChangedShell_reload() new Xchanged_r call setline(1, 'reload this') write - " Need to wait until the timestamp would change by at least a second. - sleep 2 + " Need to wait until the timestamp would change. + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'extra line' >>Xchanged_r checktime call assert_equal('changed', g:reason) @@ -50,7 +54,11 @@ func Test_FileChangedShell_reload() call assert_equal('new line', getline(1)) " Only time changed - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !touch Xchanged_r let g:reason = '' checktime @@ -65,7 +73,11 @@ func Test_FileChangedShell_reload() call setline(2, 'before write') write call setline(2, 'after write') - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'different line' >>Xchanged_r let g:reason = '' checktime @@ -140,8 +152,6 @@ func Test_FileChangedShell_edit() endfunc func Test_FileChangedShell_edit_dialog() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckNotGui CheckUnix " Using low level feedkeys() does not work on MS-Windows. @@ -156,6 +166,7 @@ func Test_FileChangedShell_edit_dialog() au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask' augroup END call assert_equal(&fileformat, 'unix') + sleep 10m " make the test less flaky in Nvim call writefile(["line1\r", "line2\r"], 'Xchanged_r') let g:reason = '' call feedkeys('L', 'L') " load file content only @@ -173,6 +184,7 @@ func Test_FileChangedShell_edit_dialog() au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask' augroup END call assert_equal(&fileformat, 'unix') + sleep 10m " make the test less flaky in Nvim call writefile(["line1\r", "line2\r"], 'Xchanged_r') let g:reason = '' call feedkeys('a', 'L') " load file content and options @@ -191,8 +203,6 @@ func Test_FileChangedShell_edit_dialog() endfunc func Test_file_changed_dialog() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckUnix CheckNotGui au! FileChangedShell @@ -200,8 +210,12 @@ func Test_file_changed_dialog() new Xchanged_d call setline(1, 'reload this') write - " Need to wait until the timestamp would change by at least a second. - sleep 2 + " Need to wait until the timestamp would change. + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'extra line' >>Xchanged_d call feedkeys('L', 'L') checktime @@ -236,7 +250,11 @@ func Test_file_changed_dialog() call assert_equal('new line', getline(1)) " Only time changed, no prompt - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !touch Xchanged_d let v:warningmsg = '' checktime Xchanged_d diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index 303b1585e2..34fe93fd55 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -1,5 +1,16 @@ " Test :setfiletype +func Test_backup_strip() + filetype on + let fname = 'Xdetect.js~~~~~~~~~~~' + call writefile(['one', 'two', 'three'], fname, 'D') + exe 'edit ' .. fname + call assert_equal('javascript', &filetype) + + bwipe! + filetype off +endfunc + func Test_detection() filetype on augroup filetypedetect @@ -97,7 +108,7 @@ func s:GetFilenameChecks() abort \ 'asterisk': ['asterisk/file.conf', 'asterisk/file.conf-file', 'some-asterisk/file.conf', 'some-asterisk/file.conf-file'], \ 'astro': ['file.astro'], \ 'atlas': ['file.atl', 'file.as'], - \ 'authzed': ['file.zed'], + \ 'authzed': ['schema.zed'], \ 'autohotkey': ['file.ahk'], \ 'autoit': ['file.au3'], \ 'automake': ['GNUmakefile.am', 'makefile.am', 'Makefile.am'], @@ -116,11 +127,12 @@ func s:GetFilenameChecks() abort \ 'blade': ['file.blade.php'], \ 'blank': ['file.bl'], \ 'blueprint': ['file.blp'], + \ 'bp': ['Android.bp'], \ 'bsdl': ['file.bsd', 'file.bsdl'], \ 'bst': ['file.bst'], \ 'bzl': ['file.bazel', 'file.bzl', 'WORKSPACE', 'WORKSPACE.bzlmod'], \ 'bzr': ['bzr_log.any', 'bzr_log.file'], - \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c', 'some-enlightenment/file.cfg'], + \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c', 'some-enlightenment/file.cfg', 'file.mdh', 'file.epro'], \ 'cabal': ['file.cabal'], \ 'cabalconfig': ['cabal.config', expand("$HOME/.config/cabal/config")] + s:WhenConfigHome('$XDG_CONFIG_HOME/cabal/config'), \ 'cabalproject': ['cabal.project', 'cabal.project.local'], @@ -134,6 +146,7 @@ func s:GetFilenameChecks() abort \ 'cf': ['file.cfm', 'file.cfi', 'file.cfc'], \ 'cfengine': ['cfengine.conf'], \ 'cfg': ['file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], + \ 'cgdbrc': ['cgdbrc'], \ 'ch': ['file.chf'], \ 'chaiscript': ['file.chai'], \ 'chaskell': ['file.chs'], @@ -143,16 +156,17 @@ func s:GetFilenameChecks() abort \ 'chuck': ['file.ck'], \ 'cl': ['file.eni'], \ 'clean': ['file.dcl', 'file.icl'], - \ 'clojure': ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'], + \ 'clojure': ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc', 'init.trans', 'any/etc/translate-shell', '.trans'], \ 'cmake': ['CMakeLists.txt', 'file.cmake', 'file.cmake.in'], + \ 'cmakecache': ['CMakeCache.txt'], \ 'cmod': ['file.cmod'], \ 'cmusrc': ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme', '/.cmus/autosave', '/.cmus/command-history', '/.cmus/file.theme', '/.cmus/rc', '/cmus/file.theme', '/cmus/rc'], \ 'cobol': ['file.cbl', 'file.cob', 'file.lib'], \ 'coco': ['file.atg'], \ 'conaryrecipe': ['file.recipe'], - \ 'conf': ['auto.master', 'file.conf'], + \ 'conf': ['auto.master', 'file.conf', 'texdoc.cnf', '.x11vncrc', '.chktexrc', '.ripgreprc', 'ripgreprc', 'file.ctags', '.mbsyncrc'], \ 'config': ['configure.in', 'configure.ac', '/etc/hostname.file', 'any/etc/hostname.file'], - \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], + \ 'confini': ['pacman.conf', 'paru.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'], \ 'cook': ['file.cook'], \ 'corn': ['file.corn'], @@ -179,6 +193,7 @@ func s:GetFilenameChecks() abort \ 'cynpp': ['file.cyn'], \ 'cypher': ['file.cypher'], \ 'd': ['file.d'], + \ 'dafny': ['file.dfy'], \ 'dart': ['file.dart', 'file.drt'], \ 'datascript': ['file.ds'], \ 'dcd': ['file.dcd'], @@ -199,16 +214,24 @@ func s:GetFilenameChecks() abort \ 'dnsmasq': ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'], \ 'dockerfile': ['Containerfile', 'Dockerfile', 'dockerfile', 'file.Dockerfile', 'file.dockerfile', 'Dockerfile.debian', 'Containerfile.something'], \ 'dosbatch': ['file.bat'], - \ 'dosini': ['/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap', 'file.vbp', 'ja2.ini', 'JA2.INI'], + \ 'dosini': ['/etc/yum.conf', '/etc/nfs.conf', '/etc/nfsmount.conf', 'file.ini', + \ 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', + \ '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap', + \ 'file.vbp', 'ja2.ini', 'JA2.INI', 'mimeapps.list', 'pip.conf', 'setup.cfg', 'pudb.cfg', + \ '.coveragerc', '.pypirc', '.gitlint', '.oelint.cfg', 'pylintrc', '.pylintrc', + \ '/home/user/.config/bpython/config', '/home/user/.config/mypy/config', '.wakatime.cfg', '.replyrc', + \ 'psprint.conf', 'sofficerc', 'any/.config/lxqt/globalkeyshortcuts.conf', 'any/.config/screengrab/screengrab.conf', + \ 'any/.local/share/flatpak/repo/config', '.notmuch-config'], \ 'dot': ['file.dot', 'file.gv'], \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], \ 'dtd': ['file.dtd'], \ 'dtrace': ['/usr/lib/dtrace/io.d'], - \ 'dts': ['file.dts', 'file.dtsi', 'file.dtso', 'file.its'], + \ 'dts': ['file.dts', 'file.dtsi', 'file.dtso', 'file.its', 'file.keymap'], \ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'], \ 'dylan': ['file.dylan'], \ 'dylanintr': ['file.intr'], \ 'dylanlid': ['file.lid'], + \ 'earthfile': ['Earthfile'], \ 'ecd': ['file.ecd'], \ 'edif': ['file.edf', 'file.edif', 'file.edo'], \ 'editorconfig': ['.editorconfig'], @@ -272,7 +295,7 @@ func s:GetFilenameChecks() abort \ 'glsl': ['file.glsl'], \ 'gn': ['file.gn', 'file.gni'], \ 'gnash': ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], - \ 'gnuplot': ['file.gpi', '.gnuplot'], + \ 'gnuplot': ['file.gpi', '.gnuplot', 'file.gnuplot', '.gnuplot_history'], \ 'go': ['file.go'], \ 'gomod': ['go.mod'], \ 'gosum': ['go.sum', 'go.work.sum'], @@ -301,7 +324,7 @@ func s:GetFilenameChecks() abort \ 'hcl': ['file.hcl'], \ 'heex': ['file.heex'], \ 'hercules': ['file.vc', 'file.ev', 'file.sum', 'file.errsum'], - \ 'hex': ['file.hex', 'file.h32'], + \ 'hex': ['file.hex', 'file.ihex', 'file.ihe', 'file.ihx', 'file.int', 'file.mcs', 'file.h32', 'file.h80', 'file.h86', 'file.a43', 'file.a90'], \ 'hgcommit': ['hg-editor-file.txt'], \ 'hjson': ['file.hjson'], \ 'hlsplaylist': ['file.m3u', 'file.m3u8'], @@ -314,6 +337,7 @@ func s:GetFilenameChecks() abort \ 'htmlm4': ['file.html.m4'], \ 'httest': ['file.htt', 'file.htb'], \ 'hurl': ['file.hurl'], + \ 'hyprlang': ['hyprlock.conf', 'hyprland.conf', 'hypridle.conf', 'hyprpaper.conf'], \ 'i3config': ['/home/user/.i3/config', '/home/user/.config/i3/config', '/etc/i3/config', '/etc/xdg/i3/config'], \ 'ibasic': ['file.iba', 'file.ibi'], \ 'icemenu': ['/.icewm/menu', 'any/.icewm/menu'], @@ -322,6 +346,7 @@ func s:GetFilenameChecks() abort \ 'inform': ['file.inf', 'file.INF'], \ 'initng': ['/etc/initng/any/file.i', 'file.ii', 'any/etc/initng/any/file.i'], \ 'inittab': ['inittab'], + \ 'inko': ['file.inko'], \ 'ipfilter': ['ipf.conf', 'ipf6.conf', 'ipf.rules'], \ 'iss': ['file.iss'], \ 'ist': ['file.ist', 'file.mst'], @@ -331,17 +356,18 @@ func s:GetFilenameChecks() abort \ 'janet': ['file.janet'], \ 'java': ['file.java', 'file.jav'], \ 'javacc': ['file.jj', 'file.jjt'], - \ 'javascript': ['file.js', 'file.jsm', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'], + \ 'javascript': ['file.js', 'file.jsm', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs', '.node_repl_history'], \ 'javascript.glimmer': ['file.gjs'], \ 'javascriptreact': ['file.jsx'], \ 'jess': ['file.clp'], \ 'jgraph': ['file.jgr'], + \ 'jj': ['file.jjdescription'], \ 'jq': ['file.jq'], \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'], - \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'], + \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', 'file.jupyterlab-settings', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf', 'file.sublime-project', 'file.sublime-settings', 'file.sublime-workspace', 'file.bd', 'file.bda', 'file.xci', 'flake.lock'], \ 'json5': ['file.json5'], - \ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], + \ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.jscsrc', '.vsconfig', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], \ 'jsonl': ['file.jsonl'], \ 'jsonnet': ['file.jsonnet', 'file.libsonnet'], \ 'jsp': ['file.jsp'], @@ -357,7 +383,7 @@ func s:GetFilenameChecks() abort \ 'kwt': ['file.k'], \ 'lace': ['file.ace', 'file.ACE'], \ 'latte': ['file.latte', 'file.lte'], - \ 'ld': ['file.ld'], + \ 'ld': ['file.ld', 'any/usr/lib/aarch64-xilinx-linux/ldscripts/aarch64elf32b.x'], \ 'ldif': ['file.ldif'], \ 'lean': ['file.lean'], \ 'ledger': ['file.ldg', 'file.ledger', 'file.journal'], @@ -372,7 +398,7 @@ func s:GetFilenameChecks() abort \ 'limits': ['/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf', '/etc/limits.conf', '/etc/limits.d/file.conf', '/etc/some-limits.conf', '/etc/some-limits.d/file.conf', 'any/etc/limits', 'any/etc/limits.conf', 'any/etc/limits.d/file.conf', 'any/etc/some-limits.conf', 'any/etc/some-limits.d/file.conf'], \ 'liquidsoap': ['file.liq'], \ 'liquid': ['file.liquid'], - \ 'lisp': ['file.lsp', 'file.lisp', 'file.asd', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc'], + \ 'lisp': ['file.lsp', 'file.lisp', 'file.asd', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc', 'file.stsg', 'any/local/share/supertux2/config'], \ 'lite': ['file.lite', 'file.lt'], \ 'litestep': ['/LiteStep/any/file.rc', 'any/LiteStep/any/file.rc'], \ 'logcheck': ['/etc/logcheck/file.d-some/file', '/etc/logcheck/file.d/file', 'any/etc/logcheck/file.d-some/file', 'any/etc/logcheck/file.d/file'], @@ -385,17 +411,17 @@ func s:GetFilenameChecks() abort \ 'lpc': ['file.lpc', 'file.ulpc'], \ 'lsl': ['file.lsl'], \ 'lss': ['file.lss'], - \ 'lua': ['file.lua', 'file.rockspec', 'file.nse', '.luacheckrc', '.busted'], + \ 'lua': ['file.lua', 'file.tlu', 'file.rockspec', 'file.nse', '.lua_history', '.luacheckrc', '.busted', 'rock_manifest', 'config.ld'], \ 'luau': ['file.luau'], \ 'lynx': ['lynx.cfg'], \ 'lyrics': ['file.lrc'], \ 'm3build': ['m3makefile', 'm3overrides'], \ 'm3quake': ['file.quake', 'cm3.cfg'], - \ 'm4': ['file.at'], + \ 'm4': ['file.at', '.m4_history'], \ 'mail': ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml', 'reportbug-file'], \ 'mailaliases': ['/etc/mail/aliases', '/etc/aliases', 'any/etc/aliases', 'any/etc/mail/aliases'], \ 'mailcap': ['.mailcap', 'mailcap'], - \ 'make': ['file.mk', 'file.mak', 'file.dsp', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile'], + \ 'make': ['file.mk', 'file.mak', 'file.dsp', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile', 'Kbuild'], \ 'mallard': ['file.page'], "\ 'man': ['file.man'], \ 'manconf': ['/etc/man.conf', 'man.config', 'any/etc/man.conf'], @@ -410,13 +436,32 @@ func s:GetFilenameChecks() abort \ 'mel': ['file.mel'], \ 'mermaid': ['file.mmd', 'file.mmdc', 'file.mermaid'], \ 'meson': ['meson.build', 'meson.options', 'meson_options.txt'], - \ 'messages': ['/log/auth', '/log/cron', '/log/daemon', '/log/debug', '/log/kern', '/log/lpr', '/log/mail', '/log/messages', '/log/news/news', '/log/syslog', '/log/user', - \ '/log/auth.log', '/log/cron.log', '/log/daemon.log', '/log/debug.log', '/log/kern.log', '/log/lpr.log', '/log/mail.log', '/log/messages.log', '/log/news/news.log', '/log/syslog.log', '/log/user.log', - \ '/log/auth.err', '/log/cron.err', '/log/daemon.err', '/log/debug.err', '/log/kern.err', '/log/lpr.err', '/log/mail.err', '/log/messages.err', '/log/news/news.err', '/log/syslog.err', '/log/user.err', - \ '/log/auth.info', '/log/cron.info', '/log/daemon.info', '/log/debug.info', '/log/kern.info', '/log/lpr.info', '/log/mail.info', '/log/messages.info', '/log/news/news.info', '/log/syslog.info', '/log/user.info', - \ '/log/auth.warn', '/log/cron.warn', '/log/daemon.warn', '/log/debug.warn', '/log/kern.warn', '/log/lpr.warn', '/log/mail.warn', '/log/messages.warn', '/log/news/news.warn', '/log/syslog.warn', '/log/user.warn', - \ '/log/auth.crit', '/log/cron.crit', '/log/daemon.crit', '/log/debug.crit', '/log/kern.crit', '/log/lpr.crit', '/log/mail.crit', '/log/messages.crit', '/log/news/news.crit', '/log/syslog.crit', '/log/user.crit', - \ '/log/auth.notice', '/log/cron.notice', '/log/daemon.notice', '/log/debug.notice', '/log/kern.notice', '/log/lpr.notice', '/log/mail.notice', '/log/messages.notice', '/log/news/news.notice', '/log/syslog.notice', '/log/user.notice'], + \ 'messages': ['/log/auth', '/log/cron', '/log/daemon', '/log/debug', + \ '/log/kern', '/log/lpr', '/log/mail', '/log/messages', + \ '/log/news/news', '/log/syslog', '/log/user', '/log/auth.log', + \ '/log/cron.log', '/log/daemon.log', '/log/debug.log', + \ '/log/kern.log', '/log/lpr.log', '/log/mail.log', + \ '/log/messages.log', '/log/news/news.log', '/log/syslog.log', + \ '/log/user.log', '/log/auth.err', '/log/cron.err', + \ '/log/daemon.err', '/log/debug.err', '/log/kern.err', + \ '/log/lpr.err', '/log/mail.err', '/log/messages.err', + \ '/log/news/news.err', '/log/syslog.err', '/log/user.err', + \ '/log/auth.info', '/log/cron.info', '/log/daemon.info', + \ '/log/debug.info', '/log/kern.info', '/log/lpr.info', + \ '/log/mail.info', '/log/messages.info', '/log/news/news.info', + \ '/log/syslog.info', '/log/user.info', '/log/auth.warn', + \ '/log/cron.warn', '/log/daemon.warn', '/log/debug.warn', + \ '/log/kern.warn', '/log/lpr.warn', '/log/mail.warn', + \ '/log/messages.warn', '/log/news/news.warn', + \ '/log/syslog.warn', '/log/user.warn', '/log/auth.crit', + \ '/log/cron.crit', '/log/daemon.crit', '/log/debug.crit', + \ '/log/kern.crit', '/log/lpr.crit', '/log/mail.crit', + \ '/log/messages.crit', '/log/news/news.crit', + \ '/log/syslog.crit', '/log/user.crit', '/log/auth.notice', + \ '/log/cron.notice', '/log/daemon.notice', '/log/debug.notice', + \ '/log/kern.notice', '/log/lpr.notice', '/log/mail.notice', + \ '/log/messages.notice', '/log/news/news.notice', + \ '/log/syslog.notice', '/log/user.notice'], \ 'mf': ['file.mf'], \ 'mgl': ['file.mgl'], \ 'mgp': ['file.mgp'], @@ -436,11 +481,23 @@ func s:GetFilenameChecks() abort \ 'msidl': ['file.odl', 'file.mof'], \ 'msql': ['file.msql'], \ 'mojo': ['file.mojo', 'file.🔥'], + \ 'msmtp': ['.msmtprc'], \ 'mupad': ['file.mu'], \ 'mush': ['file.mush'], \ 'mustache': ['file.mustache'], - \ 'muttrc': ['Muttngrc', 'Muttrc', '.muttngrc', '.muttngrc-file', '.muttrc', '.muttrc-file', '/.mutt/muttngrc', '/.mutt/muttngrc-file', '/.mutt/muttrc', '/.mutt/muttrc-file', '/.muttng/muttngrc', '/.muttng/muttngrc-file', '/.muttng/muttrc', '/.muttng/muttrc-file', '/etc/Muttrc.d/file', '/etc/Muttrc.d/file.rc', 'Muttngrc-file', 'Muttrc-file', 'any/.mutt/muttngrc', 'any/.mutt/muttngrc-file', 'any/.mutt/muttrc', 'any/.mutt/muttrc-file', 'any/.muttng/muttngrc', 'any/.muttng/muttngrc-file', 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', 'muttrc-file'], - \ 'mysql': ['file.mysql'], + \ 'muttrc': ['Muttngrc', 'Muttrc', '.muttngrc', '.muttngrc-file', '.muttrc', + \ '.muttrc-file', '/.mutt/muttngrc', '/.mutt/muttngrc-file', + \ '/.mutt/muttrc', '/.mutt/muttrc-file', '/.muttng/muttngrc', + \ '/.muttng/muttngrc-file', '/.muttng/muttrc', + \ '/.muttng/muttrc-file', '/etc/Muttrc.d/file', + \ '/etc/Muttrc.d/file.rc', 'Muttngrc-file', 'Muttrc-file', + \ 'any/.mutt/muttngrc', 'any/.mutt/muttngrc-file', + \ 'any/.mutt/muttrc', 'any/.mutt/muttrc-file', + \ 'any/.muttng/muttngrc', 'any/.muttng/muttngrc-file', + \ 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', + \ 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', + \ 'muttrc-file'], + \ 'mysql': ['file.mysql', '.mysql_history'], \ 'n1ql': ['file.n1ql', 'file.nql'], \ 'named': ['namedfile.conf', 'rndcfile.conf', 'named-file.conf', 'named.conf', 'rndc-file.conf', 'rndc-file.key', 'rndc.conf', 'rndc.key'], \ 'nanorc': ['/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'], @@ -462,9 +519,10 @@ func s:GetFilenameChecks() abort \ 'obse': ['file.obl', 'file.obse', 'file.oblivion', 'file.obscript'], \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'], \ 'occam': ['file.occ'], - \ 'octave': ['octaverc', '.octaverc', 'octave.conf'], + \ 'octave': ['octaverc', '.octaverc', 'octave.conf', 'any/.local/share/octave/history'], \ 'odin': ['file.odin'], \ 'omnimark': ['file.xom', 'file.xin'], + \ 'ondir': ['.ondirrc'], \ 'opam': ['opam', 'file.opam', 'file.opam.template'], \ 'openroad': ['file.or'], \ 'openscad': ['file.scad'], @@ -475,10 +533,11 @@ func s:GetFilenameChecks() abort \ 'pacmanlog': ['pacman.log'], \ 'pamconf': ['/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'], \ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'], + \ 'pandoc': ['file.pandoc', 'file.pdk', 'file.pd', 'file.pdc'], \ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'], \ 'pascal': ['file.pas', 'file.dpr', 'file.lpr'], \ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak', '/etc/passwd', '/etc/passwd-', '/etc/passwd.edit', '/etc/shadow', '/etc/shadow-', '/etc/shadow.edit', '/var/backups/passwd.bak', '/var/backups/shadow.bak'], - \ 'pbtxt': ['file.pbtxt'], + \ 'pbtxt': ['file.txtpb', 'file.textproto', 'file.textpb', 'file.pbtxt'], \ 'pccts': ['file.g'], \ 'pcmk': ['file.pcmk'], \ 'pdf': ['file.pdf'], @@ -519,16 +578,17 @@ func s:GetFilenameChecks() abort \ 'psl': ['file.psl'], \ 'pug': ['file.pug'], \ 'puppet': ['file.pp'], + \ 'purescript': ['file.purs'], \ 'pymanifest': ['MANIFEST.in'], \ 'pyret': ['file.arr'], \ 'pyrex': ['file.pyx', 'file.pxd'], - \ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'], + \ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', '.python_history', '.jline-jython.history', 'file.ptl', 'file.pyi', 'SConstruct'], \ 'ql': ['file.ql', 'file.qll'], \ 'qml': ['file.qml', 'file.qbs'], \ 'qmldir': ['qmldir'], \ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'], \ 'quarto': ['file.qmd'], - \ 'r': ['file.r', '.Rprofile', 'Rprofile', 'Rprofile.site'], + \ 'r': ['file.r', '.Rhistory', '.Rprofile', 'Rprofile', 'Rprofile.site'], \ 'racket': ['file.rkt', 'file.rktd', 'file.rktl'], \ 'radiance': ['file.rad', 'file.mat'], \ 'raku': ['file.pm6', 'file.p6', 'file.t6', 'file.pod6', 'file.raku', 'file.rakumod', 'file.rakudoc', 'file.rakutest'], @@ -540,7 +600,7 @@ func s:GetFilenameChecks() abort \ 'readline': ['.inputrc', 'inputrc'], \ 'rego': ['file.rego'], \ 'remind': ['.reminders', 'file.remind', 'file.rem', '.reminders-file'], - \ 'requirements': ['file.pip', 'requirements.txt'], + \ 'requirements': ['file.pip', 'requirements.txt', 'dev-requirements.txt', 'constraints.txt', 'requirements.in', 'requirements/dev.txt', 'requires/dev.txt'], \ 'rescript': ['file.res', 'file.resi'], \ 'resolv': ['resolv.conf'], \ 'reva': ['file.frt'], @@ -554,6 +614,7 @@ func s:GetFilenameChecks() abort \ 'rpgle': ['file.rpgle', 'file.rpgleinc'], \ 'robot': ['file.robot', 'file.resource'], \ 'robots': ['robots.txt'], + \ 'roc': ['file.roc'], \ 'ron': ['file.ron'], \ 'routeros': ['file.rsc'], \ 'rpcgen': ['file.x'], @@ -561,7 +622,7 @@ func s:GetFilenameChecks() abort \ 'rrst': ['file.rrst', 'file.srst'], \ 'rst': ['file.rst'], \ 'rtf': ['file.rtf'], - \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile', 'Vagrantfile'], + \ 'ruby': ['.irbrc', 'irbrc', '.irb_history', 'irb_history', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile', 'Vagrantfile'], \ 'rust': ['file.rs'], \ 'samba': ['smb.conf'], \ 'sas': ['file.sas'], @@ -581,7 +642,10 @@ func s:GetFilenameChecks() abort \ 'services': ['/etc/services', 'any/etc/services'], \ 'setserial': ['/etc/serial.conf', 'any/etc/serial.conf'], \ 'sexplib': ['file.sexp'], - \ 'sh': ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats'], + \ 'sh': ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '.bash_history', '.bash-history', + \ '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', + \ '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats', '.ash_history', 'any/etc/neofetch/config.conf', '.xprofile', + \ 'user-dirs.defaults', 'user-dirs.dirs', 'makepkg.conf', '.makepkg.conf', 'file.mdd', 'file.cygport'], \ 'sieve': ['file.siv', 'file.sieve'], \ 'sil': ['file.sil'], \ 'simula': ['file.sim'], @@ -592,6 +656,7 @@ func s:GetFilenameChecks() abort \ 'slang': ['file.sl'], \ 'sage': ['file.sage'], \ 'slice': ['file.ice'], + \ 'slint': ['file.slint'], \ 'slpconf': ['/etc/slp.conf', 'any/etc/slp.conf'], \ 'slpreg': ['/etc/slp.reg', 'any/etc/slp.reg'], \ 'slpspi': ['/etc/slp.spi', 'any/etc/slp.spi'], @@ -612,7 +677,7 @@ func s:GetFilenameChecks() abort \ 'spice': ['file.sp', 'file.spice'], \ 'spup': ['file.speedup', 'file.spdata', 'file.spd'], \ 'spyce': ['file.spy', 'file.spi'], - \ 'sql': ['file.tyb', 'file.tyc', 'file.pkb', 'file.pks'], + \ 'sql': ['file.tyb', 'file.tyc', 'file.pkb', 'file.pks', '.sqlite_history'], \ 'sqlj': ['file.sqlj'], \ 'prql': ['file.prql'], \ 'sqr': ['file.sqr', 'file.sqi'], @@ -627,6 +692,7 @@ func s:GetFilenameChecks() abort \ 'starlark': ['file.ipd', 'file.star', 'file.starlark'], \ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'], \ 'stp': ['file.stp'], + \ 'stylus': ['a.styl', 'file.stylus'], \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'], \ 'supercollider': ['file.quark'], \ 'surface': ['file.sface'], @@ -638,7 +704,45 @@ func s:GetFilenameChecks() abort \ 'swiftgyb': ['file.swift.gyb'], \ 'swig': ['file.swg', 'file.swig'], \ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf', 'any/etc/sysctl.conf', 'any/etc/sysctl.d/file.conf'], - \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.dnssd', 'any/systemd/file.link', 'any/systemd/file.mount', 'any/systemd/file.netdev', 'any/systemd/file.network', 'any/systemd/file.nspawn', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.slice', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/some.conf.d/file.conf', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile', '/.config/systemd/user/.#', '/.config/systemd/user/.#-file', '/.config/systemd/user/file.d/.#', '/.config/systemd/user/file.d/.#-file', '/.config/systemd/user/file.d/file.conf', '/etc/systemd/file.conf.d/file.conf', '/etc/systemd/system/.#', '/etc/systemd/system/.#-file', '/etc/systemd/system/file.d/.#', '/etc/systemd/system/file.d/.#-file', '/etc/systemd/system/file.d/file.conf', '/systemd/file.automount', '/systemd/file.dnssd', '/systemd/file.link', '/systemd/file.mount', '/systemd/file.netdev', '/systemd/file.network', '/systemd/file.nspawn', '/systemd/file.path', '/systemd/file.service', '/systemd/file.slice', '/systemd/file.socket', '/systemd/file.swap', '/systemd/file.target', '/systemd/file.timer', 'any/.config/systemd/user/.#', 'any/.config/systemd/user/.#-file', 'any/.config/systemd/user/file.d/.#', 'any/.config/systemd/user/file.d/.#-file', 'any/.config/systemd/user/file.d/file.conf', 'any/etc/systemd/file.conf.d/file.conf', 'any/etc/systemd/system/.#', 'any/etc/systemd/system/.#-file', 'any/etc/systemd/system/file.d/.#', 'any/etc/systemd/system/file.d/.#-file', 'any/etc/systemd/system/file.d/file.conf'], + \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.dnssd', + \ 'any/systemd/file.link', 'any/systemd/file.mount', + \ 'any/systemd/file.netdev', 'any/systemd/file.network', + \ 'any/systemd/file.nspawn', 'any/systemd/file.path', + \ 'any/systemd/file.service', 'any/systemd/file.slice', + \ 'any/systemd/file.socket', 'any/systemd/file.swap', + \ 'any/systemd/file.target', 'any/systemd/file.timer', + \ '/etc/systemd/some.conf.d/file.conf', + \ '/etc/systemd/system/some.d/file.conf', + \ '/etc/systemd/system/some.d/.#file', + \ '/etc/systemd/system/.#otherfile', + \ '/home/user/.config/systemd/user/some.d/mine.conf', + \ '/home/user/.config/systemd/user/some.d/.#file', + \ '/home/user/.config/systemd/user/.#otherfile', + \ '/.config/systemd/user/.#', '/.config/systemd/user/.#-file', + \ '/.config/systemd/user/file.d/.#', + \ '/.config/systemd/user/file.d/.#-file', + \ '/.config/systemd/user/file.d/file.conf', + \ '/etc/systemd/file.conf.d/file.conf', '/etc/systemd/system/.#', + \ '/etc/systemd/system/.#-file', '/etc/systemd/system/file.d/.#', + \ '/etc/systemd/system/file.d/.#-file', + \ '/etc/systemd/system/file.d/file.conf', + \ '/systemd/file.automount', '/systemd/file.dnssd', + \ '/systemd/file.link', '/systemd/file.mount', + \ '/systemd/file.netdev', '/systemd/file.network', + \ '/systemd/file.nspawn', '/systemd/file.path', + \ '/systemd/file.service', '/systemd/file.slice', + \ '/systemd/file.socket', '/systemd/file.swap', + \ '/systemd/file.target', '/systemd/file.timer', + \ 'any/.config/systemd/user/.#', + \ 'any/.config/systemd/user/.#-file', + \ 'any/.config/systemd/user/file.d/.#', + \ 'any/.config/systemd/user/file.d/.#-file', + \ 'any/.config/systemd/user/file.d/file.conf', + \ 'any/etc/systemd/file.conf.d/file.conf', + \ 'any/etc/systemd/system/.#', 'any/etc/systemd/system/.#-file', + \ 'any/etc/systemd/system/file.d/.#', + \ 'any/etc/systemd/system/file.d/.#-file', + \ 'any/etc/systemd/system/file.d/file.conf'], \ 'systemverilog': ['file.sv', 'file.svh'], \ 'trace32': ['file.cmm', 'file.t32'], \ 'tags': ['tags'], @@ -646,14 +750,15 @@ func s:GetFilenameChecks() abort \ 'tal': ['file.tal'], \ 'taskdata': ['pending.data', 'completed.data', 'undo.data'], \ 'taskedit': ['file.task'], - \ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc'], + \ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc', '.tclsh-history', '.xsctcmdhistory', '.xsdbcmdhistory'], \ 'tablegen': ['file.td'], \ 'teal': ['file.tl'], + \ 'templ': ['file.templ'], \ 'template': ['file.tmpl'], \ 'teraterm': ['file.ttl'], \ 'terminfo': ['file.ti'], \ 'terraform-vars': ['file.tfvars'], - \ 'tex': ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl'], + \ 'tex': ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl', 'any/.texlive/texmf-config/tex/latex/file/file.cfg', 'file.pgf', 'file.nlo', 'file.nls', 'file.thm', 'file.eps_tex', 'file.pygtex', 'file.pygstyle', 'file.clo', 'file.aux', 'file.brf', 'file.ind', 'file.lof', 'file.loe', 'file.nav', 'file.vrb', 'file.ins', 'file.tikz', 'file.bbx', 'file.cbx', 'file.beamer'], \ 'texinfo': ['file.texinfo', 'file.texi', 'file.txi'], \ 'texmf': ['texmf.cnf'], \ 'text': ['file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'], @@ -664,7 +769,7 @@ func s:GetFilenameChecks() abort \ 'tla': ['file.tla'], \ 'tli': ['file.tli'], \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf', 'tmux.conf.local'], - \ 'toml': ['file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config'], + \ 'toml': ['file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config', '.black'], \ 'tpp': ['file.tpp'], \ 'treetop': ['file.treetop'], \ 'trustees': ['trustees.conf'], @@ -674,9 +779,10 @@ func s:GetFilenameChecks() abort \ 'tssop': ['file.tssop'], \ 'tsv': ['file.tsv'], \ 'twig': ['file.twig'], - \ 'typescript': ['file.mts', 'file.cts'], + \ 'typescript': ['file.mts', 'file.cts', '.ts_node_repl_history'], \ 'typescript.glimmer': ['file.gts'], \ 'typescriptreact': ['file.tsx'], + \ 'typespec': ['file.tsp'], \ 'ungrammar': ['file.ungram'], \ 'uc': ['file.uc'], \ 'udevconf': ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'], @@ -700,12 +806,13 @@ func s:GetFilenameChecks() abort \ 'vdmpp': ['file.vpp', 'file.vdmpp'], \ 'vdmrt': ['file.vdmrt'], \ 'vdmsl': ['file.vdm', 'file.vdmsl'], + \ 'vento': ['file.vto'], \ 'vera': ['file.vr', 'file.vri', 'file.vrh'], \ 'verilogams': ['file.va', 'file.vams'], \ 'vgrindefs': ['vgrindefs'], \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho', 'some.vhdl_1', 'some.vhdl_1-file'], \ 'vhs': ['file.tape'], - \ 'vim': ['file.vim', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file'], + \ 'vim': ['file.vim', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file', '.netrwhist'], \ 'viminfo': ['.viminfo', '_viminfo'], \ 'vmasm': ['file.mar'], \ 'voscm': ['file.cm'], @@ -731,7 +838,7 @@ func s:GetFilenameChecks() abort \ 'xinetd': ['/etc/xinetd.conf', '/etc/xinetd.d/file', 'any/etc/xinetd.conf', 'any/etc/xinetd.d/file'], \ 'xkb': ['/usr/share/X11/xkb/compat/pc', '/usr/share/X11/xkb/geometry/pc', '/usr/share/X11/xkb/keycodes/evdev', '/usr/share/X11/xkb/symbols/pc', '/usr/share/X11/xkb/types/pc'], \ 'xmath': ['file.msc', 'file.msf'], - \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd'], + \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd', 'fonts.conf', 'file.xcu', 'file.xlb', 'file.xlc', 'file.xba', 'file.xpr', 'file.xpfm', 'file.spfm', 'file.bxml'], \ 'xmodmap': ['anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'], \ 'xpm': ['file.xpm'], \ 'xpm2': ['file.xpm2'], @@ -740,24 +847,30 @@ func s:GetFilenameChecks() abort \ 'xsd': ['file.xsd'], \ 'xslt': ['file.xsl', 'file.xslt'], \ 'yacc': ['file.yy', 'file.yxx', 'file.y++'], - \ 'yaml': ['file.yaml', 'file.yml', 'file.eyaml', '.clangd', '.clang-format', '.clang-tidy'], + \ 'yaml': ['file.yaml', 'file.yml', 'file.eyaml', 'any/.bundle/config', '.clangd', '.clang-format', '.clang-tidy', 'file.mplstyle', 'matplotlibrc', 'yarn.lock'], \ 'yang': ['file.yang'], \ 'yuck': ['file.yuck'], \ 'z8a': ['file.z8a'], + \ 'zathurarc': ['zathurarc'], \ 'zig': ['file.zig', 'build.zig.zon'], \ 'zimbu': ['file.zu'], \ 'zimbutempl': ['file.zut'], \ 'zserio': ['file.zs'], - \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'], + \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', 'file.zsh-theme', 'file.zunit', + \ '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zsh_history', + \ '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', + \ 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'], \ - \ 'help': [$VIMRUNTIME . '/doc/help.txt'], + \ 'help': [$VIMRUNTIME .. '/doc/help.txt'], \ } endfunc -let s:filename_case_checks = { +func s:GetFilenameCaseChecks() abort + return { \ 'modula2': ['file.DEF'], \ 'bzl': ['file.BUILD', 'BUILD', 'BUCK'], \ } +endfunc func CheckItems(checks) set noswapfile @@ -792,26 +905,29 @@ func Test_filetype_detection() filetype on call CheckItems(s:GetFilenameChecks()) if has('fname_case') - call CheckItems(s:filename_case_checks) + call CheckItems(s:GetFilenameCaseChecks()) endif filetype off endfunc " Content lines that should not result in filetype detection -let s:false_positive_checks = { +func s:GetFalsePositiveChecks() abort + return { \ '': [['test execve("/usr/bin/pstree", ["pstree"], 0x7ff0 /* 63 vars */) = 0']], \ } +endfunc " Filetypes detected from the file contents by scripts.vim -let s:script_checks = { +func s:GetScriptChecks() abort + return { \ 'virata': [['% Virata'], - \ ['', '% Virata'], - \ ['', '', '% Virata'], - \ ['', '', '', '% Virata'], - \ ['', '', '', '', '% Virata']], + \ ['', '% Virata'], + \ ['', '', '% Virata'], + \ ['', '', '', '% Virata'], + \ ['', '', '', '', '% Virata']], \ 'strace': [['execve("/usr/bin/pstree", ["pstree"], 0x7ff0 /* 63 vars */) = 0'], - \ ['15:17:47 execve("/usr/bin/pstree", ["pstree"], ... "_=/usr/bin/strace"]) = 0'], - \ ['__libc_start_main and something']], + \ ['15:17:47 execve("/usr/bin/pstree", ["pstree"], ... "_=/usr/bin/strace"]) = 0'], + \ ['__libc_start_main and something']], \ 'clojure': [['#!/path/clojure']], \ 'scala': [['#!/path/scala']], \ 'sh': [['#!/path/sh'], @@ -875,9 +991,11 @@ let s:script_checks = { \ 'janet': [['#!/path/janet']], \ 'dart': [['#!/path/dart']], \ } +endfunc " Various forms of "env" optional arguments. -let s:script_env_checks = { +func s:GetScriptEnvChecks() abort + return { \ 'perl': [['#!/usr/bin/env VAR=val perl']], \ 'scala': [['#!/usr/bin/env VAR=val VVAR=vval scala']], \ 'awk': [['#!/usr/bin/env VAR=val -i awk']], @@ -887,6 +1005,7 @@ let s:script_env_checks = { \ 'wml': [['#!/usr/bin/env VAR=val --split-string wml']], \ 'nix': [['#!/usr/bin/env nix-shell']], \ } +endfunc func Run_script_detection(test_dict) filetype on @@ -902,9 +1021,9 @@ func Run_script_detection(test_dict) endfunc func Test_script_detection() - call Run_script_detection(s:false_positive_checks) - call Run_script_detection(s:script_checks) - call Run_script_detection(s:script_env_checks) + call Run_script_detection(s:GetFalsePositiveChecks()) + call Run_script_detection(s:GetScriptChecks()) + call Run_script_detection(s:GetScriptEnvChecks()) endfunc func Test_setfiletype_completion() @@ -1570,14 +1689,14 @@ func Test_mod_file() call assert_equal('pim', b:modula2.dialect) bwipe! - " Modula-2 program MODULE with priorty (and uppercase extension) + " Modula-2 program MODULE with priority (and uppercase extension) call writefile(['MODULE Module2Mod [42];'], 'Xfile.MOD') split Xfile.MOD call assert_equal('modula2', &filetype) call assert_equal('pim', b:modula2.dialect) bwipe! - " Modula-2 implementation MODULE with priorty (and uppercase extension) + " Modula-2 implementation MODULE with priority (and uppercase extension) call writefile(['IMPLEMENTATION MODULE Module2Mod [42];'], 'Xfile.MOD') split Xfile.MOD call assert_equal('modula2', &filetype) @@ -2328,4 +2447,26 @@ func Test_def_file() filetype off endfunc +func Test_uci_file() + filetype on + + call mkdir('any/etc/config', 'pR') + call writefile(['config firewall'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_equal('uci', &filetype) + bwipe! + + call writefile(['# config for nginx here'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_notequal('uci', &filetype) + bwipe! + + call writefile(['# Copyright Cool Cats 1997', 'config firewall'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_equal('uci', &filetype) + bwipe! + + filetype off +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_format.vim b/test/old/testdir/test_format.vim index d3578e7165..36795c87ea 100644 --- a/test/old/testdir/test_format.vim +++ b/test/old/testdir/test_format.vim @@ -105,67 +105,6 @@ func Test_printf_pos_misc() END call CheckLegacyAndVim9Success(lines) - call CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") - - call CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") - call CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") - - call CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") - - call CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") - call CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") - - call CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") - - call CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") - call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") - - call CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:") - call CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:") endfunc func Test_printf_pos_float() @@ -287,8 +226,6 @@ func Test_printf_pos_float() call assert_equal("str2float('nan')", printf('%1$S', -0.0 / 0.0)) END call CheckLegacyAndVim9Success(lines) - - call CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') endfunc func Test_printf_pos_errors() @@ -299,6 +236,111 @@ func Test_printf_pos_errors() call CheckLegacyAndVim9Failure(['echo printf("%1$s")'], 'E1503:') call CheckLegacyAndVim9Failure(['echo printf("%1$d", 1.2)'], 'E805:') call CheckLegacyAndVim9Failure(['echo printf("%1$f")'], 'E1503:') + + call CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') + + call CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") + + call CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") + call CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") + + call CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") + + call CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") + + call CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") + + call CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") + call CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") + + call CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:") + call CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:") + + call CheckLegacyAndVim9Failure(["call printf('%.123456789$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%.123456789d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789d', 5)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%123456789$5.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$123456789.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$5.123456789d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$123456789.987654321d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$5.987654321d', 5)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$.123456789d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.5d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.987654321d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.987654321d', 5)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%123456789$5.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$123456789.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$5.*123456789$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$123456789.*987654321$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$5.*987654321$d', 5)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$.*123456789d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.*1$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*987654321$d', 5)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*987654321$d', 5)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%1$*2$.*1$d', 5, 9999)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*1$.*2$d', 5, 9999)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%2$*3$.*1$d', 5, 9123, 9321)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%1$*2$.*3$d', 5, 9123, 9321)"], "E1510:") + call CheckLegacyAndVim9Failure(["call printf('%2$*1$.*3$d', 5, 9123, 9312)"], "E1510:") + + call CheckLegacyAndVim9Failure(["call printf('%1$*2$d', 5, 9999)"], "E1510:") endfunc func Test_printf_pos_64bit() diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 3f9ac94782..18d0d9aa5d 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -98,6 +98,11 @@ func Test_err_teapot() call assert_fails('call err_teapot(expr)', "E503: Coffee is currently not available") endfunc +func Test_islocked() + call assert_fails('call islocked(99)', 'E475:') + call assert_fails('call islocked("s: x")', 'E488:') +endfunc + func Test_len() call assert_equal(1, len(0)) call assert_equal(2, len(12)) @@ -2590,8 +2595,6 @@ endfunc " Test confirm({msg} [, {choices} [, {default} [, {type}]]]) func Test_confirm() - " requires a UI to be active - throw 'Skipped: use test/functional/vimscript/input_spec.lua' CheckUnix CheckNotGui @@ -3401,6 +3404,73 @@ func Test_getmousepos() \ column: 8, \ coladd: 21, \ }, getmousepos()) + + 30vnew + setlocal smoothscroll number + call setline(1, join(range(100))) + exe "normal! \<C-E>" + call Ntest_setmouse(1, 5) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 5, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 5, + \ line: 1, + \ column: 27, + \ coladd: 0, + \ }, getmousepos()) + call Ntest_setmouse(2, 5) + call assert_equal(#{ + \ screenrow: 2, + \ screencol: 5, + \ winid: win_getid(), + \ winrow: 2, + \ wincol: 5, + \ line: 1, + \ column: 53, + \ coladd: 0, + \ }, getmousepos()) + + exe "normal! \<C-E>" + call Ntest_setmouse(1, 5) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 5, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 5, + \ line: 1, + \ column: 53, + \ coladd: 0, + \ }, getmousepos()) + call Ntest_setmouse(2, 5) + call assert_equal(#{ + \ screenrow: 2, + \ screencol: 5, + \ winid: win_getid(), + \ winrow: 2, + \ wincol: 5, + \ line: 1, + \ column: 79, + \ coladd: 0, + \ }, getmousepos()) + + vert resize 4 + call Ntest_setmouse(2, 2) + " This used to crash Vim + call assert_equal(#{ + \ screenrow: 2, + \ screencol: 2, + \ winid: win_getid(), + \ winrow: 2, + \ wincol: 2, + \ line: 1, + \ column: 53, + \ coladd: 0, + \ }, getmousepos()) + + bwipe! bwipe! endfunc @@ -3610,4 +3680,55 @@ func Test_glob_extended_mswin() call delete('Xtestglob', 'rf') endfunc +" Tests for the slice() function. +func Test_slice() + let lines =<< trim END + call assert_equal([1, 2, 3, 4, 5], slice(range(6), 1)) + call assert_equal([2, 3, 4, 5], slice(range(6), 2)) + call assert_equal([2, 3], slice(range(6), 2, 4)) + call assert_equal([0, 1, 2, 3], slice(range(6), 0, 4)) + call assert_equal([1, 2, 3], slice(range(6), 1, 4)) + call assert_equal([1, 2, 3, 4], slice(range(6), 1, -1)) + call assert_equal([1, 2], slice(range(6), 1, -3)) + call assert_equal([1], slice(range(6), 1, -4)) + call assert_equal([], slice(range(6), 1, -5)) + call assert_equal([], slice(range(6), 1, -6)) + + call assert_equal(0z1122334455, slice(0z001122334455, 1)) + call assert_equal(0z22334455, slice(0z001122334455, 2)) + call assert_equal(0z2233, slice(0z001122334455, 2, 4)) + call assert_equal(0z00112233, slice(0z001122334455, 0, 4)) + call assert_equal(0z112233, slice(0z001122334455, 1, 4)) + call assert_equal(0z11223344, slice(0z001122334455, 1, -1)) + call assert_equal(0z1122, slice(0z001122334455, 1, -3)) + call assert_equal(0z11, slice(0z001122334455, 1, -4)) + call assert_equal(0z, slice(0z001122334455, 1, -5)) + call assert_equal(0z, slice(0z001122334455, 1, -6)) + + call assert_equal('12345', slice('012345', 1)) + call assert_equal('2345', slice('012345', 2)) + call assert_equal('23', slice('012345', 2, 4)) + call assert_equal('0123', slice('012345', 0, 4)) + call assert_equal('123', slice('012345', 1, 4)) + call assert_equal('1234', slice('012345', 1, -1)) + call assert_equal('12', slice('012345', 1, -3)) + call assert_equal('1', slice('012345', 1, -4)) + call assert_equal('', slice('012345', 1, -5)) + call assert_equal('', slice('012345', 1, -6)) + + #" Composing chars are treated as a part of the preceding base char. + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1)) + call assert_equal('γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2)) + call assert_equal('γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2, 4)) + call assert_equal('ὰ̳β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(0, 4)) + call assert_equal('β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, 4)) + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -1)) + call assert_equal('β̳́γ̳̂', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -3)) + call assert_equal('β̳́', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -4)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -5)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -6)) + END + call CheckLegacyAndVim9Success(lines) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_global.vim b/test/old/testdir/test_global.vim index 44a8784348..8c7e7cb26b 100644 --- a/test/old/testdir/test_global.vim +++ b/test/old/testdir/test_global.vim @@ -96,7 +96,16 @@ func Test_global_newline() close! endfunc -func Test_wrong_delimiter() +" Test :g with ? as delimiter. +func Test_global_question_delimiter() + new + call setline(1, ['aaaaa', 'b?bbb', 'ccccc', 'ddd?d', 'eeeee']) + g?\??delete + call assert_equal(['aaaaa', 'ccccc', 'eeeee'], getline(1, '$')) + bwipe! +endfunc + +func Test_global_wrong_delimiter() call assert_fails('g x^bxd', 'E146:') endfunc diff --git a/test/old/testdir/test_highlight.vim b/test/old/testdir/test_highlight.vim index bcaa1dac5d..0a64c63d30 100644 --- a/test/old/testdir/test_highlight.vim +++ b/test/old/testdir/test_highlight.vim @@ -825,6 +825,24 @@ func Test_highlight_cmd_errors() let &t_fo = "" endfunc +" Test for User group highlighting used in the statusline +func Test_highlight_User() + CheckNotGui + hi User1 ctermfg=12 + redraw! + call assert_equal('12', synIDattr(synIDtrans(hlID('User1')), 'fg')) + hi clear +endfunc + +" Test for MsgArea highlighting +func Test_highlight_MsgArea() + CheckNotGui + hi MsgArea ctermfg=20 + redraw! + call assert_equal('20', synIDattr(synIDtrans(hlID('MsgArea')), 'fg')) + hi clear +endfunc + " Test for using RGB color values in a highlight group func Test_xxlast_highlight_RGB_color() CheckCanRunGui diff --git a/test/old/testdir/test_history.vim b/test/old/testdir/test_history.vim index 482328ab4a..b288abc3f6 100644 --- a/test/old/testdir/test_history.vim +++ b/test/old/testdir/test_history.vim @@ -96,6 +96,60 @@ function Test_History() call assert_fails('history xyz', 'E488:') call assert_fails('history ,abc', 'E488:') call assert_fails('call histdel(":", "\\%(")', 'E53:') + + " Test for filtering the history list + let hist_filter = execute(':filter /_\d/ :history all')->split('\n') + call assert_equal(20, len(hist_filter)) + let expected = [' # cmd history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4', + \ ' # search history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4', + \ ' # expr history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4', + \ ' # input history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4', + \ ' # debug history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4'] + call assert_equal(expected, hist_filter) + + let cmds = {'c': 'cmd', 's': 'search', 'e': 'expr', 'i': 'input', 'd': 'debug'} + for h in sort(keys(cmds)) + " find some items + let hist_filter = execute(':filter /_\d/ :history ' .. h)->split('\n') + call assert_equal(4, len(hist_filter)) + + let expected = [' # ' .. cmds[h] .. ' history', + \ ' 2 text_2', + \ ' 3 text_3', + \ '> 4 text_4'] + call assert_equal(expected, hist_filter) + + " Search for an item that is not there + let hist_filter = execute(':filter /XXXX/ :history ' .. h)->split('\n') + call assert_equal(1, len(hist_filter)) + + let expected = [' # ' .. cmds[h] .. ' history'] + call assert_equal(expected, hist_filter) + + " Invert the filter condition, find non-matches + let hist_filter = execute(':filter! /_3$/ :history ' .. h)->split('\n') + call assert_equal(3, len(hist_filter)) + + let expected = [' # ' .. cmds[h] .. ' history', + \ ' 2 text_2', + \ '> 4 text_4'] + call assert_equal(expected, hist_filter) + endfor endfunction function Test_history_truncates_long_entry() @@ -254,7 +308,7 @@ func Test_history_crypt_key() set key& bs& ts& endfunc -" The following used to overflow and causing an use-after-free +" The following used to overflow and causing a use-after-free func Test_history_max_val() set history=10 diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 917c37c324..3f67a06999 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -388,6 +388,62 @@ func Test_completefunc_info() set completefunc& endfunc +func CompleteInfoUserDefinedFn(findstart, query) + " User defined function (i_CTRL-X_CTRL-U) + if a:findstart + return col('.') + endif + return [{'word': 'foo'}, {'word': 'bar'}, {'word': 'baz'}, {'word': 'qux'}] +endfunc + +func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect) + new + if a:noselect + set completeopt=menuone,popup,noinsert,noselect + else + set completeopt=menu,preview + endif + set completefunc=CompleteInfoUserDefinedFn + call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") + let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : '' + call assert_equal(completed. "{'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': [" . + \ "{'word': 'foo', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'bar', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'baz', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'qux', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}" . + \ "]}", getline(1)) + bwipe! + set completeopt& + set completefunc& +endfunc + +func Test_complete_info_user_defined_fn() + " forward + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 2, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>", -1, v:false) + " backward + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>", -1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 2, v:false) + " forward backward + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 0, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 2, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 1, v:false) + " backward forward + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 0, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 1, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-N>\<C-N>", 1, v:false) +endfunc + " Test that mouse scrolling/movement should not interrupt completion. func Test_mouse_scroll_move_during_completion() new @@ -1152,7 +1208,7 @@ func Test_complete_wholeline_unlistedbuf() edit Xfile1 enew set complete=U - " completing from a unloaded buffer should fail + " completing from an unloaded buffer should fail exe "normal! ia\<C-X>\<C-L>\<C-P>" call assert_equal('a', getline(1)) %d @@ -2406,7 +2462,7 @@ func Test_complete_info_index() call assert_equal(-1, g:compl_info['selected']) call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx') - call assert_equal(0, g:compl_info['selected']) + call assert_equal(5, g:compl_info['selected']) call assert_equal(6 , len(g:compl_info['items'])) call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') @@ -2434,4 +2490,26 @@ func Test_complete_changed_complete_info() call StopVimInTerminal(buf) endfunc +func Test_completefunc_first_call_complete_add() + new + + func Complete(findstart, base) abort + if a:findstart + let col = col('.') + call complete_add('#') + return col - 1 + else + return [] + endif + endfunc + + set completeopt=longest completefunc=Complete + " This used to cause heap-buffer-overflow + call assert_fails('call feedkeys("ifoo#\<C-X>\<C-U>", "xt")', 'E840:') + + delfunc Complete + set completeopt& completefunc& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/test/old/testdir/test_let.vim b/test/old/testdir/test_let.vim index a9cc8a14a4..d37af45aaa 100644 --- a/test/old/testdir/test_let.vim +++ b/test/old/testdir/test_let.vim @@ -397,6 +397,45 @@ func Test_let_heredoc_fails() call assert_report('Caught exception: ' .. v:exception) endtry + try + let @- =<< trim TEXT + change + insert + append + TEXT + call assert_report('No exception thrown') + catch /E730:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E475:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [a b c] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E475:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [a; b; c] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E452:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + let text =<< trim END func WrongSyntax() let v =<< that there @@ -503,6 +542,13 @@ END XX call assert_equal(['Line1'], var1) + let var1 =<< trim XX " comment + Line1 + Line2 + Line3 + XX + call assert_equal(['Line1', ' Line2', 'Line3'], var1) + " ignore "endfunc" let var1 =<< END something @@ -569,6 +615,22 @@ append END call assert_equal(['change', 'insert', 'append'], [a, b, c]) + " unpack assignment with semicolon + let [a; b] =<< END +change +insert +append +END + call assert_equal(['change', ['insert', 'append']], [a, b]) + + " unpack assignment with registers + let [@/, @", @-] =<< END +change +insert +append +END + call assert_equal(['change', 'insert', 'append'], [@/, @", @-]) + " curly braces name and list slice assignment let foo_3_bar = ['', '', ''] let foo_{1 + 2}_bar[ : ] =<< END @@ -625,6 +687,48 @@ END END call assert_equal(['let a = {abc}', 'let b = X', 'let c = {'], code) + " Evaluate a dictionary + let d1 = #{a: 10, b: 'ss', c: {}} + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {'a': 10, 'b': 'ss', 'c': {}}"], code) + + " Empty dictionary + let d1 = {} + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {}"], code) + + " null dictionary + let d1 = v:_null_dict + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {}"], code) + + " Evaluate a List + let l1 = ['a', 'b', 'c'] + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = ['a', 'b', 'c']"], code) + + " Empty List + let l1 = [] + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = []"], code) + + " Null List + let l1 = v:_null_list + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = []"], code) + let code = 'xxx' let code =<< eval trim END let n = {5 + @@ -658,6 +762,34 @@ END LINES call CheckScriptFailure(lines, 'E15:') + " Test for using heredoc in a single string using :execute or execute() + for [cmd, res] in items({ + \ "let x =<< trim END\n one\n two\nEND": ['one', 'two'], + \ "let x =<< trim END\n one\n two\nEND": ['one', ' two'], + \ " let x =<< trim END\n one\n two\n END": ['one', 'two'], + \ " let x =<< trim END\n one\n two\n END": ['one', ' two'], + \ "let x =<< END\n one\n two\nEND": [' one', ' two'], + \ "let x =<< END\none\ntwo\nEND": ['one', 'two'], + \ "let x =<< END \" comment\none\ntwo\nEND": ['one', 'two'], + \ }) + execute cmd + call assert_equal(res, x) + unlet x + call assert_equal($"\n{string(res)}", execute($"{cmd}\necho x")) + unlet x + endfor + for [cmd, err] in items({ + \ "let x =<<\none\ntwo": "E172:", + \ "let x =<< trim\n one\n two": "E172:", + \ "let x =<< end\none\ntwo\nend": "E221:", + \ "let x =<< END\none\ntwo": "E990: Missing end marker 'END'", + \ "let x =<< END !\none\ntwo\nEND": "E488: Trailing characters: !", + \ "let x =<< eval END\none\ntwo{y}\nEND": "E121: Undefined variable: y", + \ }) + call assert_fails('execute cmd', err) + call assert_fails('call execute(cmd)', err) + endfor + " skipped heredoc if 0 let msg =<< trim eval END diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim index 649d5f5c6c..0adc3286f9 100644 --- a/test/old/testdir/test_listdict.vim +++ b/test/old/testdir/test_listdict.vim @@ -1441,4 +1441,10 @@ func Test_indexof() delfunc TestIdx endfunc +func Test_extendnew_leak() + " This used to leak memory + for i in range(100) | silent! call extendnew([], [], []) | endfor + for i in range(100) | silent! call extendnew({}, {}, {}) | endfor +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_mapping.vim b/test/old/testdir/test_mapping.vim index 623228b347..2a4d068dea 100644 --- a/test/old/testdir/test_mapping.vim +++ b/test/old/testdir/test_mapping.vim @@ -236,21 +236,25 @@ func Test_map_meta_multibyte() endfunc func Test_map_super_quotes() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-"> foo - call feedkeys("Go-\<*D-\">-\<Esc>", "xt") - call assert_equal("-foo-", getline('$')) - set nomodified - iunmap <D-"> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-"> foo + call feedkeys("Go-\<*D-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <D-"> endfunc func Test_map_super_multibyte() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-á> foo - call assert_match('i <D-á>\s*foo', execute('imap')) - iunmap <D-á> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-á> foo + call assert_match('i <D-á>\s*foo', execute('imap')) + iunmap <D-á> endfunc func Test_abbr_after_line_join() @@ -1693,7 +1697,7 @@ func Test_map_after_timed_out_nop() inoremap ab TEST inoremap a <Nop> END - call writefile(lines, 'Xtest_map_after_timed_out_nop') + call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D') let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6}) " Enter Insert mode @@ -1710,7 +1714,49 @@ func Test_map_after_timed_out_nop() " clean up call StopVimInTerminal(buf) - call delete('Xtest_map_after_timed_out_nop') +endfunc + +" Test 'showcmd' behavior with a partial mapping +func Test_showcmd_part_map() + CheckRunVimInTerminal + + let lines =<< trim END + set notimeout showcmd + nnoremap ,a <Ignore> + nnoremap ;a <Ignore> + nnoremap Àa <Ignore> + nnoremap Ëa <Ignore> + nnoremap βa <Ignore> + nnoremap ωa <Ignore> + nnoremap …a <Ignore> + nnoremap <C-W>a <Ignore> + END + call writefile(lines, 'Xtest_showcmd_part_map', 'D') + let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6}) + + call term_sendkeys(buf, ":set noruler | echo\<CR>") + call WaitForAssert({-> assert_equal('', term_getline(buf, 6))}) + + for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…'] + call term_sendkeys(buf, c) + call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + endfor + + call term_sendkeys(buf, "\<C-W>") + call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + + " Use feedkeys() as terminal buffer cannot forward unsimplified Ctrl-W. + " This is like typing Ctrl-W with modifyOtherKeys enabled. + call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>") + call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + + call StopVimInTerminal(buf) endfunc func Test_using_past_typeahead() diff --git a/test/old/testdir/test_match.vim b/test/old/testdir/test_match.vim index 1cb52b8b2a..ddf032d593 100644 --- a/test/old/testdir/test_match.vim +++ b/test/old/testdir/test_match.vim @@ -310,6 +310,7 @@ func Test_matchaddpos_error() " call assert_fails("call matchaddpos('Error', [{}])", 'E290:') call assert_fails("call matchaddpos('Error', [{}])", 'E5031:') call assert_equal(-1, matchaddpos('Error', v:_null_list)) + call assert_equal(-1, matchaddpos('Error', [])) call assert_fails("call matchaddpos('Error', [1], [], 1)", 'E745:') endfunc @@ -427,13 +428,11 @@ func Test_match_tab_with_linebreak() call setline(1, "\tix") call matchadd('ErrorMsg', '\t') END - call writefile(lines, 'XscriptMatchTabLinebreak') + call writefile(lines, 'XscriptMatchTabLinebreak', 'D') let buf = RunVimInTerminal('-S XscriptMatchTabLinebreak', #{rows: 10}) call VerifyScreenDump(buf, 'Test_match_tab_linebreak', {}) call StopVimInTerminal(buf) - call delete('XscriptMatchTabLinebreak') endfunc - " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_matchparen.vim b/test/old/testdir/test_matchparen.vim index 3138180c66..ab425b046a 100644 --- a/test/old/testdir/test_matchparen.vim +++ b/test/old/testdir/test_matchparen.vim @@ -61,6 +61,31 @@ func Test_matchparen_clear_highlight() call StopVimInTerminal(buf) endfunc +" Test for matchparen highlight when switching buffer in win_execute() +func Test_matchparen_win_execute() + CheckScreendump + + let lines =<< trim END + source $VIMRUNTIME/plugin/matchparen.vim + let s:win = win_getid() + call setline(1, '{}') + split + + func SwitchBuf() + call win_execute(s:win, 'enew | buffer #') + endfunc + END + call writefile(lines, 'XMatchparenWinExecute', 'D') + let buf = RunVimInTerminal('-S XMatchparenWinExecute', #{rows: 5}) + call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {}) + + " Switching buffer away and back shouldn't change matchparen highlight. + call term_sendkeys(buf, ":call SwitchBuf()\<CR>:\<Esc>") + call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {}) + + call StopVimInTerminal(buf) +endfunc + " Test for scrolling that modifies buffer during visual block func Test_matchparen_pum_clear() CheckScreendump diff --git a/test/old/testdir/test_mksession.vim b/test/old/testdir/test_mksession.vim index d63d10b44c..7e9cd6c8e8 100644 --- a/test/old/testdir/test_mksession.vim +++ b/test/old/testdir/test_mksession.vim @@ -631,11 +631,11 @@ endfunc func Test_mkview_no_file_name() new - " :mkview or :mkview {nr} should fail in a unnamed buffer. + " :mkview or :mkview {nr} should fail in an unnamed buffer. call assert_fails('mkview', 'E32:') call assert_fails('mkview 1', 'E32:') - " :mkview {file} should succeed in a unnamed buffer. + " :mkview {file} should succeed in an unnamed buffer. mkview Xview help source Xview diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim index 91c058df9e..a2ef07193d 100644 --- a/test/old/testdir/test_normal.vim +++ b/test/old/testdir/test_normal.vim @@ -131,7 +131,7 @@ func Test_normal01_keymodel() call assert_equal([0, 1, 1, 0], getpos("'<")) call assert_equal([0, 3, 1, 0], getpos("'>")) call feedkeys("Gz\<CR>8|\<S-PageUp>y", 'xt') - call assert_equal([0, 2, 1, 0], getpos("'<")) + call assert_equal([0, 3, 1, 0], getpos("'<")) call assert_equal([0, 3, 8, 0], getpos("'>")) " Test for <S-C-Home> and <S-C-End> call cursor(2, 12) @@ -915,12 +915,10 @@ func Test_normal14_page() set scrolloff=0 100 exe "norm! $\<c-b>" - call assert_equal('92', getline('.')) call assert_equal([0, 92, 1, 0, 1], getcurpos()) 100 set nostartofline exe "norm! $\<c-b>" - call assert_equal('92', getline('.')) call assert_equal([0, 92, 2, 0, v:maxcol], getcurpos()) " cleanup set startofline @@ -1287,7 +1285,7 @@ func Test_vert_scroll_cmds() exe "normal \<C-U>" call assert_equal(36, line('.')) exe "normal \<C-U>" - call assert_equal(10, line('.')) + call assert_equal(1, line('.')) exe "normal \<C-U>" call assert_equal(1, line('.')) set scroll& @@ -2370,6 +2368,14 @@ func Test_normal30_changecase() %d call assert_beeps('norm! ~') + " Test with multiple lines + call setline(1, ['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD']) + norm! ggguG + call assert_equal(['aa', 'bbbb', 'cccccc', 'dddddddd'], getline(1, '$')) + norm! GgUgg + call assert_equal(['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD'], getline(1, '$')) + %d + " Test for changing case across lines using 'whichwrap' call setline(1, ['aaaaaa', 'aaaaaa']) normal! gg10~ @@ -3817,8 +3823,8 @@ func Test_normal_vert_scroll_longline() call assert_equal(11, line('.')) call assert_equal(1, winline()) exe "normal \<C-B>" - call assert_equal(10, line('.')) - call assert_equal(3, winline()) + call assert_equal(11, line('.')) + call assert_equal(5, winline()) exe "normal \<C-B>\<C-B>" call assert_equal(5, line('.')) call assert_equal(5, winline()) @@ -4176,12 +4182,8 @@ endfunc " Test for { and } paragraph movements in a single line func Test_brace_single_line() - let text =<< trim [DATA] - foobar one two three - [DATA] - new - call setline(1, text) + call setline(1, ['foobar one two three']) 1 norm! 0} @@ -4191,4 +4193,99 @@ func Test_brace_single_line() bw! endfunc +" Test for Ctrl-B/Ctrl-U in buffer with a single line +func Test_single_line_scroll() + CheckFeature textprop + + new + call setline(1, ['foobar one two three']) + let vt = 'virt_above' + call prop_type_add(vt, {'highlight': 'IncSearch'}) + call prop_add(1, 0, {'type': vt, 'text': '---', 'text_align': 'above'}) + call cursor(1, 1) + + " Ctrl-B/Ctrl-U scroll up with hidden "above" virtual text. + set smoothscroll + exe "normal \<C-E>" + call assert_notequal(0, winsaveview().skipcol) + exe "normal \<C-B>" + call assert_equal(0, winsaveview().skipcol) + exe "normal \<C-E>" + call assert_notequal(0, winsaveview().skipcol) + exe "normal \<C-U>" + call assert_equal(0, winsaveview().skipcol) + + set smoothscroll& + bw! + call prop_type_delete(vt) +endfunc + +" Test for zb in buffer with a single line and filler lines +func Test_single_line_filler_zb() + call setline(1, ['', 'foobar one two three']) + diffthis + new + call setline(1, ['foobar one two three']) + diffthis + + " zb scrolls to reveal filler lines at the start of the buffer. + exe "normal \<C-E>zb" + call assert_equal(1, winsaveview().topfill) + + bw! +endfunc + +" Test for Ctrl-U not getting stuck at end of buffer with 'scrolloff'. +func Test_halfpage_scrolloff_eob() + set scrolloff=5 + + call setline(1, range(1, 100)) + exe "norm! Gzz\<C-U>zz" + call assert_notequal(100, line('.')) + + set scrolloff& + bwipe! +endfunc + +" Test for Ctrl-U/D moving the cursor at the buffer boundaries. +func Test_halfpage_cursor_startend() + call setline(1, range(1, 100)) + exe "norm! jztj\<C-U>" + call assert_equal(1, line('.')) + exe "norm! G\<C-Y>k\<C-D>" + call assert_equal(100, line('.')) + bwipe! +endfunc + +" Test for Ctrl-F/B moving the cursor to the window boundaries. +func Test_page_cursor_topbot() + 10new + call setline(1, range(1, 100)) + exe "norm! gg2\<C-F>" + call assert_equal(17, line('.')) + exe "norm! \<C-B>" + call assert_equal(18, line('.')) + exe "norm! \<C-B>\<C-F>" + call assert_equal(9, line('.')) + bwipe! +endfunc + +" Test for Ctrl-D with long line +func Test_halfpage_longline() + 10new + call setline(1, ['long'->repeat(1000), 'short']) + exe "norm! \<C-D>" + call assert_equal(2, line('.')) + bwipe! +endfunc + +" Test for Ctrl-E with long line and very narrow window, +" used to cause an inifite loop +func Test_scroll_longline_no_loop() + 4vnew + setl smoothscroll number showbreak=> scrolloff=2 + call setline(1, repeat(['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'], 3)) + exe "normal! \<C-E>" + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/test/old/testdir/test_perl.vim b/test/old/testdir/test_perl.vim index ce2a566f62..c08a042dae 100644 --- a/test/old/testdir/test_perl.vim +++ b/test/old/testdir/test_perl.vim @@ -94,6 +94,7 @@ func Test_buffer_Number() endfunc func Test_window_Cursor() + throw 'skipped: flaky ' new call setline(1, ['line1', 'line2']) perl $curwin->Cursor(2, 3) @@ -104,6 +105,7 @@ func Test_window_Cursor() endfunc func Test_window_SetHeight() + throw 'skipped: flaky ' new perl $curwin->SetHeight(2) call assert_equal(2, winheight(0)) diff --git a/test/old/testdir/test_put.vim b/test/old/testdir/test_put.vim index b1cf268a58..73b58dbe33 100644 --- a/test/old/testdir/test_put.vim +++ b/test/old/testdir/test_put.vim @@ -323,4 +323,21 @@ func Test_put_visual_replace_fold_marker() bwipe! endfunc +func Test_put_dict() + new + let d = #{a: #{b: 'abc'}, c: [1, 2], d: 0z10} + put! =d + call assert_equal(["{'a': {'b': 'abc'}, 'c': [1, 2], 'd': 0z10}", ''], + \ getline(1, '$')) + bw! +endfunc + +func Test_put_list() + new + let l = ['a', 'b', 'c'] + put! =l + call assert_equal(['a', 'b', 'c', ''], getline(1, '$')) + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_quickfix.vim b/test/old/testdir/test_quickfix.vim index b5abb08ed8..a708cabc26 100644 --- a/test/old/testdir/test_quickfix.vim +++ b/test/old/testdir/test_quickfix.vim @@ -6369,4 +6369,74 @@ func Test_efm_format_b() call setqflist([], 'f') endfunc +func XbufferTests_range(cchar) + call s:setup_commands(a:cchar) + + enew! + let lines =<< trim END + Xtestfile7:700:10:Line 700 + Xtestfile8:800:15:Line 800 + END + silent! call setline(1, lines) + norm! Vy + " Note: We cannot use :Xbuffer here, + " it doesn't properly fail, so we need to + " test using the raw c/l commands. + " (also further down) + if (a:cchar == 'c') + exe "'<,'>cbuffer!" + else + exe "'<,'>lbuffer!" + endif + let l = g:Xgetlist() + call assert_true(len(l) == 1 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700') + + enew! + let lines =<< trim END + Xtestfile9:900:55:Line 900 + Xtestfile10:950:66:Line 950 + END + silent! call setline(1, lines) + if (a:cchar == 'c') + 1cgetbuffer + else + 1lgetbuffer + endif + let l = g:Xgetlist() + call assert_true(len(l) == 1 && + \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900') + + enew! + let lines =<< trim END + Xtestfile11:700:20:Line 700 + Xtestfile12:750:25:Line 750 + END + silent! call setline(1, lines) + if (a:cchar == 'c') + 1,1caddbuffer + else + 1,1laddbuffer + endif + let l = g:Xgetlist() + call assert_true(len(l) == 2 && + \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && + \ l[1].lnum == 700 && l[1].col == 20 && l[1].text ==# 'Line 700') + enew! + + " Check for invalid range + " Using Xbuffer will not run the range check in the cbuffer/lbuffer + " commands. So directly call the commands. + if (a:cchar == 'c') + call assert_fails('900,999caddbuffer', 'E16:') + else + call assert_fails('900,999laddbuffer', 'E16:') + endif +endfunc + +func Test_cbuffer_range() + call XbufferTests_range('c') + call XbufferTests_range('l') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_recover.vim b/test/old/testdir/test_recover.vim index fa8cc1abaf..ca1ee11b44 100644 --- a/test/old/testdir/test_recover.vim +++ b/test/old/testdir/test_recover.vim @@ -385,7 +385,7 @@ func Test_recover_encrypted_swap_file() call delete('Xfile1') endfunc -" Test for :recover using a unreadable swap file +" Test for :recover using an unreadable swap file func Test_recover_unreadable_swap_file() CheckUnix CheckNotRoot diff --git a/test/old/testdir/test_regexp_latin.vim b/test/old/testdir/test_regexp_latin.vim index ece6ae518e..2cfa81e078 100644 --- a/test/old/testdir/test_regexp_latin.vim +++ b/test/old/testdir/test_regexp_latin.vim @@ -842,12 +842,26 @@ func Regex_Mark() %d endfunc +" Same test as above, but use verymagic +func Regex_Mark_Verymagic() + call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas', + \ 'dfsadfEasdf', '', '', '', '', '']) + call cursor(4, 1) + exe "normal jfSmsfEme:.-4,.+6s/\\v.%>'s.*%<'e../here/\<CR>" + exe "normal jfSmsj0fEme:.-4,.+6s/\\v.%>'s\\_.*%<'e../again/\<CR>" + call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf', + \ '', '', '', '', '', ''], getline(1, '$')) + %d +endfunc + func Test_matching_marks() new set regexpengine=1 call Regex_Mark() + call Regex_Mark_Verymagic() set regexpengine=2 call Regex_Mark() + call Regex_Mark_Verymagic() bwipe! endfunc diff --git a/test/old/testdir/test_regexp_utf8.vim b/test/old/testdir/test_regexp_utf8.vim index 97f48a0c09..728a88fa0f 100644 --- a/test/old/testdir/test_regexp_utf8.vim +++ b/test/old/testdir/test_regexp_utf8.vim @@ -372,7 +372,7 @@ func Test_multibyte_chars() endfunc " check that 'ambiwidth' does not change the meaning of \p -func Test_ambiwidth() +func Test_regexp_ambiwidth() set regexpengine=1 ambiwidth=single call assert_equal(0, match("\u00EC", '\p')) set regexpengine=1 ambiwidth=double diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim index e113bd9e75..e5add9414f 100644 --- a/test/old/testdir/test_registers.vim +++ b/test/old/testdir/test_registers.vim @@ -214,6 +214,71 @@ func Test_recording_with_select_mode() bwipe! endfunc +func Run_test_recording_with_select_mode_utf8() + new + + " Test with different text lengths: 5, 7, 9, 11, 13, 15, to check that + " a character isn't split between two buffer blocks. + for s in ['12345', '口=口', '口口口', '口=口=口', '口口=口口', '口口口口口'] + " 0x80 is K_SPECIAL + " 0x9B is CSI + " 哦: 0xE5 0x93 0xA6 + " 洛: 0xE6 0xB4 0x9B + " 固: 0xE5 0x9B 0xBA + " 四: 0xE5 0x9B 0x9B + " 最: 0xE6 0x9C 0x80 + " 倒: 0xE5 0x80 0x92 + " 倀: 0xE5 0x80 0x80 + for c in ['哦', '洛', '固', '四', '最', '倒', '倀'] + call setline(1, 'asdf') + call feedkeys($"qacc{s}\<Esc>gH{c}\<Esc>q", "tx") + call assert_equal(c, getline(1)) + call assert_equal($"cc{s}\<Esc>gH{c}\<Esc>", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal(c, getline(1)) + + " Test with Shift modifier. + let shift_c = eval($'"\<S-{c}>"') + call setline(1, 'asdf') + call feedkeys($"qacc{s}\<Esc>gH{shift_c}\<Esc>q", "tx") + call assert_equal(c, getline(1)) + call assert_equal($"cc{s}\<Esc>gH{shift_c}\<Esc>", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal(c, getline(1)) + endfor + endfor + + bwipe! +endfunc + +func Test_recording_with_select_mode_utf8() + call Run_test_recording_with_select_mode_utf8() +endfunc + +" This must be done as one of the last tests, because it starts the GUI, which +" cannot be undone. +func Test_zz_recording_with_select_mode_utf8_gui() + CheckCanRunGui + + gui -f + call Run_test_recording_with_select_mode_utf8() +endfunc + +func Test_recording_with_super_mod() + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' + endif + + nnoremap <D-j> <Ignore> + let s = repeat("\<D-j>", 1000) + " This used to crash Vim + call feedkeys($'qr{s}q', 'tx') + call assert_equal(s, @r) + nunmap <D-j> +endfunc + " Test for executing the last used register (@) func Test_last_used_exec_reg() " Test for the @: command @@ -706,13 +771,13 @@ func Test_ve_blockpaste() call cursor(1,1) exe ":norm! \<C-V>3ljdP" call assert_equal(1, col('.')) - call assert_equal(getline(1, 2), ['QWERTZ', 'ASDFGH']) + call assert_equal(['QWERTZ', 'ASDFGH'], getline(1, 2)) call cursor(1,1) exe ":norm! \<C-V>3ljd" call cursor(1,1) norm! $3lP call assert_equal(5, col('.')) - call assert_equal(getline(1, 2), ['TZ QWER', 'GH ASDF']) + call assert_equal(['TZ QWER', 'GH ASDF'], getline(1, 2)) set ve&vim bwipe! endfunc diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim index a1987ed3c9..76b4089bd1 100644 --- a/test/old/testdir/test_scroll_opt.vim +++ b/test/old/testdir/test_scroll_opt.vim @@ -552,14 +552,14 @@ func Test_smoothscroll_cursor_position() exe "normal \<C-Y>" call s:check_col_calc(1, 3, 41) - " Test "g0/g<Home>" + " Test "g0/g<Home>" exe "normal gg\<C-E>" norm $gkg0 - call s:check_col_calc(1, 2, 21) + call s:check_col_calc(4, 1, 24) " Test moving the cursor behind the <<< display with 'virtualedit' set virtualedit=all - exe "normal \<C-E>3lgkh" + exe "normal \<C-E>gkh" call s:check_col_calc(3, 2, 23) set virtualedit& @@ -741,6 +741,7 @@ func Test_smoothscroll_mouse_pos() let &mouse = save_mouse "let &term = save_term "let &ttymouse = save_ttymouse + bwipe! endfunc " this was dividing by zero @@ -832,7 +833,7 @@ func Test_smoothscroll_eob() call VerifyScreenDump(buf, 'Test_smooth_eob_1', {}) " cursor is not placed below window - call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-B>G") + call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-L>\<C-B>G") call VerifyScreenDump(buf, 'Test_smooth_eob_2', {}) call StopVimInTerminal(buf) @@ -963,4 +964,231 @@ func Test_smoothscroll_insert_bottom() call StopVimInTerminal(buf) endfunc +func Test_smoothscroll_in_qf_window() + CheckFeature quickfix + CheckScreendump + + let lines =<< trim END + set nocompatible display=lastline + copen 5 + setlocal number smoothscroll + let g:l = [{'text': 'foo'}] + repeat([{'text': join(range(30))}], 10) + call setqflist(g:l, 'r') + normal! G + wincmd t + let g:l1 = [{'text': join(range(1000))}] + END + call writefile(lines, 'XSmoothScrollInQfWindow', 'D') + let buf = RunVimInTerminal('-u NONE -S XSmoothScrollInQfWindow', #{rows: 20, cols: 60}) + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_1', {}) + + call term_sendkeys(buf, ":call setqflist([], 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_2', {}) + + call term_sendkeys(buf, ":call setqflist(g:l, 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_3', {}) + + call term_sendkeys(buf, ":call setqflist(g:l1, 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_4', {}) + + call term_sendkeys(buf, "\<C-W>b$\<C-W>t") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_5', {}) + + call term_sendkeys(buf, ":call setqflist([], 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_2', {}) + + call term_sendkeys(buf, ":call setqflist(g:l1, 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_4', {}) + + call term_sendkeys(buf, "\<C-W>b$\<C-W>t") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_5', {}) + + call term_sendkeys(buf, ":call setqflist(g:l, 'r')\<CR>") + call VerifyScreenDump(buf, 'Test_smoothscroll_in_qf_window_3', {}) + + call StopVimInTerminal(buf) +endfunc + +func Test_smoothscroll_in_zero_width_window() + set cpo+=n number smoothscroll + set winwidth=99999 winminwidth=0 + + vsplit + call assert_equal(0, winwidth(winnr('#'))) + call win_execute(win_getid(winnr('#')), "norm! \<C-Y>") + + only! + set winwidth& winminwidth& + set cpo-=n nonumber nosmoothscroll +endfunc + +func Test_smoothscroll_textoff_small_winwidth() + set smoothscroll number + call setline(1, 'llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch') + vsplit + + let textoff = getwininfo(win_getid())[0].textoff + execute 'vertical resize' textoff + 1 + redraw + call assert_equal(0, winsaveview().skipcol) + execute "normal! 0\<C-E>" + redraw + call assert_equal(1, winsaveview().skipcol) + execute 'vertical resize' textoff - 1 + " This caused a signed integer overflow. + redraw + call assert_equal(1, winsaveview().skipcol) + execute 'vertical resize' textoff + " This caused an infinite loop. + redraw + call assert_equal(1, winsaveview().skipcol) + + %bw! + set smoothscroll& number& +endfunc + +func Test_smoothscroll_page() + call NewWindow(10, 40) + setlocal smoothscroll + call setline(1, 'abcde '->repeat(150)) + + exe "norm! \<C-F>" + call assert_equal(400, winsaveview().skipcol) + exe "norm! \<C-F>" + call assert_equal(800, winsaveview().skipcol) + exe "norm! \<C-F>" + call assert_equal(880, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(480, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(80, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(0, winsaveview().skipcol) + + " Half-page scrolling does not go beyond end of buffer and moves the cursor. + " Even with 'nostartofline', the correct amount of lines is scrolled. + setl nostartofline + exe "norm! 15|\<C-D>" + call assert_equal(200, winsaveview().skipcol) + call assert_equal(215, col('.')) + exe "norm! \<C-D>" + call assert_equal(400, winsaveview().skipcol) + call assert_equal(415, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(615, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(815, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(895, col('.')) + exe "norm! \<C-U>" + call assert_equal(320, winsaveview().skipcol) + call assert_equal(695, col('.')) + exe "norm! \<C-U>" + call assert_equal(120, winsaveview().skipcol) + call assert_equal(495, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(295, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(95, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(15, col('.')) + + bwipe! +endfunc + +func Test_smoothscroll_next_topline() + call NewWindow(10, 40) + setlocal smoothscroll + call setline(1, ['abcde '->repeat(150)]->repeat(2)) + + " Scrolling a screenline that causes the cursor to move to the next buffer + " line should not skip part of that line to bring the cursor into view. + exe "norm! 22\<C-E>" + call assert_equal(880, winsaveview().skipcol) + exe "norm! \<C-E>" + redraw + call assert_equal(0, winsaveview().skipcol) + + " Also when scrolling back. + exe "norm! G\<C-Y>" + redraw + call assert_equal(880, winsaveview().skipcol) + + " Cursor in correct place when not in the first screenline of a buffer line. + exe "norm! gg4gj20\<C-D>\<C-D>" + redraw + call assert_equal(2, line('w0')) + + " Cursor does not end up above topline, adjusting topline later. + setlocal nu cpo+=n + exe "norm! G$g013\<C-Y>" + redraw + call assert_equal(2, line('.')) + call assert_equal(0, winsaveview().skipcol) + + set cpo-=n + bwipe! +endfunc + +func Test_smoothscroll_long_line_zb() + call NewWindow(10, 40) + call setline(1, 'abcde '->repeat(150)) + + " Also works without 'smoothscroll' when last line of buffer doesn't fit. + " Used to set topline to buffer line count plus one, causing an empty screen. + norm zb + redraw + call assert_equal(1, winsaveview().topline) + + " Moving cursor to bottom works on line that doesn't fit with 'smoothscroll'. + " Skipcol was adjusted later for cursor being on not visible part of line. + setlocal smoothscroll + norm zb + redraw + call assert_equal(520, winsaveview().skipcol) + + bwipe! +endfunc + +func Test_smooth_long_scrolloff() + CheckScreendump + + let lines =<< trim END + set smoothscroll scrolloff=3 + call setline(1, ['one', 'two long '->repeat(100), 'three', 'four', 'five', 'six']) + END + call writefile(lines, 'XSmoothLongScrolloff', 'D') + let buf = RunVimInTerminal('-u NONE -S XSmoothLongScrolloff', #{rows: 8, cols: 40}) + "FIXME: empty screen due to reset_skipcol()/curs_columns() shenanigans + call term_sendkeys(buf, ":norm j721|\<CR>") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_1', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_2', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_3', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_4', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_5', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_6', {}) + + call term_sendkeys(buf, "gk") + "FIXME: empty screen due to reset_skipcol()/curs_columns() shenanigans + call VerifyScreenDump(buf, 'Test_smooth_long_scrolloff_7', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_spellrare.vim b/test/old/testdir/test_spellrare.vim new file mode 100644 index 0000000000..bbb13c27c2 --- /dev/null +++ b/test/old/testdir/test_spellrare.vim @@ -0,0 +1,61 @@ +" Test spell checking + +source check.vim +CheckFeature spell + +" Test spellbadword() with argument, specifically to move to "rare" words +" in normal mode. +func Test_spellrareword() + set spell + + " Create a small word list to test that spellbadword('...') + " can return ['...', 'rare']. + let lines =<< trim END + foo + foobar/? + foobara/? +END + call writefile(lines, 'Xwords', 'D') + + mkspell! Xwords.spl Xwords + set spelllang=Xwords.spl + call assert_equal(['foobar', 'rare'], spellbadword('foo foobar')) + + new + call setline(1, ['foo', '', 'foo bar foo bar foobara foo foo foo foobar', '', 'End']) + set spell wrapscan + normal ]s + call assert_equal('foo', expand('<cword>')) + normal ]s + call assert_equal('bar', expand('<cword>')) + + normal ]r + call assert_equal('foobara', expand('<cword>')) + normal ]r + call assert_equal('foobar', expand('<cword>')) + normal ]r + call assert_equal('foobara', expand('<cword>')) + normal 2]r + call assert_equal('foobara', expand('<cword>')) + + normal [r + call assert_equal('foobar', expand('<cword>')) + normal [r + call assert_equal('foobara', expand('<cword>')) + normal [r + call assert_equal('foobar', expand('<cword>')) + normal 2[r + call assert_equal('foobar', expand('<cword>')) + + bwipe! + set nospell + + call delete('Xwords.spl') + set spelllang& + set spell& + + " set 'encoding' to clear the word list + set encoding=utf-8 +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_stat.vim b/test/old/testdir/test_stat.vim index d3059664e9..13ade5bee1 100644 --- a/test/old/testdir/test_stat.vim +++ b/test/old/testdir/test_stat.vim @@ -55,7 +55,7 @@ func SleepForTimestamp() if has('win32') sleep 2 else - sleep 2 + sleep 1 endif endfunc diff --git a/test/old/testdir/test_substitute.vim b/test/old/testdir/test_substitute.vim index a9e317da02..fdb0f6fc37 100644 --- a/test/old/testdir/test_substitute.vim +++ b/test/old/testdir/test_substitute.vim @@ -173,6 +173,16 @@ func Test_substitute_repeat() call feedkeys("Qsc\<CR>y", 'tx') bwipe! endfunc + +" Test :s with ? as delimiter. +func Test_substitute_question_delimiter() + new + call setline(1, '??:??') + %s?\?\??!!?g + call assert_equal('!!:!!', getline(1)) + bwipe! +endfunc + " Test %s/\n// which is implemented as a special case to use a " more efficient join rather than doing a regular substitution. func Test_substitute_join() diff --git a/test/old/testdir/test_syntax.vim b/test/old/testdir/test_syntax.vim index 711b2adf7c..35523df17d 100644 --- a/test/old/testdir/test_syntax.vim +++ b/test/old/testdir/test_syntax.vim @@ -197,14 +197,14 @@ func Test_syntax_completion() " Check that clearing "Aap" avoids it showing up before Boolean. hi @Aap ctermfg=blue call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('^"syn list @Aap @attribute @boolean @character ', @:) + call assert_match('^"syn list @Aap @attribute @attribute.builtin @boolean @character ', @:) hi clear @Aap call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('^"syn list @attribute @boolean @character ', @:) + call assert_match('^"syn list @attribute @attribute.builtin @boolean @character ', @:) call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('^"syn match @attribute @boolean @character ', @:) + call assert_match('^"syn match @attribute @attribute.builtin @boolean @character ', @:) syn cluster Aax contains=Aap call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx') diff --git a/test/old/testdir/test_tabpage.vim b/test/old/testdir/test_tabpage.vim index 0f038c8bee..2bd2907a55 100644 --- a/test/old/testdir/test_tabpage.vim +++ b/test/old/testdir/test_tabpage.vim @@ -117,10 +117,16 @@ function Test_tabpage() call assert_equal(3, tabpagenr()) +3tabmove call assert_equal(6, tabpagenr()) + silent -tabmove + call assert_equal(5, tabpagenr()) + silent -2 tabmove + call assert_equal(3, tabpagenr()) + silent -2 tabmove + call assert_equal(1, tabpagenr()) - " The following are a no-op norm! 2gt call assert_equal(2, tabpagenr()) + " The following are a no-op tabmove 2 call assert_equal(2, tabpagenr()) 2tabmove diff --git a/test/old/testdir/test_tagjump.vim b/test/old/testdir/test_tagjump.vim index ff1110e070..a614c19ce2 100644 --- a/test/old/testdir/test_tagjump.vim +++ b/test/old/testdir/test_tagjump.vim @@ -1551,14 +1551,14 @@ func Test_tagbsearch() \ "third\tXfoo\t3", \ "second\tXfoo\t2", \ "first\tXfoo\t1"], - \ 'Xtags') + \ 'Xtags', 'D') set tags=Xtags let code =<< trim [CODE] int first() {} int second() {} int third() {} [CODE] - call writefile(code, 'Xfoo') + call writefile(code, 'Xfoo', 'D') enew set tagbsearch @@ -1618,9 +1618,25 @@ func Test_tagbsearch() \ 'Xtags') call assert_fails('tag bbb', 'E426:') - call delete('Xtags') - call delete('Xfoo') set tags& tagbsearch& endfunc +" Test tag guessing with very short names +func Test_tag_guess_short() + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "y\tXf\t/^y()/"], + \ 'Xt', 'D') + set tags=Xt cpoptions+=t + call writefile(['', 'int * y () {}', ''], 'Xf', 'D') + + let v:statusmsg = '' + let @/ = '' + ta y + call assert_match('E435:', v:statusmsg) + call assert_equal(2, line('.')) + call assert_match('<y', @/) + + set tags& cpoptions-=t +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_termdebug.vim b/test/old/testdir/test_termdebug.vim index 33cdaf1611..fd0c850577 100644 --- a/test/old/testdir/test_termdebug.vim +++ b/test/old/testdir/test_termdebug.vim @@ -232,26 +232,26 @@ endfunc func Test_termdebug_mapping() %bw! - call assert_equal(maparg('K', 'n', 0, 1)->empty(), 1) - call assert_equal(maparg('-', 'n', 0, 1)->empty(), 1) - call assert_equal(maparg('+', 'n', 0, 1)->empty(), 1) + call assert_true(maparg('K', 'n', 0, 1)->empty()) + call assert_true(maparg('-', 'n', 0, 1)->empty()) + call assert_true(maparg('+', 'n', 0, 1)->empty()) Termdebug call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b - call assert_equal(maparg('K', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('-', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('+', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('K', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('-', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('+', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('K', 'n', 0, 1).rhs, ':Evaluate<CR>') + call assert_false(maparg('K', 'n', 0, 1)->empty()) + call assert_false(maparg('-', 'n', 0, 1)->empty()) + call assert_false(maparg('+', 'n', 0, 1)->empty()) + call assert_false(maparg('K', 'n', 0, 1).buffer) + call assert_false(maparg('-', 'n', 0, 1).buffer) + call assert_false(maparg('+', 'n', 0, 1).buffer) + call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs) wincmd t quit! redraw! call WaitForAssert({-> assert_equal(1, winnr('$'))}) - call assert_equal(maparg('K', 'n', 0, 1)->empty(), 1) - call assert_equal(maparg('-', 'n', 0, 1)->empty(), 1) - call assert_equal(maparg('+', 'n', 0, 1)->empty(), 1) + call assert_true(maparg('K', 'n', 0, 1)->empty()) + call assert_true(maparg('-', 'n', 0, 1)->empty()) + call assert_true(maparg('+', 'n', 0, 1)->empty()) %bw! nnoremap K :echom "K"<cr> @@ -260,24 +260,24 @@ func Test_termdebug_mapping() Termdebug call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b - call assert_equal(maparg('K', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('-', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('+', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('K', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('-', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('+', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('K', 'n', 0, 1).rhs, ':Evaluate<CR>') + call assert_false(maparg('K', 'n', 0, 1)->empty()) + call assert_false(maparg('-', 'n', 0, 1)->empty()) + call assert_false(maparg('+', 'n', 0, 1)->empty()) + call assert_false(maparg('K', 'n', 0, 1).buffer) + call assert_false(maparg('-', 'n', 0, 1).buffer) + call assert_false(maparg('+', 'n', 0, 1).buffer) + call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs) wincmd t quit! redraw! call WaitForAssert({-> assert_equal(1, winnr('$'))}) - call assert_equal(maparg('K', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('-', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('+', 'n', 0, 1)->empty(), 0) - call assert_equal(maparg('K', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('-', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('+', 'n', 0, 1).buffer, 0) - call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "K"<cr>') + call assert_false(maparg('K', 'n', 0, 1)->empty()) + call assert_false(maparg('-', 'n', 0, 1)->empty()) + call assert_false(maparg('+', 'n', 0, 1)->empty()) + call assert_false(maparg('K', 'n', 0, 1).buffer) + call assert_false(maparg('-', 'n', 0, 1).buffer) + call assert_false(maparg('+', 'n', 0, 1).buffer) + call assert_equal(':echom "K"<cr>', maparg('K', 'n', 0, 1).rhs) %bw! nnoremap <buffer> K :echom "bK"<cr> @@ -286,20 +286,59 @@ func Test_termdebug_mapping() Termdebug call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b - call assert_equal(maparg('K', 'n', 0, 1).buffer, 1) - call assert_equal(maparg('-', 'n', 0, 1).buffer, 1) - call assert_equal(maparg('+', 'n', 0, 1).buffer, 1) + call assert_true(maparg('K', 'n', 0, 1).buffer) + call assert_true(maparg('-', 'n', 0, 1).buffer) + call assert_true(maparg('+', 'n', 0, 1).buffer) call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "bK"<cr>') wincmd t quit! redraw! call WaitForAssert({-> assert_equal(1, winnr('$'))}) - call assert_equal(maparg('K', 'n', 0, 1).buffer, 1) - call assert_equal(maparg('-', 'n', 0, 1).buffer, 1) - call assert_equal(maparg('+', 'n', 0, 1).buffer, 1) - call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "bK"<cr>') + call assert_true(maparg('K', 'n', 0, 1).buffer) + call assert_true(maparg('-', 'n', 0, 1).buffer) + call assert_true(maparg('+', 'n', 0, 1).buffer) + call assert_equal(':echom "bK"<cr>', maparg('K', 'n', 0, 1).rhs) %bw! endfunc +func Test_termdebug_bufnames() + " Test if user has filename/folders named gdb, Termdebug-gdb-console, + " etc. in the current directory + let g:termdebug_config = {} + let g:termdebug_config['use_prompt'] = 1 + let filename = 'gdb' + let replacement_filename = 'Termdebug-gdb-console' + + call writefile(['This', 'is', 'a', 'test'], filename, 'D') + " Throw away the file once the test has done. + Termdebug + " Once termdebug has completed the startup you should have 3 windows on screen + call WaitForAssert({-> assert_equal(3, winnr('$'))}) + " A file named filename already exists in the working directory, + " hence you must call the newly created buffer differently + call WaitForAssert({-> assert_false(bufexists(filename))}) + call WaitForAssert({-> assert_true(bufexists(replacement_filename))}) + quit! + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + + " Check if error message is in :message + let g:termdebug_config['disasm_window'] = 1 + let filename = 'Termdebug-asm-listing' + call writefile(['This', 'is', 'a', 'test'], filename, 'D') + " Check only the head of the error message + let error_message = "You have a file/folder named '" .. filename .. "'" + Termdebug + " Once termdebug has completed the startup you should have 4 windows on screen + call WaitForAssert({-> assert_equal(4, winnr('$'))}) + call WaitForAssert({-> assert_notequal(-1, stridx(execute('messages'), error_message))}) + quit! + wincmd b + wincmd q + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + + unlet g:termdebug_config +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_user_func.vim b/test/old/testdir/test_user_func.vim index fc7dcd62b8..3c24412eb7 100644 --- a/test/old/testdir/test_user_func.vim +++ b/test/old/testdir/test_user_func.vim @@ -891,4 +891,23 @@ func Test_multidefer_with_exception() delfunc Foo endfunc +func Test_func_curly_brace_invalid_name() + func Fail() + func Foo{'()'}bar() + endfunc + endfunc + + call assert_fails('call Fail()', 'E475: Invalid argument: Foo()bar') + + silent! call Fail() + call assert_equal([], getcompletion('Foo', 'function')) + + set formatexpr=Fail() + normal! gqq + call assert_equal([], getcompletion('Foo', 'function')) + + set formatexpr& + delfunc Fail +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_utf8.vim b/test/old/testdir/test_utf8.vim index a5a9624ec3..51ac47f082 100644 --- a/test/old/testdir/test_utf8.vim +++ b/test/old/testdir/test_utf8.vim @@ -62,6 +62,9 @@ func Test_customlist_completion() call assert_equal('"Test3 N', getreg(':')) call garbagecollect(1) + delcommand Test1 + delcommand Test2 + delcommand Test3 endfunc " Yank one 3 byte character and check the mark columns. @@ -75,53 +78,6 @@ func Test_getvcol() call assert_equal(2, virtcol("']")) endfunc -func Test_screenchar_utf8() - new - - " 1-cell, with composing characters - call setline(1, ["ABC\u0308"]) - redraw - call assert_equal([0x0041], screenchars(1, 1)) - call assert_equal([0x0042], 1->screenchars(2)) - call assert_equal([0x0043, 0x0308], screenchars(1, 3)) - call assert_equal("A", screenstring(1, 1)) - call assert_equal("B", screenstring(1, 2)) - call assert_equal("C\u0308", screenstring(1, 3)) - - " 1-cell, with 6 composing characters - set maxcombine=6 - call setline(1, ["ABC" .. repeat("\u0308", 6)]) - redraw - call assert_equal([0x0041], screenchars(1, 1)) - call assert_equal([0x0042], 1->screenchars(2)) - " This should not use uninitialized memory - call assert_equal([0x0043] + repeat([0x0308], 6), screenchars(1, 3)) - call assert_equal("A", screenstring(1, 1)) - call assert_equal("B", screenstring(1, 2)) - call assert_equal("C" .. repeat("\u0308", 6), screenstring(1, 3)) - set maxcombine& - - " 2-cells, with composing characters - let text = "\u3042\u3044\u3046\u3099" - call setline(1, text) - redraw - call assert_equal([0x3042], screenchars(1, 1)) - call assert_equal([0], screenchars(1, 2)) - call assert_equal([0x3044], screenchars(1, 3)) - call assert_equal([0], screenchars(1, 4)) - call assert_equal([0x3046, 0x3099], screenchars(1, 5)) - - call assert_equal("\u3042", screenstring(1, 1)) - call assert_equal("", screenstring(1, 2)) - call assert_equal("\u3044", screenstring(1, 3)) - call assert_equal("", screenstring(1, 4)) - call assert_equal("\u3046\u3099", screenstring(1, 5)) - - call assert_equal([text . ' '], ScreenLines(1, 8)) - - bwipe! -endfunc - func Test_list2str_str2list_utf8() " One Unicode codepoint let s = "\u3042\u3044" @@ -169,7 +125,55 @@ func Test_list2str_str2list_latin1() call assert_equal(s, sres) endfunc +func Test_screenchar_utf8() + new + + " 1-cell, with composing characters + call setline(1, ["ABC\u0308"]) + redraw + call assert_equal([0x0041], screenchars(1, 1)) + call assert_equal([0x0042], 1->screenchars(2)) + call assert_equal([0x0043, 0x0308], screenchars(1, 3)) + call assert_equal("A", screenstring(1, 1)) + call assert_equal("B", screenstring(1, 2)) + call assert_equal("C\u0308", screenstring(1, 3)) + + " 1-cell, with 6 composing characters + set maxcombine=6 + call setline(1, ["ABC" .. repeat("\u0308", 6)]) + redraw + call assert_equal([0x0041], screenchars(1, 1)) + call assert_equal([0x0042], 1->screenchars(2)) + " This should not use uninitialized memory + call assert_equal([0x0043] + repeat([0x0308], 6), screenchars(1, 3)) + call assert_equal("A", screenstring(1, 1)) + call assert_equal("B", screenstring(1, 2)) + call assert_equal("C" .. repeat("\u0308", 6), screenstring(1, 3)) + set maxcombine& + + " 2-cells, with composing characters + let text = "\u3042\u3044\u3046\u3099" + call setline(1, text) + redraw + call assert_equal([0x3042], screenchars(1, 1)) + call assert_equal([0], screenchars(1, 2)) + call assert_equal([0x3044], screenchars(1, 3)) + call assert_equal([0], screenchars(1, 4)) + call assert_equal([0x3046, 0x3099], screenchars(1, 5)) + + call assert_equal("\u3042", screenstring(1, 1)) + call assert_equal("", screenstring(1, 2)) + call assert_equal("\u3044", screenstring(1, 3)) + call assert_equal("", screenstring(1, 4)) + call assert_equal("\u3046\u3099", screenstring(1, 5)) + + call assert_equal([text . ' '], ScreenLines(1, 8)) + + bwipe! +endfunc + func Test_setcellwidths() + new call setcellwidths([ \ [0x1330, 0x1330, 2], \ [9999, 10000, 1], @@ -212,6 +216,18 @@ func Test_setcellwidths() " Ambiguous width chars call assert_equal(2, strwidth("\u00A1")) call assert_equal(2, strwidth("\u2010")) + + call setcellwidths([]) + call setline(1, repeat("\u2103", 10)) + normal! $ + redraw + call assert_equal((aw == 'single') ? 10 : 19, wincol()) + call setcellwidths([[0x2103, 0x2103, 1]]) + redraw + call assert_equal(10, wincol()) + call setcellwidths([[0x2103, 0x2103, 2]]) + redraw + call assert_equal(19, wincol()) endfor set ambiwidth& isprint& @@ -245,6 +261,7 @@ func Test_setcellwidths() set listchars& set fillchars& call setcellwidths([]) + bwipe! endfunc func Test_getcellwidths() @@ -283,64 +300,66 @@ func Test_setcellwidths_dump() call StopVimInTerminal(buf) endfunc -func Test_print_overlong() - " Text with more composing characters than MB_MAXBYTES. - new - call setline(1, 'axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') - s/x/\=nr2char(1629)/g - print - bwipe! -endfunc +" Test setcellwidths() on characters that are not targets of 'ambiwidth'. +func Test_setcellwidths_with_non_ambiwidth_character_dump() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, [repeat("\u279c", 60), repeat("\u279c", 60)]) + set ambiwidth=single + END + call writefile(lines, 'XCellwidthsWithNonAmbiwidthCharacter', 'D') + let buf = RunVimInTerminal('-S XCellwidthsWithNonAmbiwidthCharacter', {'rows': 6, 'cols': 50}) + call term_sendkeys(buf, ":call setcellwidths([[0x279c, 0x279c, 1]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_setcellwidths_with_non_ambiwidth_character_dump_1', {}) -func Test_recording_with_select_mode_utf8() - call Run_test_recording_with_select_mode_utf8() + call term_sendkeys(buf, ":call setcellwidths([[0x279c, 0x279c, 2]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_setcellwidths_with_non_ambiwidth_character_dump_2', {}) + + call StopVimInTerminal(buf) endfunc -func Run_test_recording_with_select_mode_utf8() - new +" For some reason this test causes Test_customlist_completion() to fail on CI, +" so run it as the last test. +func Test_zz_ambiwidth_hl_dump() + CheckRunVimInTerminal - " No escaping - call feedkeys("qacc12345\<Esc>gH哦\<Esc>q", "tx") - call assert_equal("哦", getline(1)) - call assert_equal("cc12345\<Esc>gH哦\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("哦", getline(1)) - - " 固 is 0xE5 0x9B 0xBA where 0x9B is CSI - call feedkeys("qacc12345\<Esc>gH固\<Esc>q", "tx") - call assert_equal("固", getline(1)) - call assert_equal("cc12345\<Esc>gH固\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("固", getline(1)) - - " 四 is 0xE5 0x9B 0x9B where 0x9B is CSI - call feedkeys("qacc12345\<Esc>gH四\<Esc>q", "tx") - call assert_equal("四", getline(1)) - call assert_equal("cc12345\<Esc>gH四\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("四", getline(1)) - - " 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL - call feedkeys("qacc12345\<Esc>gH倒\<Esc>q", "tx") - call assert_equal("倒", getline(1)) - call assert_equal("cc12345\<Esc>gH倒\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("倒", getline(1)) + let lines =<< trim END + call setline(1, [repeat("\u2103", 60), repeat("\u2103", 60)]) + set ambiwidth=single cursorline list display=lastline + END + call writefile(lines, 'XAmbiwidthHl', 'D') + let buf = RunVimInTerminal('-S XAmbiwidthHl', {'rows': 6, 'cols': 50}) + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) - bwipe! -endfunc + call term_sendkeys(buf, ":set ambiwidth=double\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_2', {}) -" This must be done as one of the last tests, because it starts the GUI, which -" cannot be undone. -func Test_zz_recording_with_select_mode_utf8_gui() - CheckCanRunGui + call term_sendkeys(buf, ":set ambiwidth=single\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) + + call term_sendkeys(buf, ":call setcellwidths([[0x2103, 0x2103, 2]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_2', {}) + + call term_sendkeys(buf, ":call setcellwidths([[0x2103, 0x2103, 1]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) + + call StopVimInTerminal(buf) +endfunc - gui -f - call Run_test_recording_with_select_mode_utf8() +func Test_print_overlong() + " Text with more composing characters than MB_MAXBYTES. + new + call setline(1, 'axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') + s/x/\=nr2char(1629)/g + print + bwipe! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_virtualedit.vim b/test/old/testdir/test_virtualedit.vim index 6448c7a3e3..8d9656e058 100644 --- a/test/old/testdir/test_virtualedit.vim +++ b/test/old/testdir/test_virtualedit.vim @@ -709,5 +709,27 @@ func Test_virtualedit_replace_after_tab() bwipe! endfunc +" Test that setpos('.') and cursor() behave the same for v:maxcol +func Test_virtualedit_set_cursor_pos_maxcol() + new + set virtualedit=all + + call setline(1, 'foobar') + exe "normal! V\<Esc>" + call assert_equal([0, 1, 1, 0], getpos("'<")) + call assert_equal([0, 1, v:maxcol, 0], getpos("'>")) + let pos = getpos("'>") + + call cursor(1, 1) + call setpos('.', pos) + call assert_equal([0, 1, 7, 0], getpos('.')) + + call cursor(1, 1) + call cursor(pos[1:]) + call assert_equal([0, 1, 7, 0], getpos('.')) + + set virtualedit& + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim index 4c5ab9f61f..b7b5f611c4 100644 --- a/test/old/testdir/test_visual.vim +++ b/test/old/testdir/test_visual.vim @@ -1151,7 +1151,7 @@ func Test_visual_inner_block() " try to select non-existing inner block call cursor(5, 1) call assert_beeps('normal ViBiBiB') - " try to select a unclosed inner block + " try to select an unclosed inner block 8,9d call cursor(5, 1) call assert_beeps('normal ViBiB') @@ -1635,6 +1635,22 @@ func Test_visual_substitute_visual() bwipe! endfunc +func Test_virtualedit_exclusive_selection() + new + set virtualedit=all selection=exclusive + + call setline(1, "a\tb") + normal! 0v8ly + call assert_equal("a\t", getreg('"')) + normal! 0v6ly + call assert_equal('a ', getreg('"')) + normal! 06lv2ly + call assert_equal(' ', getreg('"')) + + set virtualedit& selection& + bwipe! +endfunc + func Test_visual_getregion() let lines =<< trim END new @@ -1644,18 +1660,52 @@ func Test_visual_getregion() #" Visual mode call cursor(1, 1) call feedkeys("\<ESC>vjl", 'tx') + call assert_equal(['one', 'tw'], \ 'v'->getpos()->getregion(getpos('.'))) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 0]] + \ ], + \ 'v'->getpos()->getregionpos(getpos('.'))) + call assert_equal(['one', 'tw'], \ '.'->getpos()->getregion(getpos('v'))) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 0]] + \ ], + \ '.'->getpos()->getregionpos(getpos('v'))) + call assert_equal(['o'], \ 'v'->getpos()->getregion(getpos('v'))) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 1, 0]], + \ ], + \ 'v'->getpos()->getregionpos(getpos('v'))) + call assert_equal(['w'], \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 0]], + \ ], + \ '.'->getpos()->getregionpos(getpos('.'), {'type': 'v' })) + call assert_equal(['one', 'two'], \ getpos('.')->getregion(getpos('v'), {'type': 'V' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ ], + \ getpos('.')->getregionpos(getpos('v'), {'type': 'V' })) + call assert_equal(['on', 'tw'], \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 2, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 0]], + \ ], + \ getpos('.')->getregionpos(getpos('v'), {'type': "\<C-v>" })) #" Line visual mode call cursor(1, 1) @@ -1702,6 +1752,9 @@ func Test_visual_getregion() \ "'a"->getpos()->getregion(getpos("'a"), {'type': 'V' })) call assert_equal(['one', 'two'], \ "."->getpos()->getregion(getpos("'a"), {'type': "\<c-v>" })) + call feedkeys("\<ESC>jVj\<ESC>", 'tx') + call assert_equal(['two', 'three'], getregion(getpos("'<"), getpos("'>"))) + call assert_equal(['two', 'three'], getregion(getpos("'>"), getpos("'<"))) #" Using List call cursor(1, 1) @@ -1721,65 +1774,264 @@ func Test_visual_getregion() call feedkeys("\<ESC>Vjj", 'tx') call assert_equal(['one', 'two', 'three'], \ getregion(getpos('v'), getpos('.'), {'type': 'V' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'V' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'V', 'eol': v:true })) #" Multiline with block visual mode call cursor(1, 1) call feedkeys("\<ESC>\<C-v>jj", 'tx') call assert_equal(['o', 't', 't'], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 1, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 1, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 1, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) call cursor(1, 1) call feedkeys("\<ESC>\<C-v>jj$", 'tx') call assert_equal(['one', 'two', 'three'], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", 'eol': v:true })) #" 'virtualedit' set virtualedit=all + call cursor(1, 1) call feedkeys("\<ESC>\<C-v>10ljj$", 'tx') call assert_equal(['one ', 'two ', 'three '], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 3]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 3]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 1]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", 'eol': v:true })) + + call cursor(3, 5) + call feedkeys("\<ESC>\<C-v>hkk", 'tx') + call assert_equal([' ', ' ', 'ee'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 0, 0], [bufnr('%'), 1, 0, 0]], + \ [[bufnr('%'), 2, 0, 0], [bufnr('%'), 2, 0, 0]], + \ [[bufnr('%'), 3, 4, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 4, 2]], + \ [[bufnr('%'), 2, 4, 0], [bufnr('%'), 2, 4, 2]], + \ [[bufnr('%'), 3, 4, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", 'eol': v:true })) + + call cursor(3, 5) + call feedkeys("\<ESC>\<C-v>kk", 'tx') + call assert_equal([' ', ' ', 'e'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 0, 0], [bufnr('%'), 1, 0, 0]], + \ [[bufnr('%'), 2, 0, 0], [bufnr('%'), 2, 0, 0]], + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 4, 1], [bufnr('%'), 1, 4, 2]], + \ [[bufnr('%'), 2, 4, 1], [bufnr('%'), 2, 4, 2]], + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", 'eol': v:true })) + + call cursor(1, 3) + call feedkeys("\<ESC>vjj4l", 'tx') + call assert_equal(['e', 'two', 'three '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 2]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', 'eol': v:true })) + + call cursor(1, 3) + call feedkeys("\<ESC>lvjj3l", 'tx') + call assert_equal(['', 'two', 'three '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 0, 0], [bufnr('%'), 1, 0, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 6, 2]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', 'eol': v:true })) + + call cursor(3, 5) + call feedkeys("\<ESC>v3l", 'tx') + call assert_equal(['e '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 6, 3]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', 'eol': v:true })) + + call cursor(3, 5) + call feedkeys("\<ESC>lv3l", 'tx') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 6, 0], [bufnr('%'), 3, 6, 4]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', 'eol': v:true })) + + call cursor(3, 5) + call feedkeys("\<ESC>3lv3l", 'tx') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 3, 6, 2], [bufnr('%'), 3, 6, 6]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', 'eol': v:true })) + set virtualedit& - #" Invalid position + #" using wrong types for positions call cursor(1, 1) call feedkeys("\<ESC>vjj$", 'tx') call assert_fails("call getregion(1, 2)", 'E1211:') call assert_fails("call getregion(getpos('.'), {})", 'E1211:') - call assert_equal([], getregion(getpos('.'), getpos('.'), {'type': '' })) - - #" using the wrong type call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:') + call assert_fails("call getregionpos(1, 2)", 'E1211:') + call assert_fails("call getregionpos(getpos('.'), {})", 'E1211:') + call assert_fails(':echo "."->getpos()->getregionpos("$", [])', 'E1211:') + + #" using invalid value for "type" + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '' })", 'E475:') + call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': '' })", 'E475:') #" using a mark from another buffer to current buffer new - VAR newbuf = bufnr() + LET g:buf = bufnr() call setline(1, range(10)) normal! GmA wincmd p - call assert_equal([newbuf, 10, 1, 0], getpos("'A")) + call assert_equal([g:buf, 10, 1, 0], getpos("'A")) call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' })) call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' })) - exe $':{newbuf}bwipe!' + call assert_equal([], getregionpos(getpos('.'), getpos("'A"), {'type': 'v' })) + call assert_equal([], getregionpos(getpos("'A"), getpos('.'), {'type': 'v' })) - #" using a mark from another buffer to another buffer - new - VAR anotherbuf = bufnr() - call setline(1, range(10)) - normal! GmA + #" using two marks from another buffer + wincmd p normal! GmB wincmd p - call assert_equal([anotherbuf, 10, 1, 0], getpos("'A")) - call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' })) - exe $':{anotherbuf}bwipe!' + call assert_equal([g:buf, 10, 1, 0], getpos("'B")) + call assert_equal(['9'], + \ getregion(getpos("'B"), getpos("'A"), {'type': 'v' })) + call assert_equal([ + \ [[g:buf, 10, 1, 0], [g:buf, 10, 1, 0]], + \ ], + \ getregionpos(getpos("'B"), getpos("'A"), {'type': 'v' })) + + #" using two positions from another buffer + for type in ['v', 'V', "\<C-V>"] + for exclusive in [v:false, v:true] + call assert_equal(range(10)->mapnew('string(v:val)'), + \ getregion([g:buf, 1, 1, 0], [g:buf, 10, 2, 0], + \ {'type': type, 'exclusive': exclusive })) + call assert_equal(range(10)->mapnew('string(v:val)'), + \ getregion([g:buf, 10, 2, 0], [g:buf, 1, 1, 0], + \ {'type': type, 'exclusive': exclusive })) + call assert_equal(range(1, 10)->mapnew('repeat([[g:buf, v:val, 1, 0]], 2)'), + \ getregionpos([g:buf, 1, 1, 0], [g:buf, 10, 2, 0], + \ {'type': type, 'exclusive': exclusive })) + call assert_equal(range(1, 10)->mapnew('repeat([[g:buf, v:val, 1, 0]], 2)'), + \ getregionpos([g:buf, 10, 2, 0], [g:buf, 1, 1, 0], + \ {'type': type, 'exclusive': exclusive })) + endfor + endfor + + #" using invalid positions in buffer + call assert_fails('call getregion([g:buf, 0, 1, 0], [g:buf, 10, 2, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 10, 2, 0], [g:buf, 0, 1, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 11, 2, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 11, 2, 0], [g:buf, 1, 1, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 0, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 10, 0, 0], [g:buf, 1, 1, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 3, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 10, 3, 0], [g:buf, 1, 1, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 1, 0, 0], [g:buf, 1, 1, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 1, 0, 0])', 'E964:') #" using invalid buffer - call assert_equal([], getregion([10000, 10, 1, 0], [10000, 10, 1, 0])) + call assert_fails('call getregion([10000, 10, 1, 0], [10000, 10, 1, 0])', 'E681:') + + exe $':{g:buf}bwipe!' + unlet g:buf + bwipe! END call CheckLegacyAndVim9Success(lines) - bwipe! - let lines =<< trim END #" Selection in starts or ends in the middle of a multibyte character new @@ -1788,35 +2040,95 @@ func Test_visual_getregion() \ "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9", \ "1234567890" \ ]) + call cursor(1, 3) call feedkeys("\<Esc>\<C-v>ljj", 'xt') call assert_equal(['cd', "\u00ab ", '34'], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 5, 0], [bufnr('%'), 2, 7, 1]], + \ [[bufnr('%'), 3, 3, 0], [bufnr('%'), 3, 4, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 4) call feedkeys("\<Esc>\<C-v>ljj", 'xt') call assert_equal(['de', "\U0001f1e7", '45'], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 4, 0], [bufnr('%'), 1, 5, 0]], + \ [[bufnr('%'), 2, 7, 0], [bufnr('%'), 2, 10, 0]], + \ [[bufnr('%'), 3, 4, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 5) call feedkeys("\<Esc>\<C-v>jj", 'xt') call assert_equal(['e', ' ', '5'], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 5, 0]], + \ [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 2]], + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 13, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 22, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 5, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + #" characterwise selection with multibyte chars call cursor(1, 1) call feedkeys("\<Esc>vj", 'xt') call assert_equal(['abcdefghijk«', "\U0001f1e6"], \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 13, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + set selection=exclusive + call feedkeys('l', 'xt') + call assert_equal(['abcdefghijk«', "\U0001f1e6"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 13, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 4, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) #" marks on multibyte chars - :set selection=exclusive call setpos("'a", [0, 1, 11, 0]) call setpos("'b", [0, 2, 16, 0]) call setpos("'c", [0, 2, 0, 0]) call cursor(1, 1) + call assert_equal(['ghijk', '🇨«🇩'], - \ getregion(getpos("'a"), getpos("'b"), {'type': "\<c-v>" })) + \ getregion(getpos("'a"), getpos("'b"), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 7, 0], [bufnr('%'), 1, 11, 0]], + \ [[bufnr('%'), 2, 13, 0], [bufnr('%'), 2, 22, 0]], + \ ], + \ getregionpos(getpos("'a"), getpos("'b"), {'type': "\<C-v>" })) + call assert_equal(['k«', '🇦«🇧«🇨'], \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 11, 0], [bufnr('%'), 1, 13, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 16, 0]], + \ ], + \ getregionpos(getpos("'a"), getpos("'b"), {'type': 'v' })) + call assert_equal(['k«'], \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 11, 0], [bufnr('%'), 1, 13, 0]], + \ ], + \ getregionpos(getpos("'a"), getpos("'c"), {'type': 'v' })) #" use inclusive selection, although 'selection' is exclusive call setpos("'a", [0, 1, 11, 0]) @@ -1839,12 +2151,12 @@ func Test_visual_getregion() call assert_equal(['abcdefghijk«'], \ getregion(getpos("'a"), getpos("'b"), \ {'type': 'V', 'exclusive': 1 })) - :set selection& + + set selection& + bwipe! END call CheckLegacyAndVim9Success(lines) - bwipe! - let lines =<< trim END #" Exclusive selection new @@ -1875,51 +2187,346 @@ func Test_visual_getregion() call assert_equal(["c", "x\tz"], \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) set selection& + bwipe! #" Exclusive selection 2 new call setline(1, ["a\tc", "x\tz", '', '']) + call cursor(1, 1) call feedkeys("\<Esc>v2l", 'xt') call assert_equal(["a\t"], \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 2, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) call feedkeys("\<Esc>v$G", 'xt') call assert_equal(["a\tc", "x\tz", ''], \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) call feedkeys("\<Esc>v$j", 'xt') call assert_equal(["a\tc", "x\tz"], \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) call feedkeys("\<Esc>\<C-v>$j", 'xt') call assert_equal(["a\tc", "x\tz"], \ getregion(getpos('v'), getpos('.'), \ {'exclusive': v:true, 'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'exclusive': v:true, 'type': "\<C-v>" })) + call cursor(1, 1) call feedkeys("\<Esc>\<C-v>$G", 'xt') call assert_equal(["a", "x", '', ''], \ getregion(getpos('v'), getpos('.'), \ {'exclusive': v:true, 'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 1, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 1, 0]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ [[bufnr('%'), 4, 0, 0], [bufnr('%'), 4, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'exclusive': v:true, 'type': "\<C-v>" })) + call cursor(1, 1) call feedkeys("\<Esc>wv2j", 'xt') call assert_equal(["c", "x\tz"], \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call assert_equal([ + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'exclusive': v:true })) - #" virtualedit + #" 'virtualedit' with exclusive selection set selection=exclusive set virtualedit=all + + call cursor(1, 1) + call feedkeys("\<Esc>vj", 'xt') + call assert_equal(["a\tc"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>v8l", 'xt') + call assert_equal(["a\t"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 2, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>v6l", 'xt') + call assert_equal(['a '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 2, 5]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 1) - call feedkeys("\<Esc>2lv2lj", 'xt') + call feedkeys("\<Esc>6lv2l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>lv2l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>2lv2l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call feedkeys('j', 'xt') call assert_equal([' c', 'x '], \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 3]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>6l\<C-v>2lj", 'xt') + call assert_equal([' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 2, 7]], + \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 7]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + + call cursor(1, 1) + call feedkeys("\<Esc>l\<C-v>2l2j", 'xt') + call assert_equal([' ', ' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]], + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 2]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 2]], + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 2]], + \ [[bufnr('%'), 3, 1, 1], [bufnr('%'), 3, 1, 3]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", "eol": v:true })) + call cursor(1, 1) call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt') call assert_equal([' ', ' ', ' '], \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) - set virtualedit& + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]], + \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 3]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 3]], + \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 3]], + \ [[bufnr('%'), 3, 1, 2], [bufnr('%'), 3, 1, 4]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", "eol": v:true })) + + #" 'virtualedit' with inclusive selection set selection& + call cursor(1, 1) + call feedkeys("\<Esc>vj", 'xt') + call assert_equal(["a\tc", 'x'], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 1, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>v8l", 'xt') + call assert_equal(["a\tc"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>v6l", 'xt') + call assert_equal(['a '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 2, 6]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>6lv2l", 'xt') + call assert_equal([' c'], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>lv2l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 3]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>2lv2l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 4]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call feedkeys('j', 'xt') + call assert_equal([' c', 'x '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 2, 4]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + + call cursor(1, 1) + call feedkeys("\<Esc>6l\<C-v>2lj", 'xt') + call assert_equal([' c', ' z'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 5], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + + call cursor(1, 1) + call feedkeys("\<Esc>l\<C-v>2l2j", 'xt') + call assert_equal([' ', ' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 3]], + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 3]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 2, 3]], + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 2, 3]], + \ [[bufnr('%'), 3, 1, 1], [bufnr('%'), 3, 1, 4]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", "eol": v:true })) + + call cursor(1, 1) + call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt') + call assert_equal([' ', ' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 4]], + \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 4]], + \ [[bufnr('%'), 3, 0, 0], [bufnr('%'), 3, 0, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 2, 1], [bufnr('%'), 1, 2, 4]], + \ [[bufnr('%'), 2, 2, 1], [bufnr('%'), 2, 2, 4]], + \ [[bufnr('%'), 3, 1, 2], [bufnr('%'), 3, 1, 5]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", "eol": v:true })) + + set virtualedit& + bwipe! + END + call CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + #" 'virtualedit' with TABs at end of line + new + set virtualedit=all + call setline(1, ["\t", "a\t", "aa\t"]) + + call feedkeys("gg06l\<C-v>3l2j", 'xt') + call assert_equal([' ', ' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 6], [bufnr('%'), 1, 1, 0]], + \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 2, 0]], + \ [[bufnr('%'), 3, 3, 4], [bufnr('%'), 3, 3, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 6], [bufnr('%'), 1, 2, 2]], + \ [[bufnr('%'), 2, 2, 5], [bufnr('%'), 2, 3, 2]], + \ [[bufnr('%'), 3, 3, 4], [bufnr('%'), 3, 4, 2]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': "\<C-v>", "eol": v:true })) + + call feedkeys("gg06lv3l", 'xt') + call assert_equal([' '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 6], [bufnr('%'), 1, 1, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 6], [bufnr('%'), 1, 2, 2]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), + \ {'type': 'v', "eol": v:true })) + + set virtualedit& bwipe! END call CheckLegacyAndVim9Success(lines) @@ -1935,7 +2542,41 @@ func Test_getregion_invalid_buf() call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B"))) " close the help window q - call assert_equal([], getregion(getpos("'A"), getpos("'B"))) + call assert_fails("call getregion(getpos(\"'A\"), getpos(\"'B\"))", 'E681:') + bwipe! +endfunc + +func Test_getregion_maxcol() + new + autocmd TextYankPost * + \ : if v:event.operator ==? 'y' + \ | call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ ], + \ getregionpos(getpos("'["), getpos("']"), + \ #{ mode: visualmode() })) + \ | call assert_equal(['abcd'], + \ getregion(getpos("'["), getpos("']"), + \ #{ mode: visualmode() })) + \ | call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ ], + \ getregionpos(getpos("']"), getpos("'["), + \ #{ mode: visualmode() })) + \ | call assert_equal(['abcd'], + \ getregion(getpos("']"), getpos("'["), + \ #{ mode: visualmode() })) + \ | endif + call setline(1, ['abcd', 'efghij']) + normal yy + bwipe! +endfunc + +func Test_visual_block_cursor_delete() + new + call setline(1, 'ab') + exe ":norm! $\<c-v>hI\<Del>\<ESC>" + call assert_equal(['b'], getline(1, 1)) bwipe! endfunc diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim index da1711a0a1..50da2beb40 100644 --- a/test/old/testdir/test_window_cmd.vim +++ b/test/old/testdir/test_window_cmd.vim @@ -113,64 +113,6 @@ func Test_window_quit() bw Xa Xb endfunc -func Test_window_curwin_not_prevwin() - botright split - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - quit - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - - botright split - botright split - call assert_equal(3, winnr()) - call assert_equal(2, winnr('#')) - 1quit - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - botright split - call assert_equal(1, tabpagenr()) - call assert_equal(3, winnr()) - call assert_equal(2, winnr('#')) - wincmd T - call assert_equal(2, tabpagenr()) - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - tabfirst - call assert_equal(1, tabpagenr()) - call assert_equal(2, winnr()) - call assert_equal(0, winnr('#')) - - tabonly - botright split - wincmd t - wincmd p - call assert_equal(3, winnr()) - call assert_equal(1, winnr('#')) - quit - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - botright split - wincmd t - wincmd p - call assert_equal(1, tabpagenr()) - call assert_equal(3, winnr()) - call assert_equal(1, winnr('#')) - wincmd T - call assert_equal(2, tabpagenr()) - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - tabfirst - call assert_equal(1, tabpagenr()) - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - tabonly - only -endfunc - func Test_window_horizontal_split() call assert_equal(1, winnr('$')) 3wincmd s @@ -258,6 +200,20 @@ func Test_window_split_edit_bufnr() %bw! endfunc +func s:win_layout_info(tp = tabpagenr()) abort + return #{ + \ layout: winlayout(a:tp), + \ pos_sizes: range(1, tabpagewinnr(a:tp, '$')) + \ ->map({_, nr -> win_getid(nr, a:tp)->getwininfo()[0]}) + \ ->map({_, wininfo -> #{id: wininfo.winid, + \ row: wininfo.winrow, + \ col: wininfo.wincol, + \ width: wininfo.width, + \ height: wininfo.height}}) + \ ->sort({a, b -> a.id - b.id}) + \ } +endfunc + func Test_window_split_no_room() " N horizontal windows need >= 2*N + 1 lines: " - 1 line + 1 status line in each window @@ -272,6 +228,14 @@ func Test_window_split_no_room() for s in range(1, hor_split_count) | split | endfor call assert_fails('split', 'E36:') + botright vsplit + wincmd | + let info = s:win_layout_info() + call assert_fails('wincmd J', 'E36:') + call assert_fails('wincmd K', 'E36:') + call assert_equal(info, s:win_layout_info()) + only + " N vertical windows need >= 2*(N - 1) + 1 columns: " - 1 column + 1 separator for each window (except last window) " - 1 column for the last window which does not have separator @@ -284,7 +248,37 @@ func Test_window_split_no_room() for s in range(1, ver_split_count) | vsplit | endfor call assert_fails('vsplit', 'E36:') + split + wincmd | + let info = s:win_layout_info() + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd L', 'E36:') + call assert_equal(info, s:win_layout_info()) + + " Check that the last statusline isn't lost. + " Set its window's width to 2 for the test. + wincmd j + set laststatus=0 winminwidth=0 + vertical resize 2 + " Update expected positions/sizes after the resize. Layout is unchanged. + let info.pos_sizes = s:win_layout_info().pos_sizes + set winminwidth& + call setwinvar(winnr('k'), '&statusline', '@#') + let last_stl_row = win_screenpos(0)[0] - 1 + redraw + call assert_equal('@#|', GetScreenStr(last_stl_row)) + call assert_equal('~ |', GetScreenStr(&lines - &cmdheight)) + + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd L', 'E36:') + call assert_equal(info, s:win_layout_info()) + call setwinvar(winnr('k'), '&statusline', '=-') + redraw + call assert_equal('=-|', GetScreenStr(last_stl_row)) + call assert_equal('~ |', GetScreenStr(&lines - &cmdheight)) + %bw! + set laststatus& endfunc func Test_window_exchange() @@ -1024,6 +1018,19 @@ func Test_win_splitmove() leftabove split b leftabove vsplit c leftabove split d + + " win_splitmove doesn't actually create or close any windows, so expect an + " unchanged winid and no WinNew/WinClosed events, like :wincmd H/J/K/L. + let s:triggered = [] + augroup WinSplitMove + au! + " Nvim: WinNewPre not ported yet. Also needs full port of v9.1.0117 to pass. + " au WinNewPre * let s:triggered += ['WinNewPre'] + au WinNew * let s:triggered += ['WinNew', win_getid()] + au WinClosed * let s:triggered += ['WinClosed', str2nr(expand('<afile>'))] + augroup END + let winid = win_getid() + call assert_equal(0, win_splitmove(winnr(), winnr('l'))) call assert_equal(bufname(winbufnr(1)), 'c') call assert_equal(bufname(winbufnr(2)), 'd') @@ -1046,6 +1053,11 @@ func Test_win_splitmove() call assert_equal(bufname(winbufnr(3)), 'a') call assert_equal(bufname(winbufnr(4)), 'd') call assert_fails('call win_splitmove(winnr(), winnr("k"), v:_null_dict)', 'E1297:') + call assert_equal([], s:triggered) + call assert_equal(winid, win_getid()) + + unlet! s:triggered + au! WinSplitMove only | bd call assert_fails('call win_splitmove(winnr(), 123)', 'E957:') @@ -1055,18 +1067,54 @@ func Test_win_splitmove() tabnew call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:') tabclose -endfunc -func Test_floatwin_splitmove() - vsplit - let win2 = win_getid() - let popup_winid = nvim_open_win(0, 0, {'relative': 'win', - \ 'row': 3, 'col': 3, 'width': 12, 'height': 3}) - call assert_fails('call win_splitmove(popup_winid, win2)', 'E957:') - call assert_fails('call win_splitmove(win2, popup_winid)', 'E957:') + split + augroup WinSplitMove + au! + au WinEnter * ++once call win_gotoid(win_getid(winnr('#'))) + augroup END + call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:') + + augroup WinSplitMove + au! + au WinLeave * ++once quit + augroup END + call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:') + + split + split + augroup WinSplitMove + au! + au WinEnter * ++once let s:triggered = v:true + \| call assert_fails('call win_splitmove(winnr(), winnr("$"))', 'E242:') + \| call assert_fails('call win_splitmove(winnr("$"), winnr())', 'E242:') + augroup END + quit + call assert_equal(v:true, s:triggered) + unlet! s:triggered + + new + augroup WinSplitMove + au! + au BufHidden * ++once let s:triggered = v:true + \| call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E1159:') + augroup END + hide + call assert_equal(v:true, s:triggered) + unlet! s:triggered - call nvim_win_close(popup_winid, 1) - bwipe + split + let close_win = winnr('#') + augroup WinSplitMove + au! + au WinEnter * ++once quit! + augroup END + call win_splitmove(close_win, winnr()) + call assert_equal(0, win_id2win(close_win)) + + au! WinSplitMove + augroup! WinSplitMove + %bw! endfunc " Test for the :only command @@ -2006,24 +2054,160 @@ func Test_new_help_window_on_error() call assert_equal(expand("<cword>"), "'mod'") endfunc -func Test_smoothscroll_in_zero_width_window() - let save_lines = &lines - let save_columns = &columns +func Test_splitmove_flatten_frame() + split + vsplit - winsize 0 24 - set cpo+=n - exe "noremap 0 \<C-W>n\<C-W>L" - norm 000000 - set number smoothscroll - exe "norm \<C-Y>" + wincmd L + let layout = winlayout() + wincmd K + wincmd L + call assert_equal(winlayout(), layout) only! - let &lines = save_lines - let &columns = save_columns - set cpo-=n - unmap 0 - set nonumber nosmoothscroll endfunc +func Test_autocmd_window_force_room() + " Open as many windows as possible + while v:true + try + split + catch /E36:/ + break + endtry + endwhile + while v:true + try + vsplit + catch /E36:/ + break + endtry + endwhile + + wincmd j + vsplit + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd J', 'E36:') + call assert_fails('wincmd K', 'E36:') + call assert_fails('wincmd L', 'E36:') + + edit unload me + enew + bunload! unload\ me + augroup AucmdWinForceRoom + au! + au BufEnter * ++once let s:triggered = v:true + \| call assert_equal('autocmd', win_gettype()) + augroup END + let info = s:win_layout_info() + " bufload opening the autocommand window shouldn't give E36. + call bufload('unload me') + call assert_equal(v:true, s:triggered) + call assert_equal(info, s:win_layout_info()) + + unlet! s:triggered + au! AucmdWinForceRoom + augroup! AucmdWinForceRoom + %bw! +endfunc + +func Test_win_gotoid_splitmove_textlock_cmdwin() + call setline(1, 'foo') + new + let curwin = win_getid() + call setline(1, 'bar') + + set debug+=throw indentexpr=win_gotoid(win_getid(winnr('#'))) + call assert_fails('normal! ==', 'E565:') + call assert_equal(curwin, win_getid()) + " No error if attempting to switch to curwin; nothing happens. + set indentexpr=assert_equal(1,win_gotoid(win_getid())) + normal! == + call assert_equal(curwin, win_getid()) + + set indentexpr=win_splitmove(winnr('#'),winnr()) + call assert_fails('normal! ==', 'E565:') + call assert_equal(curwin, win_getid()) + + %bw! + set debug-=throw indentexpr& + + call feedkeys('q:' + \ .. ":call assert_fails('call win_splitmove(winnr(''#''), winnr())', 'E11:')\<CR>" + \ .. ":call assert_equal('command', win_gettype())\<CR>" + \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx') + + call feedkeys('q:' + \ .. ":call assert_fails('call win_gotoid(win_getid(winnr(''#'')))', 'E11:')\<CR>" + "\ No error if attempting to switch to curwin; nothing happens. + \ .. ":call assert_equal(1, win_gotoid(win_getid()))\<CR>" + \ .. ":call assert_equal('command', win_gettype())\<CR>" + \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx') +endfunc + +func Test_winfixsize_positions() + " Check positions are correct when closing a window in a non-current tabpage + " causes non-adjacent window to fill the space due to 'winfix{width,height}'. + tabnew + vsplit + wincmd | + split + set winfixheight + split foo + tabfirst + + bwipe! foo + " Save actual values before entering the tabpage. + let info = s:win_layout_info(2) + tabnext + " Compare it with the expected value (after win_comp_pos) from entering. + call assert_equal(s:win_layout_info(), info) + + $tabnew + split + split + wincmd k + belowright vsplit + set winfixwidth + belowright vsplit foo + tabprevious + + bwipe! foo + " Save actual values before entering the tabpage. + let info = s:win_layout_info(3) + tabnext + " Compare it with the expected value (after win_comp_pos) from entering. + call assert_equal(s:win_layout_info(), info) + + " Check positions unchanged when failing to move a window, if 'winfix{width, + " height}' would otherwise cause a non-adjacent window to fill the space. + %bwipe + call assert_fails('execute "split|"->repeat(&lines)', 'E36:') + wincmd p + vsplit + set winfixwidth + vsplit + set winfixwidth + vsplit + vsplit + set winfixwidth + wincmd p + + let info = s:win_layout_info() + call assert_fails('wincmd J', 'E36:') + call assert_equal(info, s:win_layout_info()) + + only + call assert_fails('execute "vsplit|"->repeat(&columns)', 'E36:') + belowright split + set winfixheight + belowright split + + let info = s:win_layout_info() + call assert_fails('wincmd H', 'E36:') + call assert_equal(info, s:win_layout_info()) + + %bwipe +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/test_winfixbuf.vim b/test/old/testdir/test_winfixbuf.vim new file mode 100644 index 0000000000..b41eaf3c9b --- /dev/null +++ b/test/old/testdir/test_winfixbuf.vim @@ -0,0 +1,3358 @@ +" Test 'winfixbuf' + +source check.vim +source shared.vim + +" Find the number of open windows in the current tab +func s:get_windows_count() + return tabpagewinnr(tabpagenr(), '$') +endfunc + +" Create some unnamed buffers. +func s:make_buffers_list() + enew + file first + let l:first = bufnr() + + enew + file middle + let l:middle = bufnr() + + enew + file last + let l:last = bufnr() + + set winfixbuf + + return [l:first, l:last] +endfunc + +" Create some unnamed buffers and add them to an args list +func s:make_args_list() + let [l:first, l:last] = s:make_buffers_list() + + args! first middle last + + return [l:first, l:last] +endfunc + +" Create two buffers and then set the window to 'winfixbuf' +func s:make_buffer_pairs(...) + let l:reversed = get(a:, 1, 0) + + if l:reversed == 1 + enew + file original + + set winfixbuf + + enew! + file other + let l:other = bufnr() + + return l:other + endif + + enew + file other + let l:other = bufnr() + + enew + file current + + set winfixbuf + + return l:other +endfunc + +" Create 3 quick buffers and set the window to 'winfixbuf' +func s:make_buffer_trio() + edit first + let l:first = bufnr() + edit second + let l:second = bufnr() + + set winfixbuf + + edit! third + let l:third = bufnr() + + execute ":buffer! " . l:second + + return [l:first, l:second, l:third] +endfunc + +" Create a location list with at least 2 entries + a 'winfixbuf' window. +func s:make_simple_location_list() + enew + file middle + let l:middle = bufnr() + call append(0, ["winfix search-term", "another line"]) + + enew! + file first + let l:first = bufnr() + call append(0, "first search-term") + + enew! + file last + let l:last = bufnr() + call append(0, "last search-term") + + call setloclist( + \ 0, + \ [ + \ { + \ "filename": "first", + \ "bufnr": l:first, + \ "lnum": 1, + \ }, + \ { + \ "filename": "middle", + \ "bufnr": l:middle, + \ "lnum": 1, + \ }, + \ { + \ "filename": "middle", + \ "bufnr": l:middle, + \ "lnum": 2, + \ }, + \ { + \ "filename": "last", + \ "bufnr": l:last, + \ "lnum": 1, + \ }, + \ ] + \) + + set winfixbuf + + return [l:first, l:middle, l:last] +endfunc + +" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. +func s:make_simple_quickfix() + enew + file current + let l:current = bufnr() + call append(0, ["winfix search-term", "another line"]) + + enew! + file first + let l:first = bufnr() + call append(0, "first search-term") + + enew! + file last + let l:last = bufnr() + call append(0, "last search-term") + + call setqflist( + \ [ + \ { + \ "filename": "first", + \ "bufnr": l:first, + \ "lnum": 1, + \ }, + \ { + \ "filename": "current", + \ "bufnr": l:current, + \ "lnum": 1, + \ }, + \ { + \ "filename": "current", + \ "bufnr": l:current, + \ "lnum": 2, + \ }, + \ { + \ "filename": "last", + \ "bufnr": l:last, + \ "lnum": 1, + \ }, + \ ] + \) + + set winfixbuf + + return [l:current, l:last] +endfunc + +" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. +func s:make_quickfix_windows() + let [l:current, _] = s:make_simple_quickfix() + execute "buffer! " . l:current + + split + let l:first_window = win_getid() + execute "normal \<C-w>j" + let l:winfix_window = win_getid() + + " Open the quickfix in a separate split and go to it + copen + let l:quickfix_window = win_getid() + + return [l:first_window, l:winfix_window, l:quickfix_window] +endfunc + +" Revert all changes that occurred in any past test +func s:reset_all_buffers() + %bwipeout! + set nowinfixbuf + + call setqflist([]) + call setloclist(0, [], 'f') + + delmarks A-Z0-9 +endfunc + +" Find and set the first quickfix entry that points to `buffer` +func s:set_quickfix_by_buffer(buffer) + let l:index = 1 " quickfix indices start at 1 + for l:entry in getqflist() + if l:entry["bufnr"] == a:buffer + execute l:index . "cc" + + return + endif + + let l:index += 1 + endfor + + echoerr 'No quickfix entry matching "' . a:buffer . '" could be found.' +endfunc + +" Fail to call :Next on a 'winfixbuf' window unless :Next! is used. +func Test_Next() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("Next", "E1513:") + call assert_notequal(l:first, bufnr()) + + Next! + call assert_equal(l:first, bufnr()) +endfunc + +" Call :argdo and choose the next available 'nowinfixbuf' window. +func Test_argdo_choose_available_window() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :argdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + argdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :argdo and create a new split window if all available windows are 'winfixbuf'. +func Test_argdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, l:last] = s:make_args_list() + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + argdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :argedit but :argedit! is allowed +func Test_argedit() + call s:reset_all_buffers() + + args! first middle last + enew + file first + let l:first = bufnr() + + enew + file middle + let l:middle = bufnr() + + enew + file last + let l:last = bufnr() + + set winfixbuf + + let l:current = bufnr() + call assert_fails("argedit first middle last", "E1513:") + call assert_equal(l:current, bufnr()) + + argedit! first middle last + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :arglocal but :arglocal! is allowed +func Test_arglocal() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + argglobal! other + execute "buffer! " . l:current + + call assert_fails("arglocal other", "E1513:") + call assert_equal(l:current, bufnr()) + + arglocal! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :argglobal but :argglobal! is allowed +func Test_argglobal() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("argglobal other", "E1513:") + call assert_equal(l:current, bufnr()) + + argglobal! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :args but :args! is allowed +func Test_args() + call s:reset_all_buffers() + + let [l:first, _] = s:make_buffers_list() + let l:current = bufnr() + + call assert_fails("args first middle last", "E1513:") + call assert_equal(l:current, bufnr()) + + args! first middle last + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :bNext but :bNext! is allowed +func Test_bNext() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + call assert_fails("bNext", "E1513:") + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + + bNext! + call assert_equal(l:other, bufnr()) +endfunc + +" Allow :badd because it doesn't actually change the current window's buffer +func Test_badd() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + badd other + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :balt because it doesn't actually change the current window's buffer +func Test_balt() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + balt other + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :bfirst but :bfirst! is allowed +func Test_bfirst() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bfirst", "E1513:") + call assert_equal(l:current, bufnr()) + + bfirst! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :blast but :blast! is allowed +func Test_blast() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs(1) + bfirst! + let l:current = bufnr() + + call assert_fails("blast", "E1513:") + call assert_equal(l:current, bufnr()) + + blast! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bmodified but :bmodified! is allowed +func Test_bmodified() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + execute "buffer! " . l:other + set modified + execute "buffer! " . l:current + + call assert_fails("bmodified", "E1513:") + call assert_equal(l:current, bufnr()) + + bmodified! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bnext but :bnext! is allowed +func Test_bnext() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bnext", "E1513:") + call assert_equal(l:current, bufnr()) + + bnext! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bprevious but :bprevious! is allowed +func Test_bprevious() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bprevious", "E1513:") + call assert_equal(l:current, bufnr()) + + bprevious! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :brewind but :brewind! is allowed +func Test_brewind() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("brewind", "E1513:") + call assert_equal(l:current, bufnr()) + + brewind! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :browse edit but :browse edit! is allowed +func Test_browse_edit_fail() + " A GUI dialog may stall the test. + CheckNotGui + + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("browse edit other", "E1513:") + call assert_equal(l:current, bufnr()) + + try + browse edit! other + call assert_equal(l:other, bufnr()) + catch /^Vim\%((\a\+)\)\=:E338:/ + " Ignore E338, which occurs if console Vim is built with +browse. + " Console Vim without +browse will treat this as a regular :edit. + endtry +endfunc + +" Allow :browse w because it doesn't change the buffer in the current file +func Test_browse_edit_pass() + " A GUI dialog may stall the test. + CheckNotGui + + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + try + browse write other + catch /^Vim\%((\a\+)\)\=:E338:/ + " Ignore E338, which occurs if console Vim is built with +browse. + " Console Vim without +browse will treat this as a regular :write. + endtry + + call delete("other") +endfunc + +" Call :bufdo and choose the next available 'nowinfixbuf' window. +func Test_bufdo_choose_available_window() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :bufdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + + let l:current = bufnr() + let l:expected_windows = s:get_windows_count() + + call assert_notequal(l:current, l:other) + + bufdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_notequal(l:other, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :bufdo and create a new split window if all available windows are 'winfixbuf'. +func Test_bufdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, l:last] = s:make_buffers_list() + execute "buffer! " . l:first + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + bufdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :buffer but :buffer! is allowed +func Test_buffer() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("buffer " . l:other, "E1513:") + call assert_equal(l:current, bufnr()) + + execute "buffer! " . l:other + call assert_equal(l:other, bufnr()) +endfunc + +" Allow :buffer on a 'winfixbuf' window if there is no change in buffer +func Test_buffer_same_buffer() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + execute "buffer " . l:current + call assert_equal(l:current, bufnr()) + + execute "buffer! " . l:current + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :cNext but the 'nowinfixbuf' window is selected, instead +func Test_cNext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cNext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cNext + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cNfile but the 'nowinfixbuf' window is selected, instead +func Test_cNfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cNfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cNfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :caddexpr because it doesn't change the current buffer +func Test_caddexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["Error - bad-thing-found"], l:file_path, 'D') + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + execute 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :cbuffer but :cbuffer! is allowed +func Test_cbuffer() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + call assert_fails("cbuffer " . l:file_buffer) + call assert_equal(l:current, bufnr()) + + execute "cbuffer! " . l:file_buffer + call assert_equal("first.unittest", expand("%:t")) +endfunc + +" Allow :cc but the 'nowinfixbuf' window is selected, instead +func Test_cc() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + " Go up one line in the quickfix window to an quickfix entry that doesn't + " point to a winfixbuf buffer + normal k + " Attempt to make the previous window, winfixbuf buffer, to go to the + " non-winfixbuf quickfix entry + .cc + + " Confirm that :.cc did not change the winfixbuf-enabled window + call assert_equal(l:first_window, win_getid()) +endfunc + +" Call :cdo and choose the next available 'nowinfixbuf' window. +func Test_cdo_choose_available_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :cdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + cdo echo '' + + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :cdo and create a new split window if all available windows are 'winfixbuf'. +func Test_cdo_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current_buffer, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current_buffer + + let l:current_window = win_getid() + let l:current_windows = s:get_windows_count() + + cdo echo '' + call assert_notequal(l:current_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current_buffer, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :cexpr but :cexpr! is allowed +func Test_cexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file = tempname() + let l:entry = '["' . l:file . ':1:bar"]' + let l:current = bufnr() + + set winfixbuf + + call assert_fails("cexpr " . l:entry) + call assert_equal(l:current, bufnr()) + + execute "cexpr! " . l:entry + call assert_equal(fnamemodify(l:file, ":t"), expand("%:t")) +endfunc + +" Call :cfdo and choose the next available 'nowinfixbuf' window. +func Test_cfdo_choose_available_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :cfdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + cfdo echo '' + + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :cfdo and create a new split window if all available windows are 'winfixbuf'. +func Test_cfdo_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current_buffer, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current_buffer + + let l:current_window = win_getid() + let l:current_windows = s:get_windows_count() + + cfdo echo '' + call assert_notequal(l:current_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current_buffer, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :cfile but :cfile! is allowed +func Test_cfile() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + write + let l:first = bufnr() + + edit! second.unittest + call append(0, ["some-search-term"]) + write + + let l:file = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file) + + let l:current = bufnr() + + set winfixbuf + + call assert_fails(":cfile " . l:file) + call assert_equal(l:current, bufnr()) + + execute ":cfile! " . l:file + call assert_equal(l:first, bufnr()) + + call delete(l:file) + call delete("first.unittest") + call delete("second.unittest") +endfunc + +" Allow :cfirst but the 'nowinfixbuf' window is selected, instead +func Test_cfirst() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cfirst` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cfirst + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :clast but the 'nowinfixbuf' window is selected, instead +func Test_clast() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:clast` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + clast + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cnext but the 'nowinfixbuf' window is selected, instead +" Make sure no new windows are created and previous windows are reused +func Test_cnext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + let l:expected = s:get_windows_count() + + " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + cnext! + call assert_equal(l:expected, s:get_windows_count()) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cnext + call assert_equal(l:first_window, win_getid()) + call assert_equal(l:expected, s:get_windows_count()) +endfunc + +" Make sure :cnext creates a split window if no previous window exists +func Test_cnext_no_previous_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, _] = s:make_simple_quickfix() + execute "buffer! " . l:current + + let l:expected = s:get_windows_count() + + " Open the quickfix in a separate split and go to it + copen + + call assert_equal(l:expected + 1, s:get_windows_count()) +endfunc + +" Allow :cnext and create a 'nowinfixbuf' window if none exists +func Test_cnext_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, _] = s:make_simple_quickfix() + let l:current = win_getid() + + cfirst! + + let l:windows = s:get_windows_count() + let l:expected = l:windows + 1 " We're about to create a new split window + + cnext + call assert_equal(l:expected, s:get_windows_count()) + + cnext! + call assert_equal(l:expected, s:get_windows_count()) +endfunc + +" Allow :cprevious but the 'nowinfixbuf' window is selected, instead +func Test_cprevious() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cprevious` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cprevious + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cnfile but the 'nowinfixbuf' window is selected, instead +func Test_cnfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cnfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cnfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cpfile but the 'nowinfixbuf' window is selected, instead +func Test_cpfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cpfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cpfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :crewind but the 'nowinfixbuf' window is selected, instead +func Test_crewind() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:crewind` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + crewind + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow <C-w>f because it opens in a new split +func Test_ctrl_w_f() + call s:reset_all_buffers() + + enew + let l:file_name = tempname() + call writefile([], l:file_name) + let l:file_buffer = bufnr() + + enew + file other + let l:other_buffer = bufnr() + + set winfixbuf + + call setline(1, l:file_name) + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>f" + + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + call delete(l:file_name) +endfunc + +" Fail :djump but :djump! is allowed +func Test_djump() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("djump 1 /min/", "E1513:") + call assert_equal(l:current, bufnr()) + + djump! 1 /min/ + call assert_notequal(l:current, bufnr()) + + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail :drop but :drop! is allowed +func Test_drop() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("drop other", "E1513:") + call assert_equal(l:current, bufnr()) + + drop! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :edit but :edit! is allowed +func Test_edit() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("edit other", "E1513:") + call assert_equal(l:current, bufnr()) + + edit! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :e when selecting a buffer from a relative path if in a different folder +" +" In this tests there's 2 buffers +" +" foo - lives on disk, in some folder. e.g. /tmp/foo +" foo - an in-memory buffer that has not been saved to disk. If saved, it +" would live in a different folder, /other/foo. +" +" The 'winfixbuf' is looking at the in-memory buffer and trying to switch to +" the buffer on-disk (and fails, because it's a different buffer) +func Test_edit_different_buffer_on_disk_and_relative_path_to_disk() + call s:reset_all_buffers() + + let l:file_on_disk = tempname() + let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") + let l:name = fnamemodify(l:file_on_disk, ":t") + execute "edit " . l:file_on_disk + write! + + let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else" + + if !isdirectory(l:directory_on_disk2) + call mkdir(l:directory_on_disk2) + endif + + execute "cd " . l:directory_on_disk2 + execute "edit " l:name + + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + set winfixbuf + call assert_fails("edit " . l:file_on_disk, "E1513:") + call assert_equal(l:current, bufnr()) + + call delete(l:directory_on_disk1) + call delete(l:directory_on_disk2) +endfunc + +" Fail :e when selecting a buffer from a relative path if in a different folder +" +" In this tests there's 2 buffers +" +" foo - lives on disk, in some folder. e.g. /tmp/foo +" foo - an in-memory buffer that has not been saved to disk. If saved, it +" would live in a different folder, /other/foo. +" +" The 'winfixbuf' is looking at the on-disk buffer and trying to switch to +" the in-memory buffer (and fails, because it's a different buffer) +func Test_edit_different_buffer_on_disk_and_relative_path_to_memory() + call s:reset_all_buffers() + + let l:file_on_disk = tempname() + let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") + let l:name = fnamemodify(l:file_on_disk, ":t") + execute "edit " . l:file_on_disk + write! + + let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else" + + if !isdirectory(l:directory_on_disk2) + call mkdir(l:directory_on_disk2) + endif + + execute "cd " . l:directory_on_disk2 + execute "edit " l:name + execute "cd " . l:directory_on_disk1 + execute "edit " l:file_on_disk + execute "cd " . l:directory_on_disk2 + + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + set winfixbuf + call assert_fails("edit " . l:name, "E1513:") + call assert_equal(l:current, bufnr()) + + call delete(l:directory_on_disk1) + call delete(l:directory_on_disk2) +endfunc + +" Fail to call `:e first` if called from a starting, in-memory buffer +func Test_edit_first_buffer() + call s:reset_all_buffers() + + set winfixbuf + let l:current = bufnr() + + call assert_fails("edit first", "E1513:") + call assert_equal(l:current, bufnr()) + + edit! first + call assert_equal(l:current, bufnr()) + edit! somewhere_else + call assert_notequal(l:current, bufnr()) +endfunc + +" Allow reloading a buffer using :e +func Test_edit_no_arguments() + call s:reset_all_buffers() + + let l:current = bufnr() + file some_buffer + + call assert_equal(l:current, bufnr()) + set winfixbuf + edit + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :e selecting the current buffer +func Test_edit_same_buffer_in_memory() + call s:reset_all_buffers() + + let current = bufnr() + file same_buffer + + call assert_equal(current, bufnr()) + set winfixbuf + edit same_buffer + call assert_equal(current, bufnr()) + set nowinfixbuf +endfunc + +" Allow :e selecting the current buffer as a full path +func Test_edit_same_buffer_on_disk_absolute_path() + call s:reset_all_buffers() + + let file = tempname() + " file must exist for expansion of 8.3 paths to succeed + call writefile([], file, 'D') + let file = fnamemodify(file, ':p') + let current = bufnr() + execute "edit " . file + write! + + call assert_equal(current, bufnr()) + set winfixbuf + execute "edit " file + call assert_equal(current, bufnr()) + + set nowinfixbuf +endfunc + +" Fail :enew but :enew! is allowed +func Test_enew() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("enew", "E1513:") + call assert_equal(l:current, bufnr()) + + enew! + call assert_notequal(l:other, bufnr()) + call assert_notequal(3, bufnr()) +endfunc + +" Fail :ex but :ex! is allowed +func Test_ex() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("ex other", "E1513:") + call assert_equal(l:current, bufnr()) + + ex! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :find but :find! is allowed +func Test_find() + call s:reset_all_buffers() + + let l:current = bufnr() + let l:file = tempname() + call writefile([], l:file, 'D') + let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style. + let l:directory = fnamemodify(l:file, ":p:h") + let l:name = fnamemodify(l:file, ":p:t") + + let l:original_path = &path + execute "set path=" . l:directory + + set winfixbuf + + call assert_fails("execute 'find " . l:name . "'", "E1513:") + call assert_equal(l:current, bufnr()) + + execute "find! " . l:name + call assert_equal(l:file, expand("%:p")) + + execute "set path=" . l:original_path +endfunc + +" Fail :first but :first! is allowed +func Test_first() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("first", "E1513:") + call assert_notequal(l:first, bufnr()) + + first! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :grep but :grep! is allowed +func Test_grep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + let l:first = bufnr() + + edit current.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + set winfixbuf + + buffer! current.unittest + + call assert_fails("silent! grep some-search-term *.unittest", "E1513:") + call assert_equal(l:current, bufnr()) + execute "edit! " . l:first + + silent! grep! some-search-term *.unittest + call assert_notequal(l:first, bufnr()) + + call delete("first.unittest") + call delete("current.unittest") + call delete("last.unittest") +endfunc + +" Fail :ijump but :ijump! is allowed +func Test_ijump() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile([ + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') + edit main.c + + set winfixbuf + + let l:current = bufnr() + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + call assert_fails("ijump /min/", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + ijump! /min/ + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& +endfunc + +" Fail :lNext but :lNext! is allowed +func Test_lNext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + call assert_fails("lNext", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lnext! + call assert_equal(3, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lNext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lNext! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lNfile but :lNfile! is allowed +func Test_lNfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:current, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + call assert_fails("lNfile", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lnext! + call assert_equal(3, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lNfile! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Allow :laddexpr because it doesn't change the current buffer +func Test_laddexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["Error - bad-thing-found"], l:file_path, 'D') + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + execute 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :last but :last! is allowed +func Test_last() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + next! + + call assert_fails("last", "E1513:") + call assert_notequal(l:last, bufnr()) + + last! + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lbuffer but :lbuffer! is allowed +func Test_lbuffer() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + call assert_fails("lbuffer " . l:file_buffer) + call assert_equal(l:current, bufnr()) + + execute "lbuffer! " . l:file_buffer + call assert_equal("first.unittest", expand("%:t")) +endfunc + +" Fail :ldo but :ldo! is allowed +func Test_ldo() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lnext! + + call assert_fails('execute "ldo buffer ' . l:first . '"', "E1513:") + call assert_equal(l:middle, bufnr()) + execute "ldo! buffer " . l:first + call assert_notequal(l:last, bufnr()) +endfunc + +" Fail :lfdo but :lfdo! is allowed +func Test_lexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file = tempname() + let l:entry = '["' . l:file . ':1:bar"]' + let l:current = bufnr() + + set winfixbuf + + call assert_fails("lexpr " . l:entry) + call assert_equal(l:current, bufnr()) + + execute "lexpr! " . l:entry + call assert_equal(fnamemodify(l:file, ":t"), expand("%:t")) +endfunc + +" Fail :lfdo but :lfdo! is allowed +func Test_lfdo() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lnext! + + call assert_fails('execute "lfdo buffer ' . l:first . '"', "E1513:") + call assert_equal(l:middle, bufnr()) + execute "lfdo! buffer " . l:first + call assert_notequal(l:last, bufnr()) +endfunc + +" Fail :lfile but :lfile! is allowed +func Test_lfile() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + write + let l:first = bufnr() + + edit! second.unittest + call append(0, ["some-search-term"]) + write + + let l:file = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file, 'D') + + let l:current = bufnr() + + set winfixbuf + + call assert_fails(":lfile " . l:file) + call assert_equal(l:current, bufnr()) + + execute ":lfile! " . l:file + call assert_equal(l:first, bufnr()) + + call delete("first.unittest") + call delete("second.unittest") +endfunc + +" Fail :ll but :ll! is allowed +func Test_ll() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lopen + lfirst! + execute "normal \<C-w>j" + normal j + + call assert_fails(".ll", "E1513:") + execute "normal \<C-w>k" + call assert_equal(l:first, bufnr()) + execute "normal \<C-w>j" + .ll! + execute "normal \<C-w>k" + call assert_equal(l:middle, bufnr()) +endfunc + +" Fail :llast but :llast! is allowed +func Test_llast() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, _, l:last] = s:make_simple_location_list() + lfirst! + + call assert_fails("llast", "E1513:") + call assert_equal(l:first, bufnr()) + + llast! + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lnext but :lnext! is allowed +func Test_lnext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + ll! + + call assert_fails("lnext", "E1513:") + call assert_equal(l:first, bufnr()) + + lnext! + call assert_equal(l:middle, bufnr()) +endfunc + +" Fail :lnfile but :lnfile! is allowed +func Test_lnfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [_, l:current, l:last] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + call assert_fails("lnfile", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lnfile! + call assert_equal(4, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lpfile but :lpfile! is allowed +func Test_lpfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:current, _] = s:make_simple_location_list() + lnext! + + call assert_fails("lpfile", "E1513:") + call assert_equal(l:current, bufnr()) + + lnext! " Reset for the next test call + + lpfile! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lprevious but :lprevious! is allowed +func Test_lprevious() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + call assert_fails("lprevious", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lprevious! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lrewind but :lrewind! is allowed +func Test_lrewind() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + lnext! + + call assert_fails("lrewind", "E1513:") + call assert_equal(l:middle, bufnr()) + + lrewind! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :ltag but :ltag! is allowed +func Test_ltag() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("ltag one", "E1513:") + + ltag! one + + set tags& +endfunc + +" Fail vim.cmd if we try to change buffers while 'winfixbuf' is set +func Test_lua_command() + " CheckFeature lua + call s:reset_all_buffers() + + enew + file first + let l:previous = bufnr() + + enew + file second + let l:current = bufnr() + + set winfixbuf + + call assert_fails('lua vim.cmd("buffer " .. ' . l:previous . ')') + call assert_equal(l:current, bufnr()) + + execute 'lua vim.cmd("buffer! " .. ' . l:previous . ')' + call assert_equal(l:previous, bufnr()) +endfunc + +" Fail :lvimgrep but :lvimgrep! is allowed +func Test_lvimgrep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("lvimgrep /some-search-term/ *.unittest", "E1513:") + call assert_equal(l:current, bufnr()) + + lvimgrep! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :lvimgrepadd but :lvimgrepadd! is allowed +func Test_lvimgrepadd() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("lvimgrepadd /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + lvimgrepadd! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Don't allow global marks to change the current 'winfixbuf' window +func Test_marks_mappings_fail() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + execute "buffer! " . l:other + normal mA + execute "buffer! " . l:current + normal mB + + call assert_fails("normal `A", "E1513:") + call assert_equal(l:current, bufnr()) + + call assert_fails("normal 'A", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + normal `A + call assert_equal(l:other, bufnr()) +endfunc + +" Allow global marks in a 'winfixbuf' window if the jump is the same buffer +func Test_marks_mappings_pass_intra_move() + call s:reset_all_buffers() + + let l:current = bufnr() + call append(0, ["some line", "another line"]) + normal mA + normal j + normal mB + + set winfixbuf + + normal `A + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :next but :next! is allowed +func Test_next() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + first! + + call assert_fails("next", "E1513:") + call assert_equal(l:first, bufnr()) + + next! + call assert_notequal(l:first, bufnr()) +endfunc + +" Ensure :mksession saves 'winfixbuf' details +func Test_mksession() + CheckFeature mksession + call s:reset_all_buffers() + + set sessionoptions+=options + set winfixbuf + + mksession test_winfixbuf_Test_mksession.vim + + call s:reset_all_buffers() + let l:winfixbuf = &winfixbuf + call assert_equal(0, l:winfixbuf) + + source test_winfixbuf_Test_mksession.vim + + let l:winfixbuf = &winfixbuf + call assert_equal(1, l:winfixbuf) + + set sessionoptions& + call delete("test_winfixbuf_Test_mksession.vim") +endfunc + +" Allow :next if the next index is the same as the current buffer +func Test_next_same_buffer() + call s:reset_all_buffers() + + enew + file foo + enew + file bar + enew + file fizz + enew + file buzz + args foo foo bar fizz buzz + + edit foo + set winfixbuf + let l:current = bufnr() + + " Allow :next because the args list is `[foo] foo bar fizz buzz + next + call assert_equal(l:current, bufnr()) + + " Fail :next because the args list is `foo [foo] bar fizz buzz + " and the next buffer would be bar, which is a different buffer + call assert_fails("next", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Fail to jump to a tag with g<C-]> if 'winfixbuf' is enabled +func Test_normal_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled +func Test_normal_g_rightmouse() + call s:reset_all_buffers() + set mouse=n + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g\<RightMouse>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + set mouse& +endfunc + +" Fail to jump to a tag with g] if 'winfixbuf' is enabled +func Test_normal_g_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g]", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled +func Test_normal_ctrl_rightmouse() + call s:reset_all_buffers() + set mouse=n + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-RightMouse>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + set mouse& +endfunc + +" Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled +func Test_normal_ctrl_t() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-t>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Disallow <C-^> in 'winfixbuf' windows +func Test_normal_ctrl_hat() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-^>", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Allow <C-i> in 'winfixbuf' windows if the movement stays within the buffer +func Test_normal_ctrl_i_pass() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew! + file current + let l:current = bufnr() + " Add some lines so we can populate a jumplist" + call append(0, ["some line", "another line"]) + " Add an entry to the jump list + " Go up another line + normal m` + normal k + execute "normal \<C-o>" + + set winfixbuf + + let l:line = getcurpos()[1] + execute "normal 1\<C-i>" + call assert_notequal(l:line, getcurpos()[1]) +endfunc + +" Disallow <C-o> in 'winfixbuf' windows if it would cause the buffer to switch +func Test_normal_ctrl_o_fail() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-o>", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Allow <C-o> in 'winfixbuf' windows if the movement stays within the buffer +func Test_normal_ctrl_o_pass() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew! + file current + let l:current = bufnr() + " Add some lines so we can populate a jumplist + call append(0, ["some line", "another line"]) + " Add an entry to the jump list + " Go up another line + normal m` + normal k + + set winfixbuf + + execute "normal \<C-o>" + call assert_equal(l:current, bufnr()) +endfunc + +" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled +func Test_normal_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window +func Test_normal_ctrl_w_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>\<C-]>" + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + set tags& +endfunc + +" Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window +func Test_normal_ctrl_w_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>g\<C-]>" + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + set tags& +endfunc + +" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled +func Test_normal_gt() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one", "two", "three"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Prevent gF from switching a 'winfixbuf' window's buffer +func Test_normal_gF() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file, 'D') + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gF, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal gF", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal gF + call assert_notequal(l:buffer, bufnr()) + + set nohidden +endfunc + +" Prevent gf from switching a 'winfixbuf' window's buffer +func Test_normal_gf() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file, 'D') + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal gf", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal gf + call assert_notequal(l:buffer, bufnr()) + + set nohidden +endfunc + +" Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`) +func Test_normal_square_bracket_left_f() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file, 'D') + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal [f", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal [f + call assert_notequal(l:buffer, bufnr()) + + set nohidden +endfunc + +" Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled +func Test_normal_square_bracket_left_ctrl_d() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') + edit main.c + normal ]\<C-d> + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal [\<C-d>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal [\<C-d>" + call assert_notequal(l:current, bufnr()) +endfunc + +" Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled +func Test_normal_square_bracket_right_ctrl_d() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') + edit main.c + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal ]\<C-d>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal ]\<C-d>" + call assert_notequal(l:current, bufnr()) +endfunc + +" Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled +func Test_normal_square_bracket_left_ctrl_i() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(['#include "' . l:include_file . '"', + \ "min(1, 12);", + \ ], + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') + edit main.c + " Move to the line with `min(1, 12);` on it" + normal j + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal [\<C-i>", "E1513:") + + set nowinfixbuf + + execute "normal [\<C-i>" + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& +endfunc + +" Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled +func Test_normal_square_bracket_right_ctrl_i() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') + edit main.c + + set winfixbuf + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + let l:current = bufnr() + + call assert_fails("normal ]\<C-i>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal ]\<C-i>" + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& +endfunc + +" Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`) +func Test_normal_square_bracket_right_f() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file, 'D') + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal ]f", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal ]f + call assert_notequal(l:buffer, bufnr()) + + set nohidden +endfunc + +" Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled +func Test_normal_v_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal v\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled +func Test_normal_v_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal vg\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Allow :pedit because, unlike :edit, it uses a separate window +func Test_pedit() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + + pedit other + + execute "normal \<C-w>w" + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :pop but :pop! is allowed +func Test_pop() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') + edit Xother + + tag thesame + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("pop", "E1513:") + call assert_equal(l:current, bufnr()) + + pop! + call assert_notequal(l:current, bufnr()) + + set tags& +endfunc + +" Fail :previous but :previous! is allowed +func Test_previous() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("previous", "E1513:") + call assert_notequal(l:first, bufnr()) + + previous! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail pyxdo if it changes a window with 'winfixbuf' is set +func Test_pythonx_pyxdo() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + set winfixbuf + + pythonx << EOF +import vim + +def test_winfixbuf_Test_pythonx_pyxdo_set_buffer(): + buffer = vim.vars['_previous_buffer'] + vim.current.buffer = vim.buffers[buffer] +EOF + + try + pyxdo test_winfixbuf_Test_pythonx_pyxdo_set_buffer() + catch /pynvim\.api\.common\.NvimError: E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + + unlet g:_previous_buffer +endfunc + +" Fail pyxfile if it changes a window with 'winfixbuf' is set +func Test_pythonx_pyxfile() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + set winfixbuf + + call writefile(["import vim", + \ "buffer = vim.vars['_previous_buffer']", + \ "vim.current.buffer = vim.buffers[buffer]", + \ ], + \ "file.py", 'D') + + try + pyxfile file.py + catch /pynvim\.api\.common\.NvimError: E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + + unlet g:_previous_buffer +endfunc + +" Fail vim.current.buffer if 'winfixbuf' is set +func Test_pythonx_vim_current_buffer() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + let l:caught = 0 + + set winfixbuf + + try + pythonx << EOF +import vim + +buffer = vim.vars["_previous_buffer"] +vim.current.buffer = vim.buffers[buffer] +EOF + catch /pynvim\.api\.common\.NvimError: E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + unlet g:_previous_buffer +endfunc + +" Ensure remapping to a disabled action still triggers failures +func Test_remap_key_fail() + call s:reset_all_buffers() + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + nnoremap g <C-^> + + call assert_fails("normal g", "E1513:") + call assert_equal(l:current, bufnr()) + + nunmap g +endfunc + +" Ensure remapping a disabled key to something valid does trigger any failures +func Test_remap_key_pass() + call s:reset_all_buffers() + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-^>", "E1513:") + call assert_equal(l:current, bufnr()) + + " Disallow <C-^> by default but allow it if the command does something else + nnoremap <C-^> :echo "hello!" + + execute "normal \<C-^>" + call assert_equal(l:current, bufnr()) + + nunmap <C-^> +endfunc + +" Fail :rewind but :rewind! is allowed +func Test_rewind() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("rewind", "E1513:") + call assert_notequal(l:first, bufnr()) + + rewind! + call assert_equal(l:first, bufnr()) +endfunc + +" Allow :sblast because it opens the buffer in a new, split window +func Test_sblast() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs(1) + bfirst! + let l:current = bufnr() + + sblast + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :sbprevious but :sbprevious! is allowed +func Test_sbprevious() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + sbprevious + call assert_equal(l:other, bufnr()) +endfunc + +" Make sure 'winfixbuf' can be set using 'winfixbuf' or 'wfb' +func Test_short_option() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + + set winfixbuf + call assert_fails("edit something_else", "E1513:") + + set nowinfixbuf + set wfb + call assert_fails("edit another_place", "E1513:") + + set nowfb + edit last_place +endfunc + +" Allow :snext because it makes a new window +func Test_snext() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + first! + + let l:current_window = win_getid() + + snext + call assert_notequal(l:current_window, win_getid()) + call assert_notequal(l:first, bufnr()) +endfunc + +" Ensure the first has 'winfixbuf' and a new split window is 'nowinfixbuf' +func Test_split_window() + call s:reset_all_buffers() + + split + execute "normal \<C-w>j" + + set winfixbuf + + let l:winfix_window_1 = win_getid() + vsplit + let l:winfix_window_2 = win_getid() + + call assert_equal(1, getwinvar(l:winfix_window_1, "&winfixbuf")) + call assert_equal(0, getwinvar(l:winfix_window_2, "&winfixbuf")) +endfunc + +" Fail :tNext but :tNext! is allowed +func Test_tNext() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') + edit Xother + + tag thesame + execute "normal \<C-^>" + tnext! + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tNext", "E1513:") + call assert_equal(l:current, bufnr()) + + tNext! + + set tags& +endfunc + +" Call :tabdo and choose the next available 'nowinfixbuf' window. +func Test_tabdo_choose_available_window() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :tabdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + + let l:expected_windows = s:get_windows_count() + tabdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:first, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :tabdo and create a new split window if all available windows are 'winfixbuf'. +func Test_tabdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, _] = s:make_buffers_list() + execute "buffer! " . l:first + + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + tabdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:first, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :tag but :tag! is allowed +func Test_tag() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tag one", "E1513:") + call assert_equal(l:current, bufnr()) + + tag! one + call assert_notequal(l:current, bufnr()) + + set tags& +endfunc + + +" Fail :tfirst but :tfirst! is allowed +func Test_tfirst() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tfirst", "E1513:") + call assert_equal(l:current, bufnr()) + + tfirst! + call assert_notequal(l:current, bufnr()) + + set tags& +endfunc + +" Fail :tjump but :tjump! is allowed +func Test_tjump() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tjump one", "E1513:") + call assert_equal(l:current, bufnr()) + + tjump! one + call assert_notequal(l:current, bufnr()) + + set tags& +endfunc + +" Fail :tlast but :tlast! is allowed +func Test_tlast() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + edit Xfile + tjump one + edit Xfile + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tlast", "E1513:") + call assert_equal(l:current, bufnr()) + + tlast! + call assert_equal(l:current, bufnr()) + + set tags& +endfunc + +" Fail :tnext but :tnext! is allowed +func Test_tnext() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') + edit Xother + + tag thesame + execute "normal \<C-^>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tnext", "E1513:") + call assert_equal(l:current, bufnr()) + + tnext! + call assert_notequal(l:current, bufnr()) + + set tags& +endfunc + +" Fail :tprevious but :tprevious! is allowed +func Test_tprevious() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') + edit Xother + + tag thesame + execute "normal \<C-^>" + tnext! + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tprevious", "E1513:") + call assert_equal(l:current, bufnr()) + + tprevious! + + set tags& +endfunc + +" Fail :view but :view! is allowed +func Test_view() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("view other", "E1513:") + call assert_equal(l:current, bufnr()) + + view! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :visual but :visual! is allowed +func Test_visual() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("visual other", "E1513:") + call assert_equal(l:current, bufnr()) + + visual! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :vimgrep but :vimgrep! is allowed +func Test_vimgrep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("vimgrep /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + " Don't error and also do swap to the first match because ! was included + vimgrep! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :vimgrepadd but ::vimgrepadd! is allowed +func Test_vimgrepadd() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("vimgrepadd /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + vimgrepadd! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :wNext but :wNext! is allowed +func Test_wNext() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("wNext", "E1513:") + call assert_notequal(l:first, bufnr()) + + wNext! + call assert_equal(l:first, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +" Allow :windo unless `:windo foo` would change a 'winfixbuf' window's buffer +func Test_windo() + call s:reset_all_buffers() + + let l:current_window = win_getid() + let l:current_buffer = bufnr() + split + enew + file some_other_buffer + + set winfixbuf + + let l:current = win_getid() + + windo echo '' + call assert_equal(l:current_window, win_getid()) + + call assert_fails('execute "windo buffer ' . l:current_buffer . '"', "E1513:") + call assert_equal(l:current_window, win_getid()) + + execute "windo buffer! " . l:current_buffer + call assert_equal(l:current_window, win_getid()) +endfunc + +" Fail :wnext but :wnext! is allowed +func Test_wnext() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + next! + + call assert_fails("wnext", "E1513:") + call assert_notequal(l:last, bufnr()) + + wnext! + call assert_equal(l:last, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +" Fail :wprevious but :wprevious! is allowed +func Test_wprevious() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("wprevious", "E1513:") + call assert_notequal(l:first, bufnr()) + + wprevious! + call assert_equal(l:first, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +func Test_quickfix_switchbuf_invalid_prevwin() + call s:reset_all_buffers() + + call s:make_simple_quickfix() + call assert_equal(1, getqflist(#{idx: 0}).idx) + + set switchbuf=uselast + split + copen + execute winnr('#') 'quit' + call assert_equal(2, winnr('$')) + + cnext " Would've triggered a null pointer member access + call assert_equal(2, getqflist(#{idx: 0}).idx) + + set switchbuf& +endfunc + +func Test_listdo_goto_prevwin() + call s:reset_all_buffers() + call s:make_buffers_list() + + new + call assert_equal(0, &winfixbuf) + wincmd p + call assert_equal(1, &winfixbuf) + call assert_notequal(bufnr(), bufnr('#')) + + augroup ListDoGotoPrevwin + au! + au BufLeave * let s:triggered = 1 + \| call assert_equal(bufnr(), winbufnr(winnr())) + augroup END + " Should correctly switch to the window without 'winfixbuf', and curbuf should + " be consistent with curwin->w_buffer for autocommands. + bufdo " + call assert_equal(0, &winfixbuf) + call assert_equal(1, s:triggered) + unlet! s:triggered + au! ListDoGotoPrevwin + + set winfixbuf + wincmd p + call assert_equal(2, winnr('$')) + " Both curwin and prevwin have 'winfixbuf' set, so should split a new window + " without it set. + bufdo " + call assert_equal(0, &winfixbuf) + call assert_equal(3, winnr('$')) + + quit + call assert_equal(2, winnr('$')) + call assert_equal(1, &winfixbuf) + augroup ListDoGotoPrevwin + au! + au WinEnter * ++once set winfixbuf + augroup END + " Same as before, but naughty autocommands set 'winfixbuf' for the new window. + " :bufdo should give up in this case. + call assert_fails('bufdo "', 'E1513:') + + au! ListDoGotoPrevwin + augroup! ListDoGotoPrevwin +endfunc + +func Test_quickfix_changed_split_failed() + call s:reset_all_buffers() + + call s:make_simple_quickfix() + call assert_equal(1, winnr('$')) + + " Quickfix code will open a split in an attempt to get a 'nowinfixbuf' window + " to switch buffers in. Interfere with things by setting 'winfixbuf' in it. + augroup QfChanged + au! + au WinEnter * ++once call assert_equal(2, winnr('$')) + \| set winfixbuf | call setqflist([], 'f') + augroup END + call assert_fails('cnext', ['E1513:', 'E925:']) + " Check that the split was automatically closed. + call assert_equal(1, winnr('$')) + + au! QfChanged + augroup! QfChanged +endfunc + +func Test_bufdo_cnext_splitwin_fails() + call s:reset_all_buffers() + call s:make_simple_quickfix() + call assert_equal(1, getqflist(#{idx: 0}).idx) + " Make sure there is not enough room to + " split the winfixedbuf window + let &winheight=&lines + let &winminheight=&lines-2 + " Still want E1513, or it may not be clear why a split was attempted and why + " it failing caused the commands to abort. + call assert_fails(':bufdo echo 1', ['E36:', 'E1513:']) + call assert_fails(':cnext', ['E36:', 'E1513:']) + " Ensure the entry didn't change. + call assert_equal(1, getqflist(#{idx: 0}).idx) + set winminheight&vim winheight&vim +endfunc + +" Test that exiting with 'winfixbuf' and EXITFREE doesn't cause an error. +func Test_exitfree_no_error() + let lines =<< trim END + set winfixbuf + qall! + END + call writefile(lines, 'Xwfb_exitfree', 'D') + call assert_notmatch('E1513:', + "\ system(GetVimCommandClean() .. ' --not-a-term -X -S Xwfb_exitfree')) + \ system(GetVimCommandClean() .. ' -X -S Xwfb_exitfree')) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/test/old/testdir/vim9.vim b/test/old/testdir/vim9.vim index 218fab6c5e..7d1eec7d4f 100644 --- a/test/old/testdir/vim9.vim +++ b/test/old/testdir/vim9.vim @@ -46,49 +46,6 @@ func CheckScriptSuccess(lines) endtry endfunc -" :source a list of "lines" and check whether it fails with "error" -func CheckSourceFailure(lines, error, lnum = -3) - if get(a:lines, 0, '') ==# 'vim9script' - return - endif - new - call setline(1, a:lines) - try - call assert_fails('source', a:error, a:lines, a:lnum) - finally - bw! - endtry -endfunc - -" :source a list of "lines" and check whether it fails with the list of -" "errors" -func CheckSourceFailureList(lines, errors, lnum = -3) - if get(a:lines, 0, '') ==# 'vim9script' - return - endif - new - call setline(1, a:lines) - try - call assert_fails('source', a:errors, a:lines, a:lnum) - finally - bw! - endtry -endfunc - -" :source a list of "lines" and check whether it succeeds -func CheckSourceSuccess(lines) - if get(a:lines, 0, '') ==# 'vim9script' - return - endif - new - call setline(1, a:lines) - try - :source - finally - bw! - endtry -endfunc - func CheckDefAndScriptSuccess(lines) return endfunc @@ -185,3 +142,96 @@ func CheckLegacyAndVim9Failure(lines, error) \ }) call CheckLegacyFailure(legacylines, legacyError) endfunc + +" :source a list of "lines" and check whether it fails with "error" +func CheckSourceScriptFailure(lines, error, lnum = -3) + if get(a:lines, 0, '') ==# 'vim9script' + return + endif + let cwd = getcwd() + new + call setline(1, a:lines) + let bnr = bufnr() + try + call assert_fails('source', a:error, a:lines, a:lnum) + finally + call chdir(cwd) + exe $':bw! {bnr}' + endtry +endfunc + +" :source a list of "lines" and check whether it fails with the list of +" "errors" +func CheckSourceScriptFailureList(lines, errors, lnum = -3) + if get(a:lines, 0, '') ==# 'vim9script' + return + endif + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, a:lines) + try + call assert_fails('source', a:errors, a:lines, a:lnum) + finally + call chdir(cwd) + exe $':bw! {bnr}' + endtry +endfunc + +" :source a list of "lines" and check whether it succeeds +func CheckSourceScriptSuccess(lines) + if get(a:lines, 0, '') ==# 'vim9script' + return + endif + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, a:lines) + try + :source + finally + call chdir(cwd) + exe $':bw! {bnr}' + endtry +endfunc + +func CheckSourceSuccess(lines) + call CheckSourceScriptSuccess(a:lines) +endfunc + +func CheckSourceFailure(lines, error, lnum = -3) + call CheckSourceScriptFailure(a:lines, a:error, a:lnum) +endfunc + +func CheckSourceFailureList(lines, errors, lnum = -3) + call CheckSourceScriptFailureList(a:lines, a:errors, a:lnum) +endfunc + +func CheckSourceDefSuccess(lines) + return +endfunc + +func CheckSourceDefAndScriptSuccess(lines) + return +endfunc + +func CheckSourceDefCompileSuccess(lines) + return +endfunc + +func CheckSourceDefFailure(lines, error, lnum = -3) + return +endfunc + +func CheckSourceDefExecFailure(lines, error, lnum = -3) + return +endfunc + +func CheckSourceDefAndScriptFailure(lines, error, lnum = -3) + return +endfunc + +func CheckSourceDefExecAndScriptFailure(lines, error, lnum = -3) + return +endfunc + diff --git a/test/helpers.lua b/test/testutil.lua index 3d53aa3be9..439f13cf49 100644 --- a/test/helpers.lua +++ b/test/testutil.lua @@ -16,8 +16,9 @@ local function shell_quote(str) return str end ---- @class test.helpers -local module = { +--- This module uses functions from the context of the test runner. +--- @class test.testutil +local M = { paths = Paths, } @@ -30,7 +31,7 @@ end --- @param path string --- @return boolean -function module.isdir(path) +function M.isdir(path) if not path then return false end @@ -43,7 +44,7 @@ end --- @param ... string|string[] --- @return string -function module.argss_to_cmd(...) +function M.argss_to_cmd(...) local cmd = {} --- @type string[] for i = 1, select('#', ...) do local arg = select(i, ...) @@ -59,8 +60,8 @@ function module.argss_to_cmd(...) return table.concat(cmd, ' ') end -function module.popen_r(...) - return io.popen(module.argss_to_cmd(...), 'r') +function M.popen_r(...) + return io.popen(M.argss_to_cmd(...), 'r') end --- Calls fn() until it succeeds, up to `max` times or until `max_ms` @@ -69,7 +70,7 @@ end --- @param max_ms integer? --- @param fn function --- @return any -function module.retry(max, max_ms, fn) +function M.retry(max, max_ms, fn) luaassert(max == nil or max > 0) luaassert(max_ms == nil or max_ms > 0) local tries = 1 @@ -96,10 +97,10 @@ local check_logs_useless_lines = { ['See README_MISSING_SYSCALL_OR_IOCTL for guidance'] = 3, } -function module.eq(expected, actual, context) +function M.eq(expected, actual, context) return luaassert.are.same(expected, actual, context) end -function module.neq(expected, actual, context) +function M.neq(expected, actual, context) return luaassert.are_not.same(expected, actual, context) end @@ -108,7 +109,7 @@ end --- @param cond (boolean) expression to assert --- @param expected (any) description of expected result --- @param actual (any) description of actual result -function module.ok(cond, expected, actual) +function M.ok(cond, expected, actual) luaassert( (not expected and not actual) or (expected and actual), 'if "expected" is given, "actual" is also required' @@ -122,14 +123,14 @@ local function epicfail(state, arguments, _) return false end luaassert:register('assertion', 'epicfail', epicfail) -function module.fail(msg) +function M.fail(msg) return luaassert.epicfail(msg) end --- @param pat string --- @param actual string --- @return boolean -function module.matches(pat, actual) +function M.matches(pat, actual) if nil ~= string.match(actual, pat) then return true end @@ -144,14 +145,14 @@ end ---@param logfile? (string) Full path to log file (default=$NVIM_LOG_FILE) ---@param nrlines? (number) Search up to this many log lines ---@param inverse? (boolean) Assert that the pattern does NOT match. -function module.assert_log(pat, logfile, nrlines, inverse) +function M.assert_log(pat, logfile, nrlines, inverse) logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' luaassert(logfile ~= nil, 'no logfile') nrlines = nrlines or 10 inverse = inverse or false - module.retry(nil, 1000, function() - local lines = module.read_file_list(logfile, -nrlines) or {} + M.retry(nil, 1000, function() + local lines = M.read_file_list(logfile, -nrlines) or {} local msg = string.format( 'Pattern %q %sfound in log (last %d lines): %s:\n%s', pat, @@ -181,14 +182,14 @@ end --- @param pat (string) Lua pattern to match lines in the log file --- @param logfile? (string) Full path to log file (default=$NVIM_LOG_FILE) --- @param nrlines? (number) Search up to this many log lines -function module.assert_nolog(pat, logfile, nrlines) - return module.assert_log(pat, logfile, nrlines, true) +function M.assert_nolog(pat, logfile, nrlines) + return M.assert_log(pat, logfile, nrlines, true) end --- @param fn fun(...): any --- @param ... any --- @return boolean, any -function module.pcall(fn, ...) +function M.pcall(fn, ...) luaassert(type(fn) == 'function') local status, rv = pcall(fn, ...) if status then @@ -237,9 +238,9 @@ end -- --- @param fn function --- @return string -function module.pcall_err_withfile(fn, ...) +function M.pcall_err_withfile(fn, ...) luaassert(type(fn) == 'function') - local status, rv = module.pcall(fn, ...) + local status, rv = M.pcall(fn, ...) if status == true then error('expected failure, but got success') end @@ -249,12 +250,12 @@ end --- @param fn function --- @param ... any --- @return string -function module.pcall_err_withtrace(fn, ...) - local errmsg = module.pcall_err_withfile(fn, ...) +function M.pcall_err_withtrace(fn, ...) + local errmsg = M.pcall_err_withfile(fn, ...) return ( errmsg - :gsub('^%.%.%./helpers%.lua:0: ', '') + :gsub('^%.%.%./testnvim%.lua:0: ', '') :gsub('^Error executing lua:- ', '') :gsub('^%[string "<nvim>"%]:0: ', '') ) @@ -263,20 +264,20 @@ end --- @param fn function --- @param ... any --- @return string -function module.pcall_err(fn, ...) - return module.remove_trace(module.pcall_err_withtrace(fn, ...)) +function M.pcall_err(fn, ...) + return M.remove_trace(M.pcall_err_withtrace(fn, ...)) end --- @param s string --- @return string -function module.remove_trace(s) +function M.remove_trace(s) return (s:gsub('\n%s*stack traceback:.*', '')) end -- initial_path: directory to recurse into -- re: include pattern (string) -- exc_re: exclude pattern(s) (string or table) -function module.glob(initial_path, re, exc_re) +function M.glob(initial_path, re, exc_re) exc_re = type(exc_re) == 'table' and exc_re or { exc_re } local paths_to_check = { initial_path } --- @type string[] local ret = {} --- @type string[] @@ -318,10 +319,10 @@ function module.glob(initial_path, re, exc_re) return ret end -function module.check_logs() +function M.check_logs() local log_dir = os.getenv('LOG_DIR') local runtime_errors = {} - if log_dir and module.isdir(log_dir) then + if log_dir and M.isdir(log_dir) then for tail in vim.fs.dir(log_dir) do if tail:sub(1, 30) == 'valgrind-' or tail:find('san%.') then local file = log_dir .. '/' .. tail @@ -343,7 +344,7 @@ function module.check_logs() local status, f local out = io.stdout if os.getenv('SYMBOLIZER') then - status, f = pcall(module.popen_r, os.getenv('SYMBOLIZER'), '-l', file) + status, f = pcall(M.popen_r, os.getenv('SYMBOLIZER'), '-l', file) end out:write(start_msg .. '\n') if status then @@ -368,22 +369,22 @@ function module.check_logs() ) end -function module.sysname() +function M.sysname() return uv.os_uname().sysname:lower() end --- @param s 'win'|'mac'|'freebsd'|'openbsd'|'bsd' --- @return boolean -function module.is_os(s) +function M.is_os(s) if not (s == 'win' or s == 'mac' or s == 'freebsd' or s == 'openbsd' or s == 'bsd') then error('unknown platform: ' .. tostring(s)) end return not not ( - (s == 'win' and (module.sysname():find('windows') or module.sysname():find('mingw'))) - or (s == 'mac' and module.sysname() == 'darwin') - or (s == 'freebsd' and module.sysname() == 'freebsd') - or (s == 'openbsd' and module.sysname() == 'openbsd') - or (s == 'bsd' and module.sysname():find('bsd')) + (s == 'win' and (M.sysname():find('windows') or M.sysname():find('mingw'))) + or (s == 'mac' and M.sysname() == 'darwin') + or (s == 'freebsd' and M.sysname() == 'freebsd') + or (s == 'openbsd' and M.sysname() == 'openbsd') + or (s == 'bsd' and M.sysname():find('bsd')) ) end @@ -402,7 +403,7 @@ local tmpname_id = 0 local tmpdir = tmpdir_get() --- Creates a new temporary file for use by tests. -function module.tmpname() +function M.tmpname() if tmpdir_is_local(tmpdir) then -- Cannot control os.tmpname() dir, so hack our own tmpname() impl. tmpname_id = tmpname_id + 1 @@ -413,11 +414,11 @@ function module.tmpname() end local fname = os.tmpname() - if module.is_os('win') and fname:sub(1, 2) == '\\s' then + if M.is_os('win') and fname:sub(1, 2) == '\\s' then -- In Windows tmpname() returns a filename starting with -- special sequence \s, prepend $TEMP path return tmpdir .. fname - elseif module.is_os('mac') and fname:match('^/tmp') then + elseif M.is_os('mac') and fname:match('^/tmp') then -- In OS X /tmp links to /private/tmp return '/private' .. fname end @@ -432,7 +433,7 @@ end local tests_skipped = 0 -function module.check_cores(app, force) -- luacheck: ignore +function M.check_cores(app, force) -- luacheck: ignore -- Temporary workaround: skip core check as it interferes with CI. if true then return @@ -459,14 +460,14 @@ function module.check_cores(app, force) -- luacheck: ignore exc_re = { os.getenv('NVIM_TEST_CORE_EXC_RE'), local_tmpdir } db_cmd = os.getenv('NVIM_TEST_CORE_DB_CMD') or gdb_db_cmd random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP') ~= '' - elseif module.is_os('mac') then + elseif M.is_os('mac') then initial_path = '/cores' re = nil exc_re = { local_tmpdir } db_cmd = lldb_db_cmd else initial_path = '.' - if module.is_os('freebsd') then + if M.is_os('freebsd') then re = '/nvim.core$' else re = '/core[^/]*$' @@ -480,7 +481,7 @@ function module.check_cores(app, force) -- luacheck: ignore tests_skipped = tests_skipped + 1 return end - local cores = module.glob(initial_path, re, exc_re) + local cores = M.glob(initial_path, re, exc_re) local found_cores = 0 local out = io.stdout for _, core in ipairs(cores) do @@ -503,23 +504,23 @@ function module.check_cores(app, force) -- luacheck: ignore end --- @return string? -function module.repeated_read_cmd(...) +function M.repeated_read_cmd(...) for _ = 1, 10 do - local stream = module.popen_r(...) + local stream = M.popen_r(...) local ret = stream:read('*a') stream:close() if ret then return ret end end - print('ERROR: Failed to execute ' .. module.argss_to_cmd(...) .. ': nil return after 10 attempts') + print('ERROR: Failed to execute ' .. M.argss_to_cmd(...) .. ': nil return after 10 attempts') return nil end --- @generic T --- @param orig T --- @return T -function module.shallowcopy(orig) +function M.shallowcopy(orig) if type(orig) ~= 'table' then return orig end @@ -534,13 +535,13 @@ end --- @param d1 table<any,any> --- @param d2 table<any,any> --- @return table<any,any> -function module.mergedicts_copy(d1, d2) - local ret = module.shallowcopy(d1) +function M.mergedicts_copy(d1, d2) + local ret = M.shallowcopy(d1) for k, v in pairs(d2) do if d2[k] == vim.NIL then ret[k] = nil elseif type(d1[k]) == 'table' and type(v) == 'table' then - ret[k] = module.mergedicts_copy(d1[k], v) + ret[k] = M.mergedicts_copy(d1[k], v) else ret[k] = v end @@ -553,7 +554,7 @@ end --- Note: does not do copies of d2 values used. --- @param d1 table<any,any> --- @param d2 table<any,any> -function module.dictdiff(d1, d2) +function M.dictdiff(d1, d2) local ret = {} --- @type table<any,any> local hasdiff = false for k, v in pairs(d1) do @@ -562,7 +563,7 @@ function module.dictdiff(d1, d2) ret[k] = vim.NIL elseif type(v) == type(d2[k]) then if type(v) == 'table' then - local subdiff = module.dictdiff(v, d2[k]) + local subdiff = M.dictdiff(v, d2[k]) if subdiff ~= nil then hasdiff = true ret[k] = subdiff @@ -576,7 +577,7 @@ function module.dictdiff(d1, d2) hasdiff = true end end - local shallowcopy = module.shallowcopy + local shallowcopy = M.shallowcopy for k, v in pairs(d2) do if d1[k] == nil then ret[k] = shallowcopy(v) @@ -591,7 +592,7 @@ function module.dictdiff(d1, d2) end -- Concat list-like tables. -function module.concat_tables(...) +function M.concat_tables(...) local ret = {} --- @type table<any,any> for i = 1, select('#', ...) do --- @type table<any,any> @@ -608,7 +609,7 @@ end --- @param str string --- @param leave_indent? integer --- @return string -function module.dedent(str, leave_indent) +function M.dedent(str, leave_indent) -- find minimum common indent across lines local indent --- @type string? for line in str:gmatch('[^\n]+') do @@ -633,14 +634,14 @@ function module.dedent(str, leave_indent) return str end -function module.intchar2lua(ch) +function M.intchar2lua(ch) ch = tonumber(ch) return (20 <= ch and ch < 127) and ('%c'):format(ch) or ch end --- @param str string --- @return string -function module.hexdump(str) +function M.hexdump(str) local len = string.len(str) local dump = '' local hex = '' @@ -669,7 +670,7 @@ end --- @param filename string path to file --- @param start? integer start line (1-indexed), negative means "lines before end" (tail) --- @return string[]? -function module.read_file_list(filename, start) +function M.read_file_list(filename, start) local lnum = (start ~= nil and type(start) == 'number') and start or 1 local tail = (lnum < 0) local maxlines = tail and math.abs(lnum) or nil @@ -707,7 +708,7 @@ end --- Reads the entire contents of `filename` into a string. --- @param filename string --- @return string? -function module.read_file(filename) +function M.read_file(filename) local file = io.open(filename, 'r') if not file then return nil @@ -718,7 +719,7 @@ function module.read_file(filename) end -- Dedent the given text and write it to the file name. -function module.write_file(name, text, no_dedent, append) +function M.write_file(name, text, no_dedent, append) local file = assert(io.open(name, (append and 'a' or 'w'))) if type(text) == 'table' then -- Byte blob @@ -729,7 +730,7 @@ function module.write_file(name, text, no_dedent, append) text = ('%s%c'):format(text, char) end elseif not no_dedent then - text = module.dedent(text) + text = M.dedent(text) end file:write(text) file:flush() @@ -738,7 +739,7 @@ end --- @param name? 'cirrus'|'github' --- @return boolean -function module.is_ci(name) +function M.is_ci(name) local any = (name == nil) luaassert(any or name == 'github' or name == 'cirrus') local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS')) @@ -748,11 +749,11 @@ end -- Gets the (tail) contents of `logfile`. -- Also moves the file to "${NVIM_LOG_FILE}.displayed" on CI environments. -function module.read_nvim_log(logfile, ci_rename) +function M.read_nvim_log(logfile, ci_rename) logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' - local is_ci = module.is_ci() + local is_ci = M.is_ci() local keep = is_ci and 100 or 10 - local lines = module.read_file_list(logfile, -keep) or {} + local lines = M.read_file_list(logfile, -keep) or {} local log = ( ('-'):rep(78) .. '\n' @@ -771,9 +772,59 @@ end --- @param path string --- @return boolean? -function module.mkdir(path) +function M.mkdir(path) -- 493 is 0755 in decimal return (uv.fs_mkdir(path, 493)) end -return module +--- @param expected any[] +--- @param received any[] +--- @param kind string +--- @return any +function M.expect_events(expected, received, kind) + if not pcall(M.eq, expected, received) then + local msg = 'unexpected ' .. kind .. ' received.\n\n' + + msg = msg .. 'received events:\n' + for _, e in ipairs(received) do + msg = msg .. ' ' .. vim.inspect(e) .. ';\n' + end + msg = msg .. '\nexpected events:\n' + for _, e in ipairs(expected) do + msg = msg .. ' ' .. vim.inspect(e) .. ';\n' + end + M.fail(msg) + end + return received +end + +--- @param cond boolean +--- @param reason? string +--- @return boolean +function M.skip(cond, reason) + if cond then + --- @type fun(reason: string) + local pending = getfenv(2).pending + pending(reason or 'FIXME') + return true + end + return false +end + +-- Calls pending() and returns `true` if the system is too slow to +-- run fragile or expensive tests. Else returns `false`. +function M.skip_fragile(pending_fn, cond) + if pending_fn == nil or type(pending_fn) ~= type(function() end) then + error('invalid pending_fn') + end + if cond then + pending_fn('skipped (test is fragile on this system)', function() end) + return true + elseif os.getenv('TEST_SKIP_FRAGILE') then + pending_fn('skipped (TEST_SKIP_FRAGILE)', function() end) + return true + end + return false +end + +return M diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua index 9843bd5c9e..a31374bd70 100644 --- a/test/unit/api/private_helpers_spec.lua +++ b/test/unit/api/private_helpers_spec.lua @@ -1,24 +1,24 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local eval_helpers = require('test.unit.eval.helpers') -local api_helpers = require('test.unit.api.helpers') - -local cimport = helpers.cimport -local NULL = helpers.NULL -local eq = helpers.eq - -local lua2typvalt = eval_helpers.lua2typvalt -local typvalt2lua = eval_helpers.typvalt2lua -local typvalt = eval_helpers.typvalt - -local nil_value = api_helpers.nil_value -local list_type = api_helpers.list_type -local int_type = api_helpers.int_type -local type_key = api_helpers.type_key -local obj2lua = api_helpers.obj2lua -local func_type = api_helpers.func_type - -local api = cimport('./src/nvim/api/private/helpers.h', './src/nvim/api/private/converter.h') +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local t_eval = require('test.unit.eval.testutil') +local api_t = require('test.unit.api.testutil') + +local cimport = t.cimport +local NULL = t.NULL +local eq = t.eq + +local lua2typvalt = t_eval.lua2typvalt +local typvalt2lua = t_eval.typvalt2lua +local typvalt = t_eval.typvalt + +local nil_value = api_t.nil_value +local list_type = api_t.list_type +local int_type = api_t.int_type +local type_key = api_t.type_key +local obj2lua = api_t.obj2lua +local func_type = api_t.func_type + +local api = cimport('./src/nvim/api/private/t.h', './src/nvim/api/private/converter.h') describe('vim_to_object', function() local vim_to_object = function(l) diff --git a/test/unit/api/helpers.lua b/test/unit/api/testutil.lua index 23c5db43f7..0946ef194c 100644 --- a/test/unit/api/helpers.lua +++ b/test/unit/api/testutil.lua @@ -1,23 +1,20 @@ -local helpers = require('test.unit.helpers')(nil) -local eval_helpers = require('test.unit.eval.helpers') +local t = require('test.unit.testutil') +local t_eval = require('test.unit.eval.testutil') -local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local ffi = helpers.ffi +local cimport = t.cimport +local to_cstr = t.to_cstr +local ffi = t.ffi -local list_type = eval_helpers.list_type -local dict_type = eval_helpers.dict_type -local func_type = eval_helpers.func_type -local nil_value = eval_helpers.nil_value -local int_type = eval_helpers.int_type -local flt_type = eval_helpers.flt_type -local type_key = eval_helpers.type_key +local list_type = t_eval.list_type +local dict_type = t_eval.dict_type +local func_type = t_eval.func_type +local nil_value = t_eval.nil_value +local int_type = t_eval.int_type +local flt_type = t_eval.flt_type +local type_key = t_eval.type_key -local api = cimport( - './src/nvim/api/private/defs.h', - './src/nvim/api/private/helpers.h', - './src/nvim/memory.h' -) +local api = + cimport('./src/nvim/api/private/defs.h', './src/nvim/api/private/t.h', './src/nvim/memory.h') local obj2lua diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua index 1ef3e97165..a7c672322b 100644 --- a/test/unit/buffer_spec.lua +++ b/test/unit/buffer_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local to_cstr = helpers.to_cstr -local eq = helpers.eq -local NULL = helpers.NULL +local to_cstr = t.to_cstr +local eq = t.eq +local NULL = t.NULL -local buffer = helpers.cimport('./src/nvim/buffer.h') +local buffer = t.cimport('./src/nvim/buffer.h') describe('buffer functions', function() local buflist_new = function(file, flags) diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua index ad87d026e5..a70ee77716 100644 --- a/test/unit/charset/vim_str2nr_spec.lua +++ b/test/unit/charset/vim_str2nr_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(after_each) +local t = require('test.unit.testutil') local bit = require('bit') -local itp = helpers.gen_itp(it) +local itp = t.gen_itp(it) -local child_call_once = helpers.child_call_once -local cimport = helpers.cimport -local ffi = helpers.ffi +local child_call_once = t.child_call_once +local cimport = t.cimport +local ffi = t.ffi local lib = cimport('./src/nvim/charset.h') diff --git a/test/unit/eval/decode_spec.lua b/test/unit/eval/decode_spec.lua index 5a8374a2a6..7e037500b9 100644 --- a/test/unit/eval/decode_spec.lua +++ b/test/unit/eval/decode_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi +local cimport = t.cimport +local eq = t.eq +local neq = t.neq +local ffi = t.ffi local decode = cimport( './src/nvim/eval/decode.h', diff --git a/test/unit/eval/encode_spec.lua b/test/unit/eval/encode_spec.lua index 498346d7cc..5b9188163e 100644 --- a/test/unit/eval/encode_spec.lua +++ b/test/unit/eval/encode_spec.lua @@ -1,16 +1,16 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local eval_helpers = require('test.unit.eval.helpers') +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local t_eval = require('test.unit.eval.testutil') -local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local eq = helpers.eq +local cimport = t.cimport +local to_cstr = t.to_cstr +local eq = t.eq -local list = eval_helpers.list -local lst2tbl = eval_helpers.lst2tbl -local type_key = eval_helpers.type_key -local list_type = eval_helpers.list_type -local null_string = eval_helpers.null_string +local list = t_eval.list +local lst2tbl = t_eval.lst2tbl +local type_key = t_eval.type_key +local list_type = t_eval.list_type +local null_string = t_eval.null_string local encode = cimport('./src/nvim/eval/encode.h') diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/testutil.lua index 6402e1f8c9..78788e5837 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/testutil.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(nil) +local t = require('test.unit.testutil') -local ptr2key = helpers.ptr2key -local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local ffi = helpers.ffi -local eq = helpers.eq +local ptr2key = t.ptr2key +local cimport = t.cimport +local to_cstr = t.to_cstr +local ffi = t.ffi +local eq = t.eq local eval = cimport( './src/nvim/eval.h', @@ -142,56 +142,56 @@ local function typvalt2lua_tab_init() return end typvalt2lua_tab = { - [tonumber(eval.VAR_BOOL)] = function(t) + [tonumber(eval.VAR_BOOL)] = function(q) return ({ [tonumber(eval.kBoolVarFalse)] = false, [tonumber(eval.kBoolVarTrue)] = true, - })[tonumber(t.vval.v_bool)] + })[tonumber(q.vval.v_bool)] end, - [tonumber(eval.VAR_SPECIAL)] = function(t) + [tonumber(eval.VAR_SPECIAL)] = function(q) return ({ [tonumber(eval.kSpecialVarNull)] = nil_value, - })[tonumber(t.vval.v_special)] + })[tonumber(q.vval.v_special)] end, - [tonumber(eval.VAR_NUMBER)] = function(t) - return { [type_key] = int_type, value = tonumber(t.vval.v_number) } + [tonumber(eval.VAR_NUMBER)] = function(q) + return { [type_key] = int_type, value = tonumber(q.vval.v_number) } end, - [tonumber(eval.VAR_FLOAT)] = function(t) - return tonumber(t.vval.v_float) + [tonumber(eval.VAR_FLOAT)] = function(q) + return tonumber(q.vval.v_float) end, - [tonumber(eval.VAR_STRING)] = function(t) - local str = t.vval.v_string + [tonumber(eval.VAR_STRING)] = function(q) + local str = q.vval.v_string if str == nil then return null_string else return ffi.string(str) end end, - [tonumber(eval.VAR_LIST)] = function(t, processed) - return lst2tbl(t.vval.v_list, processed) + [tonumber(eval.VAR_LIST)] = function(q, processed) + return lst2tbl(q.vval.v_list, processed) end, - [tonumber(eval.VAR_DICT)] = function(t, processed) - return dct2tbl(t.vval.v_dict, processed) + [tonumber(eval.VAR_DICT)] = function(q, processed) + return dct2tbl(q.vval.v_dict, processed) end, - [tonumber(eval.VAR_FUNC)] = function(t, processed) - return { [type_key] = func_type, value = typvalt2lua_tab[eval.VAR_STRING](t, processed or {}) } + [tonumber(eval.VAR_FUNC)] = function(q, processed) + return { [type_key] = func_type, value = typvalt2lua_tab[eval.VAR_STRING](q, processed or {}) } end, - [tonumber(eval.VAR_PARTIAL)] = function(t, processed) - local p_key = ptr2key(t) + [tonumber(eval.VAR_PARTIAL)] = function(q, processed) + local p_key = ptr2key(q) if processed[p_key] then return processed[p_key] end - return partial2lua(t.vval.v_partial, processed) + return partial2lua(q.vval.v_partial, processed) end, } end -typvalt2lua = function(t, processed) +typvalt2lua = function(q, processed) typvalt2lua_tab_init() return ( - (typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner) + (typvalt2lua_tab[tonumber(q.v_type)] or function(t_inner) assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet') - end)(t, processed or {}) + end)(q, processed or {}) ) end @@ -419,7 +419,7 @@ local function alloc_len(len, get_ptr) end end -local alloc_logging_helpers = { +local alloc_logging_t = { list = function(l) return { func = 'calloc', args = { 1, ffi.sizeof('list_T') }, ret = void(l) } end, @@ -523,7 +523,7 @@ local function tbl2callback(tbl) else assert(false) end - return ffi.gc(ffi.cast('Callback*', ret), helpers.callback_free) + return ffi.gc(ffi.cast('Callback*', ret), t.callback_free) end local function dict_watchers(d) @@ -591,7 +591,7 @@ return { list_iter = list_iter, first_di = first_di, - alloc_logging_helpers = alloc_logging_helpers, + alloc_logging_t = alloc_logging_t, list_items = list_items, dict_items = dict_items, diff --git a/test/unit/eval/tricks_spec.lua b/test/unit/eval/tricks_spec.lua index ed26fd44e4..20ecf0d920 100644 --- a/test/unit/eval/tricks_spec.lua +++ b/test/unit/eval/tricks_spec.lua @@ -1,12 +1,12 @@ -local helpers = require('test.unit.helpers')(after_each) -local eval_helpers = require('test.unit.eval.helpers') +local t = require('test.unit.testutil') +local t_eval = require('test.unit.eval.testutil') -local itp = helpers.gen_itp(it) +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local eq = helpers.eq +local cimport = t.cimport +local eq = t.eq -local eval0 = eval_helpers.eval0 +local eval0 = t_eval.eval0 local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', './src/nvim/memory.h') diff --git a/test/unit/eval/tv_clear_spec.lua b/test/unit/eval/tv_clear_spec.lua index a34cf6082a..1ad537d8bf 100644 --- a/test/unit/eval/tv_clear_spec.lua +++ b/test/unit/eval/tv_clear_spec.lua @@ -1,18 +1,18 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local eval_helpers = require('test.unit.eval.helpers') +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local t_eval = require('test.unit.eval.testutil') -local alloc_log_new = helpers.alloc_log_new -local cimport = helpers.cimport -local ffi = helpers.ffi -local eq = helpers.eq +local alloc_log_new = t.alloc_log_new +local cimport = t.cimport +local ffi = t.ffi +local eq = t.eq -local a = eval_helpers.alloc_logging_helpers -local type_key = eval_helpers.type_key -local list_type = eval_helpers.list_type -local list_items = eval_helpers.list_items -local dict_items = eval_helpers.dict_items -local lua2typvalt = eval_helpers.lua2typvalt +local a = t_eval.alloc_logging_t +local type_key = t_eval.type_key +local list_type = t_eval.list_type +local list_items = t_eval.list_items +local dict_items = t_eval.dict_items +local lua2typvalt = t_eval.lua2typvalt local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/eval.h') diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index 6edd164438..c69c9b0fae 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -1,45 +1,45 @@ local bit = require('bit') -local helpers = require('test.unit.helpers')(after_each) -local eval_helpers = require('test.unit.eval.helpers') - -local itp = helpers.gen_itp(it) - -local OK = helpers.OK -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi -local FAIL = helpers.FAIL -local NULL = helpers.NULL -local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local alloc_log_new = helpers.alloc_log_new -local concat_tables = helpers.concat_tables +local t = require('test.unit.testutil') +local t_eval = require('test.unit.eval.testutil') + +local itp = t.gen_itp(it) + +local OK = t.OK +local eq = t.eq +local neq = t.neq +local ffi = t.ffi +local FAIL = t.FAIL +local NULL = t.NULL +local cimport = t.cimport +local to_cstr = t.to_cstr +local alloc_log_new = t.alloc_log_new +local concat_tables = t.concat_tables local map = vim.tbl_map -local a = eval_helpers.alloc_logging_helpers -local int = eval_helpers.int -local list = eval_helpers.list -local dict = eval_helpers.dict -local eval0 = eval_helpers.eval0 -local lst2tbl = eval_helpers.lst2tbl -local dct2tbl = eval_helpers.dct2tbl -local typvalt = eval_helpers.typvalt -local type_key = eval_helpers.type_key -local li_alloc = eval_helpers.li_alloc -local first_di = eval_helpers.first_di -local nil_value = eval_helpers.nil_value -local func_type = eval_helpers.func_type -local null_list = eval_helpers.null_list -local null_dict = eval_helpers.null_dict -local dict_items = eval_helpers.dict_items -local list_items = eval_helpers.list_items -local empty_list = eval_helpers.empty_list -local lua2typvalt = eval_helpers.lua2typvalt -local typvalt2lua = eval_helpers.typvalt2lua -local null_string = eval_helpers.null_string -local callback2tbl = eval_helpers.callback2tbl -local tbl2callback = eval_helpers.tbl2callback -local dict_watchers = eval_helpers.dict_watchers +local a = t_eval.alloc_logging_t +local int = t_eval.int +local list = t_eval.list +local dict = t_eval.dict +local eval0 = t_eval.eval0 +local lst2tbl = t_eval.lst2tbl +local dct2tbl = t_eval.dct2tbl +local typvalt = t_eval.typvalt +local type_key = t_eval.type_key +local li_alloc = t_eval.li_alloc +local first_di = t_eval.first_di +local nil_value = t_eval.nil_value +local func_type = t_eval.func_type +local null_list = t_eval.null_list +local null_dict = t_eval.null_dict +local dict_items = t_eval.dict_items +local list_items = t_eval.list_items +local empty_list = t_eval.empty_list +local lua2typvalt = t_eval.lua2typvalt +local typvalt2lua = t_eval.typvalt2lua +local null_string = t_eval.null_string +local callback2tbl = t_eval.callback2tbl +local tbl2callback = t_eval.tbl2callback +local dict_watchers = t_eval.dict_watchers local lib = cimport( './src/nvim/eval/typval.h', @@ -3223,7 +3223,7 @@ describe('typval.c', function() end) end) describe('lnum()', function() - itp('works', function() + pending('works (skip due to flakiness)', function() for _, v in ipairs({ { lib.VAR_NUMBER, { v_number = 42 }, nil, 42 }, { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, 100500 }, @@ -3352,7 +3352,7 @@ describe('typval.c', function() end end describe('string()', function() - itp('works', function() + pending('works (skip due to flakiness)', function() local buf = lib.tv_get_string(lua2typvalt(int(1))) local buf_chk = lib.tv_get_string_chk(lua2typvalt(int(1))) neq(buf, buf_chk) diff --git a/test/unit/fileio_spec.lua b/test/unit/fileio_spec.lua index 1284f84222..8f915372fe 100644 --- a/test/unit/fileio_spec.lua +++ b/test/unit/fileio_spec.lua @@ -1,13 +1,13 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) ---{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers' +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +--{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.testutil' -local eq = helpers.eq -local ffi = helpers.ffi -local to_cstr = helpers.to_cstr -local NULL = helpers.NULL +local eq = t.eq +local ffi = t.ffi +local to_cstr = t.to_cstr +local NULL = t.NULL -local fileio = helpers.cimport('./src/nvim/fileio.h') +local fileio = t.cimport('./src/nvim/fileio.h') describe('file_pat functions', function() describe('file_pat_to_reg_pat', function() diff --git a/test/unit/garray_spec.lua b/test/unit/garray_spec.lua index 0f947c42b8..30d1d3f21e 100644 --- a/test/unit/garray_spec.lua +++ b/test/unit/garray_spec.lua @@ -1,13 +1,13 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) - -local cimport = helpers.cimport -local internalize = helpers.internalize -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi -local to_cstr = helpers.to_cstr -local NULL = helpers.NULL +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) + +local cimport = t.cimport +local internalize = t.internalize +local eq = t.eq +local neq = t.neq +local ffi = t.ffi +local to_cstr = t.to_cstr +local NULL = t.NULL local garray = cimport('./src/nvim/garray.h') diff --git a/test/unit/indent_spec.lua b/test/unit/indent_spec.lua index 7902918c54..a1c3dc4a75 100644 --- a/test/unit/indent_spec.lua +++ b/test/unit/indent_spec.lua @@ -1,12 +1,12 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local to_cstr = helpers.to_cstr -local ffi = helpers.ffi -local eq = helpers.eq +local to_cstr = t.to_cstr +local ffi = t.ffi +local eq = t.eq -local indent = helpers.cimport('./src/nvim/indent.h') -local globals = helpers.cimport('./src/nvim/globals.h') +local indent = t.cimport('./src/nvim/indent.h') +local globals = t.cimport('./src/nvim/globals.h') describe('get_sts_value', function() itp([[returns 'softtabstop' when it is non-negative]], function() diff --git a/test/unit/keycodes_spec.lua b/test/unit/keycodes_spec.lua index 4a81c62ac1..948f0a3ead 100644 --- a/test/unit/keycodes_spec.lua +++ b/test/unit/keycodes_spec.lua @@ -1,12 +1,12 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq -local neq = helpers.neq +local ffi = t.ffi +local eq = t.eq +local neq = t.neq -local keycodes = helpers.cimport('./src/nvim/keycodes.h') -local NULL = helpers.NULL +local keycodes = t.cimport('./src/nvim/keycodes.h') +local NULL = t.NULL describe('keycodes.c', function() describe('find_special_key()', function() diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua index b0a861727d..cccce5ca8f 100644 --- a/test/unit/marktree_spec.lua +++ b/test/unit/marktree_spec.lua @@ -1,15 +1,15 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq -local ok = helpers.ok +local ffi = t.ffi +local eq = t.eq +local ok = t.ok -local lib = helpers.cimport('./src/nvim/marktree.h') +local lib = t.cimport('./src/nvim/marktree.h') -local function tablelength(t) +local function tablelength(tbl) local count = 0 - for _ in pairs(t) do + for _ in pairs(tbl) do count = count + 1 end return count @@ -460,7 +460,7 @@ describe('marktree', function() local ids = {} -- too much overhead on ASAN - local size_factor = helpers.is_asan() and 3 or 10 + local size_factor = t.is_asan() and 3 or 10 local at_row = {} for i = 1, 10 do @@ -528,7 +528,7 @@ describe('marktree', function() local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit -- too much overhead on ASAN - local size_factor = helpers.is_asan() and 3 or 10 + local size_factor = t.is_asan() and 3 or 10 local at_row = {} for i = 1, 10 do diff --git a/test/unit/mbyte_spec.lua b/test/unit/mbyte_spec.lua index 00a8c06ceb..8fcc67d20b 100644 --- a/test/unit/mbyte_spec.lua +++ b/test/unit/mbyte_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq +local ffi = t.ffi +local eq = t.eq -local lib = helpers.cimport('./src/nvim/mbyte.h', './src/nvim/charset.h', './src/nvim/grid.h') +local lib = t.cimport('./src/nvim/mbyte.h', './src/nvim/charset.h', './src/nvim/grid.h') describe('mbyte', function() -- Convert from bytes to string @@ -205,7 +205,7 @@ describe('mbyte', function() end) describe('utf_cp_bounds_len', function() - local to_cstr = helpers.to_cstr + local to_cstr = t.to_cstr local tests = { { diff --git a/test/unit/memory_spec.lua b/test/unit/memory_spec.lua index 8be55fdbf3..169d6b9cb0 100644 --- a/test/unit/memory_spec.lua +++ b/test/unit/memory_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local cstr = helpers.cstr -local eq = helpers.eq -local ffi = helpers.ffi -local to_cstr = helpers.to_cstr +local cimport = t.cimport +local cstr = t.cstr +local eq = t.eq +local ffi = t.ffi +local to_cstr = t.to_cstr local cimp = cimport('stdlib.h', './src/nvim/memory.h') diff --git a/test/unit/message_spec.lua b/test/unit/message_spec.lua index 71aa74d90d..fee8f5124d 100644 --- a/test/unit/message_spec.lua +++ b/test/unit/message_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local ffi = helpers.ffi -local eq = helpers.eq -local to_cstr = helpers.to_cstr +local ffi = t.ffi +local eq = t.eq +local to_cstr = t.to_cstr -local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h', './src/nvim/strings.h') +local cimp = t.cimport('./src/nvim/message.h', './src/nvim/memory.h', './src/nvim/strings.h') describe('trunc_string', function() local buflen = 40 @@ -33,26 +33,26 @@ describe('trunc_string', function() { ['desc'] = 'by copy', ['func'] = test_copy }, } - for _, t in ipairs(permutations) do - describe('populates buf ' .. t.desc, function() + for _, q in ipairs(permutations) do + describe('populates buf ' .. q.desc, function() itp('with a small string', function() - t.func('text', 'text') + q.func('text', 'text') end) itp('with a medium string', function() - t.func('a short text', 'a short text') + q.func('a short text', 'a short text') end) itp('with a string of length == 1/2 room', function() - t.func('a text that fits', 'a text that fits', 34) + q.func('a text that fits', 'a text that fits', 34) end) itp('with a string exactly the truncate size', function() - t.func('a text tha just fits', 'a text tha just fits') + q.func('a text tha just fits', 'a text tha just fits') end) itp('with a string that must be truncated', function() - t.func('a text that nott fits', 'a text t...nott fits') + q.func('a text that nott fits', 'a text t...nott fits') end) end) end diff --git a/test/unit/msgpack_spec.lua b/test/unit/msgpack_spec.lua index bd663a3c75..730c4f9e36 100644 --- a/test/unit/msgpack_spec.lua +++ b/test/unit/msgpack_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local cimport = helpers.cimport -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local cimport = t.cimport +local itp = t.gen_itp(it) local lib = cimport('./src/nvim/msgpack_rpc/unpacker.h', './src/nvim/memory.h') -local ffi = helpers.ffi -local eq = helpers.eq -local to_cstr = helpers.to_cstr +local ffi = t.ffi +local eq = t.eq +local to_cstr = t.to_cstr --- @class Unpacker --- @field read_ptr ffi.cdata* @@ -51,11 +51,11 @@ describe('msgpack', function() unpacker_goto(unpacker, payload, payload:len() - 1) local finished = unpacker_advance(unpacker) - eq(finished, false) + eq(false, finished) unpacker[0].read_size = unpacker[0].read_size + 1 finished = unpacker_advance(unpacker) - eq(finished, true) + eq(true, finished) end ) @@ -73,7 +73,7 @@ describe('msgpack', function() '\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x90\xc2' ) local finished = unpacker_advance(unpacker) - eq(finished, true) + eq(true, finished) end) end) end) diff --git a/test/unit/multiqueue_spec.lua b/test/unit/multiqueue_spec.lua index f6d11ebed0..931a5efa94 100644 --- a/test/unit/multiqueue_spec.lua +++ b/test/unit/multiqueue_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local child_call_once = helpers.child_call_once -local cimport = helpers.cimport -local ffi = helpers.ffi -local eq = helpers.eq +local child_call_once = t.child_call_once +local cimport = t.cimport +local ffi = t.ffi +local eq = t.eq local multiqueue = cimport('./test/unit/fixtures/multiqueue.h') diff --git a/test/unit/optionstr_spec.lua b/test/unit/optionstr_spec.lua index 7666db910e..b9c9ceaa85 100644 --- a/test/unit/optionstr_spec.lua +++ b/test/unit/optionstr_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local to_cstr = helpers.to_cstr -local eq = helpers.eq +local to_cstr = t.to_cstr +local eq = t.eq -local optionstr = helpers.cimport('./src/nvim/optionstr.h') +local optionstr = t.cimport('./src/nvim/optionstr.h') local check_ff_value = function(ff) return optionstr.check_ff_value(to_cstr(ff)) diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua index 2c638fcb37..d8231545f3 100644 --- a/test/unit/os/env_spec.lua +++ b/test/unit/os/env_spec.lua @@ -1,13 +1,13 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) - -local cimport = helpers.cimport -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi -local cstr = helpers.cstr -local to_cstr = helpers.to_cstr -local NULL = helpers.NULL +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) + +local cimport = t.cimport +local eq = t.eq +local neq = t.neq +local ffi = t.ffi +local cstr = t.cstr +local to_cstr = t.to_cstr +local NULL = t.NULL local OK = 0 local cimp = cimport('./src/nvim/os/os.h') @@ -306,9 +306,9 @@ describe('env.c', function() -- expand_env_esc SHOULD NOT expand the variable if there is not enough space to -- contain the result for i = 0, 3 do - eq(output[i], input[i]) + eq(input[i], output[i]) end - eq(output[4], 0) + eq(0, output[4]) end) end) end) diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua index 617141fd3a..fd9eb2bafb 100644 --- a/test/unit/os/fileio_spec.lua +++ b/test/unit/os/fileio_spec.lua @@ -1,13 +1,13 @@ local uv = vim.uv -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) - -local eq = helpers.eq -local ffi = helpers.ffi -local cimport = helpers.cimport -local cppimport = helpers.cppimport -local mkdir = helpers.mkdir +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) + +local eq = t.eq +local ffi = t.ffi +local cimport = t.cimport +local cppimport = t.cppimport +local mkdir = t.mkdir local m = cimport('./src/nvim/os/os.h', './src/nvim/os/fileio.h') cppimport('fcntl.h') diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index c15cd12fef..a829962305 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -1,22 +1,22 @@ local uv = vim.uv local bit = require('bit') -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) - -local cimport = helpers.cimport -local cppimport = helpers.cppimport -local internalize = helpers.internalize -local ok = helpers.ok -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi -local cstr = helpers.cstr -local to_cstr = helpers.to_cstr -local OK = helpers.OK -local FAIL = helpers.FAIL -local NULL = helpers.NULL -local mkdir = helpers.mkdir +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) + +local cimport = t.cimport +local cppimport = t.cppimport +local internalize = t.internalize +local ok = t.ok +local eq = t.eq +local neq = t.neq +local ffi = t.ffi +local cstr = t.cstr +local to_cstr = t.to_cstr +local OK = t.OK +local FAIL = t.FAIL +local NULL = t.NULL +local mkdir = t.mkdir local endswith = vim.endswith local NODE_NORMAL = 0 diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua index ae162f2317..94ad6f4a10 100644 --- a/test/unit/os/shell_spec.lua +++ b/test/unit/os/shell_spec.lua @@ -1,14 +1,14 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local cimported = helpers.cimport( +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local cimported = t.cimport( './src/nvim/os/shell.h', './src/nvim/option_vars.h', './src/nvim/main.h', './src/nvim/memory.h' ) -local ffi, eq = helpers.ffi, helpers.eq -local intern = helpers.internalize -local to_cstr = helpers.to_cstr +local ffi, eq = t.ffi, t.eq +local intern = t.internalize +local to_cstr = t.to_cstr local NULL = ffi.cast('void *', 0) describe('shell functions', function() @@ -125,9 +125,9 @@ describe('shell functions', function() cimported.p_sxe = to_cstr('"&|<>()@^') local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil)) - eq(ffi.string(argv[0]), '/bin/sh') - eq(ffi.string(argv[1]), '-c') - eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)') + eq('/bin/sh', ffi.string(argv[0])) + eq('-c', ffi.string(argv[1])) + eq('(echo ^&^|^<^>^(^)^@^^)', ffi.string(argv[2])) eq(nil, argv[3]) end) @@ -136,9 +136,9 @@ describe('shell functions', function() cimported.p_sxe = to_cstr('"&|<>()@^') local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/sh') - eq(ffi.string(argv[1]), '-c') - eq(ffi.string(argv[2]), '"(echo -n some text)"') + eq('/bin/sh', ffi.string(argv[0])) + eq('-c', ffi.string(argv[1])) + eq('"(echo -n some text)"', ffi.string(argv[2])) eq(nil, argv[3]) end) @@ -147,17 +147,17 @@ describe('shell functions', function() cimported.p_sxe = to_cstr('') local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/sh') - eq(ffi.string(argv[1]), '-c') - eq(ffi.string(argv[2]), '"echo -n some text"') + eq('/bin/sh', ffi.string(argv[0])) + eq('-c', ffi.string(argv[1])) + eq('"echo -n some text"', ffi.string(argv[2])) eq(nil, argv[3]) end) itp('with empty shellxquote/shellxescape', function() local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil)) - eq(ffi.string(argv[0]), '/bin/sh') - eq(ffi.string(argv[1]), '-c') - eq(ffi.string(argv[2]), 'echo -n some text') + eq('/bin/sh', ffi.string(argv[0])) + eq('-c', ffi.string(argv[1])) + eq('echo -n some text', ffi.string(argv[2])) eq(nil, argv[3]) end) end) diff --git a/test/unit/os/users_spec.lua b/test/unit/os/users_spec.lua index 679e76fae1..21d47fdb6e 100644 --- a/test/unit/os/users_spec.lua +++ b/test/unit/os/users_spec.lua @@ -1,13 +1,13 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local eq = helpers.eq -local ffi = helpers.ffi -local lib = helpers.lib -local NULL = helpers.NULL -local OK = helpers.OK -local FAIL = helpers.FAIL +local cimport = t.cimport +local eq = t.eq +local ffi = t.ffi +local lib = t.lib +local NULL = t.NULL +local OK = t.OK +local FAIL = t.FAIL local users = cimport('./src/nvim/os/os.h', 'unistd.h') diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua index c564ec119e..6f6a80f44e 100644 --- a/test/unit/path_spec.lua +++ b/test/unit/path_spec.lua @@ -1,17 +1,17 @@ local uv = vim.uv -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) - -local cimport = helpers.cimport -local eq = helpers.eq -local neq = helpers.neq -local ffi = helpers.ffi -local cstr = helpers.cstr -local to_cstr = helpers.to_cstr -local NULL = helpers.NULL -local OK = helpers.OK -local FAIL = helpers.FAIL -local mkdir = helpers.mkdir +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) + +local cimport = t.cimport +local eq = t.eq +local neq = t.neq +local ffi = t.ffi +local cstr = t.cstr +local to_cstr = t.to_cstr +local NULL = t.NULL +local OK = t.OK +local FAIL = t.FAIL +local mkdir = t.mkdir cimport('string.h') local cimp = cimport('./src/nvim/os/os.h', './src/nvim/path.h') @@ -22,11 +22,16 @@ local buffer = nil describe('path.c', function() describe('path_full_dir_name', function() + local old_dir + setup(function() + old_dir = uv.cwd() mkdir('unit-test-directory') + uv.fs_symlink(old_dir .. '/unit-test-directory', 'unit-test-symlink') end) teardown(function() + uv.fs_unlink('unit-test-symlink') uv.fs_rmdir('unit-test-directory') end) @@ -37,35 +42,64 @@ describe('path.c', function() before_each(function() -- Create empty string buffer which will contain the resulting path. - length = string.len(uv.cwd()) + 22 + length = string.len(old_dir) + 22 buffer = cstr(length, '') end) + after_each(function() + uv.chdir(old_dir) + end) + itp('returns the absolute directory name of a given relative one', function() - local result = path_full_dir_name('..', buffer, length) - eq(OK, result) - local old_dir = uv.cwd() + eq(OK, path_full_dir_name('..', buffer, length)) uv.chdir('..') local expected = uv.cwd() uv.chdir(old_dir) - eq(expected, (ffi.string(buffer))) + eq(expected, ffi.string(buffer)) end) itp('returns the current directory name if the given string is empty', function() - eq(OK, (path_full_dir_name('', buffer, length))) - eq(uv.cwd(), (ffi.string(buffer))) + eq(OK, path_full_dir_name('', buffer, length)) + eq(old_dir, ffi.string(buffer)) + end) + + local function test_full_dir_absolute() + itp('works with a normal absolute dir', function() + eq(OK, path_full_dir_name(old_dir .. '/unit-test-directory', buffer, length)) + eq(old_dir .. '/unit-test-directory', ffi.string(buffer)) + end) + + itp('works with a symlinked absolute dir', function() + eq(OK, path_full_dir_name(old_dir .. '/unit-test-symlink', buffer, length)) + eq(old_dir .. '/unit-test-directory', ffi.string(buffer)) + end) + end + + test_full_dir_absolute() + + describe('when cwd does not exist #28786', function() + before_each(function() + mkdir('dir-to-remove') + uv.chdir('dir-to-remove') + uv.fs_rmdir(old_dir .. '/dir-to-remove') + end) + + test_full_dir_absolute() end) itp('works with a normal relative dir', function() - local result = path_full_dir_name('unit-test-directory', buffer, length) - eq(uv.cwd() .. '/unit-test-directory', (ffi.string(buffer))) - eq(OK, result) + eq(OK, path_full_dir_name('unit-test-directory', buffer, length)) + eq(old_dir .. '/unit-test-directory', ffi.string(buffer)) + end) + + itp('works with a symlinked relative dir', function() + eq(OK, path_full_dir_name('unit-test-symlink', buffer, length)) + eq(old_dir .. '/unit-test-directory', ffi.string(buffer)) end) itp('works with a non-existing relative dir', function() - local result = path_full_dir_name('does-not-exist', buffer, length) - eq(uv.cwd() .. '/does-not-exist', (ffi.string(buffer))) - eq(OK, result) + eq(OK, path_full_dir_name('does-not-exist', buffer, length)) + eq(old_dir .. '/does-not-exist', ffi.string(buffer)) end) itp('fails with a non-existing absolute dir', function() @@ -380,8 +414,8 @@ describe('path.c', function() return buf, result end - local function get_buf_len(s, t) - return math.max(string.len(s), string.len(t)) + 1 + local function get_buf_len(s, q) + return math.max(string.len(s), string.len(q)) + 1 end itp('fails if given filename is NULL', function() @@ -413,12 +447,15 @@ describe('path.c', function() end) itp('fails and uses filename if given filename contains non-existing directory', function() - local filename = 'non_existing_dir/test.file' - local buflen = string.len(filename) + 1 - local do_expand = 1 - local buf, result = vim_FullName(filename, buflen, do_expand) - eq(filename, ffi.string(buf)) - eq(FAIL, result) + -- test with different filename lengths + for rep = 1, 10 do + local filename = ('non_existing_'):rep(rep) .. 'dir/test.file' + local buflen = string.len(filename) + 1 + local do_expand = 1 + local buf, result = vim_FullName(filename, buflen, do_expand) + eq(filename, ffi.string(buf)) + eq(FAIL, result) + end end) itp('concatenates filename if it does not contain a slash', function() diff --git a/test/unit/preload.lua b/test/unit/preload.lua index c2d051d98a..1865bba719 100644 --- a/test/unit/preload.lua +++ b/test/unit/preload.lua @@ -2,5 +2,5 @@ -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. local ffi = require('ffi') -local helpers = require('test.unit.helpers')(nil) +local t = require('test.unit.testutil') local preprocess = require('test.unit.preprocess') diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua index 6294114e1e..8d481df0d0 100644 --- a/test/unit/preprocess.lua +++ b/test/unit/preprocess.lua @@ -2,10 +2,10 @@ -- windows, will probably need quite a bit of adjustment to run there. local ffi = require('ffi') -local global_helpers = require('test.helpers') +local global_t = require('test.testutil') -local argss_to_cmd = global_helpers.argss_to_cmd -local repeated_read_cmd = global_helpers.repeated_read_cmd +local argss_to_cmd = global_t.argss_to_cmd +local repeated_read_cmd = global_t.repeated_read_cmd --- @alias Compiler {path: string[], type: string} diff --git a/test/unit/profile_spec.lua b/test/unit/profile_spec.lua index 011d3632d5..27b817cf42 100644 --- a/test/unit/profile_spec.lua +++ b/test/unit/profile_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local ffi = helpers.ffi -local eq = helpers.eq -local neq = helpers.neq +local cimport = t.cimport +local ffi = t.ffi +local eq = t.eq +local neq = t.neq local prof = cimport('./src/nvim/profile.h') @@ -13,13 +13,13 @@ local function split(inputstr, sep) sep = '%s' end - local t, i = {}, 1 + local q, i = {}, 1 for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do - t[i] = str + q[i] = str i = i + 1 end - return t + return q end local function trim(s) @@ -72,8 +72,8 @@ describe('profiling related functions', function() local function profile_start() return prof.profile_start() end - local function profile_end(t) - return prof.profile_end(t) + local function profile_end(q) + return prof.profile_end(q) end local function profile_zero() return prof.profile_zero() @@ -81,8 +81,8 @@ describe('profiling related functions', function() local function profile_setlimit(ms) return prof.profile_setlimit(ms) end - local function profile_passed_limit(t) - return prof.profile_passed_limit(t) + local function profile_passed_limit(q) + return prof.profile_passed_limit(q) end local function profile_add(t1, t2) return prof.profile_add(t1, t2) @@ -90,8 +90,8 @@ describe('profiling related functions', function() local function profile_sub(t1, t2) return prof.profile_sub(t1, t2) end - local function profile_divide(t, cnt) - return prof.profile_divide(t, cnt) + local function profile_divide(q, cnt) + return prof.profile_divide(q, cnt) end local function profile_cmp(t1, t2) return prof.profile_cmp(t1, t2) @@ -99,12 +99,12 @@ describe('profiling related functions', function() local function profile_equal(t1, t2) return prof.profile_equal(t1, t2) end - local function profile_msg(t) - return ffi.string(prof.profile_msg(t)) + local function profile_msg(q) + return ffi.string(prof.profile_msg(q)) end - local function toseconds(t) -- luacheck: ignore - local str = trim(profile_msg(t)) + local function toseconds(q) -- luacheck: ignore + local str = trim(profile_msg(q)) local spl = split(str, '.') local s, us = spl[1], spl[2] return tonumber(s) + tonumber(us) / 1000000 @@ -229,7 +229,7 @@ describe('profiling related functions', function() describe('profile_msg', function() itp('prints the zero time as 0.00000', function() local str = trim(profile_msg(profile_zero())) - eq(str, '0.000000') + eq('0.000000', str) end) itp('prints the time passed, in seconds.microsends', function() @@ -245,7 +245,7 @@ describe('profiling related functions', function() -- zero seconds have passed (if this is not true, either LuaJIT is too -- slow or the profiling functions are too slow and need to be fixed) - eq(s, '0') + eq('0', s) -- more or less the same goes for the microsecond part, if it doesn't -- start with 0, it's too slow. diff --git a/test/unit/rbuffer_spec.lua b/test/unit/rbuffer_spec.lua index 328e5b93da..ad18ea2ddc 100644 --- a/test/unit/rbuffer_spec.lua +++ b/test/unit/rbuffer_spec.lua @@ -1,13 +1,13 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local eq = helpers.eq -local ffi = helpers.ffi -local cstr = helpers.cstr -local to_cstr = helpers.to_cstr -local child_call_once = helpers.child_call_once +local eq = t.eq +local ffi = t.ffi +local cstr = t.cstr +local to_cstr = t.to_cstr +local child_call_once = t.child_call_once -local rbuffer = helpers.cimport('./test/unit/fixtures/rbuffer.h') +local rbuffer = t.cimport('./test/unit/fixtures/rbuffer.h') describe('rbuffer functions', function() local capacity = 16 diff --git a/test/unit/search_spec.lua b/test/unit/search_spec.lua index efe49f974a..9171cf9f06 100644 --- a/test/unit/search_spec.lua +++ b/test/unit/search_spec.lua @@ -1,12 +1,12 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local to_cstr = helpers.to_cstr -local eq = helpers.eq +local to_cstr = t.to_cstr +local eq = t.eq -local search = helpers.cimport('./src/nvim/search.h') -local globals = helpers.cimport('./src/nvim/globals.h') -local ffi = helpers.ffi +local search = t.cimport('./src/nvim/search.h') +local globals = t.cimport('./src/nvim/globals.h') +local ffi = t.ffi itp('pat_has_uppercase', function() -- works on empty string @@ -35,14 +35,15 @@ itp('pat_has_uppercase', function() end) describe('search_regcomp', function() - local search_regcomp = function(pat, pat_save, pat_use, options) + local search_regcomp = function(pat, patlen, pat_save, pat_use, options) local regmatch = ffi.new('regmmatch_T') - local fail = search.search_regcomp(to_cstr(pat), nil, pat_save, pat_use, options, regmatch) + local fail = + search.search_regcomp(to_cstr(pat), patlen, nil, pat_save, pat_use, options, regmatch) return fail, regmatch end local get_search_pat = function() - return helpers.internalize(search.get_search_pat()) + return t.internalize(search.get_search_pat()) end itp('accepts regexp pattern with invalid utf', function() @@ -50,7 +51,7 @@ describe('search_regcomp', function() globals.curwin.w_onebuf_opt.wo_rl = 1 globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s') globals.cmdmod.cmod_flags = globals.CMOD_KEEPPATTERNS - local fail = search_regcomp('a\192', 0, 0, 0) + local fail = search_regcomp('a\192', 2, 0, 0, 0) eq(1, fail) eq('\192a', get_search_pat()) end) diff --git a/test/unit/statusline_spec.lua b/test/unit/statusline_spec.lua index 83ba4176c5..973d9ec992 100644 --- a/test/unit/statusline_spec.lua +++ b/test/unit/statusline_spec.lua @@ -1,15 +1,15 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local to_cstr = helpers.to_cstr -local get_str = helpers.ffi.string -local eq = helpers.eq -local NULL = helpers.NULL +local to_cstr = t.to_cstr +local get_str = t.ffi.string +local eq = t.eq +local NULL = t.NULL -local buffer = helpers.cimport('./src/nvim/buffer.h') -local globals = helpers.cimport('./src/nvim/globals.h') -local stl = helpers.cimport('./src/nvim/statusline.h') -local grid = helpers.cimport('./src/nvim/grid.h') +local buffer = t.cimport('./src/nvim/buffer.h') +local globals = t.cimport('./src/nvim/globals.h') +local stl = t.cimport('./src/nvim/statusline.h') +local grid = t.cimport('./src/nvim/grid.h') describe('build_stl_str_hl', function() local buffer_byte_size = 100 diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua index eea669c964..25cdc27b28 100644 --- a/test/unit/strings_spec.lua +++ b/test/unit/strings_spec.lua @@ -1,10 +1,10 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local cimport = helpers.cimport -local eq = helpers.eq -local ffi = helpers.ffi -local to_cstr = helpers.to_cstr +local cimport = t.cimport +local eq = t.eq +local ffi = t.ffi +local to_cstr = t.to_cstr local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h') @@ -188,7 +188,7 @@ describe('vim_snprintf()', function() a('nan', buf, bsize, '%f', 0.0 / 0.0) a('inf', buf, bsize, '%f', 1.0 / 0.0) a('-inf', buf, bsize, '%f', -1.0 / 0.0) - a('-0.000000', buf, bsize, '%f', -0.0) + a('-0.000000', buf, bsize, '%f', tonumber('-0.0')) a('漢語', buf, bsize, '%s', '漢語') a(' 漢語', buf, bsize, '%8s', '漢語') a('漢語 ', buf, bsize, '%-8s', '漢語') @@ -233,7 +233,7 @@ describe('vim_snprintf()', function() a('nan', buf, bsize, '%1$f', 0.0 / 0.0) a('inf', buf, bsize, '%1$f', 1.0 / 0.0) a('-inf', buf, bsize, '%1$f', -1.0 / 0.0) - a('-0.000000', buf, bsize, '%1$f', -0.0) + a('-0.000000', buf, bsize, '%1$f', tonumber('-0.0')) end end) @@ -261,7 +261,7 @@ end) describe('reverse_text', function() local reverse_text = function(str) - return helpers.internalize(strings.reverse_text(to_cstr(str))) + return t.internalize(strings.reverse_text(to_cstr(str))) end itp('handles empty string', function() diff --git a/test/unit/tempfile_spec.lua b/test/unit/tempfile_spec.lua index e35490a561..1a42eed17e 100644 --- a/test/unit/tempfile_spec.lua +++ b/test/unit/tempfile_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) -local eq = helpers.eq -local neq = helpers.neq -local cimport = helpers.cimport -local child_call_once = helpers.child_call_once -local child_cleanup_once = helpers.child_cleanup_once +local eq = t.eq +local neq = t.neq +local cimport = t.cimport +local child_call_once = t.child_call_once +local child_cleanup_once = t.child_cleanup_once local lib = cimport('./src/nvim/os/os.h', './src/nvim/fileio.h') @@ -19,7 +19,7 @@ describe('tempfile related functions', function() end) local vim_gettempdir = function() - return helpers.ffi.string(lib.vim_gettempdir()) + return t.ffi.string(lib.vim_gettempdir()) end describe('vim_gettempdir', function() @@ -28,7 +28,7 @@ describe('tempfile related functions', function() assert.True(dir ~= nil and dir:len() > 0) -- os_file_is_writable returns 2 for a directory which we have rights -- to write into. - eq(lib.os_file_is_writable(helpers.to_cstr(dir)), 2) + eq(2, lib.os_file_is_writable(t.to_cstr(dir))) for entry in vim.fs.dir(dir) do assert.True(entry == '.' or entry == '..') end @@ -41,7 +41,7 @@ describe('tempfile related functions', function() describe('vim_tempname', function() local vim_tempname = function() - return helpers.ffi.string(lib.vim_tempname()) + return t.ffi.string(lib.vim_tempname()) end itp('generate name of non-existing file', function() @@ -57,7 +57,7 @@ describe('tempfile related functions', function() itp('generate file name in Nvim own temp directory', function() local dir = vim_gettempdir() local file = vim_tempname() - eq(string.sub(file, 1, string.len(dir)), dir) + eq(dir, string.sub(file, 1, string.len(dir))) end) end) end) diff --git a/test/unit/testtest_spec.lua b/test/unit/testtest_spec.lua index d2f3632b6f..0750cac5cc 100644 --- a/test/unit/testtest_spec.lua +++ b/test/unit/testtest_spec.lua @@ -1,9 +1,9 @@ -local helpers = require('test.unit.helpers')(after_each) +local t = require('test.unit.testutil') local assert = require('luassert') -local itp = helpers.gen_itp(it) +local itp = t.gen_itp(it) -local sc = helpers.sc +local sc = t.sc -- All of the below tests must fail. Check how exactly they fail. if os.getenv('NVIM_TEST_RUN_TESTTEST') ~= '1' then diff --git a/test/unit/helpers.lua b/test/unit/testutil.lua index ab4a59cfdb..a6db7beab1 100644 --- a/test/unit/helpers.lua +++ b/test/unit/testutil.lua @@ -2,16 +2,16 @@ local ffi = require('ffi') local formatc = require('test.unit.formatc') local Set = require('test.unit.set') local Preprocess = require('test.unit.preprocess') -local global_helpers = require('test.helpers') -local paths = global_helpers.paths +local t_global = require('test.testutil') +local paths = t_global.paths local assert = require('luassert') local say = require('say') -local check_cores = global_helpers.check_cores -local dedent = global_helpers.dedent -local neq = global_helpers.neq +local check_cores = t_global.check_cores +local dedent = t_global.dedent +local neq = t_global.neq local map = vim.tbl_map -local eq = global_helpers.eq +local eq = t_global.eq local trim = vim.trim -- add some standard header locations @@ -146,6 +146,9 @@ local function filter_complex_blocks(body) or string.find(line, 'value_init_') or string.find(line, 'UUID_NULL') -- static const uuid_t UUID_NULL = {...} or string.find(line, 'inline _Bool') + -- used by macOS headers + or string.find(line, 'typedef enum : ') + or string.find(line, 'mach_vm_range_recipe') ) then result[#result + 1] = line @@ -209,7 +212,7 @@ local function cimport(...) local new_cdefs = Set:new() for line in body:gmatch('[^\r\n]+') do line = trim(line) - -- give each #pragma pack an unique id, so that they don't get removed + -- give each #pragma pack a unique id, so that they don't get removed -- if they are inserted into the set -- (they are needed in the right order with the struct definitions, -- otherwise luajit has wrong memory layouts for the structs) @@ -873,8 +876,8 @@ local function is_asan() end end ---- @class test.unit.helpers.module -local module = { +--- @class test.unit.testutil.module +local M = { cimport = cimport, cppimport = cppimport, internalize = internalize, @@ -903,9 +906,7 @@ local module = { debug_log = debug_log, is_asan = is_asan, } ---- @class test.unit.helpers: test.unit.helpers.module, test.helpers -module = vim.tbl_extend('error', module, global_helpers) +--- @class test.unit.testutil: test.unit.testutil.module, test.testutil +M = vim.tbl_extend('error', M, t_global) -return function() - return module -end +return M diff --git a/test/unit/undo_spec.lua b/test/unit/undo_spec.lua index 0e2f38a8c8..5a96280caf 100644 --- a/test/unit/undo_spec.lua +++ b/test/unit/undo_spec.lua @@ -1,15 +1,15 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) local uv = vim.uv -local child_call_once = helpers.child_call_once +local child_call_once = t.child_call_once local sleep = uv.sleep -local ffi = helpers.ffi -local cimport = helpers.cimport -local to_cstr = helpers.to_cstr -local neq = helpers.neq -local eq = helpers.eq -local mkdir = helpers.mkdir +local ffi = t.ffi +local cimport = t.cimport +local to_cstr = t.to_cstr +local neq = t.neq +local eq = t.eq +local mkdir = t.mkdir local options = cimport('./src/nvim/option_vars.h') local undo = cimport('./src/nvim/undo.h') @@ -151,12 +151,12 @@ describe('u_write_undo', function() local file_contents = 'testing permissions' -- Write a text file where the undofile should go local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false)) - helpers.write_file(correct_name, file_contents, true, false) + t.write_file(correct_name, file_contents, true, false) -- Call with `forceit`. u_write_undo(correct_name, true, file_buffer, buffer_hash) - local undo_file_contents = helpers.read_file(correct_name) + local undo_file_contents = t.read_file(correct_name) neq(file_contents, undo_file_contents) local success, deletion_err = os.remove(correct_name) -- delete the file now that we're done with it. diff --git a/test/unit/viml/expressions/lexer_spec.lua b/test/unit/viml/expressions/lexer_spec.lua index 96052a5ce1..30483f4c1d 100644 --- a/test/unit/viml/expressions/lexer_spec.lua +++ b/test/unit/viml/expressions/lexer_spec.lua @@ -1,20 +1,20 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local viml_helpers = require('test.unit.viml.helpers') - -local child_call_once = helpers.child_call_once -local conv_enum = helpers.conv_enum -local cimport = helpers.cimport -local ffi = helpers.ffi -local eq = helpers.eq -local shallowcopy = helpers.shallowcopy -local intchar2lua = helpers.intchar2lua - -local conv_ccs = viml_helpers.conv_ccs -local new_pstate = viml_helpers.new_pstate -local conv_cmp_type = viml_helpers.conv_cmp_type -local pstate_set_str = viml_helpers.pstate_set_str -local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local t_viml = require('test.unit.viml.testutil') + +local child_call_once = t.child_call_once +local conv_enum = t.conv_enum +local cimport = t.cimport +local ffi = t.ffi +local eq = t.eq +local shallowcopy = t.shallowcopy +local intchar2lua = t.intchar2lua + +local conv_ccs = t_viml.conv_ccs +local new_pstate = t_viml.new_pstate +local conv_cmp_type = t_viml.conv_cmp_type +local pstate_set_str = t_viml.pstate_set_str +local conv_expr_asgn_type = t_viml.conv_expr_asgn_type local lib = cimport('./src/nvim/viml/parser/expressions.h') diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua index c7d3f8532f..6f18448bd2 100644 --- a/test/unit/viml/expressions/parser_spec.lua +++ b/test/unit/viml/expressions/parser_spec.lua @@ -1,29 +1,29 @@ -local helpers = require('test.unit.helpers')(after_each) -local itp = helpers.gen_itp(it) -local viml_helpers = require('test.unit.viml.helpers') +local t = require('test.unit.testutil') +local itp = t.gen_itp(it) +local t_viml = require('test.unit.viml.testutil') -local make_enum_conv_tab = helpers.make_enum_conv_tab -local child_call_once = helpers.child_call_once -local alloc_log_new = helpers.alloc_log_new -local kvi_destroy = helpers.kvi_destroy -local conv_enum = helpers.conv_enum -local debug_log = helpers.debug_log -local ptr2key = helpers.ptr2key -local cimport = helpers.cimport -local ffi = helpers.ffi -local neq = helpers.neq -local eq = helpers.eq -local mergedicts_copy = helpers.mergedicts_copy +local make_enum_conv_tab = t.make_enum_conv_tab +local child_call_once = t.child_call_once +local alloc_log_new = t.alloc_log_new +local kvi_destroy = t.kvi_destroy +local conv_enum = t.conv_enum +local debug_log = t.debug_log +local ptr2key = t.ptr2key +local cimport = t.cimport +local ffi = t.ffi +local neq = t.neq +local eq = t.eq +local mergedicts_copy = t.mergedicts_copy local format_string = require('test.format_string').format_string local format_luav = require('test.format_string').format_luav -local intchar2lua = helpers.intchar2lua -local dictdiff = helpers.dictdiff +local intchar2lua = t.intchar2lua +local dictdiff = t.dictdiff -local conv_ccs = viml_helpers.conv_ccs -local new_pstate = viml_helpers.new_pstate -local conv_cmp_type = viml_helpers.conv_cmp_type -local pstate_set_str = viml_helpers.pstate_set_str -local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type +local conv_ccs = t_viml.conv_ccs +local new_pstate = t_viml.new_pstate +local conv_cmp_type = t_viml.conv_cmp_type +local pstate_set_str = t_viml.pstate_set_str +local conv_expr_asgn_type = t_viml.conv_expr_asgn_type local lib = cimport('./src/nvim/viml/parser/expressions.h', './src/nvim/syntax.h') diff --git a/test/unit/viml/helpers.lua b/test/unit/viml/testutil.lua index 92661e3027..376ef538d4 100644 --- a/test/unit/viml/helpers.lua +++ b/test/unit/viml/testutil.lua @@ -1,11 +1,11 @@ -local helpers = require('test.unit.helpers')(nil) +local t = require('test.unit.testutil') -local ffi = helpers.ffi -local cimport = helpers.cimport -local kvi_new = helpers.kvi_new -local kvi_init = helpers.kvi_init -local conv_enum = helpers.conv_enum -local make_enum_conv_tab = helpers.make_enum_conv_tab +local ffi = t.ffi +local cimport = t.cimport +local kvi_new = t.kvi_new +local kvi_init = t.kvi_init +local conv_enum = t.conv_enum +local make_enum_conv_tab = t.make_enum_conv_tab local lib = cimport('./src/nvim/viml/parser/expressions.h') |