aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md4
-rw-r--r--test/functional/api/autocmd_spec.lua777
-rw-r--r--test/functional/api/buffer_spec.lua35
-rw-r--r--test/functional/api/buffer_updates_spec.lua4
-rw-r--r--test/functional/api/command_spec.lua203
-rw-r--r--test/functional/api/extmark_spec.lua71
-rw-r--r--test/functional/api/highlight_spec.lua76
-rw-r--r--test/functional/api/keymap_spec.lua230
-rw-r--r--test/functional/api/server_requests_spec.lua6
-rw-r--r--test/functional/api/vim_spec.lua98
-rw-r--r--test/functional/api/window_spec.lua44
-rw-r--r--test/functional/autocmd/autocmd_oldtest_spec.lua86
-rw-r--r--test/functional/autocmd/autocmd_spec.lua167
-rw-r--r--test/functional/autocmd/cursormoved_spec.lua1
-rw-r--r--test/functional/autocmd/dirchanged_spec.lua128
-rw-r--r--test/functional/autocmd/focus_spec.lua2
-rw-r--r--test/functional/autocmd/recording_spec.lua28
-rw-r--r--test/functional/autocmd/show_spec.lua35
-rw-r--r--test/functional/autocmd/termxx_spec.lua4
-rw-r--r--test/functional/core/channels_spec.lua32
-rw-r--r--test/functional/core/job_spec.lua7
-rw-r--r--test/functional/core/startup_spec.lua27
-rw-r--r--test/functional/editor/K_spec.lua23
-rw-r--r--test/functional/editor/meta_key_spec.lua33
-rw-r--r--test/functional/editor/mode_insert_spec.lua53
-rw-r--r--test/functional/editor/put_spec.lua22
-rw-r--r--test/functional/ex_cmds/append_spec.lua70
-rw-r--r--test/functional/ex_cmds/ctrl_c_spec.lua3
-rw-r--r--test/functional/ex_cmds/map_spec.lua221
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua16
-rw-r--r--test/functional/ex_cmds/script_spec.lua2
-rw-r--r--test/functional/ex_cmds/verbose_spec.lua168
-rw-r--r--test/functional/fixtures/autoload/provider/python3.vim (renamed from test/functional/fixtures/autoload/provider/python.vim)2
-rw-r--r--test/functional/fixtures/lua/test_plug/submodule_empty/health.lua7
-rw-r--r--test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua1
-rw-r--r--test/functional/helpers.lua1
-rw-r--r--test/functional/legacy/003_cindent_spec.lua4774
-rw-r--r--test/functional/legacy/assert_spec.lua233
-rw-r--r--test/functional/legacy/cdo_spec.lua228
-rw-r--r--test/functional/legacy/eval_spec.lua2
-rw-r--r--test/functional/legacy/ex_mode_spec.lua36
-rw-r--r--test/functional/legacy/excmd_spec.lua32
-rw-r--r--test/functional/legacy/expand_spec.lua129
-rw-r--r--test/functional/legacy/filechanged_spec.lua131
-rw-r--r--test/functional/legacy/listchars_spec.lua81
-rw-r--r--test/functional/legacy/memory_usage_spec.lua4
-rw-r--r--test/functional/legacy/packadd_spec.lua507
-rw-r--r--test/functional/legacy/put_spec.lua45
-rw-r--r--test/functional/legacy/search_stat_spec.lua121
-rw-r--r--test/functional/legacy/utf8_spec.lua2
-rw-r--r--test/functional/legacy/visual_mode_spec.lua44
-rw-r--r--test/functional/lua/api_spec.lua20
-rw-r--r--test/functional/lua/commands_spec.lua18
-rw-r--r--test/functional/lua/diagnostic_spec.lua29
-rw-r--r--test/functional/lua/filetype_spec.lua98
-rw-r--r--test/functional/lua/luaeval_spec.lua1
-rw-r--r--test/functional/lua/thread_spec.lua386
-rw-r--r--test/functional/lua/uri_spec.lua2
-rw-r--r--test/functional/lua/vim_spec.lua341
-rw-r--r--test/functional/lua/xdiff_spec.lua42
-rw-r--r--test/functional/plugin/health_spec.lua25
-rw-r--r--test/functional/plugin/lsp_spec.lua186
-rw-r--r--test/functional/plugin/shada_spec.lua8
-rw-r--r--test/functional/provider/provider_spec.lua4
-rw-r--r--test/functional/provider/python3_spec.lua43
-rw-r--r--test/functional/provider/python_spec.lua123
-rw-r--r--test/functional/terminal/buffer_spec.lua8
-rw-r--r--test/functional/terminal/cursor_spec.lua3
-rw-r--r--test/functional/terminal/edit_spec.lua1
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua7
-rw-r--r--test/functional/terminal/highlight_spec.lua1
-rw-r--r--test/functional/terminal/mouse_spec.lua116
-rw-r--r--test/functional/terminal/scrollback_spec.lua2
-rw-r--r--test/functional/terminal/tui_spec.lua36
-rw-r--r--test/functional/terminal/window_spec.lua1
-rw-r--r--test/functional/treesitter/highlight_spec.lua89
-rw-r--r--test/functional/treesitter/parser_spec.lua55
-rw-r--r--test/functional/ui/bufhl_spec.lua18
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua13
-rw-r--r--test/functional/ui/float_spec.lua22
-rw-r--r--test/functional/ui/highlight_spec.lua101
-rw-r--r--test/functional/ui/hlstate_spec.lua2
-rw-r--r--test/functional/ui/inccommand_spec.lua64
-rw-r--r--test/functional/ui/input_spec.lua42
-rw-r--r--test/functional/ui/messages_spec.lua1
-rw-r--r--test/functional/ui/output_spec.lua1
-rw-r--r--test/functional/ui/popupmenu_spec.lua148
-rw-r--r--test/functional/ui/screen_basic_spec.lua58
-rw-r--r--test/functional/ui/sign_spec.lua32
-rw-r--r--test/functional/vimscript/eval_spec.lua2
-rw-r--r--test/functional/vimscript/functions_spec.lua2
-rw-r--r--test/functional/vimscript/timer_spec.lua8
-rw-r--r--test/helpers.lua18
-rw-r--r--test/unit/buffer_spec.lua141
-rw-r--r--test/unit/charset/vim_str2nr_spec.lua2
-rw-r--r--test/unit/garray_spec.lua2
-rw-r--r--test/unit/marktree_spec.lua44
-rw-r--r--test/unit/os/env_spec.lua2
-rw-r--r--test/unit/os/fs_spec.lua4
-rw-r--r--test/unit/path_spec.lua16
100 files changed, 5142 insertions, 6302 deletions
diff --git a/test/README.md b/test/README.md
index c6e173ead2..cc630cb8bf 100644
--- a/test/README.md
+++ b/test/README.md
@@ -38,7 +38,7 @@ Layout
- `/test/functional` : functional tests
- `/test/unit` : unit tests
- `/test/config` : contains `*.in` files which are transformed into `*.lua`
- files using `configure_file` CMake command: this is for acessing CMake
+ files using `configure_file` CMake command: this is for accessing CMake
variables in lua tests.
- `/test/includes` : include-files for use by luajit `ffi.cdef` C definitions
parser: normally used to make macros not accessible via this mechanism
@@ -197,7 +197,7 @@ Guidelines
(success + fail + error + pending) is the same in all environments.
- *Note:* `pending()` is ignored if it is missing an argument, unless it is
[contained in an `it()` block](https://github.com/neovim/neovim/blob/d21690a66e7eb5ebef18046c7a79ef898966d786/test/functional/ex_cmds/grep_spec.lua#L11).
- Provide empty function argument if the `pending()` call is outside of `it()`
+ Provide empty function argument if the `pending()` call is outside `it()`
([example](https://github.com/neovim/neovim/commit/5c1dc0fbe7388528875aff9d7b5055ad718014de#diff-bf80b24c724b0004e8418102f68b0679R18)).
- Really long `source([=[...]=])` blocks may break Vim's Lua syntax
highlighting. Try `:syntax sync fromstart` to fix it.
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
new file mode 100644
index 0000000000..e50e812b4b
--- /dev/null
+++ b/test/functional/api/autocmd_spec.lua
@@ -0,0 +1,777 @@
+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 meths = helpers.meths
+local source = helpers.source
+
+before_each(clear)
+
+describe('autocmd api', function()
+ describe('nvim_create_autocmd', function()
+ it('does not allow "command" and "callback" in the same autocmd', function()
+ local ok, _ = pcall(meths.create_autocmd, "BufReadPost", {
+ pattern = "*.py,*.pyi",
+ command = "echo 'Should Have Errored",
+ callback = "not allowed",
+ })
+
+ eq(false, ok)
+ end)
+
+ it('doesnt leak when you use ++once', function()
+ eq(1, exec_lua([[
+ local count = 0
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ callback = function() count = count + 1 end,
+ once = true
+ })
+
+ vim.cmd "set filetype=txt"
+ vim.cmd "set filetype=python"
+
+ return count
+ ]], {}))
+ end)
+
+ it('allows passing buffer by key', function()
+ meths.set_var('called', 0)
+
+ meths.create_autocmd("FileType", {
+ command = "let g:called = g:called + 1",
+ buffer = 0,
+ })
+
+ meths.command "set filetype=txt"
+ eq(1, meths.get_var('called'))
+
+ -- switch to a new buffer
+ meths.command "new"
+ meths.command "set filetype=python"
+
+ eq(1, meths.get_var('called'))
+ end)
+
+ it('does not allow passing buffer and patterns', function()
+ local ok = pcall(meths.create_autocmd, "Filetype", {
+ command = "let g:called = g:called + 1",
+ buffer = 0,
+ pattern = "*.py",
+ })
+
+ eq(false, ok)
+ end)
+
+ it('does not allow passing invalid buffers', function()
+ local ok, msg = pcall(meths.create_autocmd, "Filetype", {
+ command = "let g:called = g:called + 1",
+ buffer = -1,
+ })
+
+ eq(false, ok)
+ matches('Invalid buffer id', msg)
+ end)
+
+ it('errors on non-functions for cb', function()
+ eq(false, pcall(exec_lua, [[
+ vim.api.nvim_create_autocmd("BufReadPost", {
+ pattern = "*.py,*.pyi",
+ callback = 5,
+ })
+ ]]))
+ end)
+
+ it('allow passing pattern and <buffer> in same pattern', function()
+ local ok = pcall(meths.create_autocmd, "BufReadPost", {
+ pattern = "*.py,<buffer>",
+ command = "echo 'Should Not Error'"
+ })
+
+ eq(true, ok)
+ end)
+
+ it('should handle multiple values as comma separated list', function()
+ meths.create_autocmd("BufReadPost", {
+ pattern = "*.py,*.pyi",
+ command = "echo 'Should Not Have Errored'"
+ })
+
+ -- We should have one autocmd for *.py and one for *.pyi
+ eq(2, #meths.get_autocmds { event = "BufReadPost" })
+ end)
+
+ it('should handle multiple values as array', function()
+ meths.create_autocmd("BufReadPost", {
+ pattern = { "*.py", "*.pyi", },
+ command = "echo 'Should Not Have Errored'"
+ })
+
+ -- We should have one autocmd for *.py and one for *.pyi
+ eq(2, #meths.get_autocmds { event = "BufReadPost" })
+ end)
+
+ describe('desc', function()
+ it('can add description to one autocmd', function()
+ meths.create_autocmd("BufReadPost", {
+ pattern = "*.py",
+ command = "echo 'Should Not Have Errored'",
+ desc = "Can show description",
+ })
+
+ eq("Can show description", meths.get_autocmds { event = "BufReadPost" }[1].desc)
+ end)
+
+ it('can add description to multiple autocmd', function()
+ meths.create_autocmd("BufReadPost", {
+ pattern = {"*.py", "*.pyi"},
+ command = "echo 'Should Not Have Errored'",
+ desc = "Can show description",
+ })
+
+ local aus = meths.get_autocmds { event = "BufReadPost" }
+ eq(2, #aus)
+ eq("Can show description", aus[1].desc)
+ eq("Can show description", aus[2].desc)
+ end)
+ end)
+
+ pending('script and verbose settings', function()
+ it('marks API client', function()
+ meths.create_autocmd("BufReadPost", {
+ pattern = "*.py",
+ command = "echo 'Should Not Have Errored'",
+ desc = "Can show description",
+ })
+
+ local aus = meths.get_autocmds { event = "BufReadPost" }
+ eq(1, #aus, aus)
+ end)
+ end)
+ end)
+
+ describe('nvim_get_autocmds', function()
+ describe('events', function()
+ it('should return one autocmd when there is only one for an event', function()
+ command [[au! InsertEnter]]
+ command [[au InsertEnter * :echo "1"]]
+
+ local aus = meths.get_autocmds { event = "InsertEnter" }
+ eq(1, #aus)
+ end)
+
+ it('should return two autocmds when there are two for an event', function()
+ command [[au! InsertEnter]]
+ command [[au InsertEnter * :echo "1"]]
+ command [[au InsertEnter * :echo "2"]]
+
+ local aus = meths.get_autocmds { event = "InsertEnter" }
+ eq(2, #aus)
+ end)
+
+ it('should return the same thing if you use string or list', function()
+ command [[au! InsertEnter]]
+ command [[au InsertEnter * :echo "1"]]
+ command [[au InsertEnter * :echo "2"]]
+
+ local string_aus = meths.get_autocmds { event = "InsertEnter" }
+ local array_aus = meths.get_autocmds { event = { "InsertEnter" } }
+ eq(string_aus, array_aus)
+ end)
+
+ it('should return two autocmds when there are two for an event', function()
+ command [[au! InsertEnter]]
+ command [[au! InsertLeave]]
+ command [[au InsertEnter * :echo "1"]]
+ command [[au InsertEnter * :echo "2"]]
+
+ local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ eq(2, #aus)
+ end)
+
+ it('should return different IDs for different autocmds', function()
+ command [[au! InsertEnter]]
+ command [[au! InsertLeave]]
+ command [[au InsertEnter * :echo "1"]]
+ source [[
+ call nvim_create_autocmd("InsertLeave", #{
+ \ command: ":echo 2",
+ \ })
+ ]]
+
+ local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ local first = aus[1]
+ eq(first.id, nil)
+
+ -- TODO: Maybe don't have this number, just assert it's not nil
+ local second = aus[2]
+ neq(second.id, nil)
+
+ meths.del_autocmd(second.id)
+ local new_aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ eq(1, #new_aus)
+ eq(first, new_aus[1])
+ end)
+
+ it('should return event name', function()
+ command [[au! InsertEnter]]
+ command [[au InsertEnter * :echo "1"]]
+
+ local aus = meths.get_autocmds { event = "InsertEnter" }
+ eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus)
+ end)
+ end)
+
+ describe('groups', function()
+ before_each(function()
+ command [[au! InsertEnter]]
+
+ command [[au InsertEnter * :echo "No Group"]]
+
+ command [[augroup GroupOne]]
+ command [[ au InsertEnter * :echo "GroupOne:1"]]
+ command [[augroup END]]
+
+ command [[augroup GroupTwo]]
+ command [[ au InsertEnter * :echo "GroupTwo:2"]]
+ command [[ au InsertEnter * :echo "GroupTwo:3"]]
+ command [[augroup END]]
+ end)
+
+ it('should return all groups if no group is specified', function()
+ local aus = meths.get_autocmds { event = "InsertEnter" }
+ if #aus ~= 4 then
+ eq({}, aus)
+ end
+
+ eq(4, #aus)
+ end)
+
+ it('should return only the group specified', function()
+ local aus = meths.get_autocmds {
+ event = "InsertEnter",
+ group = "GroupOne",
+ }
+
+ eq(1, #aus)
+ eq([[:echo "GroupOne:1"]], aus[1].command)
+ end)
+
+ it('should return only the group specified, multiple values', function()
+ local aus = meths.get_autocmds {
+ event = "InsertEnter",
+ group = "GroupTwo",
+ }
+
+ eq(2, #aus)
+ eq([[:echo "GroupTwo:2"]], aus[1].command)
+ eq([[:echo "GroupTwo:3"]], aus[2].command)
+ end)
+ end)
+
+ describe('groups: 2', function()
+ it('raises error for undefined augroup', function()
+ local success, code = unpack(meths.exec_lua([[
+ return {pcall(function()
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ group = "NotDefined",
+ command = "echo 'hello'",
+ })
+ end)}
+ ]], {}))
+
+ eq(false, success)
+ matches('invalid augroup: NotDefined', code)
+ end)
+ end)
+
+ describe('patterns', function()
+ before_each(function()
+ command [[au! InsertEnter]]
+
+ command [[au InsertEnter * :echo "No Group"]]
+ command [[au InsertEnter *.one :echo "GroupOne:1"]]
+ command [[au InsertEnter *.two :echo "GroupTwo:2"]]
+ command [[au InsertEnter *.two :echo "GroupTwo:3"]]
+ command [[au InsertEnter <buffer> :echo "Buffer"]]
+ end)
+
+ it('should should return for literal match', function()
+ local aus = meths.get_autocmds {
+ event = "InsertEnter",
+ pattern = "*"
+ }
+
+ eq(1, #aus)
+ eq([[:echo "No Group"]], aus[1].command)
+ end)
+
+ it('should return for multiple matches', function()
+ -- vim.api.nvim_get_autocmds
+ local aus = meths.get_autocmds {
+ event = "InsertEnter",
+ pattern = { "*.one", "*.two" },
+ }
+
+ eq(3, #aus)
+ eq([[:echo "GroupOne:1"]], aus[1].command)
+ eq([[:echo "GroupTwo:2"]], aus[2].command)
+ eq([[:echo "GroupTwo:3"]], aus[3].command)
+ end)
+
+ it('should work for buffer autocmds', function()
+ local normalized_aus = meths.get_autocmds {
+ event = "InsertEnter",
+ pattern = "<buffer=1>",
+ }
+
+ local raw_aus = meths.get_autocmds {
+ event = "InsertEnter",
+ pattern = "<buffer>",
+ }
+
+ local zero_aus = meths.get_autocmds {
+ event = "InsertEnter",
+ pattern = "<buffer=0>",
+ }
+
+ eq(normalized_aus, raw_aus)
+ eq(normalized_aus, zero_aus)
+ eq([[:echo "Buffer"]], normalized_aus[1].command)
+ end)
+ end)
+ end)
+
+ describe('nvim_do_autocmd', function()
+ it("can trigger builtin autocmds", function()
+ meths.set_var("autocmd_executed", false)
+
+ meths.create_autocmd("BufReadPost", {
+ pattern = "*",
+ command = "let g:autocmd_executed = v:true",
+ })
+
+ eq(false, meths.get_var("autocmd_executed"))
+ meths.do_autocmd("BufReadPost", {})
+ eq(true, meths.get_var("autocmd_executed"))
+ end)
+
+ it("can pass the buffer", function()
+ meths.set_var("buffer_executed", -1)
+ eq(-1, meths.get_var("buffer_executed"))
+
+ meths.create_autocmd("BufLeave", {
+ pattern = "*",
+ command = 'let g:buffer_executed = +expand("<abuf>")',
+ })
+
+ -- Doesn't execute for other non-matching events
+ meths.do_autocmd("CursorHold", { buffer = 1 })
+ eq(-1, meths.get_var("buffer_executed"))
+
+ meths.do_autocmd("BufLeave", { buffer = 1 })
+ eq(1, meths.get_var("buffer_executed"))
+ end)
+
+ it("can pass the filename, pattern match", function()
+ meths.set_var("filename_executed", 'none')
+ eq('none', meths.get_var("filename_executed"))
+
+ meths.create_autocmd("BufEnter", {
+ pattern = "*.py",
+ command = 'let g:filename_executed = expand("<afile>")',
+ })
+
+ -- Doesn't execute for other non-matching events
+ meths.do_autocmd("CursorHold", { buffer = 1 })
+ eq('none', meths.get_var("filename_executed"))
+
+ meths.command('edit __init__.py')
+ eq('__init__.py', meths.get_var("filename_executed"))
+ end)
+
+ it('cannot pass buf and fname', function()
+ local ok = pcall(meths.do_autocmd, "BufReadPre", { pattern = "literally_cannot_error.rs", buffer = 1 })
+ eq(false, ok)
+ end)
+
+ it("can pass the filename, exact match", function()
+ meths.set_var("filename_executed", 'none')
+ eq('none', meths.get_var("filename_executed"))
+
+ meths.command('edit other_file.txt')
+ meths.command('edit __init__.py')
+ eq('none', meths.get_var("filename_executed"))
+
+ meths.create_autocmd("CursorHoldI", {
+ pattern = "__init__.py",
+ command = 'let g:filename_executed = expand("<afile>")',
+ })
+
+ -- Doesn't execute for other non-matching events
+ meths.do_autocmd("CursorHoldI", { buffer = 1 })
+ eq('none', meths.get_var("filename_executed"))
+
+ meths.do_autocmd("CursorHoldI", { buffer = tonumber(meths.get_current_buf()) })
+ eq('__init__.py', meths.get_var("filename_executed"))
+
+ -- Reset filename
+ meths.set_var("filename_executed", 'none')
+
+ meths.do_autocmd("CursorHoldI", { pattern = '__init__.py' })
+ eq('__init__.py', meths.get_var("filename_executed"))
+ end)
+
+ it("works with user autocmds", function()
+ meths.set_var("matched", 'none')
+
+ meths.create_autocmd("User", {
+ pattern = "TestCommand",
+ command = 'let g:matched = "matched"'
+ })
+
+ meths.do_autocmd("User", { pattern = "OtherCommand" })
+ eq('none', meths.get_var('matched'))
+ meths.do_autocmd("User", { pattern = "TestCommand" })
+ eq('matched', meths.get_var('matched'))
+ end)
+ end)
+
+ describe('nvim_create_augroup', function()
+ before_each(function()
+ clear()
+
+ meths.set_var('executed', 0)
+ end)
+
+ local make_counting_autocmd = function(opts)
+ opts = opts or {}
+
+ local resulting = {
+ pattern = "*",
+ command = "let g:executed = g:executed + 1",
+ }
+
+ resulting.group = opts.group
+ resulting.once = opts.once
+
+ meths.create_autocmd("FileType", resulting)
+ end
+
+ local set_ft = function(ft)
+ ft = ft or "txt"
+ source(string.format("set filetype=%s", ft))
+ end
+
+ local get_executed_count = function()
+ return meths.get_var('executed')
+ end
+
+ it('can be added in a group', function()
+ local augroup = "TestGroup"
+ meths.create_augroup(augroup, { clear = true })
+ make_counting_autocmd { group = augroup }
+
+ set_ft("txt")
+ set_ft("python")
+
+ eq(get_executed_count(), 2)
+ end)
+
+ it('works getting called multiple times', function()
+ make_counting_autocmd()
+ set_ft()
+ set_ft()
+ set_ft()
+
+ eq(get_executed_count(), 3)
+ end)
+
+ it('handles ++once', function()
+ make_counting_autocmd {once = true}
+ set_ft('txt')
+ set_ft('help')
+ set_ft('txt')
+ set_ft('help')
+
+ eq(get_executed_count(), 1)
+ end)
+
+ it('errors on unexpected keys', function()
+ local success, code = pcall(meths.create_autocmd, "FileType", {
+ pattern = "*",
+ not_a_valid_key = "NotDefined",
+ })
+
+ eq(false, success)
+ matches('not_a_valid_key', code)
+ end)
+
+ it('can execute simple callback', function()
+ exec_lua([[
+ vim.g.executed = false
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ callback = function() vim.g.executed = true end,
+ })
+ ]], {})
+
+
+ eq(true, exec_lua([[
+ vim.cmd "set filetype=txt"
+ return vim.g.executed
+ ]], {}))
+ end)
+
+ it('calls multiple lua callbacks for the same autocmd execution', function()
+ eq(4, exec_lua([[
+ local count = 0
+ local counter = function()
+ count = count + 1
+ end
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ callback = counter,
+ })
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ callback = counter,
+ })
+
+ vim.cmd "set filetype=txt"
+ vim.cmd "set filetype=txt"
+
+ return count
+ ]], {}))
+ end)
+
+ it('properly releases functions with ++once', function()
+ exec_lua([[
+ WeakTable = setmetatable({}, { __mode = "k" })
+
+ OnceCount = 0
+
+ MyVal = {}
+ WeakTable[MyVal] = true
+
+ vim.api.nvim_create_autocmd("FileType", {
+ pattern = "*",
+ callback = function()
+ OnceCount = OnceCount + 1
+ MyVal = {}
+ end,
+ once = true
+ })
+ ]])
+
+ command [[set filetype=txt]]
+ eq(1, exec_lua([[return OnceCount]], {}))
+
+ exec_lua([[collectgarbage()]], {})
+
+ command [[set filetype=txt]]
+ eq(1, exec_lua([[return OnceCount]], {}))
+
+ eq(0, exec_lua([[
+ local count = 0
+ for _ in pairs(WeakTable) do
+ count = count + 1
+ end
+
+ return count
+ ]]), "Should have no keys remaining")
+ end)
+
+ it('groups can be cleared', function()
+ local augroup = "TestGroup"
+ meths.create_augroup(augroup, { clear = true })
+ meths.create_autocmd("FileType", {
+ group = augroup,
+ command = "let g:executed = g:executed + 1"
+ })
+
+ set_ft("txt")
+ set_ft("txt")
+ eq(2, get_executed_count(), "should only count twice")
+
+ meths.create_augroup(augroup, { clear = true })
+ eq({}, meths.get_autocmds { group = augroup })
+
+ set_ft("txt")
+ set_ft("txt")
+ eq(2, get_executed_count(), "No additional counts")
+ end)
+
+ it('groups work with once', function()
+ local augroup = "TestGroup"
+
+ meths.create_augroup(augroup, { clear = true })
+ make_counting_autocmd { group = augroup, once = true }
+
+ set_ft("txt")
+ set_ft("python")
+
+ eq(get_executed_count(), 1)
+ end)
+
+ it('autocmds can be registered multiple times.', function()
+ local augroup = "TestGroup"
+
+ meths.create_augroup(augroup, { clear = true })
+ make_counting_autocmd { group = augroup, once = false }
+ make_counting_autocmd { group = augroup, once = false }
+ make_counting_autocmd { group = augroup, once = false }
+
+ set_ft("txt")
+ set_ft("python")
+
+ eq(get_executed_count(), 3 * 2)
+ end)
+
+ it('can be deleted', function()
+ local augroup = "WillBeDeleted"
+
+ meths.create_augroup(augroup, { clear = true })
+ meths.create_autocmd({"Filetype"}, {
+ pattern = "*",
+ command = "echo 'does not matter'",
+ })
+
+ -- Clears the augroup from before, which erases the autocmd
+ meths.create_augroup(augroup, { clear = true })
+
+ local result = #meths.get_autocmds { group = augroup }
+
+ eq(0, result)
+ end)
+
+ it('can be used for buffer local autocmds', function()
+ local augroup = "WillBeDeleted"
+
+ meths.set_var("value_set", false)
+
+ meths.create_augroup(augroup, { clear = true })
+ meths.create_autocmd("Filetype", {
+ pattern = "<buffer>",
+ command = "let g:value_set = v:true",
+ })
+
+ command "new"
+ command "set filetype=python"
+
+ eq(false, meths.get_var("value_set"))
+ end)
+
+ it('can accept vimscript functions', function()
+ source [[
+ let g:vimscript_executed = 0
+
+ function! MyVimscriptFunction() abort
+ let g:vimscript_executed = g:vimscript_executed + 1
+ endfunction
+
+ call nvim_create_autocmd("FileType", #{
+ \ pattern: ["python", "javascript"],
+ \ callback: "MyVimscriptFunction",
+ \ })
+
+ set filetype=txt
+ set filetype=python
+ set filetype=txt
+ set filetype=javascript
+ set filetype=txt
+ ]]
+
+ eq(2, meths.get_var("vimscript_executed"))
+ end)
+ end)
+
+ describe('augroup!', function()
+ it('legacy: should clear and not return any autocmds for delete groups', function()
+ command('augroup TEMP_A')
+ command(' autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
+
+ command('augroup! TEMP_A')
+
+ eq(false, pcall(meths.get_autocmds, { group = 'TEMP_A' }))
+
+ -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild
+ -- but we managed to keep this behavior.
+ eq(1, #meths.get_autocmds { event = 'BufReadPost' })
+ end)
+
+ it('legacy: remove augroups that have no autocmds', function()
+ command('augroup TEMP_AB')
+ command('augroup END')
+
+ command('augroup! TEMP_AB')
+
+ eq(false, pcall(meths.get_autocmds, { group = 'TEMP_AB' }))
+ eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ end)
+
+ it('legacy: multiple remove and add augroup', function()
+ command('augroup TEMP_ABC')
+ command(' au!')
+ command(' autocmd BufReadPost *.py echo "Hello"')
+ command('augroup END')
+
+ command('augroup! TEMP_ABC')
+
+ -- Should still have one autocmd :'(
+ local aus = meths.get_autocmds { event = 'BufReadPost' }
+ eq(1, #aus, aus)
+
+ command('augroup TEMP_ABC')
+ command(' au!')
+ command(' autocmd BufReadPost *.py echo "Hello"')
+ command('augroup END')
+
+ -- Should now have two autocmds :'(
+ aus = meths.get_autocmds { event = 'BufReadPost' }
+ eq(2, #aus, aus)
+
+ command('augroup! TEMP_ABC')
+
+ eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABC' }))
+ eq(2, #meths.get_autocmds { event = 'BufReadPost' })
+ end)
+
+ it('api: should clear and not return any autocmds for delete groups by id', function()
+ command('augroup TEMP_ABCD')
+ command('autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
+
+ local augroup_id = meths.create_augroup("TEMP_ABCD", { clear = false })
+ meths.del_augroup_by_id(augroup_id)
+
+ -- For good reason, we kill all the autocmds from del_augroup,
+ -- so now this works as expected
+ eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCD' }))
+ eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ end)
+
+ it('api: should clear and not return any autocmds for delete groups by name', function()
+ command('augroup TEMP_ABCDE')
+ command('autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
+
+ meths.del_augroup_by_name("TEMP_ABCDE")
+
+ -- For good reason, we kill all the autocmds from del_augroup,
+ -- so now this works as expected
+ eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCDE' }))
+ eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ end)
+ end)
+end)
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 688f3abba5..dd3af8c28f 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -423,6 +423,13 @@ describe('api/buf', function()
-- will join multiple lines if needed
set_text(0, 6, 3, 4, {'bar'})
eq({'hello bar'}, get_lines(0, 1, true))
+
+ -- can use negative line numbers
+ set_text(-2, 0, -2, 5, {'goodbye'})
+ eq({'goodbye bar', ''}, get_lines(0, -1, true))
+
+ set_text(-1, 0, -1, 0, {'text'})
+ eq({'goodbye bar', 'text'}, get_lines(0, 2, true))
end)
it('works with undo', function()
@@ -537,6 +544,34 @@ describe('api/buf', function()
end)
end)
+ describe('nvim_buf_get_text', function()
+ local get_text = curbufmeths.get_text
+
+ it('works', function()
+ insert([[
+ hello foo!
+ text]])
+
+ eq({'hello'}, get_text(0, 0, 0, 5, {}))
+ eq({'hello foo!'}, get_text(0, 0, 0, 42, {}))
+ eq({'foo!'}, get_text(0, 6, 0, 10, {}))
+ eq({'foo!', 'tex'}, get_text(0, 6, 1, 3, {}))
+ eq({'foo!', 'tex'}, get_text(-2, 6, -1, 3, {}))
+ eq({''}, get_text(0, 18, 0, 20, {}))
+ eq({'ext'}, get_text(-1, 1, -1, 4, {}))
+ end)
+
+ it('errors on out-of-range', function()
+ eq(false, pcall(get_text, 2, 0, 3, 0, {}))
+ eq(false, pcall(get_text, 0, 0, 4, 0, {}))
+ end)
+
+ it('errors when start is greater than end', function()
+ eq(false, pcall(get_text, 1, 0, 0, 0, {}))
+ eq(false, pcall(get_text, 0, 1, 0, 0, {}))
+ end)
+ end)
+
describe('nvim_buf_get_offset', function()
local get_offset = curbufmeths.get_offset
it('works', function()
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index c9c9be5406..e9ad756947 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -7,6 +7,7 @@ local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err
local sleep = helpers.sleep
local write_file = helpers.write_file
+local iswin = helpers.iswin
local origlines = {"original line 1",
"original line 2",
@@ -823,7 +824,8 @@ describe('API: buffer events:', function()
end
msg = next_msg()
end
- assert(false, 'did not match/receive expected nvim_buf_lines_event lines')
+ -- FIXME: Windows
+ assert(iswin(), 'did not match/receive expected nvim_buf_lines_event lines')
end
it('when :terminal lines change', function()
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index 6f929ad1ca..b80004f67c 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -6,12 +6,18 @@ local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
local meths = helpers.meths
+local bufmeths = helpers.bufmeths
+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 funcs = helpers.funcs
describe('nvim_get_commands', function()
- local cmd_dict = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='echo "Hello World"', name='Hello', nargs='1', range=NIL, register=false, script_id=0, }
- local cmd_dict2 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='pwd', name='Pwd', nargs='?', range=NIL, register=false, script_id=0, }
+ local cmd_dict = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='echo "Hello World"', name='Hello', nargs='1', range=NIL, register=false, keepscript=false, script_id=0, }
+ local cmd_dict2 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='pwd', name='Pwd', nargs='?', range=NIL, register=false, keepscript=false, script_id=0, }
before_each(clear)
it('gets empty list if no commands were defined', function()
@@ -53,11 +59,11 @@ describe('nvim_get_commands', function()
end)
it('gets various command attributes', function()
- local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', range='10', register=false, script_id=0, }
- local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', range=NIL, register=false, script_id=1, }
- local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', range=NIL, register=false, script_id=2, }
- local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', range=NIL, register=false, script_id=3, }
- local cmd4 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R4_just_great()', name='Cmd4', nargs='0', range=NIL, register=true, script_id=4, }
+ local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', range='10', register=false, keepscript=false, script_id=0, }
+ local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', range=NIL, register=false, keepscript=false, script_id=1, }
+ local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', range=NIL, register=false, keepscript=false, script_id=2, }
+ local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', range=NIL, register=false, keepscript=false, script_id=3, }
+ local cmd4 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R4_just_great()', name='Cmd4', nargs='0', range=NIL, register=true, keepscript=false, script_id=4, }
source([[
command -complete=custom,ListUsers -nargs=+ Finger !finger <args>
]])
@@ -78,3 +84,186 @@ describe('nvim_get_commands', function()
eq({Cmd2=cmd2, Cmd3=cmd3, Cmd4=cmd4, Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false}))
end)
end)
+
+describe('nvim_add_user_command', function()
+ before_each(clear)
+
+ it('works with strings', function()
+ meths.add_user_command('SomeCommand', 'let g:command_fired = <args>', {nargs = 1})
+ meths.command('SomeCommand 42')
+ eq(42, meths.eval('g:command_fired'))
+ end)
+
+ it('works with Lua functions', function()
+ exec_lua [[
+ result = {}
+ vim.api.nvim_add_user_command('CommandWithLuaCallback', function(opts)
+ result = opts
+ end, {
+ nargs = "*",
+ bang = true,
+ count = 2,
+ })
+ ]]
+
+ eq({
+ args = [[hello my\ friend how\ are\ you?]],
+ fargs = {[[hello]], [[my\ friend]], [[how\ are\ you?]]},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = "",
+ range = 0,
+ count = 2,
+ reg = "",
+ }, exec_lua [=[
+ vim.api.nvim_command([[CommandWithLuaCallback hello my\ friend how\ are\ you?]])
+ return result
+ ]=])
+
+ eq({
+ args = 'h\tey',
+ fargs = {[[h]], [[ey]]},
+ bang = true,
+ line1 = 10,
+ line2 = 10,
+ mods = "botright",
+ range = 1,
+ count = 10,
+ reg = "",
+ }, exec_lua [=[
+ vim.api.nvim_command('botright 10CommandWithLuaCallback! h\tey')
+ return result
+ ]=])
+
+ eq({
+ args = "h",
+ fargs = {"h"},
+ bang = false,
+ line1 = 1,
+ line2 = 42,
+ mods = "",
+ range = 1,
+ count = 42,
+ reg = "",
+ }, exec_lua [[
+ vim.api.nvim_command('CommandWithLuaCallback 42 h')
+ return result
+ ]])
+
+ eq({
+ args = "",
+ fargs = {""}, -- fargs works without args
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = "",
+ range = 0,
+ count = 2,
+ reg = "",
+ }, exec_lua [[
+ vim.api.nvim_command('CommandWithLuaCallback')
+ return result
+ ]])
+
+ -- f-args doesn't split when command nargs is 1 or "?"
+ exec_lua [[
+ result = {}
+ vim.api.nvim_add_user_command('CommandWithOneArg', function(opts)
+ result = opts
+ end, {
+ nargs = "?",
+ bang = true,
+ count = 2,
+ })
+ ]]
+
+ eq({
+ args = "hello I'm one argmuent",
+ fargs = {"hello I'm one argmuent"}, -- Doesn't split args
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = "",
+ range = 0,
+ count = 2,
+ reg = "",
+ }, exec_lua [[
+ vim.api.nvim_command('CommandWithOneArg hello I\'m one argmuent')
+ return result
+ ]])
+
+ end)
+
+ it('can define buffer-local commands', function()
+ local bufnr = meths.create_buf(false, false)
+ bufmeths.add_user_command(bufnr, "Hello", "", {})
+ matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
+ meths.set_current_buf(bufnr)
+ meths.command("Hello")
+ assert_alive()
+ end)
+
+ it('can use a Lua complete function', function()
+ exec_lua [[
+ vim.api.nvim_add_user_command('Test', '', {
+ nargs = "*",
+ complete = function(arg, cmdline, pos)
+ local options = {"aaa", "bbb", "ccc"}
+ local t = {}
+ for _, v in ipairs(options) do
+ if string.find(v, "^" .. arg) then
+ table.insert(t, v)
+ end
+ end
+ return t
+ end,
+ })
+ ]]
+
+ feed(':Test a<Tab>')
+ eq('Test aaa', funcs.getcmdline())
+ feed('<C-U>Test b<Tab>')
+ eq('Test bbb', funcs.getcmdline())
+ end)
+
+ it('does not allow invalid command names', function()
+ matches("'name' must begin with an uppercase letter", pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('test', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('t@', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('T@st', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('Test!', 'echo "hi"', {})
+ ]]))
+
+ matches('Invalid command name', pcall_err(exec_lua, [[
+ vim.api.nvim_add_user_command('💩', 'echo "hi"', {})
+ ]]))
+ end)
+end)
+
+describe('nvim_del_user_command', function()
+ before_each(clear)
+
+ it('can delete global commands', function()
+ meths.add_user_command('Hello', 'echo "Hi"', {})
+ meths.command('Hello')
+ meths.del_user_command('Hello')
+ matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
+ end)
+
+ it('can delete buffer-local commands', function()
+ bufmeths.add_user_command(0, 'Hello', 'echo "Hi"', {})
+ meths.command('Hello')
+ bufmeths.del_user_command(0, 'Hello')
+ matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
+ end)
+end)
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index a8f538b951..3f96efd4ef 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -110,6 +110,22 @@ describe('API/extmarks', function()
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
end)
+ it("can end extranges past final newline when strict mode is false", function()
+ set_extmark(ns, marks[1], 0, 0, {
+ end_col = 1,
+ end_row = 1,
+ strict = false,
+ })
+ end)
+
+ it("can end extranges past final column when strict mode is false", function()
+ set_extmark(ns, marks[1], 0, 0, {
+ end_col = 6,
+ end_row = 0,
+ strict = false,
+ })
+ end)
+
it('adds, updates and deletes marks', function()
local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
eq(marks[1], rv)
@@ -1430,7 +1446,60 @@ describe('API/extmarks', function()
end_col = 0,
end_line = 1
})
- eq({ {1, 0, 0, { end_col = 0, end_row = 1 }} }, get_extmarks(ns, 0, -1, {details=true}))
+ eq({ {1, 0, 0, {
+ end_col = 0,
+ end_row = 1,
+ right_gravity = true,
+ end_right_gravity = false,
+ }} }, get_extmarks(ns, 0, -1, {details=true}))
+ end)
+
+ it('can get details', function()
+ set_extmark(ns, marks[1], 0, 0, {
+ end_col = 0,
+ end_row = 1,
+ right_gravity = false,
+ end_right_gravity = true,
+ priority = 0,
+ hl_eol = true,
+ hl_mode = "blend",
+ hl_group = "String",
+ virt_text = { { "text", "Statement" } },
+ virt_text_pos = "right_align",
+ virt_text_hide = true,
+ virt_lines = { { { "lines", "Statement" } }},
+ virt_lines_above = true,
+ virt_lines_leftcol = true,
+ })
+ set_extmark(ns, marks[2], 0, 0, {
+ priority = 0,
+ virt_text = { { "text", "Statement" } },
+ virt_text_win_col = 1,
+ })
+ eq({0, 0, {
+ end_col = 0,
+ end_row = 1,
+ right_gravity = false,
+ end_right_gravity = true,
+ priority = 0,
+ hl_eol = true,
+ hl_mode = "blend",
+ hl_group = "String",
+ virt_text = { { "text", "Statement" } },
+ virt_text_pos = "right_align",
+ virt_text_hide = true,
+ virt_lines = { { { "lines", "Statement" } }},
+ virt_lines_above = true,
+ virt_lines_leftcol = true,
+ } }, get_extmark_by_id(ns, marks[1], { details = true }))
+ eq({0, 0, {
+ right_gravity = true,
+ priority = 0,
+ virt_text = { { "text", "Statement" } },
+ virt_text_hide = false,
+ virt_text_pos = "win_col",
+ virt_text_win_col = 1,
+ } }, get_extmark_by_id(ns, marks[2], { details = true }))
end)
end)
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index 21e3094f8e..443689754c 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -3,6 +3,7 @@ local clear, nvim = helpers.clear, helpers.nvim
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 meths = helpers.meths
local funcs = helpers.funcs
local pcall_err = helpers.pcall_err
@@ -194,10 +195,12 @@ describe("API: set highlight", function()
reverse = true,
undercurl = true,
underline = true,
+ strikethrough = true,
cterm = {
italic = true,
reverse = true,
undercurl = true,
+ strikethrough = true,
}
}
local highlight3_result_gui = {
@@ -208,6 +211,7 @@ describe("API: set highlight", function()
reverse = true,
undercurl = true,
underline = true,
+ strikethrough = true,
}
local highlight3_result_cterm = {
background = highlight_color.ctermbg,
@@ -215,6 +219,7 @@ describe("API: set highlight", function()
italic = true,
reverse = true,
undercurl = true,
+ strikethrough = true,
}
local function get_ns()
@@ -237,6 +242,12 @@ describe("API: set highlight", function()
eq(highlight2_result, meths.get_hl_by_name('Test_hl', false))
end)
+ it ("can set emtpy cterm attr", function()
+ local ns = get_ns()
+ meths.set_hl(ns, 'Test_hl', { cterm = {} })
+ eq({}, meths.get_hl_by_name('Test_hl', false))
+ end)
+
it ("cterm attr defaults to gui attr", function()
local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight1)
@@ -252,4 +263,69 @@ describe("API: set highlight", function()
eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true))
eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false))
end)
+
+ it ("can set a highlight in the global namespace", function()
+ meths.set_hl(0, 'Test_hl', highlight2_config)
+ eq('Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse',
+ exec_capture('highlight Test_hl'))
+
+ meths.set_hl(0, 'Test_hl', { background = highlight_color.bg })
+ eq('Test_hl xxx guibg=#0032aa',
+ exec_capture('highlight Test_hl'))
+
+ meths.set_hl(0, 'Test_hl2', highlight3_config)
+ eq('Test_hl2 xxx cterm=undercurl,italic,reverse,strikethrough ctermfg=8 ctermbg=15 gui=bold,underline,undercurl,italic,reverse,strikethrough guifg=#ff0000 guibg=#0032aa',
+ exec_capture('highlight Test_hl2'))
+
+ -- Colors are stored exactly as they are defined.
+ meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue'})
+ eq('Test_hl3 xxx guifg=bLue guibg=reD',
+ exec_capture('highlight Test_hl3'))
+ end)
+
+ it ("can modify a highlight in the global namespace", function()
+ meths.set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue'})
+ eq('Test_hl3 xxx guifg=blue guibg=red',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { bg = 'red' })
+ eq('Test_hl3 xxx guibg=red',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12})
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 'red' , ctermfg = 'blue'})
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ meths.set_hl(0, 'Test_hl3', { ctermbg = 9 })
+ eq('Test_hl3 xxx ctermbg=9',
+ exec_capture('highlight Test_hl3'))
+
+ eq("'redd' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'}))
+
+ eq("'bleu' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'}))
+
+ meths.set_hl(0, 'Test_hl3', {fg='#FF00FF'})
+ eq('Test_hl3 xxx guifg=#FF00FF',
+ exec_capture('highlight Test_hl3'))
+
+ eq("'#FF00FF' is not a valid color",
+ pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'}))
+
+ for _, fg_val in ipairs{ nil, 'NONE', 'nOnE', '', -1 } do
+ meths.set_hl(0, 'Test_hl3', {fg = fg_val})
+ eq('Test_hl3 xxx cleared',
+ exec_capture('highlight Test_hl3'))
+ end
+
+ meths.set_hl(0, 'Test_hl3', {fg='#FF00FF', blend=50})
+ eq('Test_hl3 xxx guifg=#FF00FF blend=50',
+ exec_capture('highlight Test_hl3'))
+
+ end)
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index dd8eef7ca0..c0edcde476 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -5,6 +5,7 @@ local clear = helpers.clear
local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq, neq = helpers.eq, helpers.neq
+local exec_lua = helpers.exec_lua
local feed = helpers.feed
local funcs = helpers.funcs
local meths = helpers.meths
@@ -14,6 +15,9 @@ local pcall_err = helpers.pcall_err
local shallowcopy = helpers.shallowcopy
local sleep = helpers.sleep
+local sid_api_client = -9
+local sid_lua = -8
+
describe('nvim_get_keymap', function()
before_each(clear)
@@ -316,6 +320,55 @@ describe('nvim_get_keymap', function()
command('nnoremap \\|<Char-0x20><Char-32><Space><Bar> \\|<Char-0x20><Char-32><Space> <Bar>')
eq({space_table}, meths.get_keymap('n'))
end)
+
+ it('can handle lua keymaps', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+ eq(1, exec_lua[[return GlobalCount]])
+
+ eq(2, exec_lua[[
+ vim.api.nvim_get_keymap('n')[1].callback()
+ return GlobalCount
+ ]])
+ local mapargs = meths.get_keymap('n')
+ assert.Truthy(type(mapargs[1].callback) == 'number', 'callback is not luaref number')
+ mapargs[1].callback = nil
+ eq({
+ lhs='asdf',
+ script=0,
+ silent=0,
+ expr=0,
+ sid=sid_lua,
+ buffer=0,
+ nowait=0,
+ mode='n',
+ noremap=0,
+ lnum=0,
+ }, mapargs[1])
+ end)
+
+ it ('can handle map descriptions', function()
+ meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
+ eq({
+ lhs='lhs',
+ rhs='rhs',
+ script=0,
+ silent=0,
+ expr=0,
+ sid=sid_api_client,
+ buffer=0,
+ nowait=0,
+ mode='n',
+ noremap=0,
+ lnum=0,
+ desc='map description'
+ }, meths.get_keymap('n')[1])
+ end)
end)
describe('nvim_set_keymap, nvim_del_keymap', function()
@@ -350,9 +403,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
to_return.silent = not opts.silent and 0 or 1
to_return.nowait = not opts.nowait and 0 or 1
to_return.expr = not opts.expr and 0 or 1
- to_return.sid = not opts.sid and 0 or opts.sid
+ to_return.sid = not opts.sid and sid_api_client or opts.sid
to_return.buffer = not opts.buffer and 0 or opts.buffer
to_return.lnum = not opts.lnum and 0 or opts.lnum
+ to_return.desc = opts.desc
return to_return
end
@@ -574,7 +628,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('interprets control sequences in expr-quotes correctly when called '
..'inside vim', function()
command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
- eq(generate_mapargs('i', '<Space>', '\t', {}),
+ eq(generate_mapargs('i', '<Space>', '\t', {sid=0}),
get_mapargs('i', '<Space>'))
feed('i ')
eq({'\t'}, curbufmeths.get_lines(0, -1, 0))
@@ -717,6 +771,115 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
end
end
+
+ it('can make lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ end)
+
+ it (':map command shows lua keymap correctly', function()
+ exec_lua [[
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
+ ]]
+ assert.truthy(string.match(exec_lua[[return vim.api.nvim_exec(':nmap asdf', true)]],
+ "^\nn asdf <Lua function %d+>"))
+ end)
+
+ it ('mapcheck() returns lua keymap correctly', function()
+ exec_lua [[
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
+ ]]
+ assert.truthy(string.match(funcs.mapcheck('asdf', 'n'),
+ "^<Lua function %d+>"))
+ end)
+
+ it ('maparg() returns lua keymap correctly', function()
+ exec_lua [[
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
+ ]]
+ assert.truthy(string.match(funcs.maparg('asdf', 'n'),
+ "^<Lua function %d+>"))
+ local mapargs = funcs.maparg('asdf', 'n', false, true)
+ assert.Truthy(type(mapargs.callback) == 'number', 'callback is not luaref number')
+ mapargs.callback = nil
+ eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs)
+ end)
+
+ it('can make lua expr mappings', function()
+ exec_lua [[
+ vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true })
+ ]]
+
+ feed('aa')
+
+ eq(99, exec_lua[[return SomeValue]])
+ end)
+
+ it('does not reset pum in lua mapping', function()
+ eq(0, exec_lua [[
+ VisibleCount = 0
+ vim.api.nvim_set_keymap ('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
+ return VisibleCount
+ ]])
+ feed('i<C-X><C-V><F2><F2><esc>')
+ eq(2, exec_lua[[return VisibleCount]])
+ end)
+
+ it('can overwrite lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
+ ]]
+
+ feed('asdf\n')
+
+ eq(0, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can unmap lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ 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'))
+ end)
+
+ it('can set descriptions on keymaps', function()
+ meths.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"))
+ end)
end)
describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
@@ -814,4 +977,67 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
helpers.assert_alive()
end)
+
+ it('can make lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can make lua expr mappings', function()
+ exec_lua [[
+ vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true })
+ ]]
+
+ feed('aa')
+
+ eq(99, exec_lua[[return SomeValue ]])
+ end)
+
+ it('can overwrite lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
+ ]]
+
+ feed('asdf\n')
+
+ eq(0, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can unmap lua mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ 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'))
+ end)
end)
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 309d9084c8..cdcf08c348 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -181,12 +181,6 @@ describe('server -> client', function()
end)
describe('recursive (child) nvim client', function()
- if helpers.isCI('travis') and helpers.is_os('mac') then
- -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis macOS. #5002]", function() end)
- return
- end
-
before_each(function()
command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])")
neq(0, eval('vim'))
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 22201e21a2..71cd055e08 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -23,6 +23,7 @@ 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 pcall_err = helpers.pcall_err
local format_string = helpers.format_string
@@ -333,6 +334,7 @@ describe('API', function()
describe('nvim_command_output', function()
it('does not induce hit-enter prompt', function()
+ nvim("ui_attach", 80, 20, {})
-- Induce a hit-enter prompt use nvim_input (non-blocking).
nvim('command', 'set cmdheight=1')
nvim('input', [[:echo "hi\nhi2"<CR>]])
@@ -535,6 +537,31 @@ describe('API', function()
end)
end)
+ describe('nvim_set_current_dir', function()
+ local start_dir
+
+ before_each(function()
+ clear()
+ funcs.mkdir("Xtestdir")
+ start_dir = funcs.getcwd()
+ end)
+
+ after_each(function()
+ helpers.rmdir("Xtestdir")
+ end)
+
+ it('works', function()
+ meths.set_current_dir("Xtestdir")
+ eq(funcs.getcwd(), start_dir .. helpers.get_pathsep() .. "Xtestdir")
+ end)
+
+ it('sets previous directory', function()
+ meths.set_current_dir("Xtestdir")
+ meths.exec('cd -', false)
+ eq(funcs.getcwd(), start_dir)
+ end)
+ end)
+
describe('nvim_exec_lua', function()
it('works', function()
meths.exec_lua('vim.api.nvim_set_var("test", 3)', {})
@@ -872,6 +899,19 @@ describe('API', function()
command('lockvar lua')
eq('Key is locked: lua', pcall_err(meths.del_var, 'lua'))
eq('Key is locked: lua', pcall_err(meths.set_var, 'lua', 1))
+
+ -- Check if autoload works properly
+ local pathsep = helpers.get_pathsep()
+ local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
+ local xdata = 'Xhome' .. pathsep .. 'Xdata'
+ local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep)
+ local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep)
+ mkdir_p(autoload_folder)
+ write_file(autoload_file , [[let testload#value = 2]])
+
+ clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } }
+ eq(2, meths.get_var('testload#value'))
+ rmdir('Xhome')
end)
it('nvim_get_vvar, nvim_set_vvar', function()
@@ -1093,7 +1133,20 @@ describe('API', function()
eq({mode='n', blocking=false}, nvim("get_mode"))
end)
+ it("during press-enter prompt without UI returns blocking=false", function()
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ command("echom 'msg1'")
+ command("echom 'msg2'")
+ command("echom 'msg3'")
+ command("echom 'msg4'")
+ command("echom 'msg5'")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ nvim("input", ":messages<CR>")
+ eq({mode='n', blocking=false}, nvim("get_mode"))
+ end)
+
it("during press-enter prompt returns blocking=true", function()
+ nvim("ui_attach", 80, 20, {})
eq({mode='n', blocking=false}, nvim("get_mode"))
command("echom 'msg1'")
command("echom 'msg2'")
@@ -1117,6 +1170,7 @@ describe('API', function()
-- TODO: bug #6247#issuecomment-286403810
it("batched with input", function()
+ nvim("ui_attach", 80, 20, {})
eq({mode='n', blocking=false}, nvim("get_mode"))
command("echom 'msg1'")
command("echom 'msg2'")
@@ -1367,18 +1421,18 @@ describe('API', function()
end)
describe('nvim_feedkeys', function()
- it('CSI escaping', function()
+ it('K_SPECIAL escaping', function()
local function on_setup()
-- notice the special char(…) \xe2\80\xa6
nvim('feedkeys', ':let x1="…"\n', '', true)
-- Both nvim_replace_termcodes and nvim_feedkeys escape \x80
local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true)
- nvim('feedkeys', inp, '', true) -- escape_csi=true
+ nvim('feedkeys', inp, '', true) -- escape_ks=true
- -- nvim_feedkeys with CSI escaping disabled
+ -- nvim_feedkeys with K_SPECIAL escaping disabled
inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true)
- nvim('feedkeys', inp, '', false) -- escape_csi=false
+ nvim('feedkeys', inp, '', false) -- escape_ks=false
helpers.stop()
end
@@ -2187,6 +2241,14 @@ describe('API', function()
eq({}, meths.get_runtime_file("foobarlang/", true))
end)
+ it('can handle bad patterns', function()
+ if helpers.pending_win32(pending) then return end
+
+ eq("Vim:E220: Missing }.", pcall_err(meths.get_runtime_file, "{", false))
+
+ eq('Vim(echo):E5555: API call: Vim:E220: Missing }.',
+ exc_exec("echo nvim_get_runtime_file('{', v:false)"))
+ end)
end)
describe('nvim_get_all_options_info', function()
@@ -2551,6 +2613,34 @@ describe('API', function()
'Should be truncated%<',
{ maxwidth = 15 }))
end)
+ it('supports ASCII fillchar', function()
+ eq({ str = 'a~~~b', width = 5 },
+ meths.eval_statusline('a%=b', { fillchar = '~', maxwidth = 5 }))
+ end)
+ it('supports single-width multibyte fillchar', function()
+ eq({ str = 'a━━━b', width = 5 },
+ meths.eval_statusline('a%=b', { fillchar = '━', maxwidth = 5 }))
+ end)
+ it('rejects double-width fillchar', function()
+ eq('fillchar must be a single-width character',
+ pcall_err(meths.eval_statusline, '', { fillchar = '哦' }))
+ end)
+ it('rejects control character fillchar', function()
+ eq('fillchar must be a single-width character',
+ pcall_err(meths.eval_statusline, '', { fillchar = '\a' }))
+ end)
+ it('rejects multiple-character fillchar', function()
+ eq('fillchar must be a single-width character',
+ pcall_err(meths.eval_statusline, '', { fillchar = 'aa' }))
+ end)
+ it('rejects empty string fillchar', function()
+ eq('fillchar must be a single-width character',
+ pcall_err(meths.eval_statusline, '', { fillchar = '' }))
+ end)
+ it('rejects non-string fillchar', function()
+ eq('fillchar must be a single-width character',
+ pcall_err(meths.eval_statusline, '', { fillchar = 1 }))
+ end)
describe('highlight parsing', function()
it('works', function()
eq({
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 4d2ffa316a..c31ab2060a 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf,
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
@@ -73,8 +74,7 @@ describe('API/win', function()
eq('typing\n some dumb text', curbuf_contents())
end)
- it('does not leak memory when using invalid window ID with invalid pos',
- function()
+ it('does not leak memory when using invalid window ID with invalid pos', function()
eq('Invalid window id: 1', pcall_err(meths.win_set_cursor, 1, {"b\na"}))
end)
@@ -147,6 +147,46 @@ describe('API/win', function()
eq({2, 5}, window('get_cursor', win))
end)
+ it('updates cursorline and statusline ruler in non-current window', function()
+ local screen = Screen.new(60, 8)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [2] = {background = Screen.colors.Grey90}, -- CursorLine
+ [3] = {bold = true, reverse = true}, -- StatusLine
+ [4] = {reverse = true}, -- VertSplit, StatusLineNC
+ })
+ screen:attach()
+ command('set ruler')
+ command('set cursorline')
+ insert([[
+ aaa
+ bbb
+ ccc
+ ddd]])
+ local oldwin = curwin()
+ command('vsplit')
+ screen:expect([[
+ aaa {4:│}aaa |
+ bbb {4:│}bbb |
+ ccc {4:│}ccc |
+ {2:dd^d }{4:│}{2:ddd }|
+ {1:~ }{4:│}{1:~ }|
+ {1:~ }{4:│}{1:~ }|
+ {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 4,3 All}|
+ |
+ ]])
+ window('set_cursor', oldwin, {1, 0})
+ screen:expect([[
+ aaa {4:│}{2:aaa }|
+ bbb {4:│}bbb |
+ ccc {4:│}ccc |
+ {2:dd^d }{4:│}ddd |
+ {1:~ }{4:│}{1:~ }|
+ {1:~ }{4:│}{1:~ }|
+ {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 1,1 All}|
+ |
+ ]])
+ end)
end)
describe('{get,set}_height', function()
diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua
new file mode 100644
index 0000000000..ad3687d7b0
--- /dev/null
+++ b/test/functional/autocmd/autocmd_oldtest_spec.lua
@@ -0,0 +1,86 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local meths = helpers.meths
+local funcs = helpers.funcs
+
+local exec = function(str)
+ meths.exec(str, false)
+end
+
+describe('oldtests', function()
+ before_each(clear)
+
+ local exec_lines = function(str)
+ return funcs.split(funcs.execute(str), "\n")
+ end
+
+ local add_an_autocmd = function()
+ exec [[
+ augroup vimBarTest
+ au BufReadCmd * echo 'hello'
+ augroup END
+ ]]
+
+ eq(3, #exec_lines('au vimBarTest'))
+ eq(1, #meths.get_autocmds({ group = 'vimBarTest' }))
+ end
+
+ it('should recognize a bar before the {event}', function()
+ -- Good spacing
+ add_an_autocmd()
+ exec [[ augroup vimBarTest | au! | augroup END ]]
+ eq(1, #exec_lines('au vimBarTest'))
+ eq({}, meths.get_autocmds({ group = 'vimBarTest' }))
+
+ -- Sad spacing
+ add_an_autocmd()
+ exec [[ augroup vimBarTest| au!| augroup END ]]
+ eq(1, #exec_lines('au vimBarTest'))
+
+
+ -- test that a bar is recognized after the {event}
+ add_an_autocmd()
+ exec [[ augroup vimBarTest| au!BufReadCmd| augroup END ]]
+ eq(1, #exec_lines('au vimBarTest'))
+
+ add_an_autocmd()
+ exec [[ au! vimBarTest|echo 'hello' ]]
+ eq(1, #exec_lines('au vimBarTest'))
+ end)
+
+ it('should fire on unload buf', function()
+ funcs.writefile({'Test file Xxx1'}, 'Xxx1')
+ funcs.writefile({'Test file Xxx2'}, 'Xxx2')
+
+ local content = [[
+ func UnloadAllBufs()
+ let i = 1
+ while i <= bufnr('$')
+ if i != bufnr('%') && bufloaded(i)
+ exe i . 'bunload'
+ endif
+ let i += 1
+ endwhile
+ endfunc
+ au BufUnload * call UnloadAllBufs()
+ au VimLeave * call writefile(['Test Finished'], 'Xout')
+ set nohidden
+ edit Xxx1
+ split Xxx2
+ q
+ ]]
+
+ funcs.writefile(funcs.split(content, "\n"), 'Xtest')
+
+ funcs.delete('Xout')
+ funcs.system(meths.get_vvar('progpath') .. ' -u NORC -i NONE -N -S Xtest')
+ eq(1, funcs.filereadable('Xout'))
+
+ funcs.delete('Xxx1')
+ funcs.delete('Xxx2')
+ funcs.delete('Xtest')
+ funcs.delete('Xout')
+ end)
+end)
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 93d71a9e45..f37f04b32f 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -2,8 +2,10 @@ local helpers = require('test.functional.helpers')(after_each)
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
@@ -13,6 +15,7 @@ local funcs = helpers.funcs
local expect = helpers.expect
local command = helpers.command
local exc_exec = helpers.exc_exec
+local exec_lua = helpers.exec_lua
local curbufmeths = helpers.curbufmeths
local source = helpers.source
@@ -333,6 +336,68 @@ describe('autocmd', function()
pcall_err(command, "call nvim_set_current_win(g:winid)"))
end)
+ it("`aucmd_win` cannot be changed into a normal window #13699", function()
+ local screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {reverse = true},
+ [3] = {bold = true, reverse = true},
+ }
+
+ -- Create specific layout and ensure it's left unchanged.
+ -- Use nvim_buf_call on a hidden buffer so aucmd_win is used.
+ exec_lua [[
+ vim.cmd "wincmd s | wincmd _"
+ _G.buf = vim.api.nvim_create_buf(true, true)
+ vim.api.nvim_buf_call(_G.buf, function() vim.cmd "wincmd J" end)
+ ]]
+ screen:expect [[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ ]]
+ -- This used to crash after making aucmd_win a normal window via the above.
+ exec_lua [[
+ vim.cmd "tabnew | tabclose # | wincmd s | wincmd _"
+ vim.api.nvim_buf_call(_G.buf, function() vim.cmd "wincmd K" end)
+ ]]
+ assert_alive()
+ 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 [[
+ ^ |
+ {1:~ }|
+ {3:[No Name] }|
+ |
+ {1:~ }|
+ {2:[Scratch] }|
+ |
+ {1:~ }|
+ {2:[No Name] }|
+ |
+ ]]
+
+ -- After all of our messing around, aucmd_win should still be floating.
+ -- Use :only to ensure _G.buf is hidden again (so the aucmd_win is used).
+ 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
+ ]])
+ end)
+
it(':doautocmd does not warn "No matching autocommands" #10689', function()
local screen = Screen.new(32, 3)
screen:attach()
@@ -354,4 +419,106 @@ describe('autocmd', function()
:doautocmd SessionLoadPost |
]]}
end)
+
+ describe('old_tests', function()
+ it('vimscript: WinNew ++once', function()
+ source [[
+ " Without ++once WinNew triggers twice
+ let g:did_split = 0
+ augroup Testing
+ au!
+ au WinNew * let g:did_split += 1
+ augroup END
+ split
+ split
+ call assert_equal(2, g:did_split)
+ call assert_true(exists('#WinNew'))
+ close
+ close
+
+ " With ++once WinNew triggers once
+ let g:did_split = 0
+ augroup Testing
+ au!
+ au WinNew * ++once let g:did_split += 1
+ augroup END
+ split
+ split
+ call assert_equal(1, g:did_split)
+ call assert_false(exists('#WinNew'))
+ close
+ close
+
+ call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
+ ]]
+
+ meths.set_var('did_split', 0)
+
+ source [[
+ augroup Testing
+ au!
+ au WinNew * let g:did_split += 1
+ augroup END
+
+ split
+ split
+ ]]
+
+ eq(2, meths.get_var('did_split'))
+ eq(1, funcs.exists('#WinNew'))
+
+ -- Now with once
+ meths.set_var('did_split', 0)
+
+ source [[
+ augroup Testing
+ au!
+ au WinNew * ++once let g:did_split += 1
+ augroup END
+
+ split
+ split
+ ]]
+
+ eq(1, meths.get_var('did_split'))
+ eq(0, funcs.exists('#WinNew'))
+
+ -- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
+ local ok, msg = pcall(source, [[
+ au WinNew * ++once ++once echo bad
+ ]])
+
+ eq(false, ok)
+ eq(true, not not string.find(msg, 'E983:'))
+ end)
+
+ it('should have autocmds in filetypedetect group', function()
+ source [[filetype on]]
+ neq({}, meths.get_autocmds { group = "filetypedetect" })
+ end)
+
+ it('should not access freed mem', function()
+ source [[
+ au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
+ arg 0
+ argadd
+ all
+ all
+ au!
+ bwipe xxx
+ ]]
+ end)
+
+ it('should allow comma-separated patterns', function()
+ source [[
+ augroup TestingPatterns
+ au!
+ autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
+ autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
+ augroup END
+ ]]
+
+ eq(4, #meths.get_autocmds { event = "BufReadCmd", group = "TestingPatterns" })
+ end)
+ end)
end)
diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua
index 9641d4b096..85d8628d7e 100644
--- a/test/functional/autocmd/cursormoved_spec.lua
+++ b/test/functional/autocmd/cursormoved_spec.lua
@@ -35,6 +35,7 @@ describe('CursorMoved', function()
it("is not triggered by cursor movement prior to first CursorMoved instantiation", function()
source([[
let g:cursormoved = 0
+ autocmd! CursorMoved
autocmd CursorMoved * let g:cursormoved += 1
]])
eq(0, eval('g:cursormoved'))
diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua
index f4a1642ebf..45dc06b39b 100644
--- a/test/functional/autocmd/dirchanged_spec.lua
+++ b/test/functional/autocmd/dirchanged_spec.lua
@@ -8,7 +8,7 @@ local eval = h.eval
local request = h.request
local iswin = h.iswin
-describe('autocmd DirChanged', function()
+describe('autocmd DirChanged and DirChangedPre', function()
local curdir = string.gsub(lfs.currentdir(), '\\', '/')
local dirs = {
curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
@@ -26,31 +26,43 @@ describe('autocmd DirChanged', function()
before_each(function()
clear()
+ command('autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
+ ..'= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]')
command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] '
- ..' = [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]')
+ ..'= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]')
-- Normalize path separators.
+ command([[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]])
command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]])
- command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
+ command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
end)
- it('sets v:event and <amatch>', function()
+ it('set v:event and <amatch>', function()
command('lcd '..dirs[1])
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
command('tcd '..dirs[2])
+ eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
command('cd '..dirs[3])
+ eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ eq('global', eval('g:amatchpre'))
eq('global', eval('g:amatch'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
end)
- it('sets getcwd() during event #6260', function()
+ it('DirChanged set getcwd() during event #6260', function()
command('lcd '..dirs[1])
eq(dirs[1], eval('g:getcwd'))
@@ -61,7 +73,7 @@ describe('autocmd DirChanged', function()
eq(dirs[3], eval('g:getcwd'))
end)
- it('disallows recursion', function()
+ it('disallow recursion', function()
command('set shellslash')
-- Set up a _nested_ handler.
command('autocmd DirChanged * nested lcd '..dirs[3])
@@ -72,23 +84,36 @@ describe('autocmd DirChanged', function()
eq(dirs[3], eval('getcwd()'))
end)
- it('does not trigger if :cd fails', function()
+ it('only DirChangedPre is triggered if :cd fails', function()
command('let g:ev = {}')
+ command('let g:cdcount = 0')
local status1, err1 = pcall(function()
- command('lcd '..dirs[1] .. '/doesnotexist')
+ command('lcd '..dirs[1]..'/doesnotexist')
end)
+ eq({directory=dirs[1]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(1, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
local status2, err2 = pcall(function()
- command('lcd '..dirs[2] .. '/doesnotexist')
+ command('lcd '..dirs[2]..'/doesnotexist')
end)
+ eq({directory=dirs[2]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(2, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
local status3, err3 = pcall(function()
- command('lcd '..dirs[3] .. '/doesnotexist')
+ command('lcd '..dirs[3]..'/doesnotexist')
end)
+ eq({directory=dirs[3]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
+ eq(3, eval('g:cdprecount'))
+ eq(0, eval('g:cdcount'))
eq(false, status1)
eq(false, status2)
@@ -99,85 +124,121 @@ describe('autocmd DirChanged', function()
eq('E344:', string.match(err3, "E%d*:"))
end)
- it("is triggered by 'autochdir'", function()
+ it("are triggered by 'autochdir'", function()
command('set autochdir')
command('split '..dirs[1]..'/foo')
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
+ eq(1, eval('g:cdcount'))
command('split '..dirs[2]..'/bar')
+ eq({directory=dirs[2], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=false}, eval('g:ev'))
eq('auto', eval('g:amatch'))
-
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end)
- it('does not trigger if directory has not changed', function()
+ it('do not trigger if directory has not changed', function()
command('lcd '..dirs[1])
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('lcd '..dirs[1])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
if iswin() then
command('lcd '..win_dirs[1])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
end
command('tcd '..dirs[2])
+ eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('tcd '..dirs[2])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
if iswin() then
command('tcd '..win_dirs[2])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end
command('cd '..dirs[3])
+ eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
eq('global', eval('g:amatch'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('cd '..dirs[3])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
if iswin() then
command('cd '..win_dirs[3])
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
end
command('set autochdir')
command('split '..dirs[1]..'/foo')
+ eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
+ command('let g:evpre = {}')
command('let g:ev = {}')
command('split '..dirs[1]..'/bar')
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
if iswin() then
command('split '..win_dirs[1]..'/baz')
+ eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
end
end)
- it("is triggered by switching to win/tab with different CWD #6054", function()
+ it("are triggered by switching to win/tab with different CWD #6054", function()
command('lcd '..dirs[3]) -- window 3
command('split '..dirs[2]..'/foo') -- window 2
command('lcd '..dirs[2])
@@ -185,72 +246,105 @@ describe('autocmd DirChanged', function()
command('lcd '..dirs[1])
command('2wincmd w') -- window 2
+ eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
+ eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
command('tabnew') -- tab 2 (tab-local CWD)
+ eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tcd '..dirs[3])
command('tabnext') -- tab 1 (no tab-local CWD)
+ eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
command('tabnext') -- tab 2
+ eq({directory=dirs[3], scope='tabpage', changed_window=true}, eval('g:evpre'))
eq({cwd=dirs[3], scope='tabpage', changed_window=true}, eval('g:ev'))
+ eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
+ eq(7, eval('g:cdprecount'))
eq(7, eval('g:cdcount'))
command('tabnext') -- tab 1
command('3wincmd w') -- window 3
+ eq(9, eval('g:cdprecount'))
eq(9, eval('g:cdcount'))
command('tabnext') -- tab 2 (has the *same* CWD)
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
if iswin() then
command('tabnew') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tcd '..win_dirs[3])
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('lcd '..win_dirs[3]) -- window 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
end
end)
- it('is triggered by nvim_set_current_dir()', function()
+ it('are triggered by nvim_set_current_dir()', function()
request('nvim_set_current_dir', dirs[1])
+ eq({directory=dirs[1], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[1], scope='global', changed_window=false}, eval('g:ev'))
+ eq(1, eval('g:cdprecount'))
+ eq(1, eval('g:cdcount'))
request('nvim_set_current_dir', dirs[2])
+ eq({directory=dirs[2], scope='global', changed_window=false}, eval('g:evpre'))
eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev'))
+ eq(2, eval('g:cdprecount'))
+ eq(2, eval('g:cdcount'))
local status, err = pcall(function()
request('nvim_set_current_dir', '/doesnotexist')
end)
eq(false, status)
eq('Failed to change directory', string.match(err, ': (.*)'))
- eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev'))
+ eq({directory='/doesnotexist', scope='global', changed_window=false}, eval('g:evpre'))
+ eq(3, eval('g:cdprecount'))
+ eq(2, eval('g:cdcount'))
end)
- it('works when local to buffer', function()
+ it('work when local to buffer', function()
+ command('let g:triggeredpre = 0')
command('let g:triggered = 0')
+ command('autocmd DirChangedPre <buffer> let g:triggeredpre = 1')
command('autocmd DirChanged <buffer> let g:triggered = 1')
command('cd '..dirs[1])
+ eq(1, eval('g:triggeredpre'))
eq(1, eval('g:triggered'))
end)
end)
diff --git a/test/functional/autocmd/focus_spec.lua b/test/functional/autocmd/focus_spec.lua
index 3f9a0ad09b..e3c9e1f9ee 100644
--- a/test/functional/autocmd/focus_spec.lua
+++ b/test/functional/autocmd/focus_spec.lua
@@ -56,7 +56,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
line 3 |
line 4 |
{5:xtest-foo }|
- "xtest-foo" 4L, 28C |
+ "xtest-foo" 4L, 28B |
{3:-- TERMINAL --} |
]]}
end)
diff --git a/test/functional/autocmd/recording_spec.lua b/test/functional/autocmd/recording_spec.lua
index 81152758de..b9aec774f1 100644
--- a/test/functional/autocmd/recording_spec.lua
+++ b/test/functional/autocmd/recording_spec.lua
@@ -11,7 +11,7 @@ describe('RecordingEnter', function()
source_vim [[
let g:recorded = 0
autocmd RecordingEnter * let g:recorded += 1
- execute "normal! qqyyq"
+ call feedkeys("qqyyq", 'xt')
]]
eq(1, eval('g:recorded'))
end)
@@ -20,7 +20,7 @@ describe('RecordingEnter', function()
source_vim [[
let g:recording = ''
autocmd RecordingEnter * let g:recording = reg_recording()
- execute "normal! qqyyq"
+ call feedkeys("qqyyq", 'xt')
]]
eq('q', eval('g:recording'))
end)
@@ -32,7 +32,7 @@ describe('RecordingLeave', function()
source_vim [[
let g:recorded = 0
autocmd RecordingLeave * let g:recorded += 1
- execute "normal! qqyyq"
+ call feedkeys("qqyyq", 'xt')
]]
eq(1, eval('g:recorded'))
end)
@@ -43,10 +43,30 @@ describe('RecordingLeave', function()
let g:recording = ''
autocmd RecordingLeave * let g:recording = reg_recording()
autocmd RecordingLeave * let g:recorded = reg_recorded()
- execute "normal! qqyyq"
+ call feedkeys("qqyyq", 'xt')
]]
eq('q', eval 'g:recording')
eq('', eval 'g:recorded')
eq('q', eval 'reg_recorded()')
end)
+
+ it('populates v:event', function()
+ source_vim [[
+ let g:regname = ''
+ let g:regcontents = ''
+ autocmd RecordingLeave * let g:regname = v:event.regname
+ autocmd RecordingLeave * let g:regcontents = v:event.regcontents
+ call feedkeys("qqyyq", 'xt')
+ ]]
+ eq('q', eval 'g:regname')
+ eq('yy', eval 'g:regcontents')
+ end)
+
+ it('resets v:event', function()
+ source_vim [[
+ autocmd RecordingLeave * let g:event = v:event
+ call feedkeys("qqyyq", 'xt')
+ ]]
+ eq(0, eval 'len(v:event)')
+ end)
end)
diff --git a/test/functional/autocmd/show_spec.lua b/test/functional/autocmd/show_spec.lua
new file mode 100644
index 0000000000..59757a7d61
--- /dev/null
+++ b/test/functional/autocmd/show_spec.lua
@@ -0,0 +1,35 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local command = helpers.command
+local dedent = helpers.dedent
+local eq = helpers.eq
+local funcs = helpers.funcs
+
+describe(":autocmd", function()
+ before_each(clear)
+
+ it("should not segfault when you just do autocmd", function()
+ command ":autocmd"
+ end)
+
+ it("should filter based on ++once", function()
+ command "autocmd! BufEnter"
+ command "autocmd BufEnter * :echo 'Hello'"
+ command [[augroup TestingOne]]
+ command [[ autocmd BufEnter * :echo "Line 1"]]
+ command [[ autocmd BufEnter * :echo "Line 2"]]
+ command [[augroup END]]
+
+ eq(dedent([[
+
+ --- Autocommands ---
+ BufEnter
+ * :echo 'Hello'
+ TestingOne BufEnter
+ * :echo "Line 1"
+ :echo "Line 2"]]),
+ funcs.execute('autocmd BufEnter'))
+
+ end)
+end)
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index 1e8f981437..bc7a6d6c36 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -32,7 +32,7 @@ describe('autocmd TermClose', function()
retry(nil, nil, function() eq(23, eval('g:test_termclose')) end)
end)
- it('kills job trapping SIGTERM', function()
+ pending('kills job trapping SIGTERM', function()
if iswin() then return end
nvim('set_option', 'shell', 'sh')
nvim('set_option', 'shellcmdflag', '-c')
@@ -52,7 +52,7 @@ describe('autocmd TermClose', function()
ok(duration <= 4000) -- Epsilon for slow CI
end)
- it('kills PTY job trapping SIGHUP and SIGTERM', function()
+ pending('kills PTY job trapping SIGHUP and SIGTERM', function()
if iswin() then return end
nvim('set_option', 'shell', 'sh')
nvim('set_option', 'shellcmdflag', '-c')
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 93dec9fb35..c28300f0f4 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -100,6 +100,38 @@ describe('channels', function()
eq({"notification", "exit", {3,0}}, next_msg())
end)
+ it('can use stdio channel and on_print callback', function()
+ source([[
+ let g:job_opts = {
+ \ 'on_stdout': function('OnEvent'),
+ \ 'on_stderr': function('OnEvent'),
+ \ 'on_exit': function('OnEvent'),
+ \ }
+ ]])
+ meths.set_var("nvim_prog", nvim_prog)
+ meths.set_var("code", [[
+ function! OnStdin(id, data, event) dict
+ echo string([a:id, a:data, a:event])
+ if a:data == ['']
+ quit
+ endif
+ endfunction
+ function! OnPrint(text) dict
+ call chansend(g:x, ['OnPrint:' .. a:text])
+ endfunction
+ let g:x = stdioopen({'on_stdin': funcref('OnStdin'), 'on_print':'OnPrint'})
+ call chansend(x, "hello")
+ ]])
+ command("let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)")
+ local id = eval("g:id")
+ ok(id > 0)
+
+ eq({ "notification", "stdout", {id, { "hello" } } }, next_msg())
+
+ command("call chansend(id, 'howdy')")
+ eq({"notification", "stdout", {id, {"OnPrint:[1, ['howdy'], 'stdin']"}}}, next_msg())
+ end)
+
local function expect_twoline(id, stream, line1, line2, nobr)
local msg = next_msg()
local joined = nobr and {line1..line2} or {line1, line2}
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 5e127bce26..a0df3b7767 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -78,6 +78,7 @@ describe('jobs', function()
end)
it('append environment with pty #env', function()
+ if helpers.pending_win32(pending) then return end
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.pty = v:true")
@@ -295,12 +296,6 @@ describe('jobs', function()
end)
it("will not buffer data if it doesn't end in newlines", function()
- if helpers.isCI('travis') and os.getenv('CC') == 'gcc-4.9'
- and helpers.is_os('mac') then
- -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis macOS. #5002]")
- end
-
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "abc\\nxyz")')
eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 4220d68ee1..3da7f6ffde 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -53,6 +53,7 @@ describe('startup', function()
]])
end)
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
+ if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -104,6 +105,7 @@ describe('startup', function()
end)
end)
it('input from pipe (implicit) #7679', function()
+ if helpers.pending_win32(pending) then return end
local screen = Screen.new(25, 4)
screen:attach()
if iswin() then
@@ -224,6 +226,23 @@ describe('startup', function()
end
end)
+ it('-e sets ex mode', function()
+ local screen = Screen.new(25, 3)
+ clear('-e')
+ screen:attach()
+ -- Verify we set the proper mode both before and after :vi.
+ feed("put =mode(1)<CR>vi<CR>:put =mode(1)<CR>")
+ screen:expect([[
+ cv |
+ ^n |
+ :put =mode(1) |
+ ]])
+
+ eq('cv\n',
+ funcs.system({nvim_prog, '-n', '-es' },
+ { 'put =mode(1)', 'print', '' }))
+ end)
+
it('fails on --embed with -es/-Es', function()
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es',
funcs.system({nvim_prog, '--embed', '-es' }))
@@ -242,6 +261,7 @@ describe('startup', function()
end)
it('ENTER dismisses early message #7967', function()
+ if helpers.pending_win32(pending) then return end
local screen
screen = Screen.new(60, 6)
screen:attach()
@@ -474,6 +494,7 @@ describe('sysinit', function()
end)
it('fixed hang issue with -D (#12647)', function()
+ if helpers.pending_win32(pending) then return end
local screen
screen = Screen.new(60, 6)
screen:attach()
@@ -651,11 +672,7 @@ describe('runtime:', function()
mkdir_p(ftdetect_folder)
write_file(ftdetect_file , [[vim.g.lua_ftdetect = 1]])
- -- TODO(shadmansaleh): Figure out why this test fails without
- -- setting VIMRUNTIME
- clear{ args_rm={'-u'}, env={XDG_CONFIG_HOME=xconfig,
- XDG_DATA_HOME=xdata,
- VIMRUNTIME='runtime/'}}
+ clear{ args_rm={'-u'}, env=xenv }
eq(1, eval('g:lua_ftdetect'))
rmdir(ftdetect_folder)
diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua
index 40f36491e4..8ad81ac3d6 100644
--- a/test/functional/editor/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -33,6 +33,29 @@ describe('K', function()
feed('i'..test_file..'<ESC>K')
retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end)
eq({'fnord'}, eval("readfile('"..test_file.."')"))
+ -- Confirm that Neovim is still in terminal mode after K is pressed (#16692).
+ helpers.sleep(500)
+ eq('t', eval('mode()'))
+ feed('<space>') -- Any key, not just <space>, can be used here to escape.
+ eq('n', eval('mode()'))
+ end)
+
+ it("<esc> kills the buffer for a running 'keywordprg' command", function()
+ helpers.source('set keywordprg=less')
+ eval('writefile(["hello", "world"], "' .. test_file .. '")')
+ feed('i' .. test_file .. '<esc>K')
+ eq('t', eval('mode()'))
+ -- Confirm that an arbitrary keypress doesn't escape (i.e., the process is
+ -- still running). If the process were no longer running, an arbitrary
+ -- keypress would escape.
+ helpers.sleep(500)
+ feed('<space>')
+ eq('t', eval('mode()'))
+ -- Confirm that <esc> kills the buffer for the running command.
+ local bufnr = eval('bufnr()')
+ feed('<esc>')
+ eq('n', eval('mode()'))
+ helpers.neq(bufnr, eval('bufnr()'))
end)
end)
diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua
index 2280f5bb24..8efcc81616 100644
--- a/test/functional/editor/meta_key_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -27,6 +27,14 @@ describe('meta-keys #8226 #13042', function()
command('nnoremap <A-j> Aalt-j<Esc>')
feed('<A-j><M-l>')
expect('llo<ESC>;<ESC>;alt-jmeta-l')
+ -- Unmapped ALT-chord with characters containing K_SPECIAL bytes
+ command('nnoremap … A…<Esc>')
+ feed('<A-…><M-…>')
+ expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…')
+ command("execute 'nnoremap' nr2char(0x40000000) 'AMAX<Esc>'")
+ command("call nvim_input('<A-'.nr2char(0x40000000).'>')")
+ command("call nvim_input('<M-'.nr2char(0x40000000).'>')")
+ expect('llo<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX')
end)
it('ALT/META, visual-mode', function()
@@ -36,13 +44,20 @@ describe('meta-keys #8226 #13042', function()
expect('peach')
-- Unmapped ALT-chord resolves isolated (non-ALT) ESC mapping. #13086 #15869
command('vnoremap <ESC> A<lt>ESC>')
- feed('viw<A-;><ESC>viw<M-;><ESC>')
+ feed('viw<A-;><Esc>viw<M-;><Esc>')
expect('peach<ESC>;<ESC>;')
-- Mapped ALT-chord behaves as mapped.
command('vnoremap <M-l> Ameta-l<Esc>')
command('vnoremap <A-j> Aalt-j<Esc>')
feed('viw<A-j>viw<M-l>')
expect('peach<ESC>;<ESC>;alt-jmeta-l')
+ -- Unmapped ALT-chord with characters containing K_SPECIAL bytes
+ feed('viw<A-…><Esc>viw<M-…><Esc>')
+ expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…')
+ command("execute 'inoremap' nr2char(0x40000000) 'MAX'")
+ command("call nvim_input('viw<A-'.nr2char(0x40000000).'><Esc>')")
+ command("call nvim_input('viw<M-'.nr2char(0x40000000).'><Esc>')")
+ expect('peach<ESC>;<ESC>;alt-jmeta-l<ESC>…<ESC>…<ESC>MAX<ESC>MAX')
end)
it('ALT/META insert-mode', function()
@@ -89,4 +104,20 @@ describe('meta-keys #8226 #13042', function()
eq({ 0, 2, 1, 0, }, funcs.getpos('.'))
eq('nt', eval('mode(1)'))
end)
+
+ it('ALT/META when recording a macro #13235', function()
+ feed('ifoo<CR>bar<CR>baz<Esc>gg0')
+ -- <M-"> is reinterpreted as <Esc>"
+ feed('qrviw"ayC// This is some text: <M-">apq')
+ expect([[
+ // This is some text: foo
+ bar
+ baz]])
+ -- Should not insert an extra double quote when replaying
+ feed('j0@rj0@@')
+ expect([[
+ // This is some text: foo
+ // This is some text: bar
+ // This is some text: baz]])
+ end)
end)
diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua
index f03508035d..528e228121 100644
--- a/test/functional/editor/mode_insert_spec.lua
+++ b/test/functional/editor/mode_insert_spec.lua
@@ -75,4 +75,57 @@ describe('insert-mode', function()
expect('hello oooworld')
end)
end)
+
+ describe('Ctrl-V', function()
+ it('supports entering the decimal value of a character', function()
+ feed('i<C-V>076<C-V>167')
+ expect('L§')
+ end)
+
+ it('supports entering the octal value of a character with "o"', function()
+ feed('i<C-V>o114<C-V>o247<Esc>')
+ expect('L§')
+ end)
+
+ it('supports entering the octal value of a character with "O"', function()
+ feed('i<C-V>O114<C-V>O247<Esc>')
+ expect('L§')
+ end)
+
+ it('supports entering the hexadecimal value of a character with "x"', function()
+ feed('i<C-V>x4c<C-V>xA7<Esc>')
+ expect('L§')
+ end)
+
+ it('supports entering the hexadecimal value of a character with "X"', function()
+ feed('i<C-V>X4c<C-V>XA7<Esc>')
+ expect('L§')
+ end)
+
+ it('supports entering the hexadecimal value of a character with "u"', function()
+ feed('i<C-V>u25ba<C-V>u25C7<Esc>')
+ expect('►◇')
+ end)
+
+ it('supports entering the hexadecimal value of a character with "U"', function()
+ feed('i<C-V>U0001f600<C-V>U0001F601<Esc>')
+ expect('😀😁')
+ end)
+
+ it('entering character by value is interrupted by invalid character', function()
+ feed('i<C-V>76c<C-V>76<C-F2><C-V>u3c0j<C-V>u3c0<M-F3><C-V>U1f600j<C-V>U1f600<D-F4><Esc>')
+ expect('LcL<C-F2>πjπ<M-F3>😀j😀<D-F4>')
+ end)
+
+ it('shows o, O, u, U, x, X, and digits with modifiers', function()
+ feed('i<C-V><M-o><C-V><D-o><C-V><M-O><C-V><D-O><Esc>')
+ expect('<M-o><D-o><M-O><D-O>')
+ feed('cc<C-V><M-u><C-V><D-u><C-V><M-U><C-V><D-U><Esc>')
+ expect('<M-u><D-u><M-U><D-U>')
+ feed('cc<C-V><M-x><C-V><D-x><C-V><M-X><C-V><D-X><Esc>')
+ expect('<M-x><D-x><M-X><D-X>')
+ feed('cc<C-V><M-1><C-V><D-2><C-V><M-7><C-V><D-8><Esc>')
+ expect('<M-1><D-2><M-7><D-8>')
+ end)
+ end)
end)
diff --git a/test/functional/editor/put_spec.lua b/test/functional/editor/put_spec.lua
index 26967ecbba..c367f8fdd0 100644
--- a/test/functional/editor/put_spec.lua
+++ b/test/functional/editor/put_spec.lua
@@ -64,7 +64,7 @@ describe('put command', function()
-- one place to the right (unless we were at the end of the
-- line when we pasted).
if not (exception_table.undo_position and after_undo) then
- eq(funcs.getcurpos(), init_cursorpos)
+ eq(init_cursorpos, funcs.getcurpos())
end
end
@@ -86,7 +86,7 @@ describe('put command', function()
-- If we paste the ". register with a count we can't avoid
-- changing this register, hence avoid this check.
if not test.exception_table.dot_reg_changed then
- eq(funcs.getreg('.'), orig_dotstr)
+ eq(orig_dotstr, funcs.getreg('.'))
end
-- Doing something, undoing it, and then redoing it should
@@ -507,9 +507,11 @@ describe('put command', function()
return function(exception_table, after_redo)
test_expect(exception_table, after_redo)
if selection_string then
- eq(getreg('"'), selection_string)
+ if not conversion_table.put_backwards then
+ eq(selection_string, getreg('"'))
+ end
else
- eq(getreg('"'), 'test_string"')
+ eq('test_string"', getreg('"'))
end
end
end
@@ -714,7 +716,9 @@ describe('put command', function()
expect_base, conversion_table)
return function(exception_table, after_redo)
test_expect(exception_table, after_redo)
- eq(getreg('"'), 'Line of words 1\n')
+ if not conversion_table.put_backwards then
+ eq('Line of words 1\n', getreg('"'))
+ end
end
end
local base_expect_string = [[
@@ -748,7 +752,9 @@ describe('put command', function()
end, expect_base, conversion_table)
return function(e,c)
test_expect(e,c)
- eq(getreg('"'), 'Lin\nLin')
+ if not conversion_table.put_backwards then
+ eq('Lin\nLin', getreg('"'))
+ end
end
end
@@ -800,9 +806,9 @@ describe('put command', function()
feed('u')
-- Have to use feed('u') here to set curswant, because
-- ex_undo() doesn't do that.
- eq(funcs.getcurpos(), {0, 1, 1, 0, 1})
+ eq({0, 1, 1, 0, 1}, funcs.getcurpos())
feed('<C-r>')
- eq(funcs.getcurpos(), {0, 1, 1, 0, 1})
+ eq({0, 1, 1, 0, 1}, funcs.getcurpos())
end
end
diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua
index 0a4d701794..fadb5c9b42 100644
--- a/test/functional/ex_cmds/append_spec.lua
+++ b/test/functional/ex_cmds/append_spec.lua
@@ -1,23 +1,26 @@
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 funcs = helpers.funcs
local command = helpers.command
local curbufmeths = helpers.curbufmeths
-
-before_each(function()
- clear()
- curbufmeths.set_lines(0, 1, true, { 'foo', 'bar', 'baz' })
-end)
-
-local buffer_contents = function()
- return curbufmeths.get_lines(0, -1, false)
-end
+local Screen = require('test.functional.ui.screen')
local cmdtest = function(cmd, prep, ret1)
describe(':' .. cmd, function()
+ before_each(function()
+ clear()
+ curbufmeths.set_lines(0, 1, true, { 'foo', 'bar', 'baz' })
+ end)
+
+ local buffer_contents = function()
+ return curbufmeths.get_lines(0, -1, false)
+ end
+
it(cmd .. 's' .. prep .. ' the current line by default', function()
command(cmd .. '\nabc\ndef\n')
eq(ret1, buffer_contents())
@@ -52,3 +55,52 @@ end
cmdtest('insert', ' before', { 'abc', 'def', 'foo', 'bar', 'baz' })
cmdtest('append', ' after', { 'foo', 'abc', 'def', 'bar', 'baz' })
cmdtest('change', '', { 'abc', 'def', 'bar', 'baz' })
+
+describe('the first line is redrawn correctly after inserting text in an empty buffer', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(20, 8)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue},
+ [2] = {bold = true, reverse = true},
+ })
+ screen:attach()
+ end)
+
+ it('using :append', function()
+ exec(dedent([[
+ append
+ aaaaa
+ bbbbb
+ .]]))
+ screen:expect([[
+ aaaaa |
+ ^bbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+
+ it('using :insert', function()
+ exec(dedent([[
+ insert
+ aaaaa
+ bbbbb
+ .]]))
+ screen:expect([[
+ aaaaa |
+ ^bbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua
index f65d9f0d01..f19fab5550 100644
--- a/test/functional/ex_cmds/ctrl_c_spec.lua
+++ b/test/functional/ex_cmds/ctrl_c_spec.lua
@@ -10,8 +10,7 @@ describe("CTRL-C (mapped)", function()
it("interrupts :global", function()
-- Crashes luajit.
- if helpers.skip_fragile(pending,
- helpers.isCI('travis') or helpers.isCI('appveyor')) then
+ if helpers.skip_fragile(pending) then
return
end
diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua
index 84d5bc2335..eae36b9ae9 100644
--- a/test/functional/ex_cmds/map_spec.lua
+++ b/test/functional/ex_cmds/map_spec.lua
@@ -1,11 +1,15 @@
local helpers = require("test.functional.helpers")(after_each)
+local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
+local exec = helpers.exec
local feed = helpers.feed
local meths = helpers.meths
local clear = helpers.clear
local command = helpers.command
local expect = helpers.expect
+local insert = helpers.insert
+local eval = helpers.eval
describe(':*map', function()
before_each(clear)
@@ -25,4 +29,221 @@ describe(':*map', function()
feed('i-<M-">-')
expect('-foo-')
end)
+
+ it('shows <nop> as mapping rhs', function()
+ command('nmap asdf <Nop>')
+ eq([[
+
+n asdf <Nop>]],
+ helpers.exec_capture('nmap asdf'))
+ end)
+
+ it('mappings with description can be filtered', function()
+ meths.set_keymap('n', 'asdf1', 'qwert', {desc='do the one thing'})
+ meths.set_keymap('n', 'asdf2', 'qwert', {desc='doesnot really do anything'})
+ meths.set_keymap('n', 'asdf3', 'qwert', {desc='do the other thing'})
+ eq([[
+
+n asdf3 qwert
+ do the other thing
+n asdf1 qwert
+ do the one thing]],
+ helpers.exec_capture('filter the nmap'))
+ end)
+
+ it('<Plug> mappings ignore nore', function()
+ command('let x = 0')
+ eq(0, meths.eval('x'))
+ command [[
+ nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr>
+ nmap increase_x_remap <Plug>(Increase_x)
+ nnoremap increase_x_noremap <Plug>(Increase_x)
+ ]]
+ feed('increase_x_remap')
+ eq(1, meths.eval('x'))
+ feed('increase_x_noremap')
+ eq(2, meths.eval('x'))
+ end)
+
+ it("Doesn't auto ignore nore for keys before or after <Plug> mapping", function()
+ command('let x = 0')
+ eq(0, meths.eval('x'))
+ command [[
+ nnoremap x <nop>
+ nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr>
+ nmap increase_x_remap x<Plug>(Increase_x)x
+ nnoremap increase_x_noremap x<Plug>(Increase_x)x
+ ]]
+ insert("Some text")
+ eq('Some text', eval("getline('.')"))
+
+ feed('increase_x_remap')
+ eq(1, meths.eval('x'))
+ eq('Some text', eval("getline('.')"))
+ feed('increase_x_noremap')
+ eq(2, meths.eval('x'))
+ eq('Some te', eval("getline('.')"))
+ end)
+end)
+
+describe(':*map cursor and redrawing', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(20, 5)
+ screen:attach()
+ end)
+
+ it('cursor is restored after :map <expr> which calls input()', function()
+ command('map <expr> x input("> ")')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ feed('x')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ > ^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ > |
+ ]])
+ end)
+
+ it('cursor is restored after :imap <expr> which calls input()', function()
+ command('imap <expr> x input("> ")')
+ feed('i')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ feed('x')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ > ^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ > |
+ ]])
+ end)
+
+ it('cursor is restored after :map <expr> which redraws statusline vim-patch:8.1.2336', function()
+ exec([[
+ call setline(1, ['one', 'two', 'three'])
+ 2
+ set ls=2
+ hi! link StatusLine ErrorMsg
+ noremap <expr> <C-B> Func()
+ func Func()
+ let g:on = !get(g:, 'on', 0)
+ redraws
+ return ''
+ endfunc
+ func Status()
+ return get(g:, 'on', 0) ? '[on]' : ''
+ endfunc
+ set stl=%{Status()}
+ ]])
+ feed('<C-B>')
+ screen:expect([[
+ one |
+ ^two |
+ three |
+ [on] |
+ |
+ ]])
+ end)
+
+ it('error in :nmap <expr> does not mess up display vim-patch:4.2.4338', function()
+ screen:try_resize(40, 5)
+ command('nmap <expr> <F2> execute("throw 42")')
+ feed('<F2>')
+ screen:expect([[
+ |
+ |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed('<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ end)
+
+ it('error in :cmap <expr> handled correctly vim-patch:4.2.4338', function()
+ screen:try_resize(40, 5)
+ command('cmap <expr> <F2> execute("throw 42")')
+ feed(':echo "foo')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ :echo "foo^ |
+ ]])
+ feed('<F2>')
+ screen:expect([[
+ |
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ :echo "foo^ |
+ ]])
+ feed('"')
+ screen:expect([[
+ |
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ :echo "foo"^ |
+ ]])
+ feed('\n')
+ screen:expect([[
+ :echo "foo |
+ Error detected while processing : |
+ E605: Exception not caught: 42 |
+ foo |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+
+ it('listing mappings clears command line vim-patch:8.2.4401', function()
+ screen:try_resize(40, 5)
+ command('nmap a b')
+ feed(': nmap a<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ n a b |
+ ]])
+ end)
end)
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 09eaa36686..2702fb196f 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -5,6 +5,7 @@ local clear = helpers.clear
local command = helpers.command
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
+local neq = helpers.neq
local funcs = helpers.funcs
local matches = helpers.matches
local pesc = helpers.pesc
@@ -13,6 +14,7 @@ local rmdir = helpers.rmdir
local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec'
describe(':mksession', function()
+ if helpers.pending_win32(pending) then return end
local session_file = file_prefix .. '.vim'
local tab_dir = file_prefix .. '.d'
@@ -30,7 +32,8 @@ describe(':mksession', function()
-- If the same :terminal is displayed in multiple windows, :mksession
-- should restore it as such.
- -- Create two windows showing the same :terminal buffer.
+ -- Create three windows: first two from top show same terminal, third -
+ -- another one (created earlier).
command('terminal')
command('split')
command('terminal')
@@ -43,8 +46,8 @@ describe(':mksession', function()
-- Restore session.
command('source '..session_file)
- eq({2,2,4},
- {funcs.winbufnr(1), funcs.winbufnr(2), funcs.winbufnr(3)})
+ eq(funcs.winbufnr(1), funcs.winbufnr(2))
+ neq(funcs.winbufnr(1), funcs.winbufnr(3))
end)
it('restores tab-local working directories', function()
@@ -91,12 +94,7 @@ describe(':mksession', function()
command('tabnext 1')
eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', funcs.expand('%:p'))
command('tabnext 2')
- -- :mksession stores paths using unix slashes, but Nvim doesn't adjust these
- -- for absolute paths in all cases yet. Absolute paths are used in the
- -- session file after :tcd, so we need to expect unix slashes here for now
- -- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
- eq(cwd_dir:gsub([[\]], '/') .. '/' .. tmpfile_base .. '2',
- funcs.expand('%:p'))
+ eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
end)
it('restores CWD for :terminal buffers #11288', function()
diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua
index 0a772c559b..f249b9ba7c 100644
--- a/test/functional/ex_cmds/script_spec.lua
+++ b/test/functional/ex_cmds/script_spec.lua
@@ -62,10 +62,10 @@ describe('script_get-based command', function()
-- Provider-based scripts
test_garbage_exec('ruby', not missing_provider('ruby'))
- test_garbage_exec('python', not missing_provider('python'))
test_garbage_exec('python3', not missing_provider('python3'))
-- Missing scripts
+ test_garbage_exec('python', false)
test_garbage_exec('tcl', false)
test_garbage_exec('mzscheme', false)
test_garbage_exec('perl', false)
diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua
new file mode 100644
index 0000000000..326104dc3c
--- /dev/null
+++ b/test/functional/ex_cmds/verbose_spec.lua
@@ -0,0 +1,168 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+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.meths.call_function
+
+describe('lua :verbose', function()
+ local script_location, script_file
+ -- All test cases below use the same nvim instance.
+ setup(function()
+ clear{args={'-V1'}}
+ 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}
+
+ write_file(script_file, [[
+vim.api.nvim_set_option('hlsearch', false)
+vim.bo.expandtab = true
+vim.opt.number = true
+vim.api.nvim_set_keymap('n', '<leader>key1', ':echo "test"<cr>', {noremap = true})
+vim.keymap.set('n', '<leader>key2', ':echo "test"<cr>')
+
+vim.api.nvim_exec("augroup test_group\
+ autocmd!\
+ autocmd FileType c setl cindent\
+ augroup END\
+ ", false)
+
+vim.api.nvim_command("command Bdelete :bd")
+vim.api.nvim_add_user_command("TestCommand", ":echo 'Hello'", {})
+
+vim.api.nvim_exec ("\
+function Close_Window() abort\
+ wincmd -\
+endfunction\
+", false)
+
+local ret = vim.api.nvim_exec ("\
+function! s:return80()\
+ return 80\
+endfunction\
+let &tw = s:return80()\
+", true)
+]])
+ exec(':source '..script_file)
+ end)
+
+ teardown(function()
+ os.remove(script_file)
+ end)
+
+ it('"Last set" for option set by Lua', function()
+ local result = exec_capture(':verbose set hlsearch?')
+ eq(string.format([[
+nohlsearch
+ Last set from %s line 1]],
+ script_location), result)
+ end)
+
+ it('"Last set" for option set by vim.o', function()
+ local result = exec_capture(':verbose set expandtab?')
+ eq(string.format([[
+ expandtab
+ Last set from %s line 2]],
+ script_location), result)
+ end)
+
+ it('"Last set" for option set by vim.opt', function()
+ local result = exec_capture(':verbose set number?')
+ eq(string.format([[
+ number
+ Last set from %s line 3]],
+ script_location), result)
+ end)
+
+ it('"Last set" for keymap set by Lua', function()
+ local result = exec_capture(':verbose map <leader>key1')
+ eq(string.format([[
+
+n \key1 * :echo "test"<CR>
+ Last set from %s line 4]],
+ script_location), result)
+ end)
+
+ it('"Last set" for keymap set by vim.keymap', function()
+ local result = exec_capture(':verbose map <leader>key2')
+ eq(string.format([[
+
+n \key2 * :echo "test"<CR>
+ Last set from %s line 5]],
+ script_location), result)
+ end)
+
+ it('"Last set" for autocmd by vim.api.nvim_exec', function()
+ local result = exec_capture(':verbose autocmd test_group Filetype c')
+ eq(string.format([[
+--- Autocommands ---
+test_group FileType
+ c setl cindent
+ Last set from %s line 7]],
+ script_location), result)
+ end)
+
+ it('"Last set" for command defined by nvim_command', function()
+ local result = exec_capture(':verbose command Bdelete')
+ eq(string.format([[
+ Name Args Address Complete Definition
+ Bdelete 0 :bd
+ Last set from %s line 13]],
+ script_location), result)
+ end)
+
+ it('"Last set" for command defined by nvim_add_user_command', function()
+ local result = exec_capture(':verbose command TestCommand')
+ eq(string.format([[
+ Name Args Address Complete Definition
+ TestCommand 0 :echo 'Hello'
+ Last set from %s line 14]],
+ script_location), result)
+ end)
+
+ it('"Last set for function', function()
+ local result = exec_capture(':verbose function Close_Window')
+ eq(string.format([[
+ function Close_Window() abort
+ Last set from %s line 16
+1 wincmd -
+ endfunction]],
+ script_location), result)
+ end)
+
+ it('"Last set" works with anonymous sid', function()
+ local result = exec_capture(':verbose set tw?')
+ eq(string.format([[
+ textwidth=80
+ Last set from %s line 22]],
+ script_location), result)
+ end)
+end)
+
+describe('lua verbose:', function()
+ local script_file
+
+ setup(function()
+ clear()
+ script_file = 'test_luafile.lua'
+ write_file(script_file, [[
+ vim.api.nvim_set_option('hlsearch', false)
+ ]])
+ exec(':source '..script_file)
+ end)
+
+ teardown(function()
+ os.remove(script_file)
+ end)
+
+ it('is disabled when verbose = 0', function()
+ local result = exec_capture(':verbose set hlsearch?')
+ eq([[
+nohlsearch
+ Last set from Lua]], result)
+ end)
+end)
+
diff --git a/test/functional/fixtures/autoload/provider/python.vim b/test/functional/fixtures/autoload/provider/python3.vim
index d68360ac30..8ed4330a35 100644
--- a/test/functional/fixtures/autoload/provider/python.vim
+++ b/test/functional/fixtures/autoload/provider/python3.vim
@@ -1,6 +1,6 @@
" Dummy test provider, missing this required variable:
" let g:loaded_brokenenabled_provider = 0
-function! provider#python#Call(method, args)
+function! provider#python3#Call(method, args)
return 42
endfunction
diff --git a/test/functional/fixtures/lua/test_plug/submodule_empty/health.lua b/test/functional/fixtures/lua/test_plug/submodule_empty/health.lua
new file mode 100644
index 0000000000..d2cf86e4f0
--- /dev/null
+++ b/test/functional/fixtures/lua/test_plug/submodule_empty/health.lua
@@ -0,0 +1,7 @@
+local M = {}
+
+M.check = function()
+ return {}
+end
+
+return M
diff --git a/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua b/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua
new file mode 100644
index 0000000000..c1c33d787e
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua
@@ -0,0 +1 @@
+return {doit=function() return 9004 end}
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index f152a487af..1845786c4b 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -451,6 +451,7 @@ function module.new_argv(...)
'GCOV_ERROR_FILE',
'XDG_DATA_DIRS',
'TMPDIR',
+ 'VIMRUNTIME',
}) do
if not env_tbl[k] then
env_tbl[k] = os.getenv(k)
diff --git a/test/functional/legacy/003_cindent_spec.lua b/test/functional/legacy/003_cindent_spec.lua
deleted file mode 100644
index 061904c42f..0000000000
--- a/test/functional/legacy/003_cindent_spec.lua
+++ /dev/null
@@ -1,4774 +0,0 @@
--- Test for 'cindent'.
--- For new tests, consider putting them in test_cindent.vim.
---
--- There are 50+ test command blocks (the stuff between STARTTEST and ENDTEST)
--- in the original test. These have been converted to "it" test cases here.
-
-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
-
--- Inserts text as usual, and additionally positions the cursor on line 1 and
--- sets 'cindent' and tab settings. (In the original "test3.in" the modeline at
--- the top of the file takes care of this.)
-local function insert_(content)
- insert(content)
- feed_command('1', 'set cin ts=4 sw=4')
-end
-
--- luacheck: ignore 621 (Indentation)
--- luacheck: ignore 613 (Trailing whitespace in a string)
-describe('cindent', function()
- before_each(clear)
-
- it('1 is working', function()
- insert_([=[
-
- /* start of AUTO matically checked vim: set ts=4 : */
- {
- if (test)
- cmd1;
- cmd2;
- }
-
- {
- if (test)
- cmd1;
- else
- cmd2;
- }
-
- {
- if (test)
- {
- cmd1;
- cmd2;
- }
- }
-
- {
- if (test)
- {
- cmd1;
- else
- }
- }
-
- {
- while (this)
- if (test)
- cmd1;
- cmd2;
- }
-
- {
- while (this)
- if (test)
- cmd1;
- else
- cmd2;
- }
-
- {
- if (test)
- {
- cmd;
- }
-
- if (test)
- cmd;
- }
-
- {
- if (test) {
- cmd;
- }
-
- if (test) cmd;
- }
-
- {
- cmd1;
- for (blah)
- while (this)
- if (test)
- cmd2;
- cmd3;
- }
-
- {
- cmd1;
- for (blah)
- while (this)
- if (test)
- cmd2;
- cmd3;
-
- if (test)
- {
- cmd1;
- cmd2;
- cmd3;
- }
- }
-
-
- /* Test for 'cindent' do/while mixed with if/else: */
-
- {
- do
- if (asdf)
- asdfasd;
- while (cond);
-
- do
- if (asdf)
- while (asdf)
- asdf;
- while (asdf);
- }
-
- /* Test for 'cindent' with two ) on a continuation line */
- {
- if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
- aal;sdkjf ( ;asldfkja;sldfk
- al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
- line up here;
- }
-
-
- /* C++ tests: */
-
- // foo() these three lines should remain in column 0
- // {
- // }
-
- /* Test for continuation and unterminated lines: */
- {
- i = 99 + 14325 +
- 21345 +
- 21345 +
- 21345 + ( 21345 +
- 21345) +
- 2345 +
- 1234;
- c = 1;
- }
-
- /*
- testje for indent with empty line
-
- here */
-
- {
- if (testing &&
- not a joke ||
- line up here)
- hay;
- if (testing &&
- (not a joke || testing
- )line up here)
- hay;
- if (testing &&
- (not a joke || testing
- line up here))
- hay;
- }
-
-
- {
- switch (c)
- {
- case xx:
- do
- if (asdf)
- do
- asdfasdf;
- while (asdf);
- else
- asdfasdf;
- while (cond);
- case yy:
- case xx:
- case zz:
- testing;
- }
- }
-
- {
- if (cond) {
- foo;
- }
- else
- {
- bar;
- }
- }
-
- {
- if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
- alsdkfj (asldk;fj
- awith cino=(0 ;lf this one goes to below the paren with ==
- ;laksjfd ;lsakdjf ;alskdf asd)
- asdfasdf;)))
- asdfasdf;
- }
-
- int
- func(a, b)
- int a;
- int c;
- {
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3)
- )
- }
-
- {
- while (asd)
- {
- if (asdf)
- if (test)
- if (that)
- {
- if (asdf)
- do
- cdasd;
- while (as
- df);
- }
- else
- if (asdf)
- asdf;
- else
- asdf;
- asdf;
- }
- }
-
- {
- s = "/*"; b = ';'
- s = "/*"; b = ';';
- a = b;
- }
-
- {
- switch (a)
- {
- case a:
- switch (t)
- {
- case 1:
- cmd;
- break;
- case 2:
- cmd;
- break;
- }
- cmd;
- break;
- case b:
- {
- int i;
- cmd;
- }
- break;
- case c: {
- int i;
- cmd;
- }
- case d: if (cond &&
- test) { /* this line doesn't work right */
- int i;
- cmd;
- }
- break;
- }
- }
-
- {
- if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
- (bp_to->b_p_initialized ||
- (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
- return;
- label :
- asdf = asdf ?
- asdf : asdf;
- asdf = asdf ?
- asdf: asdf;
- }
-
- /* Special Comments : This function has the added complexity (compared */
- /* : to addtolist) of having to check for a detail */
- /* : texture and add that to the list first. */
-
- char *(array[100]) = {
- "testje",
- "foo",
- "bar",
- }
-
- enum soppie
- {
- yes = 0,
- no,
- maybe
- };
-
- typedef enum soppie
- {
- yes = 0,
- no,
- maybe
- };
-
- static enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- public static enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- static private enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- {
- int a,
- b;
- }
-
- {
- struct Type
- {
- int i;
- char *str;
- } var[] =
- {
- 0, "zero",
- 1, "one",
- 2, "two",
- 3, "three"
- };
-
- float matrix[3][3] =
- {
- {
- 0,
- 1,
- 2
- },
- {
- 3,
- 4,
- 5
- },
- {
- 6,
- 7,
- 8
- }
- };
- }
-
- {
- /* blah ( blah */
- /* where does this go? */
-
- /* blah ( blah */
- cmd;
-
- func(arg1,
- /* comment */
- arg2);
- a;
- {
- b;
- {
- c; /* Hey, NOW it indents?! */
- }
- }
-
- {
- func(arg1,
- arg2,
- arg3);
- /* Hey, what am I doing here? Is this coz of the ","? */
- }
- }
-
- main ()
- {
- if (cond)
- {
- a = b;
- }
- if (cond) {
- a = c;
- }
- if (cond)
- a = d;
- return;
- }
-
- {
- case 2: if (asdf &&
- asdfasdf)
- aasdf;
- a = 9;
- case 3: if (asdf)
- aasdf;
- a = 9;
- case 4: x = 1;
- y = 2;
-
- label: if (asdf)
- here;
-
- label: if (asdf &&
- asdfasdf)
- {
- }
-
- label: if (asdf &&
- asdfasdf) {
- there;
- }
-
- label: if (asdf &&
- asdfasdf)
- there;
- }
-
- {
- /*
- hello with ":set comments= cino=c5"
- */
-
- /*
- hello with ":set comments= cino="
- */
- }
-
-
- {
- if (a < b) {
- a = a + 1;
- } else
- a = a + 2;
-
- if (a)
- do {
- testing;
- } while (asdfasdf);
- a = b + 1;
- asdfasdf
- }
-
- {
- for ( int i = 0;
- i < 10; i++ )
- {
- }
- i = 0;
- }
-
- class bob
- {
- int foo() {return 1;}
- int bar;
- }
-
- main()
- {
- while(1)
- if (foo)
- {
- bar;
- }
- else {
- asdf;
- }
- misplacedline;
- }
-
- {
- if (clipboard.state == SELECT_DONE
- && ((row == clipboard.start.lnum
- && col >= clipboard.start.col)
- || row > clipboard.start.lnum))
- }
-
- {
- if (1) {i += 4;}
- where_am_i;
- return 0;
- }
-
- {
- {
- } // sdf(asdf
- if (asdf)
- asd;
- }
-
- {
- label1:
- label2:
- }
-
- {
- int fooRet = foo(pBar1, false /*fKB*/,
- true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
- f() {
- for ( i = 0;
- i < m;
- /* c */ i++ ) {
- a = b;
- }
- }
- }
-
- {
- f1(/*comment*/);
- f2();
- }
-
- {
- do {
- if (foo) {
- } else
- ;
- } while (foo);
- foo(); // was wrong
- }
-
- int x; // no extra indent because of the ;
- void func()
- {
- }
-
- char *tab[] = {"aaa",
- "};", /* }; */ NULL}
- int indented;
- {}
-
- char *a[] = {"aaa", "bbb",
- "ccc", NULL};
- // here
-
- char *tab[] = {"aaa",
- "xx", /* xx */}; /* asdf */
- int not_indented;
-
- {
- do {
- switch (bla)
- {
- case 1: if (foo)
- bar;
- }
- } while (boo);
- wrong;
- }
-
- int foo,
- bar;
- int foo;
-
- #if defined(foo) \
- && defined(bar)
- char * xx = "asdf\
- foo\
- bor";
- int x;
-
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
-
- void f()
- {
- #if defined(foo) \
- && defined(bar)
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
- {
- int i;
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
- }
- #endif
- }
- #endif
-
- int y; // comment
- // comment
-
- // comment
-
- {
- Constructor(int a,
- int b ) : BaseClass(a)
- {
- }
- }
-
- void foo()
- {
- char one,
- two;
- struct bla piet,
- jan;
- enum foo kees,
- jannie;
- static unsigned sdf,
- krap;
- unsigned int piet,
- jan;
- int
- kees,
- jan;
- }
-
- {
- t(int f,
- int d); // )
- d();
- }
-
- Constructor::Constructor(int a,
- int b
- ) :
- BaseClass(a,
- b,
- c),
- mMember(b),
- {
- }
-
- Constructor::Constructor(int a,
- int b ) :
- BaseClass(a)
- {
- }
-
- Constructor::Constructor(int a,
- int b ) /*x*/ : /*x*/ BaseClass(a),
- member(b)
- {
- }
-
- A::A(int a, int b)
- : aa(a),
- bb(b),
- cc(c)
- {
- }
-
- class CAbc :
- public BaseClass1,
- protected BaseClass2
- {
- int Test() { return FALSE; }
- int Test1() { return TRUE; }
-
- CAbc(int a, int b ) :
- BaseClass(a)
- {
- switch(xxx)
- {
- case abc:
- asdf();
- break;
-
- case 999:
- baer();
- break;
- }
- }
-
- public: // <-- this was incoreectly indented before!!
- void testfall();
- protected:
- void testfall();
- };
-
- class CAbc : public BaseClass1,
- protected BaseClass2
- {
- };
-
- static struct
- {
- int a;
- int b;
- } variable[COUNT] =
- {
- {
- 123,
- 456
- },
- {
- 123,
- 456
- }
- };
-
- static struct
- {
- int a;
- int b;
- } variable[COUNT] =
- {
- { 123, 456 },
- { 123, 456 }
- };
-
- void asdf() /* ind_maxparen may cause trouble here */
- {
- if ((0
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1)) break;
- }
-
- foo()
- {
- a = cond ? foo() : asdf
- + asdf;
-
- a = cond ?
- foo() : asdf
- + asdf;
- }
-
- int main(void)
- {
- if (a)
- if (b)
- 2;
- else 3;
- next_line_of_code();
- }
-
- barry()
- {
- Foo::Foo (int one,
- int two)
- : something(4)
- {}
- }
-
- barry()
- {
- Foo::Foo (int one, int two)
- : something(4)
- {}
- }
-
- Constructor::Constructor(int a,
- int b
- ) :
- BaseClass(a,
- b,
- c),
- mMember(b)
- {
- }
- int main ()
- {
- if (lala)
- do
- ++(*lolo);
- while (lili
- && lele);
- lulu;
- }
-
- int main ()
- {
- switch (c)
- {
- case 'c': if (cond)
- {
- }
- }
- }
-
- main()
- {
- (void) MyFancyFuasdfadsfnction(
- argument);
- }
-
- main()
- {
- char foo[] = "/*";
- /* as
- df */
- hello
- }
-
- /* valid namespaces with normal indent */
- namespace
- {
- {
- 111111111111;
- }
- }
- namespace /* test */
- {
- 11111111111111111;
- }
- namespace // test
- {
- 111111111111111111;
- }
- namespace
- {
- 111111111111111111;
- }
- namespace test
- {
- 111111111111111111;
- }
- namespace{
- 111111111111111111;
- }
- namespace test{
- 111111111111111111;
- }
- namespace {
- 111111111111111111;
- }
- namespace test {
- 111111111111111111;
- namespace test2 {
- 22222222222222222;
- }
- }
-
- /* invalid namespaces use block indent */
- namespace test test2 {
- 111111111111111111111;
- }
- namespace11111111111 {
- 111111111111;
- }
- namespace() {
- 1111111111111;
- }
- namespace()
- {
- 111111111111111111;
- }
- namespace test test2
- {
- 1111111111111111111;
- }
- namespace111111111
- {
- 111111111111111111;
- }
- void getstring() {
- /* Raw strings */
- const char* s = R"(
- test {
- # comment
- field: 123
- }
- )";
- }
- void getstring() {
- const char* s = R"foo(
- test {
- # comment
- field: 123
- }
- )foo";
- }
-
- {
- int a[4] = {
- [0] = 0,
- [1] = 1,
- [2] = 2,
- [3] = 3,
- };
- }
-
- {
- a = b[2]
- + 3;
- }
-
- {
- if (1)
- /* aaaaa
- * bbbbb
- */
- a = 1;
- }
-
- void func()
- {
- switch (foo)
- {
- case (bar):
- if (baz())
- quux();
- break;
- case (shmoo):
- if (!bar)
- {
- }
- case (foo1):
- switch (bar)
- {
- case baz:
- baz_f();
- break;
- }
- break;
- default:
- baz();
- baz();
- break;
- }
- }
-
- /* end of AUTO */
- ]=])
-
- feed_command('/start of AUTO')
- feed('=/end of AUTO<cr>')
-
- expect([=[
-
- /* start of AUTO matically checked vim: set ts=4 : */
- {
- if (test)
- cmd1;
- cmd2;
- }
-
- {
- if (test)
- cmd1;
- else
- cmd2;
- }
-
- {
- if (test)
- {
- cmd1;
- cmd2;
- }
- }
-
- {
- if (test)
- {
- cmd1;
- else
- }
- }
-
- {
- while (this)
- if (test)
- cmd1;
- cmd2;
- }
-
- {
- while (this)
- if (test)
- cmd1;
- else
- cmd2;
- }
-
- {
- if (test)
- {
- cmd;
- }
-
- if (test)
- cmd;
- }
-
- {
- if (test) {
- cmd;
- }
-
- if (test) cmd;
- }
-
- {
- cmd1;
- for (blah)
- while (this)
- if (test)
- cmd2;
- cmd3;
- }
-
- {
- cmd1;
- for (blah)
- while (this)
- if (test)
- cmd2;
- cmd3;
-
- if (test)
- {
- cmd1;
- cmd2;
- cmd3;
- }
- }
-
-
- /* Test for 'cindent' do/while mixed with if/else: */
-
- {
- do
- if (asdf)
- asdfasd;
- while (cond);
-
- do
- if (asdf)
- while (asdf)
- asdf;
- while (asdf);
- }
-
- /* Test for 'cindent' with two ) on a continuation line */
- {
- if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
- aal;sdkjf ( ;asldfkja;sldfk
- al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
- line up here;
- }
-
-
- /* C++ tests: */
-
- // foo() these three lines should remain in column 0
- // {
- // }
-
- /* Test for continuation and unterminated lines: */
- {
- i = 99 + 14325 +
- 21345 +
- 21345 +
- 21345 + ( 21345 +
- 21345) +
- 2345 +
- 1234;
- c = 1;
- }
-
- /*
- testje for indent with empty line
-
- here */
-
- {
- if (testing &&
- not a joke ||
- line up here)
- hay;
- if (testing &&
- (not a joke || testing
- )line up here)
- hay;
- if (testing &&
- (not a joke || testing
- line up here))
- hay;
- }
-
-
- {
- switch (c)
- {
- case xx:
- do
- if (asdf)
- do
- asdfasdf;
- while (asdf);
- else
- asdfasdf;
- while (cond);
- case yy:
- case xx:
- case zz:
- testing;
- }
- }
-
- {
- if (cond) {
- foo;
- }
- else
- {
- bar;
- }
- }
-
- {
- if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
- alsdkfj (asldk;fj
- awith cino=(0 ;lf this one goes to below the paren with ==
- ;laksjfd ;lsakdjf ;alskdf asd)
- asdfasdf;)))
- asdfasdf;
- }
-
- int
- func(a, b)
- int a;
- int c;
- {
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3)
- )
- }
-
- {
- while (asd)
- {
- if (asdf)
- if (test)
- if (that)
- {
- if (asdf)
- do
- cdasd;
- while (as
- df);
- }
- else
- if (asdf)
- asdf;
- else
- asdf;
- asdf;
- }
- }
-
- {
- s = "/*"; b = ';'
- s = "/*"; b = ';';
- a = b;
- }
-
- {
- switch (a)
- {
- case a:
- switch (t)
- {
- case 1:
- cmd;
- break;
- case 2:
- cmd;
- break;
- }
- cmd;
- break;
- case b:
- {
- int i;
- cmd;
- }
- break;
- case c: {
- int i;
- cmd;
- }
- case d: if (cond &&
- test) { /* this line doesn't work right */
- int i;
- cmd;
- }
- break;
- }
- }
-
- {
- if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
- (bp_to->b_p_initialized ||
- (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
- return;
- label :
- asdf = asdf ?
- asdf : asdf;
- asdf = asdf ?
- asdf: asdf;
- }
-
- /* Special Comments : This function has the added complexity (compared */
- /* : to addtolist) of having to check for a detail */
- /* : texture and add that to the list first. */
-
- char *(array[100]) = {
- "testje",
- "foo",
- "bar",
- }
-
- enum soppie
- {
- yes = 0,
- no,
- maybe
- };
-
- typedef enum soppie
- {
- yes = 0,
- no,
- maybe
- };
-
- static enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- public static enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- static private enum
- {
- yes = 0,
- no,
- maybe
- } soppie;
-
- {
- int a,
- b;
- }
-
- {
- struct Type
- {
- int i;
- char *str;
- } var[] =
- {
- 0, "zero",
- 1, "one",
- 2, "two",
- 3, "three"
- };
-
- float matrix[3][3] =
- {
- {
- 0,
- 1,
- 2
- },
- {
- 3,
- 4,
- 5
- },
- {
- 6,
- 7,
- 8
- }
- };
- }
-
- {
- /* blah ( blah */
- /* where does this go? */
-
- /* blah ( blah */
- cmd;
-
- func(arg1,
- /* comment */
- arg2);
- a;
- {
- b;
- {
- c; /* Hey, NOW it indents?! */
- }
- }
-
- {
- func(arg1,
- arg2,
- arg3);
- /* Hey, what am I doing here? Is this coz of the ","? */
- }
- }
-
- main ()
- {
- if (cond)
- {
- a = b;
- }
- if (cond) {
- a = c;
- }
- if (cond)
- a = d;
- return;
- }
-
- {
- case 2: if (asdf &&
- asdfasdf)
- aasdf;
- a = 9;
- case 3: if (asdf)
- aasdf;
- a = 9;
- case 4: x = 1;
- y = 2;
-
- label: if (asdf)
- here;
-
- label: if (asdf &&
- asdfasdf)
- {
- }
-
- label: if (asdf &&
- asdfasdf) {
- there;
- }
-
- label: if (asdf &&
- asdfasdf)
- there;
- }
-
- {
- /*
- hello with ":set comments= cino=c5"
- */
-
- /*
- hello with ":set comments= cino="
- */
- }
-
-
- {
- if (a < b) {
- a = a + 1;
- } else
- a = a + 2;
-
- if (a)
- do {
- testing;
- } while (asdfasdf);
- a = b + 1;
- asdfasdf
- }
-
- {
- for ( int i = 0;
- i < 10; i++ )
- {
- }
- i = 0;
- }
-
- class bob
- {
- int foo() {return 1;}
- int bar;
- }
-
- main()
- {
- while(1)
- if (foo)
- {
- bar;
- }
- else {
- asdf;
- }
- misplacedline;
- }
-
- {
- if (clipboard.state == SELECT_DONE
- && ((row == clipboard.start.lnum
- && col >= clipboard.start.col)
- || row > clipboard.start.lnum))
- }
-
- {
- if (1) {i += 4;}
- where_am_i;
- return 0;
- }
-
- {
- {
- } // sdf(asdf
- if (asdf)
- asd;
- }
-
- {
- label1:
- label2:
- }
-
- {
- int fooRet = foo(pBar1, false /*fKB*/,
- true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
- f() {
- for ( i = 0;
- i < m;
- /* c */ i++ ) {
- a = b;
- }
- }
- }
-
- {
- f1(/*comment*/);
- f2();
- }
-
- {
- do {
- if (foo) {
- } else
- ;
- } while (foo);
- foo(); // was wrong
- }
-
- int x; // no extra indent because of the ;
- void func()
- {
- }
-
- char *tab[] = {"aaa",
- "};", /* }; */ NULL}
- int indented;
- {}
-
- char *a[] = {"aaa", "bbb",
- "ccc", NULL};
- // here
-
- char *tab[] = {"aaa",
- "xx", /* xx */}; /* asdf */
- int not_indented;
-
- {
- do {
- switch (bla)
- {
- case 1: if (foo)
- bar;
- }
- } while (boo);
- wrong;
- }
-
- int foo,
- bar;
- int foo;
-
- #if defined(foo) \
- && defined(bar)
- char * xx = "asdf\
- foo\
- bor";
- int x;
-
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
-
- void f()
- {
- #if defined(foo) \
- && defined(bar)
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
- {
- int i;
- char *foo = "asdf\
- asdf\
- asdf",
- *bar;
- }
- #endif
- }
- #endif
-
- int y; // comment
- // comment
-
- // comment
-
- {
- Constructor(int a,
- int b ) : BaseClass(a)
- {
- }
- }
-
- void foo()
- {
- char one,
- two;
- struct bla piet,
- jan;
- enum foo kees,
- jannie;
- static unsigned sdf,
- krap;
- unsigned int piet,
- jan;
- int
- kees,
- jan;
- }
-
- {
- t(int f,
- int d); // )
- d();
- }
-
- Constructor::Constructor(int a,
- int b
- ) :
- BaseClass(a,
- b,
- c),
- mMember(b),
- {
- }
-
- Constructor::Constructor(int a,
- int b ) :
- BaseClass(a)
- {
- }
-
- Constructor::Constructor(int a,
- int b ) /*x*/ : /*x*/ BaseClass(a),
- member(b)
- {
- }
-
- A::A(int a, int b)
- : aa(a),
- bb(b),
- cc(c)
- {
- }
-
- class CAbc :
- public BaseClass1,
- protected BaseClass2
- {
- int Test() { return FALSE; }
- int Test1() { return TRUE; }
-
- CAbc(int a, int b ) :
- BaseClass(a)
- {
- switch(xxx)
- {
- case abc:
- asdf();
- break;
-
- case 999:
- baer();
- break;
- }
- }
-
- public: // <-- this was incoreectly indented before!!
- void testfall();
- protected:
- void testfall();
- };
-
- class CAbc : public BaseClass1,
- protected BaseClass2
- {
- };
-
- static struct
- {
- int a;
- int b;
- } variable[COUNT] =
- {
- {
- 123,
- 456
- },
- {
- 123,
- 456
- }
- };
-
- static struct
- {
- int a;
- int b;
- } variable[COUNT] =
- {
- { 123, 456 },
- { 123, 456 }
- };
-
- void asdf() /* ind_maxparen may cause trouble here */
- {
- if ((0
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1
- && 1)) break;
- }
-
- foo()
- {
- a = cond ? foo() : asdf
- + asdf;
-
- a = cond ?
- foo() : asdf
- + asdf;
- }
-
- int main(void)
- {
- if (a)
- if (b)
- 2;
- else 3;
- next_line_of_code();
- }
-
- barry()
- {
- Foo::Foo (int one,
- int two)
- : something(4)
- {}
- }
-
- barry()
- {
- Foo::Foo (int one, int two)
- : something(4)
- {}
- }
-
- Constructor::Constructor(int a,
- int b
- ) :
- BaseClass(a,
- b,
- c),
- mMember(b)
- {
- }
- int main ()
- {
- if (lala)
- do
- ++(*lolo);
- while (lili
- && lele);
- lulu;
- }
-
- int main ()
- {
- switch (c)
- {
- case 'c': if (cond)
- {
- }
- }
- }
-
- main()
- {
- (void) MyFancyFuasdfadsfnction(
- argument);
- }
-
- main()
- {
- char foo[] = "/*";
- /* as
- df */
- hello
- }
-
- /* valid namespaces with normal indent */
- namespace
- {
- {
- 111111111111;
- }
- }
- namespace /* test */
- {
- 11111111111111111;
- }
- namespace // test
- {
- 111111111111111111;
- }
- namespace
- {
- 111111111111111111;
- }
- namespace test
- {
- 111111111111111111;
- }
- namespace{
- 111111111111111111;
- }
- namespace test{
- 111111111111111111;
- }
- namespace {
- 111111111111111111;
- }
- namespace test {
- 111111111111111111;
- namespace test2 {
- 22222222222222222;
- }
- }
-
- /* invalid namespaces use block indent */
- namespace test test2 {
- 111111111111111111111;
- }
- namespace11111111111 {
- 111111111111;
- }
- namespace() {
- 1111111111111;
- }
- namespace()
- {
- 111111111111111111;
- }
- namespace test test2
- {
- 1111111111111111111;
- }
- namespace111111111
- {
- 111111111111111111;
- }
- void getstring() {
- /* Raw strings */
- const char* s = R"(
- test {
- # comment
- field: 123
- }
- )";
- }
- void getstring() {
- const char* s = R"foo(
- test {
- # comment
- field: 123
- }
- )foo";
- }
-
- {
- int a[4] = {
- [0] = 0,
- [1] = 1,
- [2] = 2,
- [3] = 3,
- };
- }
-
- {
- a = b[2]
- + 3;
- }
-
- {
- if (1)
- /* aaaaa
- * bbbbb
- */
- a = 1;
- }
-
- void func()
- {
- switch (foo)
- {
- case (bar):
- if (baz())
- quux();
- break;
- case (shmoo):
- if (!bar)
- {
- }
- case (foo1):
- switch (bar)
- {
- case baz:
- baz_f();
- break;
- }
- break;
- default:
- baz();
- baz();
- break;
- }
- }
-
- /* end of AUTO */
- ]=])
- end)
-
- it('2 is working', function()
- insert_([=[
-
- {
-
- /* this is
- * a real serious important big
- * comment
- */
- /* insert " about life, the universe, and the rest" after "serious" */
- }
- ]=])
-
- feed_command('set tw=0 noai fo=croq')
- feed_command('let &wm = &columns - 20')
- feed_command('/serious/e')
- feed('a about life, the universe, and the rest<esc>')
-
- expect([=[
-
- {
-
- /* this is
- * a real serious
- * about life, the
- * universe, and the
- * rest important big
- * comment
- */
- /* insert " about life, the universe, and the rest" after "serious" */
- }
- ]=])
- end)
-
- it('3 is working', function()
- insert_([=[
-
- {
- /*
- * Testing for comments, without 'cin' set
- */
-
- /*
- * what happens here?
- */
-
- /*
- the end of the comment, try inserting a line below */
-
- /* how about
- this one */
- }
- ]=])
-
- feed_command('set nocin')
- feed_command('/comments')
- feed('joabout life<esc>/happens<cr>')
- feed('jothere<esc>/below<cr>')
- feed('oline<esc>/this<cr>')
- feed('Ohello<esc>')
-
- expect([=[
-
- {
- /*
- * Testing for comments, without 'cin' set
- */
- about life
-
- /*
- * what happens here?
- */
- there
-
- /*
- the end of the comment, try inserting a line below */
- line
-
- /* how about
- hello
- this one */
- }
- ]=])
- end)
-
- it('4 is working', function()
- insert_([=[
-
- {
- var = this + that + vec[0] * vec[0]
- + vec[1] * vec[1]
- + vec2[2] * vec[2];
- }
- ]=])
- feed_command('set cin')
- feed_command('/vec2')
- feed('==<cr>')
-
- expect([=[
-
- {
- var = this + that + vec[0] * vec[0]
- + vec[1] * vec[1]
- + vec2[2] * vec[2];
- }
- ]=])
- end)
-
- it('5 is working', function()
- insert_([=[
-
- {
- asdf asdflkajds f;
- if (tes & ting) {
- asdf asdf asdf ;
- asdfa sdf asdf;
- }
- testing1;
- if (tes & ting)
- {
- asdf asdf asdf ;
- asdfa sdf asdf;
- }
- testing2;
- }
- ]=])
-
- feed_command('set cin')
- feed_command('set cino=}4')
- feed_command('/testing1')
- feed('k2==/testing2<cr>')
- feed('k2==<cr>')
-
- expect([=[
-
- {
- asdf asdflkajds f;
- if (tes & ting) {
- asdf asdf asdf ;
- asdfa sdf asdf;
- }
- testing1;
- if (tes & ting)
- {
- asdf asdf asdf ;
- asdfa sdf asdf;
- }
- testing2;
- }
- ]=])
- end)
-
- it('6 is working', function()
- insert_([=[
-
- main ( int first_par, /*
- * Comment for
- * first par
- */
- int second_par /*
- * Comment for
- * second par
- */
- )
- {
- func( first_par, /*
- * Comment for
- * first par
- */
- second_par /*
- * Comment for
- * second par
- */
- );
-
- }
- ]=])
-
- feed_command('set cin')
- feed_command('set cino=(0,)20')
- feed_command('/main')
- feed('=][<cr>')
-
- expect([=[
-
- main ( int first_par, /*
- * Comment for
- * first par
- */
- int second_par /*
- * Comment for
- * second par
- */
- )
- {
- func( first_par, /*
- * Comment for
- * first par
- */
- second_par /*
- * Comment for
- * second par
- */
- );
-
- }
- ]=])
- end)
-
- it('7 is working', function()
- insert_([=[
-
- main(void)
- {
- /* Make sure that cino=X0s is not parsed like cino=Xs. */
- if (cond)
- foo();
- else
- {
- bar();
- }
- }
- ]=])
-
- feed_command('set cin')
- feed_command('set cino=es,n0s')
- feed_command('/main')
- feed('=][<cr>')
-
- expect([=[
-
- main(void)
- {
- /* Make sure that cino=X0s is not parsed like cino=Xs. */
- if (cond)
- foo();
- else
- {
- bar();
- }
- }
- ]=])
- end)
-
- it('8 is working', function()
- insert_([=[
-
- {
- do
- {
- if ()
- {
- if ()
- asdf;
- else
- asdf;
- }
- } while ();
- cmd; /* this should go under the } */
- }
- ]=])
-
- feed_command('set cin')
- feed_command('set cino=')
- feed(']]=][<cr>')
-
- expect([=[
-
- {
- do
- {
- if ()
- {
- if ()
- asdf;
- else
- asdf;
- }
- } while ();
- cmd; /* this should go under the } */
- }
- ]=])
- end)
-
- it('9 is working', function()
- insert_([=[
-
- void f()
- {
- if ( k() ) {
- l();
-
- } else { /* Start (two words) end */
- m();
- }
-
- n();
- }
- ]=])
-
- feed(']]=][<cr>')
-
- expect([=[
-
- void f()
- {
- if ( k() ) {
- l();
-
- } else { /* Start (two words) end */
- m();
- }
-
- n();
- }
- ]=])
- end)
-
- it('10 is working', function()
- -- This is nasty. This is the only test case where the buffer content
- -- differs from the original. Why? Proper behaviour of this test depends on
- -- the fact that the setup code contains an (unbalanced) opening curly
- -- bracket in "set cino={s,e-s". This bracket actually affects the outcome
- -- of the test: without it the curly bracket under "void f()" would not be
- -- indented properly. And that's why we've had to add one explicitly.
- insert_([=[
- { <= THIS IS THE CURLY BRACKET EXPLAINED IN THE COMMENT.
-
- void f()
- {
- if ( k() )
- {
- l();
- } else { /* Start (two words) end */
- m();
- }
- n(); /* should be under the if () */
- }
- ]=])
-
- feed_command('set cino={s,e-s')
- feed(']]=][<cr>')
-
- expect([=[
- { <= THIS IS THE CURLY BRACKET EXPLAINED IN THE COMMENT.
-
- void f()
- {
- if ( k() )
- {
- l();
- } else { /* Start (two words) end */
- m();
- }
- n(); /* should be under the if () */
- }
- ]=])
- end)
-
- it('11 is working', function()
- insert_([=[
-
- void bar(void)
- {
- static array[2][2] =
- {
- { 1, 2 },
- { 3, 4 },
- }
-
- while (a)
- {
- foo(&a);
- }
-
- {
- int a;
- {
- a = a + 1;
- }
- }
- b = a;
- }
-
- void func(void)
- {
- a = 1;
- {
- b = 2;
- }
- c = 3;
- d = 4;
- }
- /* foo */
- ]=])
-
- feed_command('set cino={s,fs')
- feed(']]=/ foo<cr>')
-
- expect([=[
-
- void bar(void)
- {
- static array[2][2] =
- {
- { 1, 2 },
- { 3, 4 },
- }
-
- while (a)
- {
- foo(&a);
- }
-
- {
- int a;
- {
- a = a + 1;
- }
- }
- b = a;
- }
-
- void func(void)
- {
- a = 1;
- {
- b = 2;
- }
- c = 3;
- d = 4;
- }
- /* foo */
- ]=])
- end)
-
- it('12 is working', function()
- insert_([=[
-
- a()
- {
- do {
- a = a +
- a;
- } while ( a ); /* add text under this line */
- if ( a )
- a;
- }
- ]=])
-
- feed_command('set cino=')
- feed_command('/while')
- feed('ohere<esc>')
-
- expect([=[
-
- a()
- {
- do {
- a = a +
- a;
- } while ( a ); /* add text under this line */
- here
- if ( a )
- a;
- }
- ]=])
- end)
-
- it('13 is working', function()
- insert_([=[
-
- a()
- {
- label1:
- /* hmm */
- // comment
- }
- ]=])
-
- feed_command('set cino= com=')
- feed_command('/comment')
- feed('olabel2: b();<cr>label3 /* post */:<cr>/* pre */ label4:<cr>f(/*com*/);<cr>if (/*com*/)<cr>cmd();<esc>')
-
- expect([=[
-
- a()
- {
- label1:
- /* hmm */
- // comment
- label2: b();
- label3 /* post */:
- /* pre */ label4:
- f(/*com*/);
- if (/*com*/)
- cmd();
- }
- ]=])
- end)
-
- it('14 is working', function()
- insert_([=[
-
- /*
- * A simple comment
- */
-
- /*
- ** A different comment
- */
- ]=])
-
- feed_command('set comments& comments^=s:/*,m:**,ex:*/')
- feed_command('/simple')
- feed('=5j<cr>')
-
- expect([=[
-
- /*
- * A simple comment
- */
-
- /*
- ** A different comment
- */
- ]=])
- end)
-
- it('15 is working', function()
- insert_([=[
-
-
- void f()
- {
-
- /*********
- A comment.
- *********/
- }
- ]=])
-
- feed_command('set cino=c0')
- feed_command('set comments& comments-=s1:/* comments^=s0:/*')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
-
- /*********
- A comment.
- *********/
- }
- ]=])
- end)
-
- it('16 is working', function()
- insert_([=[
-
-
- void f()
- {
-
- /*********
- A comment.
- *********/
- }
- ]=])
-
- feed_command('set cino=c0,C1')
- feed_command('set comments& comments-=s1:/* comments^=s0:/*')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
-
- /*********
- A comment.
- *********/
- }
- ]=])
- end)
-
- it('17 is working', function()
- insert_([=[
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
-
- feed_command('set cino=')
- feed(']]=][<cr>')
-
- expect([=[
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
- end)
-
- it('18 is working', function()
- insert_([=[
-
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
-
- feed_command('set cino=(s')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
- end)
-
- it('19 is working', function()
- insert_([=[
-
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
-
- feed_command('set cino=(s,U1 ')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
- end)
-
- it('20 is working', function()
- insert_([=[
-
-
- void f()
- {
- if ( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
-
- feed_command('set cino=(0')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- if ( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
- end)
-
- it('21 is working', function()
- insert_([=[
-
-
- void f()
- {
- if ( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
-
- feed_command('set cino=(0,w1 ')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- if ( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
- end)
-
- it('22 is working', function()
- insert_([=[
-
-
- void f()
- {
- c = c1 && (
- c2 ||
- c3
- ) && c4;
- if (
- c1 && c2
- )
- foo;
- }
- ]=])
-
- feed_command('set cino=(s')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- c = c1 && (
- c2 ||
- c3
- ) && c4;
- if (
- c1 && c2
- )
- foo;
- }
- ]=])
- end)
-
- it('23 is working', function()
- insert_([=[
-
-
- void f()
- {
- c = c1 && (
- c2 ||
- c3
- ) && c4;
- if (
- c1 && c2
- )
- foo;
- }
- ]=])
-
- feed_command('set cino=(s,m1 ')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- c = c1 && (
- c2 ||
- c3
- ) && c4;
- if (
- c1 && c2
- )
- foo;
- }
- ]=])
- end)
-
- it('24 is working', function()
- insert_([=[
-
-
- void f()
- {
- switch (x)
- {
- case 1:
- a = b;
- break;
- default:
- a = 0;
- break;
- }
- }
- ]=])
-
- feed_command('set cino=b1')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- switch (x)
- {
- case 1:
- a = b;
- break;
- default:
- a = 0;
- break;
- }
- }
- ]=])
- end)
-
- it('25 is working', function()
- insert_([=[
-
-
- void f()
- {
- invokeme(
- argu,
- ment);
- invokeme(
- argu,
- ment
- );
- invokeme(argu,
- ment
- );
- }
- ]=])
-
- feed_command('set cino=(0,W5')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- invokeme(
- argu,
- ment);
- invokeme(
- argu,
- ment
- );
- invokeme(argu,
- ment
- );
- }
- ]=])
- end)
-
- it('26 is working', function()
- insert_([=[
-
-
- void f()
- {
- statement;
- // comment 1
- // comment 2
- }
- ]=])
-
- feed_command('set cino=/6')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void f()
- {
- statement;
- // comment 1
- // comment 2
- }
- ]=])
- end)
-
- it('27 is working', function()
- insert_([=[
-
-
- void f()
- {
- statement;
- // comment 1
- // comment 2
- }
- ]=])
-
- feed_command('set cino=')
- feed('2kdd]]/comment 1/+1<cr>')
- feed('==<cr>')
-
- expect([=[
-
- void f()
- {
- statement;
- // comment 1
- // comment 2
- }
- ]=])
- end)
-
- it('28 is working', function()
- insert_([=[
-
-
- class CAbc
- {
- int Test() { return FALSE; }
-
- public: // comment
- void testfall();
- protected:
- void testfall();
- };
- ]=])
-
- feed_command('set cino=g0')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- class CAbc
- {
- int Test() { return FALSE; }
-
- public: // comment
- void testfall();
- protected:
- void testfall();
- };
- ]=])
- end)
-
- it('29 is working', function()
- insert_([=[
-
-
- class Foo : public Bar
- {
- public:
- virtual void method1(void) = 0;
- virtual void method2(int arg1,
- int arg2,
- int arg3) = 0;
- };
- ]=])
-
- feed_command('set cino=(0,gs,hs')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- class Foo : public Bar
- {
- public:
- virtual void method1(void) = 0;
- virtual void method2(int arg1,
- int arg2,
- int arg3) = 0;
- };
- ]=])
- end)
-
- it('30 is working', function()
- insert_([=[
-
-
- void
- foo()
- {
- if (a)
- {
- } else
- asdf;
- }
- ]=])
-
- feed_command('set cino=+20')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- void
- foo()
- {
- if (a)
- {
- } else
- asdf;
- }
- ]=])
- end)
-
- it('31 is working', function()
- insert_([=[
-
-
- {
- averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
- asdasdf,
- func(asdf,
- asdfadsf),
- asdfasdf
- );
-
- /* those are ugly, but consequent */
-
- func()->asd(asdasdf,
- averylongfunctionname(
- abc,
- dec)->averylongfunctionname(
- asdfadsf,
- asdfasdf,
- asdfasdf,
- ),
- func(asdfadf,
- asdfasdf
- ),
- asdasdf
- );
-
- averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
- abc,
- dec)->asdfasdfasdf(
- asdfadsf,
- asdfasdf,
- asdfasdf,
- ),
- func(asdfadf,
- asdfasdf),
- asdasdf
- );
- }
- ]=])
-
- feed_command('set cino=(0,W2s')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- {
- averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
- asdasdf,
- func(asdf,
- asdfadsf),
- asdfasdf
- );
-
- /* those are ugly, but consequent */
-
- func()->asd(asdasdf,
- averylongfunctionname(
- abc,
- dec)->averylongfunctionname(
- asdfadsf,
- asdfasdf,
- asdfasdf,
- ),
- func(asdfadf,
- asdfasdf
- ),
- asdasdf
- );
-
- averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
- abc,
- dec)->asdfasdfasdf(
- asdfadsf,
- asdfasdf,
- asdfasdf,
- ),
- func(asdfadf,
- asdfasdf),
- asdasdf
- );
- }
- ]=])
- end)
-
- it('32 is working', function()
- insert_([=[
-
-
- int main ()
- {
- if (cond1 &&
- cond2
- )
- foo;
- }
- ]=])
-
- feed_command('set cino=M1')
- feed('2kdd]]=][<cr>')
-
- expect([=[
-
- int main ()
- {
- if (cond1 &&
- cond2
- )
- foo;
- }
- ]=])
- end)
-
- it('33 is working', function()
- insert_([=[
-
-
- void func(int a
- #if defined(FOO)
- , int b
- , int c
- #endif
- )
- {
- }
- ]=])
-
- feed_command('set cino=(0,ts')
- feed('2kdd2j=][<cr>')
-
- expect([=[
-
- void func(int a
- #if defined(FOO)
- , int b
- , int c
- #endif
- )
- {
- }
- ]=])
- end)
-
- it('34 is working', function()
- insert_([=[
-
-
-
- void
- func(int a
- #if defined(FOO)
- , int b
- , int c
- #endif
- )
- {
- }
- ]=])
-
- feed_command('set cino=(0')
- feed('2kdd2j=][<cr>')
-
- expect([=[
-
-
- void
- func(int a
- #if defined(FOO)
- , int b
- , int c
- #endif
- )
- {
- }
- ]=])
- end)
-
- it('35 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if(x==y)
- if(y==z)
- foo=1;
- else { bar=1;
- baz=2;
- }
- printf("Foo!\n");
- }
-
- void func1(void)
- {
- char* tab[] = {"foo", "bar",
- "baz", "quux",
- "this line used", "to be indented incorrectly"};
- foo();
- }
-
- void func2(void)
- {
- int tab[] =
- {1, 2,
- 3, 4,
- 5, 6};
-
- printf("This line used to be indented incorrectly.\n");
- }
-
- int foo[]
- #ifdef BAR
-
- = { 1, 2, 3,
- 4, 5, 6 }
-
- #endif
- ;
- int baz;
-
- void func3(void)
- {
- int tab[] = {
- 1, 2,
- 3, 4,
- 5, 6};
-
- printf("Don't you dare indent this line incorrectly!\n");
- }
-
- void
- func4(a, b,
- c)
- int a;
- int b;
- int c;
- {
- }
-
- void
- func5(
- int a,
- int b)
- {
- }
-
- void
- func6(
- int a)
- {
- }
- ]=])
-
- feed_command('set cino&')
- feed('2kdd2j=7][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if(x==y)
- if(y==z)
- foo=1;
- else { bar=1;
- baz=2;
- }
- printf("Foo!\n");
- }
-
- void func1(void)
- {
- char* tab[] = {"foo", "bar",
- "baz", "quux",
- "this line used", "to be indented incorrectly"};
- foo();
- }
-
- void func2(void)
- {
- int tab[] =
- {1, 2,
- 3, 4,
- 5, 6};
-
- printf("This line used to be indented incorrectly.\n");
- }
-
- int foo[]
- #ifdef BAR
-
- = { 1, 2, 3,
- 4, 5, 6 }
-
- #endif
- ;
- int baz;
-
- void func3(void)
- {
- int tab[] = {
- 1, 2,
- 3, 4,
- 5, 6};
-
- printf("Don't you dare indent this line incorrectly!\n");
- }
-
- void
- func4(a, b,
- c)
- int a;
- int b;
- int c;
- {
- }
-
- void
- func5(
- int a,
- int b)
- {
- }
-
- void
- func6(
- int a)
- {
- }
- ]=])
- end)
-
- it('36 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- int tab[] =
- {
- 1, 2, 3,
- 4, 5, 6};
-
- printf("Indent this line correctly!\n");
-
- switch (foo)
- {
- case bar:
- printf("bar");
- break;
- case baz: {
- printf("baz");
- break;
- }
- case quux:
- printf("But don't break the indentation of this instruction\n");
- break;
- }
- }
- ]=])
-
- feed_command('set cino&')
- feed_command('set cino+=l1')
- feed('2kdd2j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- int tab[] =
- {
- 1, 2, 3,
- 4, 5, 6};
-
- printf("Indent this line correctly!\n");
-
- switch (foo)
- {
- case bar:
- printf("bar");
- break;
- case baz: {
- printf("baz");
- break;
- }
- case quux:
- printf("But don't break the indentation of this instruction\n");
- break;
- }
- }
- ]=])
- end)
-
- it('37 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- cout << "a"
- << "b"
- << ") :"
- << "c";
- }
- ]=])
-
- feed_command('set cino&')
- feed('2kdd2j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- cout << "a"
- << "b"
- << ") :"
- << "c";
- }
- ]=])
- end)
-
- it('38 is working', function()
- insert_([=[
-
- void func(void)
- {
- /*
- * This is a comment.
- */
- }
- ]=])
-
- feed_command('set com=s1:/*,m:*,ex:*/')
- feed(']]3jofoo();<esc>')
-
- expect([=[
-
- void func(void)
- {
- /*
- * This is a comment.
- */
- foo();
- }
- ]=])
- end)
-
- it('39 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- for (int i = 0; i < 10; ++i)
- if (i & 1) {
- foo(1);
- } else
- foo(0);
- baz();
- }
- ]=])
-
- feed_command('set cino&')
- feed('2kdd2j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- for (int i = 0; i < 10; ++i)
- if (i & 1) {
- foo(1);
- } else
- foo(0);
- baz();
- }
- ]=])
- end)
-
- it('40 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
-
- feed_command('set cino=k2s,(0')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
- end)
-
- it('41 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
-
- feed_command('set cino=k2s,(s')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
- end)
-
- it('42 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
-
- feed_command('set cino=k2s,(s,U1')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- c = c1 &&
- (
- c2 ||
- c3
- ) && c4;
- }
- ]=])
- end)
-
- it('43 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- if ( c1
- && ( c2
- || c3))
- foo;
-
- a_long_line(
- argument,
- argument);
- a_short_line(argument,
- argument);
- }
- ]=])
-
- feed_command('set cino=k2s,(0,W4')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- if ( c1
- && ( c2
- || c3))
- foo;
-
- a_long_line(
- argument,
- argument);
- a_short_line(argument,
- argument);
- }
- ]=])
- end)
-
- it('44 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
- }
- ]=])
-
- feed_command('set cino=k2s,u2')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
- }
- ]=])
- end)
-
- it('45 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
-
- feed_command('set cino=k2s,(0,w1')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- if (c123456789
- && (c22345
- || c3))
- printf("foo\n");
-
- if ( c1
- && ( c2
- || c3))
- foo;
- func( c1
- && ( c2
- || c3))
- foo;
- }
- ]=])
- end)
-
- it('46 is working', function()
- insert_([=[
-
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- }
- ]=])
-
- feed_command('set cino=k2,(s')
- feed('2kdd3j=][<cr>')
-
- expect([=[
-
- void func(void)
- {
- if (condition1
- && condition2)
- action();
- function(argument1
- && argument2);
-
- if (c1 && (c2 ||
- c3))
- foo;
- if (c1 &&
- (c2 || c3))
- {
- }
- }
- ]=])
- end)
-
- it('47 is working', function()
- insert_([=[
-
- NAMESPACESTART
- /* valid namespaces with normal indent */
- namespace
- {
- {
- 111111111111;
- }
- }
- namespace /* test */
- {
- 11111111111111111;
- }
- namespace // test
- {
- 111111111111111111;
- }
- namespace
- {
- 111111111111111111;
- }
- namespace test
- {
- 111111111111111111;
- }
- namespace test::cpp17
- {
- 111111111111111111;
- }
- namespace ::incorrectcpp17
- {
- 111111111111111111;
- }
- namespace test::incorrectcpp17::
- {
- 111111111111111111;
- }
- namespace test:incorrectcpp17
- {
- 111111111111111111;
- }
- namespace test:::incorrectcpp17
- {
- 111111111111111111;
- }
- namespace{
- 111111111111111111;
- }
- namespace test{
- 111111111111111111;
- }
- namespace {
- 111111111111111111;
- }
- namespace test {
- 111111111111111111;
- namespace test2 {
- 22222222222222222;
- }
- }
-
- /* invalid namespaces use block indent */
- namespace test test2 {
- 111111111111111111111;
- }
- namespace11111111111 {
- 111111111111;
- }
- namespace() {
- 1111111111111;
- }
- namespace()
- {
- 111111111111111111;
- }
- namespace test test2
- {
- 1111111111111111111;
- }
- namespace111111111
- {
- 111111111111111111;
- }
- NAMESPACEEND
- ]=])
-
- feed_command('set cino=N-s')
- feed_command('/^NAMESPACESTART')
- feed('=/^NAMESPACEEND<cr>')
-
- expect([=[
-
- NAMESPACESTART
- /* valid namespaces with normal indent */
- namespace
- {
- {
- 111111111111;
- }
- }
- namespace /* test */
- {
- 11111111111111111;
- }
- namespace // test
- {
- 111111111111111111;
- }
- namespace
- {
- 111111111111111111;
- }
- namespace test
- {
- 111111111111111111;
- }
- namespace test::cpp17
- {
- 111111111111111111;
- }
- namespace ::incorrectcpp17
- {
- 111111111111111111;
- }
- namespace test::incorrectcpp17::
- {
- 111111111111111111;
- }
- namespace test:incorrectcpp17
- {
- 111111111111111111;
- }
- namespace test:::incorrectcpp17
- {
- 111111111111111111;
- }
- namespace{
- 111111111111111111;
- }
- namespace test{
- 111111111111111111;
- }
- namespace {
- 111111111111111111;
- }
- namespace test {
- 111111111111111111;
- namespace test2 {
- 22222222222222222;
- }
- }
-
- /* invalid namespaces use block indent */
- namespace test test2 {
- 111111111111111111111;
- }
- namespace11111111111 {
- 111111111111;
- }
- namespace() {
- 1111111111111;
- }
- namespace()
- {
- 111111111111111111;
- }
- namespace test test2
- {
- 1111111111111111111;
- }
- namespace111111111
- {
- 111111111111111111;
- }
- NAMESPACEEND
- ]=])
- end)
-
- it('48 is working', function()
- insert_([=[
-
- JSSTART
- var bar = {
- foo: {
- that: this,
- some: ok,
- },
- "bar":{
- a : 2,
- b: "123abc",
- x: 4,
- "y": 5
- }
- }
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- var bar = {
- foo: {
- that: this,
- some: ok,
- },
- "bar":{
- a : 2,
- b: "123abc",
- x: 4,
- "y": 5
- }
- }
- JSEND
- ]=])
- end)
-
- it('49 is working', function()
- insert_([=[
-
- JSSTART
- var foo = [
- 1,
- 2,
- 3
- ];
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- var foo = [
- 1,
- 2,
- 3
- ];
- JSEND
- ]=])
- end)
-
- it('50 is working', function()
- insert_([=[
-
- JSSTART
- function bar() {
- var foo = [
- 1,
- 2,
- 3
- ];
- }
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- function bar() {
- var foo = [
- 1,
- 2,
- 3
- ];
- }
- JSEND
- ]=])
- end)
-
- it('51 is working', function()
- insert_([=[
-
- JSSTART
- (function($){
-
- if (cond &&
- cond) {
- stmt;
- }
- window.something.left =
- (width - 50 + offset) + "px";
- var class_name='myclass';
-
- function private_method() {
- }
-
- var public_method={
- method: function(options,args){
- private_method();
- }
- }
-
- function init(options) {
-
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
-
- $.fn[class_name]=function() {
-
- var _arguments=arguments;
- return this.each(function(){
-
- var options=$(this).data(class_name+'_public');
- if (!options) {
- init.apply(this,_arguments);
-
- } else {
- var method=public_method[_arguments[0]];
-
- if (typeof(method)!='function') {
- console.log(class_name+' has no method "'+_arguments[0]+'"');
- return false;
- }
- _arguments[0]=options;
- method.apply(this,_arguments);
- }
- });
- }
-
- })(jQuery);
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- (function($){
-
- if (cond &&
- cond) {
- stmt;
- }
- window.something.left =
- (width - 50 + offset) + "px";
- var class_name='myclass';
-
- function private_method() {
- }
-
- var public_method={
- method: function(options,args){
- private_method();
- }
- }
-
- function init(options) {
-
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
-
- $.fn[class_name]=function() {
-
- var _arguments=arguments;
- return this.each(function(){
-
- var options=$(this).data(class_name+'_public');
- if (!options) {
- init.apply(this,_arguments);
-
- } else {
- var method=public_method[_arguments[0]];
-
- if (typeof(method)!='function') {
- console.log(class_name+' has no method "'+_arguments[0]+'"');
- return false;
- }
- _arguments[0]=options;
- method.apply(this,_arguments);
- }
- });
- }
-
- })(jQuery);
- JSEND
- ]=])
- end)
-
- it('52 is working', function()
- insert_([=[
-
- JSSTART
- function init(options) {
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- function init(options) {
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
- JSEND
- ]=])
- end)
-
- it('53 is working', function()
- insert_([=[
-
- JSSTART
- (function($){
- function init(options) {
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
- })(jQuery);
- JSEND
- ]=])
-
- feed_command('set cino=j1,J1')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- (function($){
- function init(options) {
- $(this).data(class_name+'_public',$.extend({},{
- foo: 'bar',
- bar: 2,
- foobar: [
- 1,
- 2,
- 3
- ],
- callback: function(){
- return true;
- }
- }, options||{}));
- }
- })(jQuery);
- JSEND
- ]=])
- end)
-
- it('javascript indent / vim-patch 7.4.670', function()
- insert_([=[
-
- JSSTART
- // Results of JavaScript indent
- // 1
- (function(){
- var a = [
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 2
- (function(){
- var a = [
- 0 +
- 5 *
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 3
- (function(){
- var a = [
- 0 +
- // comment 1
- 5 *
- /* comment 2 */
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 4
- {
- var a = [
- 0,
- 1
- ];
- var b;
- var c;
- }
-
- // 5
- {
- var a = [
- [
- 0
- ],
- 2,
- 3
- ];
- }
-
- // 6
- {
- var a = [
- [
- 0,
- 1
- ],
- 2,
- 3
- ];
- }
-
- // 7
- {
- var a = [
- // [
- 0,
- // 1
- // ],
- 2,
- 3
- ];
- }
-
- // 8
- var x = [
- (function(){
- var a,
- b,
- c,
- d,
- e,
- f,
- g,
- h,
- i;
- })
- ];
-
- // 9
- var a = [
- 0 +
- 5 *
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
-
- // 10
- var a,
- b,
- c,
- d,
- e,
- f,
- g,
- h,
- i;
- JSEND
- ]=])
-
- -- :set cino=j1,J1,+2
- feed_command('set cino=j1,J1,+2')
- feed_command('/^JSSTART')
- feed('=/^JSEND<cr>')
-
- expect([=[
-
- JSSTART
- // Results of JavaScript indent
- // 1
- (function(){
- var a = [
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 2
- (function(){
- var a = [
- 0 +
- 5 *
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 3
- (function(){
- var a = [
- 0 +
- // comment 1
- 5 *
- /* comment 2 */
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
- }())
-
- // 4
- {
- var a = [
- 0,
- 1
- ];
- var b;
- var c;
- }
-
- // 5
- {
- var a = [
- [
- 0
- ],
- 2,
- 3
- ];
- }
-
- // 6
- {
- var a = [
- [
- 0,
- 1
- ],
- 2,
- 3
- ];
- }
-
- // 7
- {
- var a = [
- // [
- 0,
- // 1
- // ],
- 2,
- 3
- ];
- }
-
- // 8
- var x = [
- (function(){
- var a,
- b,
- c,
- d,
- e,
- f,
- g,
- h,
- i;
- })
- ];
-
- // 9
- var a = [
- 0 +
- 5 *
- 9 *
- 'a',
- 'b',
- 0 +
- 5 *
- 9 *
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i'
- ];
-
- // 10
- var a,
- b,
- c,
- d,
- e,
- f,
- g,
- h,
- i;
- JSEND
- ]=])
- end)
-
- it('line continuations in macros / vim-patch 8.0.0148', function()
- insert_([=[
- /* start of define */
- {
- }
- #define AAA \
- BBB\
- CCC
-
- #define CNT \
- 1 + \
- 2 + \
- 4
- /* end of define */]=])
-
- feed_command('set cino&')
- feed_command('/start of define')
- feed('=/end of define<cr>')
-
- expect([=[
- /* start of define */
- {
- }
- #define AAA \
- BBB\
- CCC
-
- #define CNT \
- 1 + \
- 2 + \
- 4
- /* end of define */]=])
- end)
-
- it('* immediately follows comment / vim-patch 8.0.1291', function()
- insert_([=[
- {
- a = second/*bug*/*line;
- }]=])
-
- feed_command('set cin cino&')
- feed_command('/a = second')
- feed('ox')
-
- expect([=[
- {
- a = second/*bug*/*line;
- x
- }]=])
- end)
-end)
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index c2b22472bf..dd6a9d0bde 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -19,36 +19,10 @@ describe('assert function:', function()
clear()
end)
- describe('assert_beeps', function()
- it('works', function()
- call('assert_beeps', 'normal h')
- expected_empty()
- call('assert_beeps', 'normal 0')
- expected_errors({'command did not beep: normal 0'})
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(0, 'normal h'->assert_beeps())
- call assert_equal(1, 'normal 0'->assert_beeps())
- ]]
- expected_errors({tmpname .. ' line 2: command did not beep: normal 0'})
- end)
- end)
-
-- assert_equal({expected}, {actual}, [, {msg}])
describe('assert_equal', function()
it('should not change v:errors when expected is equal to actual', function()
source([[
- let s = 'foo'
- call assert_equal('foo', s)
- let n = 4
- call assert_equal(4, n)
- let l = [1, 2, 3]
- call assert_equal([1, 2, 3], l)
- call assert_equal(v:_null_list, v:_null_list)
- call assert_equal(v:_null_list, [])
- call assert_equal([], v:_null_list)
fu Func()
endfu
let F1 = function('Func')
@@ -98,30 +72,6 @@ describe('assert function:', function()
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
exc_exec('call CheckAssert()'))
end)
-
- it('can specify a message and get a message about what failed', function()
- call('assert_equal', 'foo', 'bar', 'testing')
- expected_errors({"testing: Expected 'foo' but got 'bar'"})
- end)
-
- it('should shorten a long message', function()
- call ('assert_equal', 'XxxxxxxxxxxxxxxxxxxxxxX', 'XyyyyyyyyyyyyyyyyyyyyyyyyyX')
- expected_errors({"Expected 'X\\[x occurs 21 times]X' but got 'X\\[y occurs 25 times]X'"})
- end)
- end)
-
- -- assert_notequal({expected}, {actual}[, {msg}])
- describe('assert_notequal', function()
- it('should not change v:errors when expected differs from actual', function()
- eq(0, call('assert_notequal', 'foo', 4))
- eq(0, call('assert_notequal', {1, 2, 3}, 'foo'))
- expected_empty()
- end)
-
- it('should change v:errors when expected is equal to actual', function()
- eq(1, call('assert_notequal', 'foo', 'foo'))
- expected_errors({"Expected not equal to 'foo'"})
- end)
end)
-- assert_false({actual}, [, {msg}])
@@ -141,14 +91,6 @@ describe('assert function:', function()
call('assert_false', {})
expected_errors({'Expected False but got []'})
end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(0, v:false->assert_false())
- call assert_equal(1, 123->assert_false())
- ]]
- expected_errors({tmpname .. ' line 2: Expected False but got 123'})
- end)
end)
-- assert_true({actual}, [, {msg}])
@@ -164,14 +106,6 @@ describe('assert function:', function()
eq(1, call('assert_true', 1.5))
expected_errors({'Expected True but got 1.5'})
end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(0, v:true->assert_true())
- call assert_equal(1, 0->assert_true())
- ]]
- expected_errors({tmpname .. ' line 2: Expected True but got 0'})
- end)
end)
describe('v:errors', function()
@@ -217,76 +151,10 @@ describe('assert function:', function()
tmpname_two .. " line 1: file two: Expected True but got ''",
})
end)
-
- it('is reset to a list by assert functions', function()
- source([[
- let save_verrors = v:errors
- let v:['errors'] = {'foo': 3}
- call assert_equal('yes', 'no')
- let verrors = v:errors
- let v:errors = save_verrors
- call assert_equal(type([]), type(verrors))
- ]])
- expected_empty()
- end)
- end)
-
- -- assert_match({pat}, {text}[, {msg}])
- describe('assert_match', function()
- it('should not change v:errors when pat matches text', function()
- call('assert_match', '^f.*b.*r$', 'foobar')
- expected_empty()
- end)
-
- it('should change v:errors when pat does not match text', function()
- call('assert_match', 'bar.*foo', 'foobar')
- expected_errors({"Pattern 'bar.*foo' does not match 'foobar'"})
- end)
-
- it('should set v:errors to msg when given and match fails', function()
- call('assert_match', 'bar.*foo', 'foobar', 'wrong')
- expected_errors({"wrong: Pattern 'bar.*foo' does not match 'foobar'"})
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(1, 'foobar'->assert_match('bar.*foo', 'wrong'))
- ]]
- expected_errors({
- tmpname .. " line 1: wrong: Pattern 'bar.*foo' does not match 'foobar'"
- })
- end)
- end)
-
- -- assert_notmatch({pat}, {text}[, {msg}])
- describe('assert_notmatch', function()
- it('should not change v:errors when pat does not match text', function()
- call('assert_notmatch', 'foo', 'bar')
- call('assert_notmatch', '^foobar$', 'foobars')
- expected_empty()
- end)
-
- it('should change v:errors when pat matches text', function()
- call('assert_notmatch', 'foo', 'foobar')
- expected_errors({"Pattern 'foo' does match 'foobar'"})
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(1, 'foobar'->assert_notmatch('foo'))
- ]]
- expected_errors({tmpname .. " line 1: Pattern 'foo' does match 'foobar'"})
- end)
end)
-- assert_fails({cmd}, [, {error}])
describe('assert_fails', function()
- it('should change v:errors when error does not match v:errmsg', function()
- eq(1, eval([[assert_fails('xxx', 'E12345')]]))
- command([[call assert_match("Expected 'E12345' but got 'E492:", v:errors[0])]])
- expected_errors({"Expected 'E12345' but got 'E492: Not an editor command: xxx': xxx"})
- end)
-
it('should not change v:errors when cmd errors', function()
eq(0, eval([[assert_fails('NonexistentCmd')]]))
expected_empty()
@@ -296,106 +164,5 @@ describe('assert function:', function()
eq(1, eval([[assert_fails('call empty("")', '')]]))
expected_errors({'command did not fail: call empty("")'})
end)
-
- it('can specify and get a message about what failed', function()
- eq(1, eval([[assert_fails('xxx', 'E9876', 'stupid')]]))
- command([[call assert_match("stupid: Expected 'E9876' but got 'E492:", v:errors[0])]])
- expected_errors({"stupid: Expected 'E9876' but got 'E492: Not an editor command: xxx': stupid"})
- end)
-
- it('can specify and get a message even when cmd succeeds', function()
- eq(1, eval([[assert_fails('echo', '', 'echo command')]]))
- expected_errors({'command did not fail: echo command'})
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(1, 'echo'->assert_fails('', 'echo command'))
- ]]
- expected_errors({
- tmpname .. ' line 1: command did not fail: echo command'
- })
- end)
- end)
-
- -- assert_inrange({lower}, {upper}, {actual}[, {msg}])
- describe('assert_inrange()', function()
- it('should not change v:errors when actual is in range', function()
- call('assert_inrange', 7, 7, 7)
- call('assert_inrange', 5, 7, 5)
- call('assert_inrange', 5, 7, 6)
- call('assert_inrange', 5, 7, 7)
- expected_empty()
- end)
-
- it('should change v:errors when actual is not in range', function()
- call('assert_inrange', 5, 7, 4)
- call('assert_inrange', 5, 7, 8)
- expected_errors({
- "Expected range 5 - 7, but got 4",
- "Expected range 5 - 7, but got 8",
- })
- end)
-
- it('assert_inrange(1, 1) returns E119', function()
- eq('Vim(call):E119: Not enough arguments for function: assert_inrange',
- exc_exec("call assert_inrange(1, 1)"))
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(0, 5->assert_inrange(5, 7))
- call assert_equal(0, 7->assert_inrange(5, 7))
- call assert_equal(1, 8->assert_inrange(5, 7))
- ]]
- expected_errors({tmpname .. ' line 3: Expected range 5 - 7, but got 8'})
- end)
- end)
-
- -- assert_report({msg})
- describe('assert_report()', function()
- it('should add a message to v:errors', function()
- eq(1, call('assert_report', 'something is wrong'))
- command("call assert_match('something is wrong', v:errors[0])")
- command('call remove(v:errors, 0)')
- expected_empty()
- end)
-
- it('can be used as a method', function()
- local tmpname = source [[
- call assert_equal(1, 'also wrong'->assert_report())
- ]]
- expected_errors({tmpname .. ' line 1: also wrong'})
- end)
- end)
-
- -- assert_exception({cmd}, [, {error}])
- describe('assert_exception()', function()
- it('should assert thrown exceptions properly', function()
- source([[
- try
- nocommand
- catch
- call assert_equal(0, assert_exception('E492'))
- endtry
- ]])
- expected_empty()
- end)
-
- it('should work properly when nested', function()
- source([[
- try
- nocommand
- catch
- try
- " illegal argument, get NULL for error
- call assert_equal(1, assert_exception([]))
- catch
- call assert_equal(0, assert_exception('E730'))
- endtry
- endtry
- ]])
- expected_empty()
- end)
end)
end)
diff --git a/test/functional/legacy/cdo_spec.lua b/test/functional/legacy/cdo_spec.lua
deleted file mode 100644
index 8b3216cbfd..0000000000
--- a/test/functional/legacy/cdo_spec.lua
+++ /dev/null
@@ -1,228 +0,0 @@
--- Tests for the :cdo, :cfdo, :ldo and :lfdo commands
-
-local helpers = require('test.functional.helpers')(after_each)
-local nvim, clear = helpers.meths, helpers.clear
-local call, feed = helpers.call, helpers.feed
-local source, eq = helpers.source, helpers.eq
-
-local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
-end
-
-describe('cdo', function()
- before_each(function()
- clear()
-
- call('writefile', {'Line1', 'Line2', 'Line3'}, 'Xtestfile1')
- call('writefile', {'Line1', 'Line2', 'Line3'}, 'Xtestfile2')
- call('writefile', {'Line1', 'Line2', 'Line3'}, 'Xtestfile3')
-
- source([=[
- " Returns the current line in '<filename> <linenum>L <column>C' format
- function GetRuler()
- return expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C'
- endfunction
-
- " Tests for the :cdo and :ldo commands
- function XdoTests(cchar)
- enew
-
- " Shortcuts for calling the cdo and ldo commands
- let Xdo = a:cchar . 'do'
- let Xgetexpr = a:cchar . 'getexpr'
- let Xprev = a:cchar. 'prev'
- let XdoCmd = Xdo . ' call add(l, GetRuler())'
-
- " Try with an empty list
- let l = []
- exe XdoCmd
- call assert_equal([], l)
-
- " Populate the list and then try
- exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:3:1:Line3']"
-
- let l = []
- exe XdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l)
-
- " Run command only on selected error lines
- let l = []
- enew
- exe "2,3" . XdoCmd
- call assert_equal(['Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l)
-
- " Boundary condition tests
- let l = []
- enew
- exe "1,1" . XdoCmd
- call assert_equal(['Xtestfile1 1L 3C'], l)
-
- let l = []
- enew
- exe "3" . XdoCmd
- call assert_equal(['Xtestfile3 3L 1C'], l)
-
- " Range test commands
- let l = []
- enew
- exe "%" . XdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l)
-
- let l = []
- enew
- exe "1,$" . XdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l)
-
- let l = []
- enew
- exe Xprev
- exe "." . XdoCmd
- call assert_equal(['Xtestfile2 2L 2C'], l)
-
- let l = []
- enew
- exe "+" . XdoCmd
- call assert_equal(['Xtestfile3 3L 1C'], l)
-
- " Invalid error lines test
- let l = []
- enew
- exe "silent! 27" . XdoCmd
- exe "silent! 4,5" . XdoCmd
- call assert_equal([], l)
-
- " Run commands from an unsaved buffer when 'hidden' is unset
- set nohidden
- let v:errmsg=''
- let l = []
- enew
- setlocal modified
- exe "silent! 2,2" . XdoCmd
- if v:errmsg !~# 'No write since last change'
- call add(v:errors, 'Unsaved file change test failed')
- endif
-
- " If the executed command fails, then the operation should be aborted
- enew!
- let subst_count = 0
- exe "silent!" . Xdo . " s/Line/xLine/ | let subst_count += 1"
- if subst_count != 1 || getline('.') != 'xLine1'
- call add(v:errors, 'Abort command on error test failed')
- endif
- set hidden
-
- let l = []
- exe "2,2" . Xdo . "! call add(l, GetRuler())"
- call assert_equal(['Xtestfile2 2L 2C'], l)
-
- " List with no valid error entries
- let l = []
- edit! +2 Xtestfile1
- exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
- exe XdoCmd
- call assert_equal([], l)
- exe "silent! 2" . XdoCmd
- call assert_equal([], l)
- let v:errmsg=''
- exe "%" . XdoCmd
- exe "1,$" . XdoCmd
- exe "." . XdoCmd
- call assert_equal('', v:errmsg)
-
- " List with only one valid entry
- let l = []
- exe Xgetexpr . " ['Xtestfile3:3:1:Line3']"
- exe XdoCmd
- call assert_equal(['Xtestfile3 3L 1C'], l)
-
- endfunction
-
- " Tests for the :cfdo and :lfdo commands
- function XfdoTests(cchar)
- enew
-
- " Shortcuts for calling the cfdo and lfdo commands
- let Xfdo = a:cchar . 'fdo'
- let Xgetexpr = a:cchar . 'getexpr'
- let XfdoCmd = Xfdo . ' call add(l, GetRuler())'
- let Xpfile = a:cchar. 'pfile'
-
- " Clear the quickfix/location list
- exe Xgetexpr . " []"
-
- " Try with an empty list
- let l = []
- exe XfdoCmd
- call assert_equal([], l)
-
- " Populate the list and then try
- exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', 'Xtestfile1:2:1:Line2', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:2:3:Line2', 'Xtestfile3:3:1:Line3']"
-
- let l = []
- exe XfdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l)
-
- " Run command only on selected error lines
- let l = []
- exe "2,3" . XfdoCmd
- call assert_equal(['Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l)
-
- " Boundary condition tests
- let l = []
- exe "3" . XfdoCmd
- call assert_equal(['Xtestfile3 2L 3C'], l)
-
- " Range test commands
- let l = []
- exe "%" . XfdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l)
-
- let l = []
- exe "1,$" . XfdoCmd
- call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l)
-
- let l = []
- exe Xpfile
- exe "." . XfdoCmd
- call assert_equal(['Xtestfile2 2L 2C'], l)
-
- " List with only one valid entry
- let l = []
- exe Xgetexpr . " ['Xtestfile2:2:5:Line2']"
- exe XfdoCmd
- call assert_equal(['Xtestfile2 2L 5C'], l)
-
- endfunction
- ]=])
- end)
-
- after_each(function()
- os.remove('Xtestfile1')
- os.remove('Xtestfile2')
- os.remove('Xtestfile3')
- end)
-
- it('works for :cdo', function()
- -- call('XdoTests', 'c')
- feed(":call XdoTests('c')<CR><C-l>")
- expected_empty()
- end)
-
- it('works for :cfdo', function()
- -- call('XfdoTests', 'c')
- feed(":call XfdoTests('c')<CR><C-l>")
- expected_empty()
- end)
-
- it('works for :ldo', function()
- -- call('XdoTests', 'l')
- feed(":call XdoTests('l')<CR><C-l>")
- expected_empty()
- end)
-
- it('works for :lfdo', function()
- -- call('XfdoTests', 'l')
- feed(":call XfdoTests('l')<CR><C-l>")
- expected_empty()
- end)
-end)
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index b5de5cd232..05d853622e 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -666,7 +666,7 @@ describe('eval', function()
source([[
" Vim script used in test_eval.in. Needed for script-local function.
- func! s:Testje()
+ func s:Testje()
return "foo"
endfunc
diff --git a/test/functional/legacy/ex_mode_spec.lua b/test/functional/legacy/ex_mode_spec.lua
new file mode 100644
index 0000000000..44719027a6
--- /dev/null
+++ b/test/functional/legacy/ex_mode_spec.lua
@@ -0,0 +1,36 @@
+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 meths = helpers.meths
+
+before_each(clear)
+
+describe('Ex mode', function()
+ it('supports command line editing', function()
+ local function test_ex_edit(expected, cmd)
+ feed('gQ' .. cmd .. '<C-b>"<CR>')
+ local ret = eval('@:[1:]') -- Remove leading quote.
+ feed('visual<CR>')
+ eq(meths.replace_termcodes(expected, true, true, true), ret)
+ end
+ command('set sw=2')
+ test_ex_edit('bar', 'foo bar<C-u>bar')
+ test_ex_edit('1<C-u>2', '1<C-v><C-u>2')
+ test_ex_edit('213', '1<C-b>2<C-e>3')
+ test_ex_edit('2013', '01<Home>2<End>3')
+ test_ex_edit('0213', '01<Left>2<Right>3')
+ test_ex_edit('0342', '012<Left><Left><Insert>3<Insert>4')
+ test_ex_edit('foo ', 'foo bar<C-w>')
+ test_ex_edit('foo', 'fooba<Del><Del>')
+ test_ex_edit('foobar', 'foo<Tab>bar')
+ test_ex_edit('abbreviate', 'abbrev<Tab>')
+ test_ex_edit('1<C-t><C-t>', '1<C-t><C-t>')
+ test_ex_edit('1<C-t><C-t>', '1<C-t><C-t><C-d>')
+ test_ex_edit(' foo', ' foo<C-d>')
+ test_ex_edit(' foo0', ' foo0<C-d>')
+ test_ex_edit(' foo^', ' foo^<C-d>')
+ end)
+end)
diff --git a/test/functional/legacy/excmd_spec.lua b/test/functional/legacy/excmd_spec.lua
new file mode 100644
index 0000000000..174f7d292e
--- /dev/null
+++ b/test/functional/legacy/excmd_spec.lua
@@ -0,0 +1,32 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local meths = helpers.meths
+local source = helpers.source
+local eq = helpers.eq
+
+local function sizeoflong()
+ if not exec_lua('return pcall(require, "ffi")') then
+ pending('missing LuaJIT FFI')
+ end
+ return exec_lua('return require("ffi").sizeof(require("ffi").typeof("long"))')
+end
+
+describe('Ex command', function()
+ before_each(clear)
+ after_each(function() eq({}, meths.get_vvar('errors')) end)
+
+ it('checks for address line overflow', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ call setline(1, 'text')
+ call assert_fails('|.44444444444444444444444', 'E1247:')
+ call assert_fails('|.9223372036854775806', 'E1247:')
+ bwipe!
+ ]]
+ end)
+end)
diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua
deleted file mode 100644
index cd3713eabe..0000000000
--- a/test/functional/legacy/expand_spec.lua
+++ /dev/null
@@ -1,129 +0,0 @@
--- Test for expanding file names
-
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local call = helpers.call
-local nvim = helpers.meths
-local clear = helpers.clear
-local source = helpers.source
-
-local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
-end
-
-describe('expand file name', function()
- after_each(function()
- helpers.rmdir('Xdir1')
- helpers.rmdir('Xdir2')
- helpers.rmdir('Xdir3')
- helpers.rmdir('Xdir4')
- end)
-
- before_each(function()
- clear()
-
- source([[
- func Test_with_directories()
- call mkdir('Xdir1')
- call mkdir('Xdir2')
- call mkdir('Xdir3')
- cd Xdir3
- call mkdir('Xdir4')
- cd ..
-
- split Xdir1/file
- call setline(1, ['a', 'b'])
- w
- w Xdir3/Xdir4/file
- close
-
- next Xdir?/*/file
- call assert_equal('Xdir3/Xdir4/file', expand('%'))
- if has('unix')
- next! Xdir?/*/nofile
- call assert_equal('Xdir?/*/nofile', expand('%'))
- endif
- " Edit another file, on MS-Windows the swap file would be in use and can't
- " be deleted
- edit foo
-
- call assert_equal(0, delete('Xdir1', 'rf'))
- call assert_equal(0, delete('Xdir2', 'rf'))
- call assert_equal(0, delete('Xdir3', 'rf'))
- endfunc
-
- func Test_with_tilde()
- let dir = getcwd()
- call mkdir('Xdir ~ dir')
- call assert_true(isdirectory('Xdir ~ dir'))
- cd Xdir\ ~\ dir
- call assert_true(getcwd() =~ 'Xdir \~ dir')
- exe 'cd ' . fnameescape(dir)
- call delete('Xdir ~ dir', 'd')
- call assert_false(isdirectory('Xdir ~ dir'))
- endfunc
-
- func Test_expand_tilde_filename()
- split ~
- call assert_equal('~', expand('%'))
- call assert_notequal(expand('%:p'), expand('~/'))
- call assert_match('\~', expand('%:p'))
- bwipe!
- endfunc
-
- func Test_expandcmd()
- let $FOO = 'Test'
- call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y'))
- unlet $FOO
-
- new
- edit Xfile1
- call assert_equal('e Xfile1', expandcmd('e %'))
- edit Xfile2
- edit Xfile1
- call assert_equal('e Xfile2', 'e #'->expandcmd())
- edit Xfile2
- edit Xfile3
- edit Xfile4
- let bnum = bufnr('Xfile2')
- call assert_equal('e Xfile2', expandcmd('e #' . bnum))
- call setline('.', 'Vim!@#')
- call assert_equal('e Vim', expandcmd('e <cword>'))
- call assert_equal('e Vim!@#', expandcmd('e <cWORD>'))
- enew!
- edit Xfile.java
- call assert_equal('e Xfile.py', expandcmd('e %:r.py'))
- call assert_equal('make abc.java', expandcmd('make abc.%:e'))
- call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?'))
- edit a1a2a3.rb
- call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o'))
-
- call assert_fails('call expandcmd("make <afile>")', 'E495:')
- call assert_fails('call expandcmd("make <afile>")', 'E495:')
- enew
- call assert_fails('call expandcmd("make %")', 'E499:')
- close
- endfunc
- ]])
- end)
-
- it('works with directories', function()
- call('Test_with_directories')
- expected_empty()
- end)
-
- it('works with tilde', function()
- call('Test_with_tilde')
- expected_empty()
- end)
-
- it('does not expand tilde if it is a filename', function()
- call('Test_expand_tilde_filename')
- expected_empty()
- end)
-
- it('works with expandcmd()', function()
- call('Test_expandcmd')
- expected_empty()
- end)
-end)
diff --git a/test/functional/legacy/filechanged_spec.lua b/test/functional/legacy/filechanged_spec.lua
new file mode 100644
index 0000000000..6eb853d630
--- /dev/null
+++ b/test/functional/legacy/filechanged_spec.lua
@@ -0,0 +1,131 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, source = helpers.clear, helpers.source
+local call, eq, meths = helpers.call, helpers.eq, helpers.meths
+
+local function expected_empty()
+ eq({}, meths.get_vvar('errors'))
+end
+
+describe('file changed dialog', function()
+ before_each(function()
+ clear()
+ meths.ui_attach(80, 24, {})
+ meths.set_option('autoread', false)
+ meths.set_option('fsync', true)
+ end)
+
+ it('works', function()
+ if helpers.pending_win32(pending) then return end
+ 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
+ call assert_equal('', v:warningmsg)
+ call assert_equal(1, line('$'))
+ call assert_equal('new line', getline(1))
+
+ 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/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua
index dc6ccd3628..7a1afa1fd6 100644
--- a/test/functional/legacy/listchars_spec.lua
+++ b/test/functional/legacy/listchars_spec.lua
@@ -1,7 +1,8 @@
-- Tests for 'listchars' display with 'list' and :list.
local helpers = require('test.functional.helpers')(after_each)
-local feed, insert, source = helpers.feed, helpers.insert, helpers.source
+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
-- luacheck: ignore 621 (Indentation)
@@ -13,7 +14,7 @@ describe("'listchars'", function()
-- luacheck: ignore 613 (Trailing whitespace in a string)
it("works with 'list'", function()
- source([[
+ exec([[
function GetScreenCharsForLine(lnum)
return join(map(range(1, virtcol('$')), 'nr2char(screenchar(a:lnum, v:val))'), '')
endfunction
@@ -98,4 +99,80 @@ describe("'listchars'", function()
.....h>-$
iii<<<<><<$]])
end)
+
+ it('"exceeds" character does not appear in foldcolumn vim-patch:8.2.3121', function()
+ local screen = Screen.new(60, 10)
+ screen:attach()
+ exec([[
+ call setline(1, ['aaa', '', 'a', 'aaaaaa'])
+ vsplit
+ vsplit
+ windo set signcolumn=yes foldcolumn=1 winminwidth=0 nowrap list listchars=extends:>,precedes:<
+ ]])
+ feed('13<C-W>>')
+ screen:expect([[
+ aaa │ a>│ ^aaa |
+ │ │ |
+ a │ a │ a |
+ aaaaaa │ a>│ aaaaaa |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ [No Name] [+] <[+] [No Name] [+] |
+ |
+ ]])
+ feed('<C-W>>')
+ screen:expect([[
+ aaa │ >│ ^aaa |
+ │ │ |
+ a │ a│ a |
+ aaaaaa │ >│ aaaaaa |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ [No Name] [+] <+] [No Name] [+] |
+ |
+ ]])
+ feed('<C-W>>')
+ screen:expect([[
+ aaa │ │ ^aaa |
+ │ │ |
+ a │ │ a |
+ aaaaaa │ │ aaaaaa |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ [No Name] [+] <] [No Name] [+] |
+ |
+ ]])
+ feed('<C-W>>')
+ screen:expect([[
+ aaa │ │ ^aaa |
+ │ │ |
+ a │ │ a |
+ aaaaaa │ │ aaaaaa |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ ~ │~ │~ |
+ [No Name] [+] < [No Name] [+] |
+ |
+ ]])
+ feed('<C-W>>')
+ screen:expect([[
+ aaa │ │ ^aaa |
+ │ │ |
+ a │ │ a |
+ aaaaaa │ │ aaaaaa |
+ ~ │~│~ |
+ ~ │~│~ |
+ ~ │~│~ |
+ ~ │~│~ |
+ [No Name] [+] < [No Name] [+] |
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index d86caca0e9..8d25b9d927 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -195,10 +195,10 @@ describe('memory usage', function()
local after = monitor_memory_usage(pid)
source('bwipe!')
poke_eventloop()
- -- Allow for an increase of 5% in memory usage, which accommodates minor fluctuation,
+ -- Allow for an increase of 10% in memory usage, which accommodates minor fluctuation,
-- but is small enough that if memory were not released (prior to PR #14884), the test
-- would fail.
- local upper = before.last * 1.05
+ local upper = before.last * 1.10
check_result({before=before, after=after}, pcall(ok, after.last <= upper))
end)
end)
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
deleted file mode 100644
index 4f9f5a0237..0000000000
--- a/test/functional/legacy/packadd_spec.lua
+++ /dev/null
@@ -1,507 +0,0 @@
--- Tests for 'packpath' and :packadd
-
-local helpers = require('test.functional.helpers')(after_each)
-local clear, source, command = helpers.clear, helpers.source, helpers.command
-local call, eq, nvim = helpers.call, helpers.eq, helpers.meths
-local feed = helpers.feed
-
-local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
-end
-
-describe('packadd', function()
- before_each(function()
- clear()
-
- source([=[
- func Escape(s)
- return escape(a:s, '\~')
- endfunc
-
- func SetUp()
- let s:topdir = expand(getcwd() . '/Xdir')
- if isdirectory(s:topdir)
- call delete(s:topdir, 'rf')
- endif
- exe 'set packpath=' . s:topdir
- let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest')
- endfunc
-
- func TearDown()
- call delete(s:topdir, 'rf')
- endfunc
-
- func Test_packadd()
- if !exists('s:plugdir')
- echomsg 'when running this test manually, call SetUp() first'
- return
- endif
-
- call mkdir(s:plugdir . '/plugin/also', 'p')
- call mkdir(s:plugdir . '/ftdetect', 'p')
- call mkdir(s:plugdir . '/after', 'p')
- set rtp&
- let rtp = &rtp
- filetype on
-
- let rtp_entries = split(rtp, ',')
- for entry in rtp_entries
- if entry =~? '\<after\>'
- let first_after_entry = entry
- break
- endif
- endfor
-
- exe 'split ' . s:plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 42')
- wq
-
- exe 'split ' . s:plugdir . '/plugin/also/loaded.vim'
- call setline(1, 'let g:plugin_also_works = 77')
- wq
-
- exe 'split ' . s:plugdir . '/ftdetect/test.vim'
- call setline(1, 'let g:ftdetect_works = 17')
- wq
-
- packadd mytest
-
- call assert_true(42, g:plugin_works)
- call assert_equal(77, g:plugin_also_works)
- call assert_true(17, g:ftdetect_works)
- call assert_true(len(&rtp) > len(rtp))
- call assert_match(Escape(s:plugdir) . '\($\|,\)', &rtp)
-
- let new_after = match(&rtp, Escape(expand(s:plugdir . '/after') . ','))
- let forwarded = substitute(first_after_entry, '\\', '[/\\\\]', 'g')
- let old_after = match(&rtp, ',' . escape(forwarded, '~') . '\>')
- call assert_true(new_after > 0, 'rtp is ' . &rtp)
- call assert_true(old_after > 0, 'match ' . forwarded . ' in ' . &rtp)
- call assert_true(new_after < old_after, 'rtp is ' . &rtp)
-
- " NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest'
- call mkdir(fnamemodify(s:plugdir, ':h') . '/myte', 'p')
- let rtp = &rtp
- packadd myte
-
- " Check the path of 'myte' is added
- call assert_true(len(&rtp) > len(rtp))
- call assert_match(Escape(s:plugdir) . '\($\|,\)', &rtp)
-
- " Check exception
- call assert_fails("packadd directorynotfound", 'E919:')
- call assert_fails("packadd", 'E471:')
- endfunc
-
- func Test_packadd_start()
- let plugdir = expand(s:topdir . '/pack/mine/start/other')
- call mkdir(plugdir . '/plugin', 'p')
- set rtp&
- let rtp = &rtp
- filetype on
-
- exe 'split ' . plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 24')
- wq
-
- exe 'split ' . plugdir . '/plugin/test.lua'
- call setline(1, 'vim.g.plugin_lua_works = 24')
- wq
-
- packadd other
-
- call assert_equal(24, g:plugin_works)
- call assert_equal(24, g:plugin_lua_works)
- call assert_true(len(&rtp) > len(rtp))
- call assert_match(Escape(plugdir) . '\($\|,\)', &rtp)
- endfunc
-
- func Test_packadd_noload()
- call mkdir(s:plugdir . '/plugin', 'p')
- call mkdir(s:plugdir . '/syntax', 'p')
- set rtp&
- let rtp = &rtp
-
- exe 'split ' . s:plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 42')
- wq
- exe 'split ' . s:plugdir . '/plugin/test.lua'
- call setline(1, 'let g:plugin_lua_works = 42')
- wq
- let g:plugin_works = 0
- let g:plugin_lua_works = 0
-
- packadd! mytest
-
- call assert_true(len(&rtp) > len(rtp))
- call assert_match(Escape(s:plugdir) . '\($\|,\)', &rtp)
- call assert_equal(0, g:plugin_works)
- call assert_equal(0, g:plugin_lua_works)
-
- " check the path is not added twice
- let new_rtp = &rtp
- packadd! mytest
- call assert_equal(new_rtp, &rtp)
- endfunc
-
- func Test_packadd_symlink_dir()
- let top2_dir = expand(s:topdir . '/Xdir2')
- let real_dir = expand(s:topdir . '/Xsym')
- call mkdir(real_dir, 'p')
- if has('win32')
- exec "silent! !mklink /d" top2_dir "Xsym"
- else
- exec "silent! !ln -s Xsym" top2_dir
- endif
- let &rtp = top2_dir . ',' . expand(top2_dir . '/after')
- let &packpath = &rtp
-
- let s:plugdir = expand(top2_dir . '/pack/mine/opt/mytest')
- call mkdir(s:plugdir . '/plugin', 'p')
-
- exe 'split ' . s:plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 44')
- wq
- let g:plugin_works = 0
-
- packadd mytest
-
- " Must have been inserted in the middle, not at the end
- call assert_match(Escape(expand('/pack/mine/opt/mytest').','), &rtp)
- call assert_equal(44, g:plugin_works)
-
- " No change when doing it again.
- let rtp_before = &rtp
- packadd mytest
- call assert_equal(rtp_before, &rtp)
-
- set rtp&
- let rtp = &rtp
- exec "silent !" (has('win32') ? "rd /q/s" : "rm") top2_dir
- endfunc
-
- func Test_packadd_symlink_dir2()
- let top2_dir = expand(s:topdir . '/Xdir2')
- let real_dir = expand(s:topdir . '/Xsym/pack')
- call mkdir(top2_dir, 'p')
- call mkdir(real_dir, 'p')
- let &rtp = top2_dir . ',' . top2_dir . '/after'
- let &packpath = &rtp
-
- if has('win32')
- exec "silent! !mklink /d" top2_dir "Xsym"
- else
- exec "silent !ln -s ../Xsym/pack" top2_dir . '/pack'
- endif
- let s:plugdir = expand(top2_dir . '/pack/mine/opt/mytest')
- call mkdir(s:plugdir . '/plugin', 'p')
-
- exe 'split ' . s:plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 48')
- wq
- let g:plugin_works = 0
-
- packadd mytest
-
- " Must have been inserted in the middle, not at the end
- call assert_match(Escape(expand('/Xdir2/pack/mine/opt/mytest').','), &rtp)
- call assert_equal(48, g:plugin_works)
-
- " No change when doing it again.
- let rtp_before = &rtp
- packadd mytest
- call assert_equal(rtp_before, &rtp)
-
- set rtp&
- let rtp = &rtp
- if has('win32')
- exec "silent !rd /q/s" top2_dir
- else
- exec "silent !rm" top2_dir . '/pack'
- exec "silent !rmdir" top2_dir
- endif
- endfunc
-
- func Test_packloadall()
- " plugin foo with an autoload directory
- let fooplugindir = &packpath . '/pack/mine/start/foo/plugin'
- call mkdir(fooplugindir, 'p')
- call writefile(['let g:plugin_foo_number = 1234',
- \ 'let g:plugin_foo_auto = bbb#value',
- \ 'let g:plugin_extra_auto = extra#value'], fooplugindir . '/bar.vim')
- let fooautodir = &packpath . '/pack/mine/start/foo/autoload'
- call mkdir(fooautodir, 'p')
- call writefile(['let bar#value = 77'], fooautodir . '/bar.vim')
-
- " plugin aaa with an autoload directory
- let aaaplugindir = &packpath . '/pack/mine/start/aaa/plugin'
- call mkdir(aaaplugindir, 'p')
- call writefile(['let g:plugin_aaa_number = 333',
- \ 'let g:plugin_aaa_auto = bar#value'], aaaplugindir . '/bbb.vim')
- let aaaautodir = &packpath . '/pack/mine/start/aaa/autoload'
- call mkdir(aaaautodir, 'p')
- call writefile(['let bbb#value = 55'], aaaautodir . '/bbb.vim')
-
- " plugin extra with only an autoload directory
- let extraautodir = &packpath . '/pack/mine/start/extra/autoload'
- call mkdir(extraautodir, 'p')
- call writefile(['let extra#value = 99'], extraautodir . '/extra.vim')
-
- packloadall
- call assert_equal(1234, g:plugin_foo_number)
- call assert_equal(55, g:plugin_foo_auto)
- call assert_equal(99, g:plugin_extra_auto)
- call assert_equal(333, g:plugin_aaa_number)
- call assert_equal(77, g:plugin_aaa_auto)
-
- " only works once
- call writefile(['let g:plugin_bar_number = 4321'],
- \ fooplugindir . '/bar2.vim')
- packloadall
- call assert_false(exists('g:plugin_bar_number'))
-
- " works when ! used
- packloadall!
- call assert_equal(4321, g:plugin_bar_number)
- endfunc
-
- func Test_helptags()
- let docdir1 = &packpath . '/pack/mine/start/foo/doc'
- let docdir2 = &packpath . '/pack/mine/start/bar/doc'
- call mkdir(docdir1, 'p')
- call mkdir(docdir2, 'p')
- call writefile(['look here: *look-here*'], docdir1 . '/bar.txt')
- call writefile(['look away: *look-away*'], docdir2 . '/foo.txt')
- exe 'set rtp=' . &packpath . '/pack/mine/start/foo,' . &packpath . '/pack/mine/start/bar'
-
- helptags ALL
-
- let tags1 = readfile(docdir1 . '/tags')
- call assert_match('look-here', tags1[0])
- let tags2 = readfile(docdir2 . '/tags')
- call assert_match('look-away', tags2[0])
-
- call assert_fails('helptags abcxyz', 'E150:')
- endfunc
-
- func Test_colorscheme()
- let colordirrun = &packpath . '/runtime/colors'
- let colordirstart = &packpath . '/pack/mine/start/foo/colors'
- let colordiropt = &packpath . '/pack/mine/opt/bar/colors'
- call mkdir(colordirrun, 'p')
- call mkdir(colordirstart, 'p')
- call mkdir(colordiropt, 'p')
- call writefile(['let g:found_one = 1'], colordirrun . '/one.vim')
- call writefile(['let g:found_two = 1'], colordirstart . '/two.vim')
- call writefile(['let g:found_three = 1'], colordiropt . '/three.vim')
- exe 'set rtp=' . &packpath . '/runtime'
-
- colorscheme one
- call assert_equal(1, g:found_one)
- colorscheme two
- call assert_equal(1, g:found_two)
- colorscheme three
- call assert_equal(1, g:found_three)
- endfunc
-
- func Test_runtime()
- let rundir = &packpath . '/runtime/extra'
- let startdir = &packpath . '/pack/mine/start/foo/extra'
- let optdir = &packpath . '/pack/mine/opt/bar/extra'
- call mkdir(rundir, 'p')
- call mkdir(startdir, 'p')
- call mkdir(optdir, 'p')
- call writefile(['let g:sequence .= "run"'], rundir . '/bar.vim')
- call writefile(['let g:sequence .= "start"'], startdir . '/bar.vim')
- call writefile(['let g:sequence .= "foostart"'], startdir . '/foo.vim')
- call writefile(['let g:sequence .= "opt"'], optdir . '/bar.vim')
- call writefile(['let g:sequence .= "xxxopt"'], optdir . '/xxx.vim')
- exe 'set rtp=' . &packpath . '/runtime'
-
- let g:sequence = ''
- runtime extra/bar.vim
- call assert_equal('run', g:sequence)
- let g:sequence = ''
- runtime START extra/bar.vim
- call assert_equal('start', g:sequence)
- let g:sequence = ''
- runtime OPT extra/bar.vim
- call assert_equal('opt', g:sequence)
- let g:sequence = ''
- runtime PACK extra/bar.vim
- call assert_equal('start', g:sequence)
- let g:sequence = ''
- runtime! PACK extra/bar.vim
- call assert_equal('startopt', g:sequence)
- let g:sequence = ''
- runtime PACK extra/xxx.vim
- call assert_equal('xxxopt', g:sequence)
-
- let g:sequence = ''
- runtime ALL extra/bar.vim
- call assert_equal('run', g:sequence)
- let g:sequence = ''
- runtime ALL extra/foo.vim
- call assert_equal('foostart', g:sequence)
- let g:sequence = ''
- runtime! ALL extra/xxx.vim
- call assert_equal('xxxopt', g:sequence)
- let g:sequence = ''
- runtime! ALL extra/bar.vim
- call assert_equal('runstartopt', g:sequence)
- endfunc
- ]=])
- call('SetUp')
- end)
-
- after_each(function()
- call('TearDown')
- end)
-
- it('is working', function()
- call('Test_packadd')
- expected_empty()
- end)
-
- it('works with packadd!', function()
- call('Test_packadd_noload')
- expected_empty()
- end)
-
- it('works with symlinks', function()
- call('Test_packadd_symlink_dir')
- expected_empty()
- end)
-
- it('works with :packloadall', function()
- call('Test_packloadall')
- expected_empty()
- end)
-
- it('works with helptags', function()
- call('Test_helptags')
- expected_empty()
- end)
-
- it('works with colorschemes', function()
- call('Test_colorscheme')
- expected_empty()
- end)
-
- it('works with :runtime [what]', function()
- call('Test_runtime')
- expected_empty()
- end)
-
- it('loads packages from "start" directory', function()
- call('Test_packadd_start')
- expected_empty()
- end)
-
- describe('command line completion', function()
- local Screen = require('test.functional.ui.screen')
- local screen
-
- before_each(function()
- screen = Screen.new(30, 5)
- screen:attach()
- screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {
- foreground = Screen.colors.Black,
- background = Screen.colors.Yellow,
- },
- [2] = {bold = true, reverse = true}
- })
-
- command([[let optdir1 = &packpath . '/pack/mine/opt']])
- command([[let optdir2 = &packpath . '/pack/candidate/opt']])
- command([[call mkdir(optdir1 . '/pluginA', 'p')]])
- command([[call mkdir(optdir1 . '/pluginC', 'p')]])
- command([[call mkdir(optdir2 . '/pluginB', 'p')]])
- command([[call mkdir(optdir2 . '/pluginC', 'p')]])
- end)
-
- it('works', function()
- feed(':packadd <Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {1:pluginA}{2: pluginB pluginC }|
- :packadd pluginA^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:pluginA }{1:pluginB}{2: pluginC }|
- :packadd pluginB^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:pluginA pluginB }{1:pluginC}{2: }|
- :packadd pluginC^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:pluginA pluginB pluginC }|
- :packadd ^ |
- ]=])
- end)
-
- it('works for colorschemes', function()
- source([[
- let colordirrun = &packpath . '/runtime/colors'
- let colordirstart = &packpath . '/pack/mine/start/foo/colors'
- let colordiropt = &packpath . '/pack/mine/opt/bar/colors'
- call mkdir(colordirrun, 'p')
- call mkdir(colordirstart, 'p')
- call mkdir(colordiropt, 'p')
- call writefile(['let g:found_one = 1'], colordirrun . '/one.vim')
- call writefile(['let g:found_two = 1'], colordirstart . '/two.vim')
- call writefile(['let g:found_three = 1'], colordiropt . '/three.vim')
- exe 'set rtp=' . &packpath . '/runtime']])
-
- feed(':colorscheme <Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {1:one}{2: three two }|
- :colorscheme one^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:one }{1:three}{2: two }|
- :colorscheme three^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:one three }{1:two}{2: }|
- :colorscheme two^ |
- ]=])
- feed('<Tab>')
- screen:expect([=[
- |
- {0:~ }|
- {0:~ }|
- {2:one three two }|
- :colorscheme ^ |
- ]=])
- end)
- end)
-end)
diff --git a/test/functional/legacy/put_spec.lua b/test/functional/legacy/put_spec.lua
new file mode 100644
index 0000000000..3ddf65490e
--- /dev/null
+++ b/test/functional/legacy/put_spec.lua
@@ -0,0 +1,45 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local meths = helpers.meths
+local source = helpers.source
+local eq = helpers.eq
+
+local function sizeoflong()
+ if not exec_lua('return pcall(require, "ffi")') then
+ pending('missing LuaJIT FFI')
+ end
+ return exec_lua('return require("ffi").sizeof(require("ffi").typeof("long"))')
+end
+
+describe('put', function()
+ before_each(clear)
+ after_each(function() eq({}, meths.get_vvar('errors')) end)
+
+ it('very large count 64-bit', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ let @" = repeat('x', 100)
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+ ]]
+ end)
+
+ it('very large count (visual block) 64-bit', function()
+ if sizeoflong() < 8 then
+ pending('Skipped: only works with 64 bit long ints')
+ end
+
+ source [[
+ new
+ call setline(1, repeat('x', 100))
+ exe "norm \<C-V>$y"
+ call assert_fails('norm 999999999p', 'E1240:')
+ bwipe!
+ ]]
+ end)
+end)
diff --git a/test/functional/legacy/search_stat_spec.lua b/test/functional/legacy/search_stat_spec.lua
new file mode 100644
index 0000000000..fdd46c0cb9
--- /dev/null
+++ b/test/functional/legacy/search_stat_spec.lua
@@ -0,0 +1,121 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, feed, exec, command = helpers.clear, helpers.feed, helpers.exec, helpers.command
+local poke_eventloop = helpers.poke_eventloop
+
+describe('search stat', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(30, 10)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [2] = {background = Screen.colors.Yellow}, -- Search
+ [3] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}, -- Folded
+ })
+ screen:attach()
+ end)
+
+ it('right spacing with silent mapping vim-patch:8.1.1970', function()
+ exec([[
+ set shortmess-=S
+ " Append 50 lines with text to search for, "foobar" appears 20 times
+ call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 20))
+ call setline(2, 'find this')
+ call setline(70, 'find this')
+ nnoremap n n
+ let @/ = 'find this'
+ call cursor(1,1)
+ norm n
+ ]])
+ screen:expect([[
+ foobar |
+ {2:^find this} |
+ fooooobar |
+ foba |
+ foobar |
+ foobar |
+ foo |
+ fooooobar |
+ foba |
+ /find this [1/2] |
+ ]])
+ command('nnoremap <silent> n n')
+ feed('gg0n')
+ screen:expect([[
+ foobar |
+ {2:^find this} |
+ fooooobar |
+ foba |
+ foobar |
+ foobar |
+ foo |
+ fooooobar |
+ foba |
+ [1/2] |
+ ]])
+ end)
+
+ it('when only match is in fold vim-patch:8.2.0840', function()
+ exec([[
+ set shortmess-=S
+ setl foldenable foldmethod=indent foldopen-=search
+ call append(0, ['if', "\tfoo", "\tfoo", 'endif'])
+ let @/ = 'foo'
+ call cursor(1,1)
+ norm n
+ ]])
+ screen:expect([[
+ if |
+ {3:^+-- 2 lines: foo·············}|
+ endif |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /foo [1/2] |
+ ]])
+ feed('n')
+ poke_eventloop()
+ screen:expect_unchanged()
+ feed('n')
+ poke_eventloop()
+ screen:expect_unchanged()
+ end)
+
+ it('is cleared by gd and gD vim-patch:8.2.3583', function()
+ exec([[
+ call setline(1, ['int cat;', 'int dog;', 'cat = dog;'])
+ set shortmess-=S
+ set hlsearch
+ ]])
+ feed('/dog<CR>')
+ screen:expect([[
+ int cat; |
+ int {2:^dog}; |
+ cat = {2:dog}; |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /dog [1/2] |
+ ]])
+ feed('G0gD')
+ screen:expect([[
+ int {2:^cat}; |
+ int dog; |
+ {2:cat} = dog; |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua
index 8b5fc02d11..67a4bec4c5 100644
--- a/test/functional/legacy/utf8_spec.lua
+++ b/test/functional/legacy/utf8_spec.lua
@@ -28,7 +28,7 @@ describe('utf8', function()
expect([[
start:
axaa
- xあああ
+ xあああ
bxbb]])
end)
diff --git a/test/functional/legacy/visual_mode_spec.lua b/test/functional/legacy/visual_mode_spec.lua
index c8e83ed649..8b5dd0c2dc 100644
--- a/test/functional/legacy/visual_mode_spec.lua
+++ b/test/functional/legacy/visual_mode_spec.lua
@@ -1,5 +1,3 @@
--- Test visual line mode selection redraw after scrolling
-
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
@@ -10,6 +8,7 @@ local feed_command = helpers.feed_command
local funcs = helpers.funcs
local meths = helpers.meths
local eq = helpers.eq
+local exec = helpers.exec
describe('visual line mode', function()
local screen
@@ -40,3 +39,44 @@ describe('visual line mode', function()
]])
end)
end)
+
+describe('visual block mode', function()
+ it('shows selection correctly with virtualedit=block', function()
+ clear()
+ local screen = Screen.new(30, 7)
+ screen:set_default_attr_ids({
+ [1] = {bold = true}, -- ModeMsg
+ [2] = {background = Screen.colors.LightGrey}, -- Visual
+ [3] = {foreground = Screen.colors.Blue, bold = true} -- NonText
+ })
+ screen:attach()
+
+ exec([[
+ call setline(1, ['aaaaaa', 'bbbb', 'cc'])
+ set virtualedit=block
+ normal G
+ ]])
+
+ feed('<C-V>gg$')
+ screen:expect([[
+ {2:aaaaaa}^ |
+ {2:bbbb } |
+ {2:cc } |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:-- VISUAL BLOCK --} |
+ ]])
+
+ feed('<Esc>gg<C-V>G$')
+ screen:expect([[
+ {2:aaaaaa } |
+ {2:bbbb } |
+ {2:cc}^ {2: } |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:-- VISUAL BLOCK --} |
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index 81e00bba6d..f173a15d32 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -8,6 +8,7 @@ local clear = helpers.clear
local eval = helpers.eval
local NIL = helpers.NIL
local eq = helpers.eq
+local exec_lua = helpers.exec_lua
before_each(clear)
@@ -101,6 +102,13 @@ describe('luaeval(vim.api.…)', function()
eq(false, funcs.luaeval('vim.api.nvim__id(false)'))
eq(NIL, funcs.luaeval('vim.api.nvim__id(nil)'))
+ -- API strings from Blobs can work as NUL-terminated C strings
+ eq('Vim(call):E5555: API call: Vim:E15: Invalid expression: ',
+ exc_exec('call nvim_eval(v:_null_blob)'))
+ eq('Vim(call):E5555: API call: Vim:E15: Invalid expression: ',
+ exc_exec('call nvim_eval(0z)'))
+ eq(1, eval('nvim_eval(0z31)'))
+
eq(0, eval([[type(luaeval('vim.api.nvim__id(1)'))]]))
eq(1, eval([[type(luaeval('vim.api.nvim__id("1")'))]]))
eq(3, eval([[type(luaeval('vim.api.nvim__id({1})'))]]))
@@ -111,6 +119,12 @@ describe('luaeval(vim.api.…)', function()
eq(7, eval([[type(luaeval('vim.api.nvim__id(nil)'))]]))
eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api.nvim__id({foo=1, bar={42, {{baz=true}, 5}}})'))
+
+ eq(true, funcs.luaeval('vim.api.nvim__id(vim.api.nvim__id)(true)'))
+ eq(42, exec_lua [[
+ local f = vim.api.nvim__id({42, vim.api.nvim__id})
+ return f[2](f[1])
+ ]])
end)
it('correctly converts container objects with type_idx to API objects', function()
@@ -159,12 +173,8 @@ describe('luaeval(vim.api.…)', function()
it('errors out correctly when working with API', function()
-- Conversion errors
- eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua table',
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])))
- eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]])))
-- Errors in number of arguments
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id()")]])))
@@ -180,6 +190,8 @@ describe('luaeval(vim.api.…)', function()
remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Number is not integral',
remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])))
+ eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected Lua number',
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_win_is_valid(nil)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])))
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index 9b9ba531b0..b8346df290 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -141,6 +141,24 @@ describe(':lua command', function()
{4:Press ENTER or type command to continue}^ |
]]}
end)
+
+ it('Can print results of =expr', function()
+ helpers.exec_lua("x = 5")
+ eq("5", helpers.exec_capture(':lua =x'))
+ helpers.exec_lua("function x() return 'hello' end")
+ eq([["hello"]], helpers.exec_capture(':lua = x()'))
+ helpers.exec_lua("x = {a = 1, b = 2}")
+ eq("{\n a = 1,\n b = 2\n}", helpers.exec_capture(':lua =x'))
+ helpers.exec_lua([[function x(success)
+ if success then
+ return true, "Return value"
+ else
+ return false, nil, "Error message"
+ end
+ end]])
+ eq([[true "Return value"]], helpers.exec_capture(':lua =x(true)'))
+ eq([[false nil "Error message"]], helpers.exec_capture(':lua =x(false)'))
+ end)
end)
describe(':luado command', function()
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index a88da63e90..b58fad1cab 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -208,10 +208,10 @@ describe('vim.diagnostic', function()
eq(all_highlights, exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 3),
}
local ns_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
+ make_warning("Warning 1", 2, 1, 2, 3),
}
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
@@ -255,10 +255,10 @@ describe('vim.diagnostic', function()
eq({0, 2}, exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 3),
}
local ns_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
+ make_warning("Warning 1", 2, 1, 2, 3),
}
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
@@ -599,10 +599,10 @@ describe('vim.diagnostic', function()
eq(all_highlights, exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 3),
}
local ns_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
+ make_warning("Warning 1", 2, 1, 2, 3),
}
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
@@ -787,7 +787,7 @@ describe('vim.diagnostic', function()
eq(2, exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 1, 1, 2, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 3),
})
return #vim.diagnostic.get(diagnostic_bufnr)
@@ -798,9 +798,9 @@ describe('vim.diagnostic', function()
eq({2, 3, 2}, exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 1, 1, 2, 5),
- make_info("Ignored information", 1, 1, 2, 5),
- make_hint("Here's a hint", 1, 1, 2, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 3),
+ make_info("Ignored information", 1, 1, 2, 3),
+ make_hint("Here's a hint", 1, 1, 2, 3),
})
return {
@@ -820,8 +820,8 @@ describe('vim.diagnostic', function()
eq(1, exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 1, 1, 2, 5),
- make_info("Ignored information", 1, 1, 2, 5),
+ make_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),
})
@@ -1119,6 +1119,11 @@ describe('vim.diagnostic', function()
end)
describe('set()', function()
+ it('validates its arguments', function()
+ matches("expected a list of diagnostics",
+ pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]]))
+ end)
+
it('can perform updates after insert_leave', function()
exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
nvim("input", "o")
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
new file mode 100644
index 0000000000..729ebc601b
--- /dev/null
+++ b/test/functional/lua/filetype_spec.lua
@@ -0,0 +1,98 @@
+local helpers = require('test.functional.helpers')(after_each)
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local clear = helpers.clear
+local pathroot = helpers.pathroot
+
+local root = pathroot()
+
+describe('vim.filetype', function()
+ before_each(function()
+ clear()
+
+ exec_lua [[
+ local bufnr = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_set_current_buf(bufnr)
+ ]]
+ end)
+
+ it('works with extensions', function()
+ eq('radicalscript', exec_lua [[
+ vim.filetype.add({
+ extension = {
+ rs = 'radicalscript',
+ },
+ })
+ vim.filetype.match('main.rs')
+ return vim.bo.filetype
+ ]])
+ end)
+
+ it('prioritizes filenames over extensions', function()
+ eq('somethingelse', exec_lua [[
+ vim.filetype.add({
+ extension = {
+ rs = 'radicalscript',
+ },
+ filename = {
+ ['main.rs'] = 'somethingelse',
+ },
+ })
+ vim.filetype.match('main.rs')
+ return vim.bo.filetype
+ ]])
+ end)
+
+ it('works with filenames', function()
+ eq('nim', exec_lua [[
+ vim.filetype.add({
+ filename = {
+ ['s_O_m_e_F_i_l_e'] = 'nim',
+ },
+ })
+ vim.filetype.match('s_O_m_e_F_i_l_e')
+ return vim.bo.filetype
+ ]])
+
+ eq('dosini', exec_lua([[
+ local root = ...
+ vim.filetype.add({
+ filename = {
+ ['config'] = 'toml',
+ [root .. '/.config/fun/config'] = 'dosini',
+ },
+ })
+ vim.filetype.match(root .. '/.config/fun/config')
+ return vim.bo.filetype
+ ]], root))
+ end)
+
+ it('works with patterns', function()
+ eq('markdown', exec_lua([[
+ local root = ...
+ vim.filetype.add({
+ pattern = {
+ ['~/blog/.*%.txt'] = 'markdown',
+ }
+ })
+ vim.filetype.match('~/blog/why_neovim_is_awesome.txt')
+ return vim.bo.filetype
+ ]], root))
+ end)
+
+ it('works with functions', function()
+ eq('foss', exec_lua [[
+ vim.filetype.add({
+ pattern = {
+ ["relevant_to_(%a+)"] = function(path, bufnr, capture)
+ if capture == "me" then
+ return "foss"
+ end
+ end,
+ }
+ })
+ vim.filetype.match('relevant_to_me')
+ return vim.bo.filetype
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index c543dd1995..1322155595 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -532,6 +532,7 @@ describe('v:lua', function()
command('set pp+=test/functional/fixtures')
eq('\tbadval', eval("v:lua.require'leftpad'('badval')"))
eq(9003, eval("v:lua.require'bar'.doit()"))
+ eq(9004, eval("v:lua.require'baz-quux'.doit()"))
end)
it('throw errors for invalid use', function()
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
new file mode 100644
index 0000000000..2e0ab7bdff
--- /dev/null
+++ b/test/functional/lua/thread_spec.lua
@@ -0,0 +1,386 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
+local clear = helpers.clear
+local feed = helpers.feed
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local next_msg = helpers.next_msg
+local NIL = helpers.NIL
+local pcall_err = helpers.pcall_err
+
+describe('thread', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {bold = true, reverse = true},
+ [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {bold = true},
+ })
+ end)
+
+ it('entry func is executed in protected mode', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ error('Error in thread entry func')
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv thread:} |
+ {3:[string "<nvim>"]:2: Error in thread entry func} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<cr>')
+ assert_alive()
+ end)
+
+ it('callback is executed in protected mode', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ local timer = vim.loop.new_timer()
+ local function ontimeout()
+ timer:stop()
+ timer:close()
+ error('Error in thread callback')
+ end
+ timer:start(10, 0, ontimeout)
+ vim.loop.run()
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv callback, thread:} |
+ {3:[string "<nvim>"]:6: Error in thread callback} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ feed('<cr>')
+ assert_alive()
+ end)
+
+ describe('print', function()
+ it('works', function()
+ exec_lua [[
+ local thread = vim.loop.new_thread(function()
+ print('print in thread')
+ end)
+ vim.loop.thread_join(thread)
+ ]]
+
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ print in thread |
+ ]])
+ end)
+ end)
+
+ describe('vim.*', function()
+ before_each(function()
+ clear()
+ exec_lua [[
+ Thread_Test = {}
+
+ Thread_Test.entry_func = function(async, entry_str, args)
+ local decoded_args = vim.mpack.decode(args)
+ assert(loadstring(entry_str))(async, decoded_args)
+ end
+
+ function Thread_Test:do_test()
+ local async
+ local on_async = self.on_async
+ async = vim.loop.new_async(function(ret)
+ on_async(ret)
+ async:close()
+ end)
+ local thread =
+ vim.loop.new_thread(self.entry_func, async, self.entry_str, self.args)
+ vim.loop.thread_join(thread)
+ end
+
+ Thread_Test.new = function(entry, on_async, ...)
+ self = {}
+ setmetatable(self, {__index = Thread_Test})
+ self.args = vim.mpack.encode({...})
+ self.entry_str = string.dump(entry)
+ self.on_async = on_async
+ return self
+ end
+ ]]
+ end)
+
+ it('is_thread', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.is_thread())
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {true}}, next_msg())
+ end)
+
+ it('loop', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.loop.version())
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ local msg = next_msg()
+ eq(msg[1], 'notification')
+ assert(tonumber(msg[2]) >= 72961)
+ end)
+
+ it('mpack', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.mpack.encode({33, vim.NIL, 'text'}))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', vim.mpack.decode(ret))
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('json', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.json.encode({33, vim.NIL, 'text'}))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', vim.json.decode(ret))
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('diff', function()
+ exec_lua [[
+ local entry = function(async)
+ async:send(vim.diff('Hello\n', 'Helli\n'))
+ end
+ local on_async = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local thread_test = Thread_Test.new(entry, on_async)
+ thread_test:do_test()
+ ]]
+
+ eq({'notification', 'result',
+ {table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n')}},
+ next_msg())
+ end)
+ end)
+end)
+
+describe('threadpool', function()
+ before_each(clear)
+
+ it('is_thread', function()
+ eq(false, exec_lua [[return vim.is_thread()]])
+
+ exec_lua [[
+ local work_fn = function()
+ return vim.is_thread()
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local work = vim.loop.new_work(work_fn, after_work_fn)
+ work:queue()
+ ]]
+
+ eq({'notification', 'result', {true}}, next_msg())
+ end)
+
+ it('with invalid argument', function()
+ local status = pcall_err(exec_lua, [[
+ local work = vim.loop.new_thread(function() end, function() end)
+ work:queue({})
+ ]])
+
+ eq([[Error executing lua: [string "<nvim>"]:0: Error: thread arg not support type 'function' at 1]],
+ status)
+ end)
+
+ it('with invalid return value', function()
+ local screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {bold = true, reverse = true},
+ [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [5] = {bold = true},
+ })
+
+ exec_lua [[
+ local work = vim.loop.new_work(function() return {} end, function() end)
+ work:queue()
+ ]]
+
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2: }|
+ {3:Error in luv thread:} |
+ {3:Error: thread arg not support type 'table' at 1} |
+ {4:Press ENTER or type command to continue}^ |
+ ]])
+ end)
+
+ describe('vim.*', function()
+ before_each(function()
+ clear()
+ exec_lua [[
+ Threadpool_Test = {}
+
+ Threadpool_Test.work_fn = function(work_fn_str, args)
+ local decoded_args = vim.mpack.decode(args)
+ return assert(loadstring(work_fn_str))(decoded_args)
+ end
+
+ function Threadpool_Test:do_test()
+ local work =
+ vim.loop.new_work(self.work_fn, self.after_work)
+ work:queue(self.work_fn_str, self.args)
+ end
+
+ Threadpool_Test.new = function(work_fn, after_work, ...)
+ self = {}
+ setmetatable(self, {__index = Threadpool_Test})
+ self.args = vim.mpack.encode({...})
+ self.work_fn_str = string.dump(work_fn)
+ self.after_work = after_work
+ return self
+ end
+ ]]
+ end)
+
+ it('loop', function()
+ exec_lua [[
+ local work_fn = function()
+ return vim.loop.version()
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, ret)
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ local msg = next_msg()
+ eq(msg[1], 'notification')
+ assert(tonumber(msg[2]) >= 72961)
+ end)
+
+ it('mpack', function()
+ exec_lua [[
+ local work_fn = function()
+ local var = vim.mpack.encode({33, vim.NIL, 'text'})
+ return var
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', vim.mpack.decode(ret))
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('json', function()
+ exec_lua [[
+ local work_fn = function()
+ local var = vim.json.encode({33, vim.NIL, 'text'})
+ return var
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', vim.json.decode(ret))
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ end)
+
+ it('work', function()
+ exec_lua [[
+ local work_fn = function()
+ return vim.diff('Hello\n', 'Helli\n')
+ end
+ local after_work_fn = function(ret)
+ vim.rpcnotify(1, 'result', ret)
+ end
+ local threadpool_test = Threadpool_Test.new(work_fn, after_work_fn)
+ threadpool_test:do_test()
+ ]]
+
+ eq({'notification', 'result',
+ {table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n')}},
+ next_msg())
+ end)
+ end)
+end)
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index fa11fdf794..4635f17557 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -101,7 +101,7 @@ describe('URI methods', function()
eq('C:\\Foo\\Bar\\Baz.txt', exec_lua(test_case))
end)
- it('file path includes only ascii charactors with encoded colon character', function()
+ it('file path includes only ascii characters with encoded colon character', function()
local test_case = [[
local uri = 'file:///C%3A/Foo/Bar/Baz.txt'
return vim.uri_to_fname(uri)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 317f92fcdc..7ec986acdd 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -19,6 +19,9 @@ local NIL = helpers.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
before_each(clear)
@@ -906,6 +909,7 @@ describe('lua stdlib', function()
exec_lua("vim.validate{arg1={nil, 'thread', true }}")
exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}")
exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
+ exec_lua("vim.validate{arg1={5, {'n', 's'} }, arg2={ 'foo', {'n', 's'} }}")
matches('expected table, got number',
pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
@@ -935,6 +939,8 @@ describe('lua stdlib', function()
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
matches('arg1: expected %?, got 3',
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
+ matches('arg1: expected number|string, got nil',
+ pcall_err(exec_lua, "vim.validate{ arg1={ nil, {'n', 's'} }}"))
-- Pass an additional message back.
matches('arg1: expected %?, got 3. Info: TEST_MSG',
@@ -984,6 +990,52 @@ describe('lua stdlib', function()
matches([[attempt to index .* nil value]],
pcall_err(exec_lua, 'return vim.g[0].testing'))
+
+ exec_lua [[
+ local counter = 0
+ vim.g.AddCounter = function() counter = counter + 1 end
+ vim.g.GetCounter = function() return counter end
+ ]]
+
+ eq(0, eval('g:GetCounter()'))
+ eval('g:AddCounter()')
+ eq(1, eval('g:GetCounter()'))
+ eval('g:AddCounter()')
+ eq(2, eval('g:GetCounter()'))
+ exec_lua([[vim.g.AddCounter()]])
+ eq(3, exec_lua([[return vim.g.GetCounter()]]))
+ exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
+
+ exec_lua [[
+ local counter = 0
+ vim.api.nvim_set_var('AddCounter', function() counter = counter + 1 end)
+ vim.api.nvim_set_var('GetCounter', function() return counter end)
+ ]]
+
+ eq(0, eval('g:GetCounter()'))
+ eval('g:AddCounter()')
+ eq(1, eval('g:GetCounter()'))
+ eval('g:AddCounter()')
+ eq(2, eval('g:GetCounter()'))
+ exec_lua([[vim.g.AddCounter()]])
+ eq(3, exec_lua([[return vim.g.GetCounter()]]))
+ exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
+
+ -- Check if autoload works properly
+ local pathsep = helpers.get_pathsep()
+ local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
+ local xdata = 'Xhome' .. pathsep .. 'Xdata'
+ local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep)
+ local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep)
+ mkdir_p(autoload_folder)
+ write_file(autoload_file , [[let testload#value = 2]])
+
+ clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } }
+
+ eq(2, exec_lua("return vim.g['testload#value']"))
+ rmdir('Xhome')
end)
it('vim.b', function()
@@ -1019,6 +1071,38 @@ describe('lua stdlib', function()
eq(NIL, funcs.luaeval "vim.b.to_delete")
exec_lua [[
+ local counter = 0
+ vim.b.AddCounter = function() counter = counter + 1 end
+ vim.b.GetCounter = function() return counter end
+ ]]
+
+ eq(0, eval('b:GetCounter()'))
+ eval('b:AddCounter()')
+ eq(1, eval('b:GetCounter()'))
+ eval('b:AddCounter()')
+ eq(2, eval('b:GetCounter()'))
+ exec_lua([[vim.b.AddCounter()]])
+ eq(3, exec_lua([[return vim.b.GetCounter()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
+ local counter = 0
+ vim.api.nvim_buf_set_var(0, 'AddCounter', function() counter = counter + 1 end)
+ vim.api.nvim_buf_set_var(0, 'GetCounter', function() return counter end)
+ ]]
+
+ eq(0, eval('b:GetCounter()'))
+ eval('b:AddCounter()')
+ eq(1, eval('b:GetCounter()'))
+ eval('b:AddCounter()')
+ eq(2, eval('b:GetCounter()'))
+ exec_lua([[vim.b.AddCounter()]])
+ eq(3, exec_lua([[return vim.b.GetCounter()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
vim.cmd "vnew"
]]
@@ -1056,6 +1140,38 @@ describe('lua stdlib', function()
eq(NIL, funcs.luaeval "vim.w.to_delete")
exec_lua [[
+ local counter = 0
+ vim.w.AddCounter = function() counter = counter + 1 end
+ vim.w.GetCounter = function() return counter end
+ ]]
+
+ eq(0, eval('w:GetCounter()'))
+ eval('w:AddCounter()')
+ eq(1, eval('w:GetCounter()'))
+ eval('w:AddCounter()')
+ eq(2, eval('w:GetCounter()'))
+ exec_lua([[vim.w.AddCounter()]])
+ eq(3, exec_lua([[return vim.w.GetCounter()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
+ local counter = 0
+ vim.api.nvim_win_set_var(0, 'AddCounter', function() counter = counter + 1 end)
+ vim.api.nvim_win_set_var(0, 'GetCounter', function() return counter end)
+ ]]
+
+ eq(0, eval('w:GetCounter()'))
+ eval('w:AddCounter()')
+ eq(1, eval('w:GetCounter()'))
+ eval('w:AddCounter()')
+ eq(2, eval('w:GetCounter()'))
+ exec_lua([[vim.w.AddCounter()]])
+ eq(3, exec_lua([[return vim.w.GetCounter()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
vim.cmd "vnew"
]]
@@ -1088,6 +1204,38 @@ describe('lua stdlib', function()
eq(NIL, funcs.luaeval "vim.t.to_delete")
exec_lua [[
+ local counter = 0
+ vim.t.AddCounter = function() counter = counter + 1 end
+ vim.t.GetCounter = function() return counter end
+ ]]
+
+ eq(0, eval('t:GetCounter()'))
+ eval('t:AddCounter()')
+ eq(1, eval('t:GetCounter()'))
+ eval('t:AddCounter()')
+ eq(2, eval('t:GetCounter()'))
+ exec_lua([[vim.t.AddCounter()]])
+ eq(3, exec_lua([[return vim.t.GetCounter()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
+ local counter = 0
+ vim.api.nvim_tabpage_set_var(0, 'AddCounter', function() counter = counter + 1 end)
+ vim.api.nvim_tabpage_set_var(0, 'GetCounter', function() return counter end)
+ ]]
+
+ eq(0, eval('t:GetCounter()'))
+ eval('t:AddCounter()')
+ eq(1, eval('t:GetCounter()'))
+ eval('t:AddCounter()')
+ eq(2, eval('t:GetCounter()'))
+ exec_lua([[vim.t.AddCounter()]])
+ eq(3, exec_lua([[return vim.t.GetCounter()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
+ eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
+
+ exec_lua [[
vim.cmd "tabnew"
]]
@@ -2200,6 +2348,40 @@ describe('lua stdlib', function()
end)
end)
+ it('vim.notify_once', function()
+ local screen = Screen.new(60,5)
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {foreground=Screen.colors.Red},
+ })
+ screen:attach()
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ exec_lua [[vim.notify_once("I'll only tell you this once...", vim.log.levels.WARN)]]
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:I'll only tell you this once...} |
+ ]]}
+ feed('<C-l>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ exec_lua [[vim.notify_once("I'll only tell you this once...")]]
+ screen:expect_unchanged()
+ end)
+
describe('vim.schedule_wrap', function()
it('preserves argument lists', function()
exec_lua [[
@@ -2241,6 +2423,17 @@ describe('lua stdlib', function()
eq(buf1, meths.get_current_buf())
eq(buf2, val)
end)
+
+ it('does not cause ml_get errors with invalid visual selection', function()
+ -- Should be fixed by vim-patch:8.2.4028.
+ exec_lua [[
+ local a = vim.api
+ local t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
+ a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
+ a.nvim_feedkeys(t "G<C-V>", "txn", false)
+ a.nvim_buf_call(a.nvim_create_buf(false, true), function() vim.cmd "redraw" end)
+ ]]
+ end)
end)
describe('vim.api.nvim_win_call', function()
@@ -2269,6 +2462,75 @@ describe('lua stdlib', function()
eq(win1, meths.get_current_win())
eq(win2, val)
end)
+
+ it('does not cause ml_get errors with invalid visual selection', function()
+ -- Add lines to the current buffer and make another window looking into an empty buffer.
+ exec_lua [[
+ _G.a = vim.api
+ _G.t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
+ _G.win_lines = a.nvim_get_current_win()
+ vim.cmd "new"
+ _G.win_empty = a.nvim_get_current_win()
+ a.nvim_set_current_win(win_lines)
+ a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
+ ]]
+
+ -- Start Visual in current window, redraw in other window with fewer lines.
+ -- Should be fixed by vim-patch:8.2.4018.
+ exec_lua [[
+ a.nvim_feedkeys(t "G<C-V>", "txn", false)
+ a.nvim_win_call(win_empty, function() vim.cmd "redraw" end)
+ ]]
+
+ -- Start Visual in current window, extend it in other window with more lines.
+ -- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected.
+ exec_lua [[
+ a.nvim_feedkeys(t "<Esc>gg", "txn", false)
+ a.nvim_set_current_win(win_empty)
+ a.nvim_feedkeys(t "gg<C-V>", "txn", false)
+ a.nvim_win_call(win_lines, function() a.nvim_feedkeys(t "G<C-V>", "txn", false) end)
+ vim.cmd "redraw"
+ ]]
+ end)
+
+ it('updates ruler if cursor moved', function()
+ -- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too!
+ local screen = Screen.new(30, 5)
+ screen:set_default_attr_ids {
+ [1] = {reverse = true},
+ [2] = {bold = true, reverse = true},
+ }
+ screen:attach()
+ exec_lua [[
+ _G.a = vim.api
+ vim.opt.ruler = true
+ local lines = {}
+ for i = 0, 499 do lines[#lines + 1] = tostring(i) end
+ a.nvim_buf_set_lines(0, 0, -1, true, lines)
+ a.nvim_win_set_cursor(0, {20, 0})
+ vim.cmd "split"
+ _G.win = a.nvim_get_current_win()
+ vim.cmd "wincmd w | redraw"
+ ]]
+ screen:expect [[
+ 19 |
+ {1:[No Name] [+] 20,1 3%}|
+ ^19 |
+ {2:[No Name] [+] 20,1 3%}|
+ |
+ ]]
+ exec_lua [[
+ a.nvim_win_call(win, function() a.nvim_win_set_cursor(0, {100, 0}) end)
+ vim.cmd "redraw"
+ ]]
+ screen:expect [[
+ 99 |
+ {1:[No Name] [+] 100,1 19%}|
+ ^19 |
+ {2:[No Name] [+] 20,1 3%}|
+ |
+ ]]
+ end)
end)
end)
@@ -2295,3 +2557,82 @@ describe('lua: require("mod") from packages', function()
eq('I am fancy_z.lua', exec_lua [[ return require'fancy_z' ]])
end)
end)
+
+describe('vim.keymap', function()
+ it('can make a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can make an expr mapping', function()
+ exec_lua [[
+ vim.keymap.set('n', 'aa', function() return ':lua SomeValue = 99<cr>' end, {expr = true})
+ ]]
+
+ feed('aa')
+
+ eq(99, exec_lua[[return SomeValue]])
+ end)
+
+ it('can overwrite a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount - 1 end)
+ ]]
+
+ feed('asdf\n')
+
+ eq(0, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can unmap a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.keymap.del('n', 'asdf')
+ ]]
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
+ end)
+
+ it('can do <Plug> mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', '<plug>(asdf)', function() GlobalCount = GlobalCount + 1 end)
+ vim.keymap.set('n', 'ww', '<plug>(asdf)')
+ return GlobalCount
+ ]])
+
+ feed('ww\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ end)
+
+end)
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
index 4f28f84c01..d55268fc78 100644
--- a/test/functional/lua/xdiff_spec.lua
+++ b/test/functional/lua/xdiff_spec.lua
@@ -90,6 +90,48 @@ describe('xdiff bindings', function()
exec_lua([[return vim.diff(a2, b2, {result_type = 'indices'})]]))
end)
+ it('can run different algorithms', function()
+ local a = table.concat({
+ '.foo1 {',
+ ' margin: 0;',
+ '}',
+ '',
+ '.bar {',
+ ' margin: 0;',
+ '}',
+ ''}, '\n')
+
+ local b = table.concat({
+ '.bar {',
+ ' margin: 0;',
+ '}',
+ '',
+ '.foo1 {',
+ ' margin: 0;',
+ ' color: green;',
+ '}',
+ ''}, '\n')
+
+ eq(
+ table.concat({'@@ -1,4 +0,0 @@',
+ '-.foo1 {',
+ '- margin: 0;',
+ '-}',
+ '-',
+ '@@ -7,0 +4,5 @@',
+ '+',
+ '+.foo1 {',
+ '+ margin: 0;',
+ '+ color: green;',
+ '+}',
+ ''}, '\n'),
+ exec_lua([[
+ local args = {...}
+ return vim.diff(args[1], args[2], {
+ algorithm = 'patience'
+ })
+ ]], a, b))
+ end)
end)
it('can handle bad args', function()
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index 37de5d0ce6..a9bd76ce24 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -153,6 +153,10 @@ describe('health.vim', function()
## report 2
- OK: nothing to see here
+ test_plug.submodule_empty: require("test_plug.submodule_empty.health").check()
+ ========================================================================
+ - ERROR: The healthcheck report for "test_plug.submodule_empty" plugin is empty.
+
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
========================================================================
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
@@ -172,6 +176,16 @@ describe('health.vim', function()
]])
end)
+ it("... including empty reports", function()
+ command("checkhealth test_plug.submodule_empty")
+ helpers.expect([[
+
+ test_plug.submodule_empty: require("test_plug.submodule_empty.health").check()
+ ========================================================================
+ - ERROR: The healthcheck report for "test_plug.submodule_empty" plugin is empty.
+ ]])
+ end)
+
it("gracefully handles broken lua healthcheck", function()
command("checkhealth test_plug.submodule_failed")
local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
@@ -230,3 +244,14 @@ describe('health.vim', function()
end)
end)
end)
+
+describe(':checkhealth provider', function()
+ it("works correctly with a wrongly configured 'shell'", function()
+ clear()
+ command([[set shell=echo\ WRONG!!!]])
+ command('let g:loaded_perl_provider = 0')
+ command('let g:loaded_python3_provider = 0')
+ command('checkhealth provider')
+ eq(nil, string.match(curbuf_contents(), 'WRONG!!!'))
+ end)
+end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 1af31c38f8..eab520948f 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -73,8 +73,11 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options)
on_init = function(client, result)
TEST_RPC_CLIENT = client
vim.rpcrequest(1, "init", result)
- client.config.flags.allow_incremental_sync = options.allow_incremental_sync or false
end;
+ flags = {
+ allow_incremental_sync = options.allow_incremental_sync or false;
+ debounce_text_changes = options.debounce_text_changes or 0;
+ };
on_exit = function(...)
vim.rpcnotify(1, "exit", ...)
end;
@@ -926,7 +929,60 @@ describe('LSP', function()
local client
test_rpc_server {
test_name = "basic_check_buffer_open_and_change_incremental";
- options = { allow_incremental_sync = true };
+ options = {
+ allow_incremental_sync = true,
+ };
+ on_setup = function()
+ exec_lua [[
+ BUFFER = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_buf_set_lines(BUFFER, 0, -1, false, {
+ "testing";
+ "123";
+ })
+ ]]
+ end;
+ on_init = function(_client)
+ client = _client
+ local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ eq(sync_kind, client.resolved_capabilities().text_document_did_change)
+ eq(true, client.resolved_capabilities().text_document_open_close)
+ exec_lua [[
+ assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
+ ]]
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ on_handler = function(err, result, ctx)
+ if ctx.method == 'start' then
+ exec_lua [[
+ vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
+ "123boop";
+ })
+ ]]
+ client.notify('finish')
+ end
+ eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end;
+ }
+ end)
+ it('should check the body and didChange incremental with debounce', function()
+ local expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="finish", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ }
+ local client
+ test_rpc_server {
+ test_name = "basic_check_buffer_open_and_change_incremental";
+ options = {
+ allow_incremental_sync = true,
+ debounce_text_changes = 5
+ };
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1235,7 +1291,7 @@ describe('LSP', function()
make_edit(2, 0, 2, 2, {"3"});
make_edit(3, 2, 3, 4, {""});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'123First line of text';
'2econd line of text';
@@ -1255,7 +1311,7 @@ describe('LSP', function()
make_edit(3, #'', 3, #"Fourth", {"another line of text", "before this"});
make_edit(3, #'Fourth', 3, #"Fourth line of text", {"!"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'';
'123';
@@ -1279,7 +1335,7 @@ describe('LSP', function()
make_edit(3, #"Fourth", 3, #'', {"another line of text", "before this"});
make_edit(3, #"Fourth line of text", 3, #'Fourth', {"!"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'';
'123';
@@ -1296,7 +1352,7 @@ describe('LSP', function()
local edits = {
make_edit(4, 3, 4, 4, {"ä"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Second line of text';
@@ -1309,7 +1365,7 @@ describe('LSP', function()
local edits = {
make_edit(5, 0, 5, 0, "foobar");
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Second line of text';
@@ -1319,6 +1375,20 @@ describe('LSP', function()
'foobar';
}, buf_lines(1))
end)
+ it('applies multiple text edits at the end of the document', function()
+ local edits = {
+ make_edit(4, 0, 5, 0, "");
+ make_edit(5, 0, 5, 0, "foobar");
+ }
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ eq({
+ 'First line of text';
+ 'Second line of text';
+ 'Third line of text';
+ 'Fourth line of text';
+ 'foobar';
+ }, buf_lines(1))
+ end)
describe('cursor position', function()
it('don\'t fix the cursor if the range contains the cursor', function()
@@ -1326,7 +1396,7 @@ describe('LSP', function()
local edits = {
make_edit(1, 0, 1, 19, 'Second line of text')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Second line of text';
@@ -1343,7 +1413,7 @@ describe('LSP', function()
make_edit(1, 0, 1, 6, ''),
make_edit(1, 6, 1, 19, '')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'';
@@ -1360,7 +1430,7 @@ describe('LSP', function()
make_edit(1, 0, 1, 6, ''),
make_edit(0, 18, 5, 0, '')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
}, buf_lines(1))
@@ -1372,7 +1442,7 @@ describe('LSP', function()
local edits = {
make_edit(1, 0, 2, 0, '')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Third line of text';
@@ -1387,7 +1457,7 @@ describe('LSP', function()
local edits = {
make_edit(1, 7, 1, 11, '')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Second of text';
@@ -1403,7 +1473,7 @@ describe('LSP', function()
local edits = {
make_edit(0, 11, 1, 12, '')
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({
'First line of text';
'Third line of text';
@@ -1419,21 +1489,21 @@ describe('LSP', function()
local edits = {
make_edit(0, 0, 5, 0, {"All replaced"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({'All replaced'}, buf_lines(1))
end)
it('applies edits when the end line is 2 larger than vim\'s', function()
local edits = {
make_edit(0, 0, 6, 0, {"All replaced"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({'All replaced'}, buf_lines(1))
end)
it('applies edits with a column offset', function()
local edits = {
make_edit(0, 0, 5, 2, {"All replaced"});
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
eq({'All replaced'}, buf_lines(1))
end)
end)
@@ -1461,7 +1531,7 @@ describe('LSP', function()
]]
end)
it('correctly goes ahead with the edit if all is normal', function()
- exec_lua('vim.lsp.util.apply_text_document_edit(...)', text_document_edit(5))
+ exec_lua("vim.lsp.util.apply_text_document_edit(..., nil, 'utf-16')", text_document_edit(5))
eq({
'First ↥ 🤦 🦄 line of text';
'2nd line of 语text';
@@ -1473,7 +1543,7 @@ describe('LSP', function()
local bufnr = select(1, ...)
local text_edit = select(2, ...)
vim.lsp.util.buf_versions[bufnr] = 10
- vim.lsp.util.apply_text_document_edit(text_edit)
+ vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
]], target_bufnr, text_document_edit(0))
eq({
'First ↥ 🤦 🦄 line of text';
@@ -1486,7 +1556,7 @@ describe('LSP', function()
local args = {...}
local versionedBuf = args[2]
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
- vim.lsp.util.apply_text_document_edit(args[1])
+ vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16')
]], edit, versionedBuf)
end
@@ -1512,17 +1582,36 @@ describe('LSP', function()
describe('workspace_apply_edit', function()
it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function()
- local expected = {
- applied = true;
- failureReason = nil;
+ local expected_handlers = {
+ {NIL, {}, {method="test", client_id=1}};
+ }
+ test_rpc_server {
+ test_name = "basic_init";
+ on_init = function(client, _)
+ client.stop()
+ end;
+ -- If the program timed out, then code will be nil.
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end;
+ -- Note that NIL must be used here.
+ -- on_handler(err, method, result, client_id)
+ on_handler = function(...)
+ local expected = {
+ applied = true;
+ failureReason = nil;
+ }
+ eq(expected, exec_lua [[
+ local apply_edit = {
+ label = nil;
+ edit = {};
+ }
+ return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit, {client_id = TEST_RPC_CLIENT_ID})
+ ]])
+ eq(table.remove(expected_handlers), {...})
+ end;
}
- eq(expected, exec_lua [[
- local apply_edit = {
- label = nil;
- edit = {};
- }
- return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit)
- ]])
end)
end)
@@ -1596,7 +1685,7 @@ describe('LSP', function()
local workspace_edits = args[1]
local target_bufnr = args[2]
- vim.lsp.util.apply_workspace_edit(workspace_edits)
+ vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
]], make_workspace_edit(edits), target_bufnr))
@@ -1618,7 +1707,7 @@ describe('LSP', function()
local workspace_edits = args[1]
local target_bufnr = args[2]
- vim.lsp.util.apply_workspace_edit(workspace_edits)
+ vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
]], make_workspace_edit(edits), target_bufnr))
@@ -1635,7 +1724,7 @@ describe('LSP', function()
},
}
}
- exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit)
+ exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile))
end)
it('createFile does not touch file if it exists and ignoreIfExists is set', function()
@@ -1653,7 +1742,7 @@ describe('LSP', function()
},
}
}
- exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit)
+ exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile))
eq('Dummy content', read_file(tmpfile))
end)
@@ -1673,7 +1762,7 @@ describe('LSP', function()
},
}
}
- exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit)
+ exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile))
eq('', read_file(tmpfile))
end)
@@ -1694,7 +1783,7 @@ describe('LSP', function()
}
}
}
- eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit))
+ eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
eq(false, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile))
eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile))
end)
@@ -1855,7 +1944,7 @@ describe('LSP', function()
}
},
}
- return vim.lsp.util.locations_to_items(locations)
+ return vim.lsp.util.locations_to_items(locations, 'utf-16')
]]
eq(expected, actual)
end)
@@ -1885,7 +1974,7 @@ describe('LSP', function()
}
},
}
- return vim.lsp.util.locations_to_items(locations)
+ return vim.lsp.util.locations_to_items(locations, 'utf-16')
]]
eq(expected, actual)
end)
@@ -2189,7 +2278,7 @@ describe('LSP', function()
end
local jump = function(msg)
- eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg))
+ eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, "utf-16"))
eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]])
return {
line = exec_lua[[return vim.fn.line('.')]],
@@ -2263,6 +2352,27 @@ describe('LSP', function()
end)
end)
+ describe('lsp.util.convert_signature_help_to_markdown_lines', function()
+ it('can handle negative activeSignature', function()
+ local result = exec_lua[[
+ local signature_help = {
+ activeParameter = 0,
+ activeSignature = -1,
+ signatures = {
+ {
+ documentation = "",
+ label = "TestEntity.TestEntity()",
+ parameters = {}
+ },
+ }
+ }
+ return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'cs', {','})
+ ]]
+ local expected = {'```cs', 'TestEntity.TestEntity()', '```', ''}
+ eq(expected, result)
+ end)
+ end)
+
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, softtabstop)
exec_lua(string.format([[
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index a4d78682ad..6f22f865e6 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
-local eq, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf =
- helpers.eq, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec,
+local eq, meths, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf =
+ helpers.eq, helpers.meths, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec,
helpers.funcs, helpers.feed, helpers.curbuf
local neq = helpers.neq
local read_file = helpers.read_file
@@ -2162,6 +2162,10 @@ describe('plugin/shada.vim', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
+
+ local bufread_commands = meths.get_autocmds({ group = "ShaDaCommands", event = "BufReadCmd" })
+ eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]])
+
-- Need to set nohidden so that the buffer containing 'fname' is not unloaded
-- after loading 'fname_tmp', otherwise the '++opt not supported' test below
-- won't work since the BufReadCmd autocmd won't be triggered.
diff --git a/test/functional/provider/provider_spec.lua b/test/functional/provider/provider_spec.lua
index 78bc4a4edb..3895b8613f 100644
--- a/test/functional/provider/provider_spec.lua
+++ b/test/functional/provider/provider_spec.lua
@@ -14,8 +14,8 @@ describe('providers', function()
command('set loadplugins')
-- Using test-fixture with broken impl:
-- test/functional/fixtures/autoload/provider/python.vim
- eq('Vim:provider: python: missing required variable g:loaded_python_provider',
- pcall_err(eval, "has('python')"))
+ eq('Vim:provider: python3: missing required variable g:loaded_python3_provider',
+ pcall_err(eval, "has('python3')"))
end)
it('with g:loaded_xx_provider, missing #Call()', function()
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index d100db8de2..603f4d91b9 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -8,6 +8,7 @@ local source = helpers.source
local missing_provider = helpers.missing_provider
local matches = helpers.matches
local pcall_err = helpers.pcall_err
+local funcs = helpers.funcs
do
clear()
@@ -93,16 +94,40 @@ describe('python3 provider', function()
ghi]])
end)
- it('py3eval', function()
- eq({1, 2, {['key'] = 'val'}}, eval([[py3eval('[1, 2, {"key": "val"}]')]]))
+ describe('py3eval()', function()
+ it('works', function()
+ eq({1, 2, {['key'] = 'val'}}, funcs.py3eval('[1, 2, {"key": "val"}]'))
+ end)
+
+ it('errors out when given non-string', function()
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(10)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:_null_dict)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:_null_list)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(0.0)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(function("tr"))'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:true)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:false)'))
+ eq('Vim:E474: Invalid argument', pcall_err(eval, 'py3eval(v:null)'))
+ end)
+
+ it('accepts NULL string', function()
+ matches('.*SyntaxError.*', pcall_err(eval, 'py3eval($XXX_NONEXISTENT_VAR_XXX)'))
+ end)
end)
it('pyxeval #10758', function()
- eq(0, eval([[&pyxversion]]))
+ eq(3, eval([[&pyxversion]]))
eq(3, eval([[pyxeval('sys.version_info[:3][0]')]]))
eq(3, eval([[&pyxversion]]))
end)
+ it("setting 'pyxversion'", function()
+ command 'set pyxversion=3' -- no error
+ eq('Vim(set):E474: Invalid argument: pyxversion=2', pcall_err(command, 'set pyxversion=2'))
+ command 'set pyxversion=0' -- allowed, but equivalent to pyxversion=3
+ eq(3, eval'&pyxversion')
+ end)
+
it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function()
helpers.add_builddir_to_rtp()
source([=[
@@ -120,3 +145,15 @@ describe('python3 provider', function()
assert_alive()
end)
end)
+
+describe('python2 feature test', function()
+ -- python2 is not supported, so correct behaviour is to return 0
+ it('works', function()
+ eq(0, funcs.has('python2'))
+ eq(0, funcs.has('python'))
+ eq(0, funcs.has('python_compiled'))
+ eq(0, funcs.has('python_dynamic'))
+ eq(0, funcs.has('python_dynamic_'))
+ eq(0, funcs.has('python_'))
+ end)
+end)
diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua
deleted file mode 100644
index d60d8d1001..0000000000
--- a/test/functional/provider/python_spec.lua
+++ /dev/null
@@ -1,123 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local eq = helpers.eq
-local neq = helpers.neq
-local feed = helpers.feed
-local clear = helpers.clear
-local funcs = helpers.funcs
-local meths = helpers.meths
-local insert = helpers.insert
-local expect = helpers.expect
-local command = helpers.command
-local exc_exec = helpers.exc_exec
-local write_file = helpers.write_file
-local curbufmeths = helpers.curbufmeths
-local missing_provider = helpers.missing_provider
-local matches = helpers.matches
-local pcall_err = helpers.pcall_err
-
-do
- clear()
- local reason = missing_provider('python')
- if reason then
- it(':python reports E319 if provider is missing', function()
- local expected = [[Vim%(py.*%):E319: No "python" provider found.*]]
- matches(expected, pcall_err(command, 'py print("foo")'))
- matches(expected, pcall_err(command, 'pyfile foo'))
- end)
- pending(string.format('Python 2 (or the pynvim module) is broken/missing (%s)', reason), function() end)
- return
- end
-end
-
-before_each(function()
- clear()
- command('python import vim')
-end)
-
-describe('python feature test', function()
- it('works', function()
- eq(1, funcs.has('python'))
- eq(1, funcs.has('python_compiled'))
- eq(1, funcs.has('python_dynamic'))
- eq(0, funcs.has('python_dynamic_'))
- eq(0, funcs.has('python_'))
- end)
-end)
-
-describe(':python command', function()
- it('works with a line', function()
- command('python vim.vars["set_by_python"] = [100, 0]')
- eq({100, 0}, meths.get_var('set_by_python'))
- end)
-
- -- TODO(ZyX-I): works with << EOF
- -- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"…
-
- it('supports nesting', function()
- command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]])
- eq(555, meths.get_var('set_by_nested_python'))
- end)
-
- it('supports range', function()
- insert([[
- line1
- line2
- line3
- line4]])
- feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>')
- eq({'line2', 'line3'}, meths.get_var('range'))
- end)
-end)
-
-describe(':pyfile command', function()
- it('works', function()
- local fname = 'pyfile.py'
- write_file(fname, 'vim.command("let set_by_pyfile = 123")')
- command('pyfile pyfile.py')
- eq(123, meths.get_var('set_by_pyfile'))
- os.remove(fname)
- end)
-end)
-
-describe(':pydo command', function()
- it('works', function()
- -- :pydo 42 returns None for all lines,
- -- the buffer should not be changed
- command('normal :pydo 42')
- eq(false, curbufmeths.get_option('modified'))
- -- insert some text
- insert('abc\ndef\nghi')
- expect([[
- abc
- def
- ghi]])
- -- go to top and select and replace the first two lines
- feed('ggvj:pydo return str(linenr)<CR>')
- expect([[
- 1
- 2
- ghi]])
- end)
-end)
-
-describe('pyeval()', function()
- it('works', function()
- eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]'))
- end)
-
- it('errors out when given non-string', function()
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)'))
- eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)'))
- end)
-
- it('accepts NULL string', function()
- neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)'))
- end)
-end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index f25cfa2039..1cef771f0d 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -258,6 +258,7 @@ describe(':terminal buffer', function()
end)
it('it works with set rightleft #11438', function()
+ if helpers.pending_win32(pending) then return end
local columns = eval('&columns')
feed(string.rep('a', columns))
command('set rightleft')
@@ -292,10 +293,9 @@ describe(':terminal buffer', function()
command('quit')
end)
- it('does not segfault when pasting empty buffer #13955', function()
- feed_command('terminal')
+ it('does not segfault when pasting empty register #13955', function()
feed('<c-\\><c-n>')
- feed_command('put a') -- buffer a is empty
+ feed_command('put a') -- register a is empty
helpers.assert_alive()
end)
end)
@@ -350,7 +350,7 @@ describe('on_lines does not emit out-of-bounds line indexes when', function()
end)
it('creating a terminal buffer #16394', function()
- feed_command([[autocmd TermOpen * ++once call v:lua.register_callback(expand("<abuf>"))]])
+ feed_command('autocmd TermOpen * ++once call v:lua.register_callback(str2nr(expand("<abuf>")))')
feed_command('terminal')
sleep(500)
eq('', exec_lua([[return _G.cb_error]]))
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index e9495f45a2..3b905f1f56 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -87,6 +87,7 @@ describe(':terminal cursor', function()
describe('when invisible', function()
it('is not highlighted and is detached from screen cursor', function()
+ if helpers.pending_win32(pending) then return end
hide_cursor()
screen:expect([[
tty ready |
@@ -176,6 +177,7 @@ describe('cursor with customized highlighting', function()
end)
describe('buffer cursor position is correct in terminal without number column', function()
+ if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
@@ -526,6 +528,7 @@ describe('buffer cursor position is correct in terminal without number column',
end)
describe('buffer cursor position is correct in terminal with number column', function()
+ if helpers.pending_win32(pending) then return end
local screen
local function setup_ex_register(str)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index fabc5524ed..e7025d6739 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -36,6 +36,7 @@ describe(':edit term://*', function()
end)
it("runs TermOpen early enough to set buffer-local 'scrollback'", function()
+ if helpers.pending_win32(pending) then return end
local columns, lines = 20, 4
local scr = get_screen(columns, lines)
local rep = 97
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 065dd72485..b4f29a586a 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -142,6 +142,7 @@ describe(':terminal (with fake shell)', function()
end
it('with no argument, acts like termopen()', function()
+ if helpers.pending_win32(pending) then return end
terminal_with_fake_shell()
retry(nil, 4 * screen.timeout, function()
screen:expect([[
@@ -165,6 +166,7 @@ describe(':terminal (with fake shell)', function()
end)
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
+ if helpers.pending_win32(pending) then return end
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
terminal_with_fake_shell()
screen:expect([[
@@ -176,6 +178,7 @@ describe(':terminal (with fake shell)', function()
end)
it('executes a given command through the shell', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
screen:expect([[
@@ -187,6 +190,7 @@ describe(':terminal (with fake shell)', function()
end)
it("executes a given command through the shell, when 'shell' has arguments", function()
+ if helpers.pending_win32(pending) then return end
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
@@ -199,6 +203,7 @@ describe(':terminal (with fake shell)', function()
end)
it('allows quotes and slashes', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell([[echo 'hello' \ "world"]])
screen:expect([[
@@ -235,6 +240,7 @@ describe(':terminal (with fake shell)', function()
end)
it('works with :find', function()
+ if helpers.pending_win32(pending) then return end
terminal_with_fake_shell()
screen:expect([[
^ready $ |
@@ -253,6 +259,7 @@ describe(':terminal (with fake shell)', function()
end)
it('works with gf', function()
+ if helpers.pending_win32(pending) then return end
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell([[echo "scripts/shadacat.py"]])
retry(nil, 4 * screen.timeout, function()
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 8d3f0218af..ebbae1df14 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -117,6 +117,7 @@ describe(':terminal highlight', function()
end)
it(':terminal highlight has lower precedence than editor #9964', function()
+ if helpers.pending_win32(pending) then return end
clear()
local screen = Screen.new(30, 4)
screen:set_default_attr_ids({
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index 833ded9479..6e2c851df7 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -1,7 +1,7 @@
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, nvim = helpers.feed, helpers.nvim
+local feed, nvim, command = helpers.feed, helpers.nvim, helpers.command
local feed_data = thelpers.feed_data
describe(':terminal mouse', function()
@@ -10,9 +10,9 @@ describe(':terminal mouse', function()
before_each(function()
clear()
nvim('set_option', 'statusline', '==========')
- nvim('command', 'highlight StatusLine cterm=NONE')
- nvim('command', 'highlight StatusLineNC cterm=NONE')
- nvim('command', 'highlight VertSplit cterm=NONE')
+ command('highlight StatusLine cterm=NONE')
+ command('highlight StatusLineNC cterm=NONE')
+ command('highlight VertSplit cterm=NONE')
screen = thelpers.screen_setup()
local lines = {}
for i = 1, 30 do
@@ -38,6 +38,26 @@ describe(':terminal mouse', function()
eq('nt', eval('mode(1)'))
end)
+ it('will exit focus and trigger Normal mode mapping on mouse click', function()
+ command('let g:got_leftmouse = 0')
+ command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>')
+ eq('t', eval('mode(1)'))
+ eq(0, eval('g:got_leftmouse'))
+ feed('<LeftMouse>')
+ eq('nt', eval('mode(1)'))
+ eq(1, eval('g:got_leftmouse'))
+ end)
+
+ it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function()
+ command('let g:got_ctrl_leftmouse = 0')
+ command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>')
+ eq('t', eval('mode(1)'))
+ eq(0, eval('g:got_ctrl_leftmouse'))
+ feed('<C-LeftMouse>')
+ eq('nt', eval('mode(1)'))
+ eq(1, eval('g:got_ctrl_leftmouse'))
+ end)
+
it('will exit focus on <C-\\> + mouse-scroll', function()
eq('t', eval('mode(1)'))
feed('<C-\\>')
@@ -66,7 +86,7 @@ describe(':terminal mouse', function()
]])
end)
- it('will forward mouse clicks to the program', function()
+ it('will forward mouse press, drag and release to the program', function()
if helpers.pending_win32(pending) then return end
feed('<LeftMouse><1,2>')
screen:expect([[
@@ -78,6 +98,36 @@ describe(':terminal mouse', function()
"#{1: } |
{3:-- TERMINAL --} |
]])
+ feed('<LeftDrag><2,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ @##{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftDrag><3,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ @$#{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftRelease><3,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ #$#{1: } |
+ {3:-- TERMINAL --} |
+ ]])
end)
it('will forward mouse scroll to the program', function()
@@ -94,9 +144,63 @@ describe(':terminal mouse', function()
]])
end)
+ it('dragging and scrolling do not interfere with each other', function()
+ if helpers.pending_win32(pending) then return end
+ feed('<LeftMouse><1,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ "#{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<ScrollWheelUp><1,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ `"#{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftDrag><2,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ @##{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<ScrollWheelUp><2,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ `##{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftRelease><2,2>')
+ screen:expect([[
+ line27 |
+ line28 |
+ line29 |
+ line30 |
+ mouse enabled |
+ ###{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
it('will forward mouse clicks to the program with the correct even if set nu', function()
if helpers.pending_win32(pending) then return end
- nvim('command', 'set number')
+ command('set number')
-- When the display area such as a number is clicked, it returns to the
-- normal mode.
feed('<LeftMouse><3,0>')
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 11bdc73a47..d1cfc7e91b 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -345,6 +345,7 @@ end)
describe(':terminal prints more lines than the screen height and exits', function()
it('will push extra lines to scrollback', function()
+ if helpers.pending_win32(pending) then return end
clear()
local screen = Screen.new(30, 7)
screen:attach({rgb=false})
@@ -576,6 +577,7 @@ describe("pending scrollback line handling", function()
end)
it("does not crash after nvim_buf_call #14891", function()
+ if helpers.pending_win32(pending) then return end
exec_lua [[
local a = vim.api
local bufnr = a.nvim_create_buf(false, true)
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index bf57b135cb..faf44fa01d 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -20,7 +20,6 @@ local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
local ok = helpers.ok
local read_file = helpers.read_file
-local exec_lua = helpers.exec_lua
if helpers.pending_win32(pending) then return end
@@ -581,34 +580,21 @@ describe('TUI', function()
end)
it("paste: 'nomodifiable' buffer", function()
- local has_luajit = exec_lua('return jit ~= nil')
child_session:request('nvim_command', 'set nomodifiable')
child_session:request('nvim_exec_lua', [[
- -- Stack traces for this test are non-deterministic, so disable them
- _G.debug.traceback = function(msg) return msg end
+ -- Truncate the error message to hide the line number
+ _G.debug.traceback = function(msg) return msg:sub(-49) end
]], {})
feed_data('\027[200~fail 1\nfail 2\n\027[201~')
- if has_luajit then
- screen:expect{grid=[[
- |
- {4:~ }|
- {5: }|
- {8:paste: Error executing lua: vim.lua:0: Vim:E21: Ca}|
- {8:nnot make changes, 'modifiable' is off} |
- {10:Press ENTER or type command to continue}{1: } |
- {3:-- TERMINAL --} |
- ]]}
- else
- screen:expect{grid=[[
- |
- {4:~ }|
- {5: }|
- {8:paste: Error executing lua: Vim:E21: Cannot make c}|
- {8:hanges, 'modifiable' is off} |
- {10:Press ENTER or type command to continue}{1: } |
- {3:-- TERMINAL --} |
- ]]}
- end
+ screen:expect{grid=[[
+ |
+ {4:~ }|
+ {5: }|
+ {8:paste: Error executing lua: Vim:E21: Cannot make c}|
+ {8:hanges, 'modifiable' is off} |
+ {10:Press ENTER or type command to continue}{1: } |
+ {3:-- TERMINAL --} |
+ ]]}
feed_data('\n') -- <Enter>
child_session:request('nvim_command', 'set modifiable')
feed_data('\027[200~success 1\nsuccess 2\n\027[201~')
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 9f278fd157..0d3295cf32 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -18,6 +18,7 @@ describe(':terminal window', function()
end)
it('sets topline correctly #8556', function()
+ if helpers.pending_win32(pending) then return end
-- Test has hardcoded assumptions of dimensions.
eq(7, eval('&lines'))
feed_data('\n\n\n') -- Add blank lines.
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 175525b3f2..ed28d8a37d 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -23,7 +23,7 @@ local hl_query = [[
"enum" @type
"extern" @type
- (string_literal) @string
+ (string_literal) @string.nonexistent-specializer-for-string.should-fallback-to-string
(number_literal) @number
(char_literal) @string
@@ -613,4 +613,91 @@ describe('treesitter highlighting', function()
[12] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Grey100};
}}
end)
+
+ it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function()
+ if pending_c_parser(pending) then return end
+
+ insert([[
+ char* x = "Will somebody ever read this?";
+ ]])
+
+ screen:expect{grid=[[
+ char* x = "Will somebody ever read this?"; |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ local parser = vim.treesitter.get_parser(0, "c", {})
+ local highlighter = vim.treesitter.highlighter
+ highlighter.hl_map['foo.bar'] = 'Type'
+ highlighter.hl_map['foo'] = 'String'
+ test_hl = highlighter.new(parser, {queries = {c = "(primitive_type) @foo.bar (string_literal) @foo"}})
+ ]]
+
+ screen:expect{grid=[[
+ {3:char}* x = {5:"Will somebody ever read this?"}; |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it("hl_map has the correct fallback behavior", function()
+ exec_lua [[
+ local hl_map = vim.treesitter.highlighter.hl_map
+ hl_map["foo"] = 1
+ hl_map["foo.bar"] = 2
+ hl_map["foo.bar.baz"] = 3
+
+ assert(hl_map["foo"] == 1)
+ assert(hl_map["foo.a.b.c.d"] == 1)
+ assert(hl_map["foo.bar"] == 2)
+ assert(hl_map["foo.bar.a.b.c.d"] == 2)
+ assert(hl_map["foo.bar.baz"] == 3)
+ assert(hl_map["foo.bar.baz.d"] == 3)
+
+ hl_map["FOO"] = 1
+ hl_map["FOO.BAR"] = 2
+ assert(hl_map["FOO.BAR.BAZ"] == 2)
+
+ hl_map["foo.missing.exists"] = 3
+ assert(hl_map["foo.missing"] == 1)
+ assert(hl_map["foo.missing.exists"] == 3)
+ assert(hl_map["foo.missing.exists.bar"] == 3)
+ assert(hl_map["total.nonsense.but.a.lot.of.dots"] == nil)
+ -- It will not perform a second look up of this variable but return a sentinel value
+ assert(hl_map["total.nonsense.but.a.lot.of.dots"] == "__notfound")
+ ]]
+
+ end)
end)
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 911fa017ab..599c74102c 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -167,6 +167,27 @@ void ui_refresh(void)
eq('variable', ret)
end)
+ it("supports caching queries", function()
+ local long_query = query:rep(100)
+ local first_run = exec_lua ([[
+ local before = vim.loop.hrtime()
+ cquery = vim.treesitter.parse_query("c", ...)
+ local after = vim.loop.hrtime()
+ return after - before
+ ]], long_query)
+
+ local subsequent_runs = exec_lua ([[
+ local before = vim.loop.hrtime()
+ for i=1,100,1 do
+ cquery = vim.treesitter.parse_query("c", ...)
+ end
+ local after = vim.loop.hrtime()
+ return after - before
+ ]], long_query)
+
+ assert.True(1000 * subsequent_runs < first_run)
+ end)
+
it('support query and iter by capture', function()
insert(test_text)
@@ -264,6 +285,25 @@ end]]
eq(true, result)
end)
+ it('support getting empty text if node range is zero width', function()
+ local text = [[
+```lua
+{}
+```]]
+ insert(text)
+ local result = exec_lua([[
+ local fake_node = {}
+ function fake_node:start()
+ return 1, 0, 7
+ end
+ function fake_node:end_()
+ return 1, 0, 7
+ end
+ return vim.treesitter.get_node_text(fake_node, 0) == ''
+ ]])
+ eq(true, result)
+ end)
+
it('can match special regex characters like \\ * + ( with `vim-match?`', function()
insert('char* astring = "\\n"; (1 + 1) * 2 != 2;')
@@ -645,6 +685,21 @@ int x = INT_MAX;
-- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y))
}, get_ranges())
end)
+
+ it("should not inject bad languages", function()
+ if helpers.pending_win32(pending) then return end
+ exec_lua([=[
+ vim.treesitter.add_directive("inject-bad!", function(match, _, _, pred, metadata)
+ metadata.language = "{"
+ metadata.combined = true
+ metadata.content = pred[2]
+ end)
+
+ parser = vim.treesitter.get_parser(0, "c", {
+ injections = {
+ c = "(preproc_function_def value: ((preproc_arg) @_a (#inject-bad! @_a)))"}})
+ ]=])
+ end)
end)
describe("when using the offset directive", function()
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index 16ed3b9486..9f84b71ece 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -755,12 +755,26 @@ describe('Buffer highlighting', function()
-- TODO: only a virtual text from the same ns curretly overrides
-- an existing virtual text. We might add a prioritation system.
set_virtual_text(id1, 0, s1, {})
- eq({{1, 0, 0, { priority = 0, virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
+ eq({{1, 0, 0, {
+ priority = 0,
+ virt_text = s1,
+ -- other details
+ right_gravity = true,
+ virt_text_pos = 'eol',
+ virt_text_hide = false,
+ }}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
-- TODO: is this really valid? shouldn't the max be line_count()-1?
local lastline = line_count()
set_virtual_text(id1, line_count(), s2, {})
- eq({{3, lastline, 0, { priority = 0, virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
+ eq({{3, lastline, 0, {
+ priority = 0,
+ virt_text = s2,
+ -- other details
+ right_gravity = true,
+ virt_text_pos = 'eol',
+ virt_text_hide = false,
+ }}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 9c746b99bd..384761ab17 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -33,7 +33,7 @@ before_each(function()
let g:NUM_LVLS = 4
function Redraw()
mode
- return ''
+ return "\<Ignore>"
endfunction
let g:id = ''
cnoremap <expr> {REDRAW} Redraw()
@@ -42,7 +42,7 @@ before_each(function()
let Cb = g:Nvim_color_input{g:id}
let out = input({'prompt': ':', 'highlight': Cb})
let g:out{id} = out
- return (a:do_return ? out : '')
+ return (a:do_return ? out : "\<Ignore>")
endfunction
nnoremap <expr> {PROMPT} DoPrompt(0)
cnoremap <expr> {PROMPT} DoPrompt(1)
@@ -410,7 +410,7 @@ describe('Command-line coloring', function()
end)
it('stops executing callback after a number of errors', function()
set_color_cb('SplittedMultibyteStart')
- start_prompt('let x = "«»«»«»«»«»"\n')
+ start_prompt('let x = "«»«»«»«»«»"')
screen:expect([[
{EOB:~ }|
{EOB:~ }|
@@ -419,7 +419,7 @@ describe('Command-line coloring', function()
:let x = " |
{ERR:E5405: Chunk 0 start 10 splits multibyte}|
{ERR: character} |
- ^:let x = "«»«»«»«»«»" |
+ :let x = "«»«»«»«»«»"^ |
]])
feed('\n')
screen:expect([[
@@ -432,6 +432,7 @@ describe('Command-line coloring', function()
{EOB:~ }|
|
]])
+ feed('\n')
eq('let x = "«»«»«»«»«»"', meths.get_var('out'))
local msg = '\nE5405: Chunk 0 start 10 splits multibyte character'
eq(msg:rep(1), funcs.execute('messages'))
@@ -474,14 +475,14 @@ describe('Command-line coloring', function()
]])
feed('\n')
screen:expect([[
- |
+ ^ |
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
{EOB:~ }|
- ^:echo 42 |
+ :echo 42 |
]])
feed('\n')
eq('echo 42', meths.get_var('out'))
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 5f29261b17..dc26c52f1a 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -417,6 +417,28 @@ describe('float window', function()
eq(winids, eval('winids'))
end)
+ it('closed when the last non-float window is closed', function()
+ local tabpage = exec_lua([[
+ vim.cmd('edit ./src/nvim/main.c')
+ vim.cmd('tabedit %')
+
+ local buf = vim.api.nvim_create_buf(false, true)
+ local win = vim.api.nvim_open_win(buf, false, {
+ relative = 'win',
+ row = 1,
+ col = 1,
+ width = 10,
+ height = 2
+ })
+
+ vim.cmd('quit')
+
+ return vim.api.nvim_get_current_tabpage()
+ ]])
+
+ eq(1, tabpage)
+ end)
+
local function with_ext_multigrid(multigrid)
local screen
before_each(function()
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 0983d0d4ad..12643eec1e 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local command = helpers.command
+local command, exec = helpers.command, helpers.exec
local eval, exc_exec = helpers.eval, helpers.exc_exec
local feed_command, eq = helpers.feed_command, helpers.eq
local curbufmeths = helpers.curbufmeths
@@ -1172,6 +1172,105 @@ describe('CursorLine highlight', function()
end)
end)
+describe('ColorColumn highlight', function()
+ local screen
+
+ 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
+ -- NonText and ColorColumn
+ [6] = {foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true},
+ [7] = {reverse = true, bold = true}, -- StatusLine
+ [8] = {reverse = true}, -- StatusLineNC
+ })
+ screen:attach()
+ end)
+
+ it('when entering a buffer vim-patch:8.1.2073', function()
+ exec([[
+ set nohidden
+ split
+ edit X
+ call setline(1, ["1111111111","22222222222","3333333333"])
+ set nomodified
+ set colorcolumn=3,9
+ set number cursorline cursorlineopt=number
+ wincmd w
+ 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:~ }|
+ {5:~ }|
+ {5:~ }|
+ {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:~ }|
+ {5:~ }|
+ {5:~ }|
+ {7:X }|
+ |
+ ]])
+ end)
+
+ it("in 'breakindent' vim-patch:8.2.1689", function()
+ exec([[
+ call setline(1, 'The quick brown fox jumped over the lazy dogs')
+ 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:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ |
+ ]])
+ end)
+
+ it("in 'showbreak' vim-patch:8.2.1689", function()
+ exec([[
+ call setline(1, 'The quick brown fox jumped over the lazy dogs')
+ 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:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ |
+ ]])
+ end)
+end)
describe("MsgSeparator highlight and msgsep fillchar", function()
local screen
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 2a567b28ee..295b70f265 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -179,6 +179,8 @@ describe('ext_hlstate detailed highlights', function()
end)
it("work with :terminal", function()
+ if helpers.pending_win32(pending) then return end
+
screen:set_default_attr_ids({
[1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}},
[2] = {{foreground = tonumber('0x00ccff'), fg_indexed=true}, {{kind = "term"}}},
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index b6e2f2311f..10700d9508 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -293,6 +293,70 @@ describe(":substitute, 'inccommand' preserves", function()
end)
end
+ for _, case in ipairs({'', 'split', 'nosplit'}) do
+ it('previous substitute string ~ (inccommand='..case..') #12109', function()
+ local screen = Screen.new(30,10)
+ common_setup(screen, case, default_text)
+
+ feed(':%s/Inc/SUB<CR>')
+ expect([[
+ SUB substitution on
+ two lines
+ ]])
+
+ feed(':%s/line/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB substitution on
+ two SUBs
+ ]])
+
+ feed(':%s/sti/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('B')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB subSUBBtution on
+ two SUBs
+ ]])
+
+ feed(':%s/ion/NEW<CR>')
+ expect([[
+ SUB subSUBBtutNEW on
+ two SUBs
+ ]])
+
+ feed(':%s/two/')
+ poke_eventloop()
+ feed('N')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB subSUBBtutNEW on
+ NNEW SUBs
+ ]])
+
+ feed(':%s/bS/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('W')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB suNNEWWUBBtutNEW on
+ NNEW SUBs
+ ]])
+ end)
+ end
end)
describe(":substitute, 'inccommand' preserves undo", function()
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index ea8968a653..7000505909 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -114,11 +114,49 @@ describe('mappings', function()
end)
end)
-describe('input utf sequences that contain CSI/K_SPECIAL', function()
+describe('input utf sequences that contain K_SPECIAL (0x80)', function()
it('ok', function()
feed('i…<esc>')
expect('…')
end)
+
+ it('can be mapped', function()
+ command('inoremap … E280A6')
+ feed('i…<esc>')
+ expect('E280A6')
+ end)
+end)
+
+describe('input utf sequences that contain CSI (0x9B)', function()
+ it('ok', function()
+ feed('iě<esc>')
+ expect('ě')
+ end)
+
+ it('can be mapped', function()
+ command('inoremap ě C49B')
+ feed('iě<esc>')
+ expect('C49B')
+ end)
+end)
+
+describe('input split utf sequences', function()
+ it('ok', function()
+ local str = '►'
+ feed('i' .. str:sub(1, 1))
+ helpers.sleep(10)
+ feed(str:sub(2, 3))
+ expect('►')
+ end)
+
+ it('can be mapped', function()
+ command('inoremap ► E296BA')
+ local str = '►'
+ feed('i' .. str:sub(1, 1))
+ helpers.sleep(10)
+ feed(str:sub(2, 3))
+ expect('E296BA')
+ end)
end)
describe('input non-printable chars', function()
@@ -146,7 +184,7 @@ describe('input non-printable chars', function()
{1:~ }|
{1:~ }|
{1:~ }|
- "Xtest-overwrite" [noeol] 1L, 6C |
+ "Xtest-overwrite" [noeol] 1L, 6B |
]])
-- The timestamp is in second resolution, wait two seconds to be sure.
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index f038348253..949591870a 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1206,6 +1206,7 @@ end)
describe('ui/msg_puts_printf', function()
it('output multibyte characters correctly', function()
+ if helpers.pending_win32(pending) then return end
local screen
local cmd = ''
local locale_dir = test_build_dir..'/share/locale/ja/LC_MESSAGES'
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 50e5dfac84..7305baa761 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -14,6 +14,7 @@ local has_powershell = helpers.has_powershell
local set_shell_powershell = helpers.set_shell_powershell
describe("shell command :!", function()
+ if helpers.pending_win32(pending) then return end
local screen
before_each(function()
clear()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 4fc5c389e5..c44e59cfd3 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -10,6 +10,7 @@ local funcs = helpers.funcs
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
local pcall_err = helpers.pcall_err
+local exec_lua = helpers.exec_lua
describe('ui/ext_popupmenu', function()
local screen
@@ -25,6 +26,7 @@ describe('ui/ext_popupmenu', function()
[5] = {bold = true, foreground = Screen.colors.SeaGreen},
[6] = {background = Screen.colors.WebGray},
[7] = {background = Screen.colors.LightMagenta},
+ [8] = {foreground = Screen.colors.Red},
})
source([[
function! TestComplete() abort
@@ -369,6 +371,111 @@ describe('ui/ext_popupmenu', function()
{1:~ }|
{2:-- INSERT --} |
]])
+
+ command('iunmap <f1>')
+ command('iunmap <f2>')
+ command('iunmap <f3>')
+ exec_lua([[
+ vim.keymap.set('i', '<f1>', function() vim.api.nvim_select_popupmenu_item(2, true, false, {}) end)
+ vim.keymap.set('i', '<f2>', function() vim.api.nvim_select_popupmenu_item(-1, false, false, {}) end)
+ vim.keymap.set('i', '<f3>', function() vim.api.nvim_select_popupmenu_item(1, false, true, {}) end)
+ ]])
+ feed('<C-r>=TestComplete()<CR>')
+ screen:expect([[
+ |
+ foo^ |
+ {6:fo x the foo }{1: }|
+ {7:bar }{1: }|
+ {7:spam }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
+
+ feed('<f1>')
+ screen:expect([[
+ |
+ spam^ |
+ {7:fo x the foo }{1: }|
+ {7:bar }{1: }|
+ {6:spam }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
+
+ feed('<f2>')
+ screen:expect([[
+ |
+ spam^ |
+ {7:fo x the foo }{1: }|
+ {7:bar }{1: }|
+ {7:spam }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
+
+ feed('<f3>')
+ screen:expect([[
+ |
+ bar^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
+
+ feed('<esc>ddiaa bb cc<cr>')
+ feed('<c-x><c-n>')
+ screen:expect([[
+ aa bb cc |
+ aa^ |
+ {6:aa }{1: }|
+ {7:bb }{1: }|
+ {7:cc }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- Keyword Local completion (^N^P) }{5:match 1 of 3} |
+ ]])
+
+ feed('<f1>')
+ screen:expect([[
+ aa bb cc |
+ cc^ |
+ {7:aa }{1: }|
+ {7:bb }{1: }|
+ {6:cc }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- Keyword Local completion (^N^P) }{5:match 3 of 3} |
+ ]])
+
+ feed('<f2>')
+ screen:expect([[
+ aa bb cc |
+ cc^ |
+ {7:aa }{1: }|
+ {7:bb }{1: }|
+ {7:cc }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- Keyword Local completion (^N^P) }{8:Back at original} |
+ ]])
+
+ feed('<f3>')
+ screen:expect([[
+ aa bb cc |
+ bb^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
end)
local function source_complete_month()
@@ -2214,6 +2321,47 @@ describe('builtin popupmenu', function()
assert_alive()
end)
+ it('is closed by :stopinsert from timer #12976', function()
+ screen:try_resize(32,14)
+ command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]])
+ feed('Gah<C-N>')
+ screen:expect([[
+ hello |
+ hullo |
+ heeee |
+ hello^ |
+ {s:hello }{1: }|
+ {n:hullo }{1: }|
+ {n:heeee }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- }{5:match 1 of 3} |
+ ]])
+ command([[call timer_start(100, { -> execute('stopinsert') })]])
+ helpers.sleep(200)
+ feed('k') -- cursor should move up in Normal mode
+ screen:expect([[
+ hello |
+ hullo |
+ heee^e |
+ hello |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+
it('truncates double-width character correctly when there is no scrollbar', function()
screen:try_resize(32,8)
command('set completeopt+=menuone,noselect')
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index 958e137f65..09bcbc2bbd 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -6,6 +6,7 @@ local insert = helpers.insert
local eq = helpers.eq
local eval = helpers.eval
local iswin = helpers.iswin
+local funcs, meths, exec_lua = helpers.funcs, helpers.meths, helpers.exec_lua
describe('screen', function()
local screen
@@ -127,14 +128,67 @@ local function screen_tests(linegrid)
end)
it('has correct default title with named file', function()
- local expected = (iswin() and 'myfile (C:\\mydir) - NVIM'
- or 'myfile (/mydir) - NVIM')
+ local expected = (iswin() and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM')
command('set title')
command(iswin() and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
screen:expect(function()
eq(expected, screen.title)
end)
end)
+
+ describe('is not changed by', function()
+ local file1 = iswin() and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
+ local file2 = iswin() and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
+ local expected = (iswin() and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM')
+ local buf2
+
+ before_each(function()
+ command('edit '..file1)
+ buf2 = funcs.bufadd(file2)
+ command('set title')
+ end)
+
+ it('calling setbufvar() to set an option in a hidden buffer from i_CTRL-R', function()
+ command([[inoremap <F2> <C-R>=setbufvar(]]..buf2..[[, '&autoindent', 1) ? '' : ''<CR>]])
+ feed('i<F2><Esc>')
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('an RPC call to nvim_buf_set_option in a hidden buffer', function()
+ meths.buf_set_option(buf2, 'autoindent', true)
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('a Lua callback calling nvim_buf_set_option in a hidden buffer', function()
+ exec_lua(string.format([[
+ vim.schedule(function()
+ vim.api.nvim_buf_set_option(%d, 'autoindent', true)
+ end)
+ ]], buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('a Lua callback calling nvim_buf_call in a hidden buffer', function()
+ exec_lua(string.format([[
+ vim.schedule(function()
+ vim.api.nvim_buf_call(%d, function() end)
+ end)
+ ]], buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+ end)
end)
describe(':set icon', function()
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index dcd31cfdb7..f718786557 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -446,7 +446,7 @@ describe('Signs', function()
{1:>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: }{6:^ 4 } |
+ {2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
@@ -468,7 +468,7 @@ describe('Signs', function()
{1:>>>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: ^ }{6: 4 } |
+ {2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
@@ -512,7 +512,33 @@ describe('Signs', function()
{1:>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
- {2: }{6: ^4 } |
+ {2: }{6: 4 }^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('shows the line number when signcolumn=number but no marks on a line have text', function()
+ feed('ia<cr>b<cr>c<cr><esc>')
+ command('set number signcolumn=number')
+ command('sign define pietSearch text=>> texthl=Search numhl=Error')
+ command('sign define pietError text= texthl=Search numhl=Error')
+ command('sign place 1 line=1 name=pietSearch buffer=1')
+ command('sign place 2 line=2 name=pietError buffer=1')
+ -- no signcolumn, line number for "a" is Search, for "b" is Error, for "c" is LineNr
+ screen:expect([[
+ {1: >> }a |
+ {8: 2 }b |
+ {6: 3 }c |
+ {6: 4 }^ |
{0:~ }|
{0:~ }|
{0:~ }|
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
index e1459ab5b8..0c2ca8de78 100644
--- a/test/functional/vimscript/eval_spec.lua
+++ b/test/functional/vimscript/eval_spec.lua
@@ -5,7 +5,7 @@
-- null_spec.lua
-- operators_spec.lua
--
--- Tests for the Vimscript |functions| library should live in:
+-- Tests for the Vimscript |builtin-functions| library should live in:
-- test/functional/vimscript/<funcname>_spec.lua
-- test/functional/vimscript/functions_spec.lua
diff --git a/test/functional/vimscript/functions_spec.lua b/test/functional/vimscript/functions_spec.lua
index 0ad7fd8010..20c1400030 100644
--- a/test/functional/vimscript/functions_spec.lua
+++ b/test/functional/vimscript/functions_spec.lua
@@ -1,4 +1,4 @@
--- Tests for misc Vimscript |functions|.
+-- Tests for misc Vimscript |builtin-functions|.
--
-- If a function is non-trivial, consider moving its spec to:
-- test/functional/vimscript/<funcname>_spec.lua
diff --git a/test/functional/vimscript/timer_spec.lua b/test/functional/vimscript/timer_spec.lua
index e45b64422f..25e46062b7 100644
--- a/test/functional/vimscript/timer_spec.lua
+++ b/test/functional/vimscript/timer_spec.lua
@@ -272,4 +272,12 @@ describe('timers', function()
]]
eq("Vim(call):E48: Not allowed in sandbox", exc_exec("sandbox call timer_start(0, 'Scary')"))
end)
+
+ it('can be triggered after an empty string <expr> mapping', function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+ command([=[imap <expr> <F2> [timer_start(0, { _ -> execute("throw 'x'", "") }), ''][-1]]=])
+ feed('i<F2>')
+ screen:expect({any='E605: Exception not caught: x'})
+ end)
end)
diff --git a/test/helpers.lua b/test/helpers.lua
index 87431e4342..7d2f8f760a 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -58,9 +58,9 @@ local check_logs_useless_lines = {
--- Invokes `fn` and includes the tail of `logfile` in the error message if it
--- fails.
---
----@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
----@param fn Function to invoke
----@param ... Function arguments
+---@param logfile string Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
+---@param fn string Function to invoke
+---@param ... string Function arguments
local function dumplog(logfile, fn, ...)
-- module.validate({
-- logfile={logfile,'s',true},
@@ -102,8 +102,8 @@ end
--- Asserts that `pat` matches one or more lines in the tail of $NVIM_LOG_FILE.
---
----@param pat (string) Lua pattern to search for in the log file.
----@param logfile (string, default=$NVIM_LOG_FILE) full path to log file.
+---@param pat string Lua pattern to search for in the log file
+---@param logfile string Full path to log file (default=$NVIM_LOG_FILE)
function module.assert_log(pat, logfile)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local nrlines = 10
@@ -801,12 +801,10 @@ end
function module.isCI(name)
local any = (name == nil)
- assert(any or name == 'appveyor' or name == 'travis' or name == 'sourcehut' or name == 'github')
- local av = ((any or name == 'appveyor') and nil ~= os.getenv('APPVEYOR'))
- local tr = ((any or name == 'travis') and nil ~= os.getenv('TRAVIS'))
+ assert(any or name == 'sourcehut' or name == 'github')
local sh = ((any or name == 'sourcehut') and nil ~= os.getenv('SOURCEHUT'))
local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS'))
- return tr or av or sh or gh
+ return sh or gh
end
@@ -815,7 +813,7 @@ end
function module.read_nvim_log(logfile, ci_rename)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local is_ci = module.isCI()
- local keep = is_ci and 999 or 10
+ local keep = is_ci and 100 or 10
local lines = module.read_file_list(logfile, -keep) or {}
local log = (('-'):rep(78)..'\n'
..string.format('$NVIM_LOG_FILE: %s\n', logfile)
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index 3692e19379..34c88248e6 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -249,7 +249,7 @@ describe('buffer functions', function()
--
-- @param arg Options can be placed in an optional dictionary as the last parameter
-- .expected_cell_count The expected number of cells build_stl_str_hl will return
- -- .expected_byte_length The expected byte length of the string
+ -- .expected_byte_length The expected byte length of the string (defaults to byte length of expected_stl)
-- .file_name The name of the file to be tested (useful in %f type tests)
-- .fillchar The character that will be used to fill any 'extra' space in the stl
local function statusline_test (description,
@@ -264,7 +264,7 @@ describe('buffer functions', function()
local fillchar = option.fillchar or (' '):byte()
local expected_cell_count = option.expected_cell_count or statusline_cell_count
- local expected_byte_length = option.expected_byte_length or expected_cell_count
+ local expected_byte_length = option.expected_byte_length or #expected_stl
itp(description, function()
if option.file_name then
@@ -312,12 +312,12 @@ describe('buffer functions', function()
statusline_test('should put fillchar `~` in between text', 10,
'abc%=def', 'abc~~~~def',
{fillchar=('~'):byte()})
+ statusline_test('should put fillchar `━` in between text', 10,
+ 'abc%=def', 'abc━━━━def',
+ {fillchar=0x2501})
statusline_test('should handle zero-fillchar as a space', 10,
'abcde%=', 'abcde ',
{fillchar=0})
- statusline_test('should handle multibyte-fillchar as a dash', 10,
- 'abcde%=', 'abcde-----',
- {fillchar=0x80})
statusline_test('should print the tail file name', 80,
'%t', 'buffer_spec.lua',
{file_name='test/unit/buffer_spec.lua', expected_cell_count=15})
@@ -366,70 +366,86 @@ describe('buffer functions', function()
statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
- -- alignment testing
- statusline_test('should right align when using =', 20,
- 'neo%=vim', 'neo vim')
- statusline_test('should, when possible, center text when using %=text%=', 20,
- 'abc%=neovim%=def', 'abc neovim def')
- statusline_test('should handle uneven spacing in the buffer when using %=text%=', 20,
- 'abc%=neo_vim%=def', 'abc neo_vim def')
- statusline_test('should have equal spaces even with non-equal sides when using =', 20,
- 'foobar%=test%=baz', 'foobar test baz')
- statusline_test('should have equal spaces even with longer right side when using =', 20,
- 'a%=test%=longtext', 'a test longtext')
- statusline_test('should handle an empty left side when using ==', 20,
- '%=test%=baz', ' test baz')
- statusline_test('should handle an empty right side when using ==', 20,
- 'foobar%=test%=', 'foobar test ')
- statusline_test('should handle consecutive empty ==', 20,
- '%=%=test%=', ' test ')
- statusline_test('should handle an = alone', 20,
- '%=', ' ')
- statusline_test('should right align text when it is alone with =', 20,
- '%=foo', ' foo')
- statusline_test('should left align text when it is alone with =', 20,
- 'foo%=', 'foo ')
-
- statusline_test('should approximately center text when using %=text%=', 21,
- 'abc%=neovim%=def', 'abc neovim def')
- statusline_test('should completely fill the buffer when using %=text%=', 21,
- 'abc%=neo_vim%=def', 'abc neo_vim def')
- statusline_test('should have equal spaces even with non-equal sides when using =', 21,
- 'foobar%=test%=baz', 'foobar test baz')
- statusline_test('should have equal spaces even with longer right side when using =', 21,
- 'a%=test%=longtext', 'a test longtext')
- statusline_test('should handle an empty left side when using ==', 21,
- '%=test%=baz', ' test baz')
- statusline_test('should handle an empty right side when using ==', 21,
- 'foobar%=test%=', 'foobar test ')
-
- statusline_test('should quadrant the text when using 3 %=', 40,
- 'abcd%=n%=eovim%=ef', 'abcd n eovim ef')
- statusline_test('should work well with %t', 40,
- '%t%=right_aligned', 'buffer_spec.lua right_aligned',
+ -- alignment testing with fillchar
+ local function statusline_test_align (description,
+ statusline_cell_count,
+ input_stl,
+ expected_stl,
+ arg)
+ arg = arg or {}
+ statusline_test(description .. ' without fillchar',
+ statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg)
+ arg.fillchar = ('!'):byte()
+ statusline_test(description .. ' with fillchar `!`',
+ statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg)
+ arg.fillchar = 0x2501
+ statusline_test(description .. ' with fillchar `━`',
+ statusline_cell_count, input_stl, expected_stl:gsub('%~', '━'), arg)
+ end
+
+ statusline_test_align('should right align when using =', 20,
+ 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
+ statusline_test_align('should, when possible, center text when using %=text%=', 20,
+ 'abc%=neovim%=def', 'abc~~~~neovim~~~~def')
+ statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20,
+ 'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def')
+ statusline_test_align('should have equal spaces even with non-equal sides when using =', 20,
+ 'foobar%=test%=baz', 'foobar~~~test~~~~baz')
+ statusline_test_align('should have equal spaces even with longer right side when using =', 20,
+ 'a%=test%=longtext', 'a~~~test~~~~longtext')
+ statusline_test_align('should handle an empty left side when using ==', 20,
+ '%=test%=baz', '~~~~~~test~~~~~~~baz')
+ statusline_test_align('should handle an empty right side when using ==', 20,
+ 'foobar%=test%=', 'foobar~~~~~test~~~~~')
+ statusline_test_align('should handle consecutive empty ==', 20,
+ '%=%=test%=', '~~~~~~~~~~test~~~~~~')
+ statusline_test_align('should handle an = alone', 20,
+ '%=', '~~~~~~~~~~~~~~~~~~~~')
+ statusline_test_align('should right align text when it is alone with =', 20,
+ '%=foo', '~~~~~~~~~~~~~~~~~foo')
+ statusline_test_align('should left align text when it is alone with =', 20,
+ 'foo%=', 'foo~~~~~~~~~~~~~~~~~')
+
+ statusline_test_align('should approximately center text when using %=text%=', 21,
+ 'abc%=neovim%=def', 'abc~~~~neovim~~~~~def')
+ statusline_test_align('should completely fill the buffer when using %=text%=', 21,
+ 'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def')
+ statusline_test_align('should have equal spacing even with non-equal sides when using =', 21,
+ 'foobar%=test%=baz', 'foobar~~~~test~~~~baz')
+ statusline_test_align('should have equal spacing even with longer right side when using =', 21,
+ 'a%=test%=longtext', 'a~~~~test~~~~longtext')
+ statusline_test_align('should handle an empty left side when using ==', 21,
+ '%=test%=baz', '~~~~~~~test~~~~~~~baz')
+ statusline_test_align('should handle an empty right side when using ==', 21,
+ 'foobar%=test%=', 'foobar~~~~~test~~~~~~')
+
+ statusline_test_align('should quadrant the text when using 3 %=', 40,
+ 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef')
+ statusline_test_align('should work well with %t', 40,
+ '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should work well with %t and regular text', 40,
- 'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r',
+ statusline_test_align('should work well with %t and regular text', 40,
+ 'l%=m_l %t m_r%=r', 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should work well with %=, %t, %L, and %l', 40,
- '%t %= %L %= %l', 'buffer_spec.lua 1 0',
+ statusline_test_align('should work well with %=, %t, %L, and %l', 40,
+ '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should quadrant the text when using 3 %=', 41,
- 'abcd%=n%=eovim%=ef', 'abcd n eovim ef')
- statusline_test('should work well with %t', 41,
- '%t%=right_aligned', 'buffer_spec.lua right_aligned',
+ statusline_test_align('should quadrant the text when using 3 %=', 41,
+ 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef')
+ statusline_test_align('should work well with %t', 41,
+ '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should work well with %t and regular text', 41,
- 'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r',
+ statusline_test_align('should work well with %t and regular text', 41,
+ 'l%=m_l %t m_r%=r', 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should work well with %=, %t, %L, and %l', 41,
- '%t %= %L %= %l', 'buffer_spec.lua 1 0',
+ statusline_test_align('should work well with %=, %t, %L, and %l', 41,
+ '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
{file_name='test/unit/buffer_spec.lua'})
- statusline_test('should work with 10 %=', 50,
+ statusline_test_align('should work with 10 %=', 50,
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
- 'aaaa b c d e fg hi jk lmnop qrstuv wxyz')
+ 'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz')
-- stl item testing
local tabline = ''
@@ -452,11 +468,10 @@ describe('buffer functions', function()
-- multi-byte testing
statusline_test('should handle multibyte characters', 10,
- 'Ĉ%=x', 'Ĉ x',
- {expected_byte_length=11})
+ 'Ĉ%=x', 'Ĉ x')
statusline_test('should handle multibyte characters and different fillchars', 10,
'Ą%=mid%=end', 'Ą@mid@@end',
- {fillchar=('@'):byte(), expected_byte_length=11})
+ {fillchar=('@'):byte()})
-- escaping % testing
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')
diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua
index 5fc3b83a13..caf330c378 100644
--- a/test/unit/charset/vim_str2nr_spec.lua
+++ b/test/unit/charset/vim_str2nr_spec.lua
@@ -463,7 +463,7 @@ describe('vim_str2nr()', function()
test_vim_str2nr("1'2'3'4", flags, {len = 7, num = 1234, unum = 1234, pre = 0}, 0)
-- counter-intuitive, but like Vim, strict=true should partially accept
- -- these: (' and - are not alpha-numeric)
+ -- these: (' and - are not alphanumeric)
test_vim_str2nr("7''331", flags, {len = 1, num = 7, unum = 7, pre = 0}, 0)
test_vim_str2nr("123'x4", flags, {len = 3, num = 123, unum = 123, pre = 0}, 0)
test_vim_str2nr("1337'", flags, {len = 4, num = 1337, unum = 1337, pre = 0}, 0)
diff --git a/test/unit/garray_spec.lua b/test/unit/garray_spec.lua
index 28df8a6e3f..5d41dd39ec 100644
--- a/test/unit/garray_spec.lua
+++ b/test/unit/garray_spec.lua
@@ -18,7 +18,7 @@ local growsize = 95
-- constructing a class wrapper around garray. It could for example associate
-- ga_clear_strings to the underlying garray cdata if the garray is a string
-- array. But for now I estimate that that kind of magic might make testing
--- less "transparant" (i.e.: the interface would become quite different as to
+-- less "transparent" (i.e.: the interface would become quite different as to
-- how one would use it from C.
-- accessors
diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua
index 10d02d2eb4..3c96bc5f58 100644
--- a/test/unit/marktree_spec.lua
+++ b/test/unit/marktree_spec.lua
@@ -32,11 +32,11 @@ local function shadoworder(tree, shadow, iter, giveorder)
local mark = lib.marktree_itr_current(iter)
local id = tonumber(mark.id)
local spos = shadow[id]
- if (mark.row ~= spos[1] or mark.col ~= spos[2]) then
- error("invalid pos for "..id..":("..mark.row..", "..mark.col..") instead of ("..spos[1]..", "..spos[2]..")")
+ if (mark.pos.row ~= spos[1] or mark.pos.col ~= spos[2]) then
+ error("invalid pos for "..id..":("..mark.pos.row..", "..mark.pos.col..") instead of ("..spos[1]..", "..spos[2]..")")
end
- if mark.right_gravity ~= spos[3] then
- error("invalid gravity for "..id..":("..mark.row..", "..mark.col..")")
+ if lib.mt_right_test(mark) ~= spos[3] then
+ error("invalid gravity for "..id..":("..mark.pos.row..", "..mark.pos.col..")")
end
if count > 0 then
if not pos_leq(last, spos) then
@@ -87,7 +87,21 @@ local function dosplice(tree, shadow, start, old_extent, new_extent)
shadowsplice(shadow, start, old_extent, new_extent)
end
+local last_id = nil
+
+local function put(tree, row, col, gravitate)
+ last_id = last_id + 1
+ local my_id = last_id
+
+ lib.marktree_put_test(tree, my_id, row, col, gravitate);
+ return my_id
+end
+
describe('marktree', function()
+ before_each(function()
+ last_id = 0
+ end)
+
itp('works', function()
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
local shadow = {}
@@ -97,7 +111,7 @@ describe('marktree', function()
for i = 1,100 do
for j = 1,100 do
local gravitate = (i%2) > 0
- local id = tonumber(lib.marktree_put(tree, j, i, gravitate, 0))
+ local id = put(tree, j, i, gravitate)
ok(id > 0)
eq(nil, shadow[id])
shadow[id] = {j,i,gravitate}
@@ -115,12 +129,12 @@ describe('marktree', function()
eq({}, id2pos)
for i,ipos in pairs(shadow) do
- local pos = lib.marktree_lookup(tree, i, iter)
- eq(ipos[1], pos.row)
- eq(ipos[2], pos.col)
+ local p = lib.marktree_lookup_ns(tree, -1, i, false, iter)
+ eq(ipos[1], p.pos.row)
+ eq(ipos[2], p.pos.col)
local k = lib.marktree_itr_current(iter)
- eq(ipos[1], k.row)
- eq(ipos[2], k.col, ipos[1])
+ eq(ipos[1], k.pos.row)
+ eq(ipos[2], k.pos.col, ipos[1])
lib.marktree_itr_next(tree, iter)
-- TODO(bfredl): use id2pos to check neighbour?
-- local k2 = lib.marktree_itr_current(iter)
@@ -130,8 +144,8 @@ describe('marktree', function()
lib.marktree_itr_get(tree, ipos[1], ipos[2], iter)
local k = lib.marktree_itr_current(iter)
eq(i, tonumber(k.id))
- eq(ipos[1], k.row)
- eq(ipos[2], k.col)
+ eq(ipos[1], k.pos.row)
+ eq(ipos[2], k.pos.col)
end
ok(lib.marktree_itr_first(tree, iter))
@@ -146,8 +160,8 @@ describe('marktree', function()
lib.marktree_itr_get(tree, i, 50+ci, iter)
local k = lib.marktree_itr_current(iter)
local id = tonumber(k.id)
- eq(shadow[id][1], k.row)
- eq(shadow[id][2], k.col)
+ eq(shadow[id][1], k.pos.row)
+ eq(shadow[id][2], k.pos.col)
lib.marktree_del_itr(tree, iter, false)
shadow[id] = nil
end
@@ -191,7 +205,7 @@ describe('marktree', function()
-- https://github.com/neovim/neovim/pull/14719
lib.marktree_clear(tree)
for i = 1,20 do
- lib.marktree_put(tree, i, i, false, 0)
+ put(tree, i, i, false)
end
lib.marktree_itr_get(tree, 10, 10, iter)
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index e7cb5e5d5e..a0e02b6624 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -191,7 +191,7 @@ describe('env.c', function()
if ffi.abi('64bit') then
-- couldn't use a bigger number because it gets converted to
- -- double somewere, should be big enough anyway
+ -- double somewhere, should be big enough anyway
-- maxuint64 = ffi.new 'size_t', 18446744073709551615
local maxuint64 = ffi.new('size_t', 18446744073709000000)
eq(NULL, cimp.os_getenvname_at_index(maxuint64))
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 7fd71cb1ae..0bb33772cd 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -1029,7 +1029,7 @@ describe('fs.c', function()
itp('returns the correct blocksize of a file', function()
local path = 'unit-test-directory/test.file'
-- there is a bug in luafilesystem where
- -- `lfs.attributes path, 'blksize'` returns the worng value:
+ -- `lfs.attributes path, 'blksize'` returns the wrong value:
-- https://github.com/keplerproject/luafilesystem/pull/44
-- using this workaround for now:
local blksize = lfs.attributes(path).blksize
@@ -1038,7 +1038,7 @@ describe('fs.c', function()
if blksize then
eq(blksize, fs.os_fileinfo_blocksize(info))
else
- -- luafs dosn't support blksize on windows
+ -- luafs doesn't support blksize on windows
-- libuv on windows returns a constant value as blocksize
-- checking for this constant value should be enough
eq(2048, fs.os_fileinfo_blocksize(info))
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index 15ce59747e..fb476397e6 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -626,4 +626,20 @@ describe('path.c', function()
eq(false, path_with_extension('/some/path/file', 'lua'))
end)
end)
+
+ describe('path_with_url', function()
+ itp('scheme is alpha and inner hyphen only', function()
+ local function path_with_url(fname)
+ return cimp.path_with_url(to_cstr(fname))
+ end
+ eq(1, path_with_url([[test://xyz/foo/b0]]))
+ eq(2, path_with_url([[test:\\xyz\foo\b0]]))
+ eq(0, path_with_url([[test+abc://xyz/foo/b1]]))
+ eq(0, path_with_url([[test_abc://xyz/foo/b2]]))
+ eq(1, path_with_url([[test-abc://xyz/foo/b3]]))
+ eq(2, path_with_url([[test-abc:\\xyz\foo\b3]]))
+ eq(0, path_with_url([[-test://xyz/foo/b4]]))
+ eq(0, path_with_url([[test-://xyz/foo/b5]]))
+ end)
+ end)
end)