aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/vim_spec.lua12
-rw-r--r--test/functional/core/fileio_spec.lua7
-rw-r--r--test/functional/core/path_spec.lua74
-rw-r--r--test/functional/editor/completion_spec.lua9
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua58
-rw-r--r--test/functional/legacy/digraph_spec.lua6
-rw-r--r--test/functional/legacy/edit_spec.lua2
-rw-r--r--test/functional/lua/vim_spec.lua8
-rw-r--r--test/functional/plugin/lsp/snippet_spec.lua243
-rw-r--r--test/functional/plugin/lsp_spec.lua48
-rw-r--r--test/functional/terminal/window_spec.lua41
-rw-r--r--test/functional/treesitter/fold_spec.lua113
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua2
-rw-r--r--test/functional/ui/highlight_spec.lua19
-rw-r--r--test/functional/ui/messages_spec.lua2
-rw-r--r--test/functional/ui/popupmenu_spec.lua4
-rw-r--r--test/functional/ui/screen_basic_spec.lua2
-rw-r--r--test/old/testdir/setup.vim6
-rw-r--r--test/old/testdir/test_diffmode.vim36
-rw-r--r--test/old/testdir/test_filetype.vim1
-rw-r--r--test/old/testdir/test_fold.vim9
-rw-r--r--test/old/testdir/test_functions.vim18
-rw-r--r--test/old/testdir/test_history.vim5
-rw-r--r--test/old/testdir/test_options.vim312
-rw-r--r--test/old/testdir/test_scroll_opt.vim84
25 files changed, 897 insertions, 224 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 09495fbaac..f28d6ea869 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -2869,6 +2869,18 @@ describe('API', function()
eq(false, eval('g:fired'))
end)
+ it('TextChanged and TextChangedI do not trigger without changes', function()
+ local buf = meths.create_buf(true, false)
+ command([[let g:changed = '']])
+ meths.create_autocmd({'TextChanged', 'TextChangedI'}, {
+ buffer = buf,
+ command = 'let g:changed ..= mode()',
+ })
+ meths.set_current_buf(buf)
+ feed('i')
+ eq('', meths.get_var('changed'))
+ end)
+
it('scratch-buffer', function()
eq({id=2}, meths.create_buf(false, true))
eq({id=3}, meths.create_buf(true, true))
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index f2b360f0d8..a23dad226a 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -40,6 +40,7 @@ describe('fileio', function()
os.remove('Xtest_startup_file1')
os.remove('Xtest_startup_file1~')
os.remove('Xtest_startup_file2')
+ os.remove('Xtest_startup_file2~')
os.remove('Xtest_тест.md')
os.remove('Xtest-u8-int-max')
os.remove('Xtest-overwrite-forced')
@@ -136,7 +137,7 @@ describe('fileio', function()
it('backup with full path with spaces', function()
skip(is_ci('cirrus'))
clear()
- mkdir('Xtest_backup with spaces')
+ mkdir('Xtest_backupdir with spaces')
command('set backup')
command('set backupdir=Xtest_backupdir\\ with\\ spaces//')
command('write Xtest_startup_file1')
@@ -258,8 +259,8 @@ describe('fileio', function()
screen:expect([[
{2:WARNING: The file has been changed since}|
{2: reading it!!!} |
- {3:Do you really want to write to it (y/n)^?}|
- |
+ {3:Do you really want to write to it (y/n)?}|
+ ^ |
]])
feed("n")
diff --git a/test/functional/core/path_spec.lua b/test/functional/core/path_spec.lua
index a786887bbd..06fa13dca5 100644
--- a/test/functional/core/path_spec.lua
+++ b/test/functional/core/path_spec.lua
@@ -6,16 +6,19 @@ local command = helpers.command
local insert = helpers.insert
local feed = helpers.feed
local is_os = helpers.is_os
+local mkdir = helpers.mkdir
+local rmdir = helpers.rmdir
+local write_file = helpers.write_file
+
+local function join_path(...)
+ local pathsep = (is_os('win') and '\\' or '/')
+ return table.concat({...}, pathsep)
+end
describe('path collapse', function()
local targetdir
local expected_path
- local function join_path(...)
- local pathsep = (is_os('win') and '\\' or '/')
- return table.concat({...}, pathsep)
- end
-
before_each(function()
targetdir = join_path('test', 'functional', 'fixtures')
clear()
@@ -57,7 +60,28 @@ describe('path collapse', function()
end)
end)
-describe('file search', function()
+describe('expand wildcard', function()
+ before_each(clear)
+
+ it('with special characters #24421', function()
+ local folders = is_os('win') and {
+ '{folder}',
+ 'folder$name'
+ } or {
+ 'folder-name',
+ 'folder#name'
+ }
+ for _, folder in ipairs(folders) do
+ mkdir(folder)
+ local file = join_path(folder, 'file.txt')
+ write_file(file, '')
+ eq(file, eval('expand("'..folder..'/*")'))
+ rmdir(folder)
+ end
+ end)
+end)
+
+describe('file search (gf, <cfile>)', function()
before_each(clear)
it('find multibyte file name in line #20517', function()
@@ -67,4 +91,42 @@ describe('file search', function()
feed('gf')
eq('filename_with_unicode_ααα', eval('expand("%:t")'))
end)
+
+ it('matches Windows drive-letter filepaths (without ":" in &isfname)', function()
+ local iswin = is_os('win')
+ local function test_cfile(input, expected, expected_win)
+ expected = (iswin and expected_win or expected) or input
+ command('%delete')
+ insert(input)
+ command('norm! 0')
+ eq(expected, eval('expand("<cfile>")'))
+ end
+
+ test_cfile([[c:/d:/foo/bar.txt]]) -- TODO(justinmk): should return "d:/foo/bar.txt" ?
+ test_cfile([[//share/c:/foo/bar/]])
+ test_cfile([[file://c:/foo/bar]])
+ test_cfile([[file://c:/foo/bar:42]])
+ test_cfile([[file://c:/foo/bar:42:666]])
+ test_cfile([[https://c:/foo/bar]])
+ test_cfile([[\foo\bar]], [[foo]], [[\foo\bar]])
+ test_cfile([[/foo/bar]], [[/foo/bar]])
+ test_cfile([[c:\foo\bar]], [[c:]], [[c:\foo\bar]])
+ test_cfile([[c:\foo\bar:42:666]], [[c:]], [[c:\foo\bar]])
+ test_cfile([[c:/foo/bar]])
+ test_cfile([[c:/foo/bar:42]], [[c:/foo/bar]])
+ test_cfile([[c:/foo/bar:42:666]], [[c:/foo/bar]])
+ test_cfile([[c:foo\bar]], [[c]])
+ test_cfile([[c:foo/bar]], [[c]])
+ test_cfile([[c:foo]], [[c]])
+ -- Examples from: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#example-ways-to-refer-to-the-same-file
+ test_cfile([[c:\temp\test-file.txt]], [[c:]], [[c:\temp\test-file.txt]])
+ test_cfile([[\\127.0.0.1\c$\temp\test-file.txt]], [[127.0.0.1]], [[\\127.0.0.1\c$\temp\test-file.txt]])
+ test_cfile([[\\LOCALHOST\c$\temp\test-file.txt]], [[LOCALHOST]], [[\\LOCALHOST\c$\temp\test-file.txt]])
+ -- not supported yet
+ test_cfile([[\\.\c:\temp\test-file.txt]], [[.]], [[\\.\c]])
+ -- not supported yet
+ test_cfile([[\\?\c:\temp\test-file.txt]], [[c:]], [[\\]])
+ test_cfile([[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]], [[.]], [[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]])
+ test_cfile([[\\127.0.0.1\c$\temp\test-file.txt]], [[127.0.0.1]], [[\\127.0.0.1\c$\temp\test-file.txt]])
+ end)
end)
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua
index 8c299636cc..ea3397d50d 100644
--- a/test/functional/editor/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -941,6 +941,15 @@ describe('completion', function()
end)
end)
+ it('cmdline completion supports various string options', function()
+ eq('auto', funcs.getcompletion('set foldcolumn=', 'cmdline')[2])
+ eq({'nosplit', 'split'}, funcs.getcompletion('set inccommand=', 'cmdline'))
+ eq({'ver:3,hor:6', 'hor:', 'ver:'}, funcs.getcompletion('set mousescroll=', 'cmdline'))
+ eq('BS', funcs.getcompletion('set termpastefilter=', 'cmdline')[2])
+ eq('SpecialKey', funcs.getcompletion('set winhighlight=', 'cmdline')[1])
+ eq('SpecialKey', funcs.getcompletion('set winhighlight=NonText:', 'cmdline')[1])
+ end)
+
describe('from the commandline window', function()
it('is cleared after CTRL-C', function ()
feed('q:')
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index 3e0f6d1fcc..436873b464 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -171,6 +171,7 @@ describe('swapfile detection', function()
local screen2 = Screen.new(256, 40)
screen2:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
-- With shortmess+=F
command('set shortmess+=F')
@@ -219,11 +220,29 @@ describe('swapfile detection', function()
nvim2:close()
end)
+ it('default SwapExists handler selects "(E)dit" and skips prompt', function()
+ exec(init)
+ command('edit Xfile1')
+ command("put ='some text...'")
+ command('preserve') -- Make sure the swap file exists.
+ local nvimpid = funcs.getpid()
+
+ local nvim1 = spawn(new_argv(), true, nil, true)
+ set_session(nvim1)
+ local screen = Screen.new(75, 18)
+ screen:attach()
+ exec(init)
+ feed(':edit Xfile1\n')
+
+ screen:expect({ any = ('W325: Ignoring swapfile from Nvim process %d'):format(nvimpid) })
+ nvim1:close()
+ end)
+
-- oldtest: Test_swap_prompt_splitwin()
it('selecting "q" in the attention prompt', function()
exec(init)
command('edit Xfile1')
- command('preserve') -- should help to make sure the swap file exists
+ command('preserve') -- Make sure the swap file exists.
local screen = Screen.new(75, 18)
screen:set_default_attr_ids({
@@ -235,7 +254,9 @@ describe('swapfile detection', function()
set_session(nvim1)
screen:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
feed(':split Xfile1\n')
+ -- The default SwapExists handler does _not_ skip this prompt.
screen:expect({
any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
})
@@ -267,6 +288,7 @@ describe('swapfile detection', function()
set_session(nvim2)
screen:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
command('set more')
command('au bufadd * let foo_w = wincol()')
feed(':e Xfile1<CR>')
@@ -300,8 +322,9 @@ describe('swapfile detection', function()
nvim2:close()
end)
- -- oldtest: Test_nocatch_process_still_running()
- it('allows deleting swapfile created before boot vim-patch:8.2.2586', function()
+ --- @param swapexists boolean Enable the default SwapExists handler.
+ --- @param on_swapfile_running fun(screen: any) Called after swapfile ("STILL RUNNING") prompt.
+ local function test_swapfile_after_reboot(swapexists, on_swapfile_running)
local screen = Screen.new(75, 30)
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
@@ -311,6 +334,9 @@ describe('swapfile detection', function()
screen:attach()
exec(init)
+ if not swapexists then
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ end
command('set nohidden')
exec([=[
@@ -347,12 +373,7 @@ describe('swapfile detection', function()
os.rename('Xswap', swname)
feed(':edit Xswaptest<CR>')
- screen:expect({any = table.concat({
- pesc('{2:E325: ATTENTION}'),
- 'file name: .*Xswaptest',
- 'process ID: %d* %(STILL RUNNING%)',
- pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
- }, '.*')})
+ on_swapfile_running(screen)
feed('e')
@@ -374,7 +395,26 @@ describe('swapfile detection', function()
}, '.*')})
feed('e')
+ end
+
+ -- oldtest: Test_nocatch_process_still_running()
+ it('swapfile created before boot vim-patch:8.2.2586', function()
+ test_swapfile_after_reboot(false, function(screen)
+ screen:expect({any = table.concat({
+ pesc('{2:E325: ATTENTION}'),
+ 'file name: .*Xswaptest',
+ 'process ID: %d* %(STILL RUNNING%)',
+ pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
+ }, '.*')})
+ end)
+ end)
+
+ it('swapfile created before boot + default SwapExists handler', function()
+ test_swapfile_after_reboot(true, function(screen)
+ screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' })
+ end)
end)
+
end)
describe('quitting swapfile dialog on startup stops TUI properly', function()
diff --git a/test/functional/legacy/digraph_spec.lua b/test/functional/legacy/digraph_spec.lua
index 0cb0bb84be..7eeb83eb5f 100644
--- a/test/functional/legacy/digraph_spec.lua
+++ b/test/functional/legacy/digraph_spec.lua
@@ -22,7 +22,7 @@ describe('digraph', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
feed('1')
screen:expect([[
@@ -31,7 +31,7 @@ describe('digraph', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
feed('2')
screen:expect([[
@@ -40,7 +40,7 @@ describe('digraph', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
end)
end)
diff --git a/test/functional/legacy/edit_spec.lua b/test/functional/legacy/edit_spec.lua
index 186bf395cc..939999e21b 100644
--- a/test/functional/legacy/edit_spec.lua
+++ b/test/functional/legacy/edit_spec.lua
@@ -43,7 +43,7 @@ describe('edit', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
feed('=')
screen:expect([[
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index bd3d8f5247..c69990d84b 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2401,6 +2401,14 @@ describe('lua stdlib', function()
insert([[αα]])
eq({0,5}, exec_lua[[ return vim.region(0,{0,0},{0,4},'3',true)[0] ]])
end)
+ it('linewise', function()
+ insert(dedent( [[
+ text tααt tααt text
+ text tαxt txtα tex
+ text tαxt tαxt
+ ]]))
+ eq({0,-1}, exec_lua[[ return vim.region(0,{1,5},{1,14},'V',true)[1] ]])
+ end)
it('getpos() input', function()
insert('getpos')
eq({0,6}, exec_lua[[ return vim.region(0,{0,0},'.','v',true)[0] ]])
diff --git a/test/functional/plugin/lsp/snippet_spec.lua b/test/functional/plugin/lsp/snippet_spec.lua
index 7903885420..13df861b91 100644
--- a/test/functional/plugin/lsp/snippet_spec.lua
+++ b/test/functional/plugin/lsp/snippet_spec.lua
@@ -1,130 +1,70 @@
local helpers = require('test.functional.helpers')(after_each)
-local snippet = require('vim.lsp._snippet')
+local snippet = require('vim.lsp._snippet_grammar')
local eq = helpers.eq
local exec_lua = helpers.exec_lua
-describe('vim.lsp._snippet', function()
+describe('vim.lsp._snippet_grammar', function()
before_each(helpers.clear)
after_each(helpers.clear)
local parse = function(...)
- return exec_lua('return require("vim.lsp._snippet").parse(...)', ...)
+ local res = exec_lua('return require("vim.lsp._snippet_grammar").parse(...)', ...)
+ return res.data.children
end
- it('should parse only text', function()
+ it('parses only text', function()
eq({
- type = snippet.NodeType.SNIPPET,
- children = {
- {
- type = snippet.NodeType.TEXT,
- raw = 'TE\\$\\}XT',
- esc = 'TE$}XT',
- },
- },
+ { type = snippet.NodeType.Text, data = { text = 'TE$}XT' } },
}, parse('TE\\$\\}XT'))
end)
- it('should parse tabstop', function()
+ it('parses tabstops', function()
eq({
- type = snippet.NodeType.SNIPPET,
- children = {
- {
- type = snippet.NodeType.TABSTOP,
- tabstop = 1,
- },
- {
- type = snippet.NodeType.TABSTOP,
- tabstop = 2,
- },
- },
+ { type = snippet.NodeType.Tabstop, data = { tabstop = 1 } },
+ { type = snippet.NodeType.Tabstop, data = { tabstop = 2 } },
}, parse('$1${2}'))
end)
- it('should parse placeholders', function()
+ it('parses nested placeholders', function()
eq({
- type = snippet.NodeType.SNIPPET,
- children = {
- {
- type = snippet.NodeType.PLACEHOLDER,
+ {
+ type = snippet.NodeType.Placeholder,
+ data = {
tabstop = 1,
- children = {
- {
- type = snippet.NodeType.PLACEHOLDER,
+ value = {
+ type = snippet.NodeType.Placeholder,
+ data = {
tabstop = 2,
- children = {
- {
- type = snippet.NodeType.TEXT,
- raw = 'TE\\$\\}XT',
- esc = 'TE$}XT',
- },
- {
- type = snippet.NodeType.TABSTOP,
- tabstop = 3,
- },
- {
- type = snippet.NodeType.TABSTOP,
- tabstop = 1,
- transform = {
- type = snippet.NodeType.TRANSFORM,
- pattern = 'regex',
- option = 'i',
- format = {
- {
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- modifier = 'upcase',
- },
- },
- },
- },
- {
- type = snippet.NodeType.TEXT,
- raw = 'TE\\$\\}XT',
- esc = 'TE$}XT',
- },
- },
+ value = { type = snippet.NodeType.Tabstop, data = { tabstop = 3 } },
},
},
},
},
- }, parse('${1:${2:TE\\$\\}XT$3${1/regex/${1:/upcase}/i}TE\\$\\}XT}}'))
+ }, parse('${1:${2:${3}}}'))
end)
- it('should parse variables', function()
+ it('parses variables', function()
eq({
- type = snippet.NodeType.SNIPPET,
- children = {
- {
- type = snippet.NodeType.VARIABLE,
- name = 'VAR',
- },
- {
- type = snippet.NodeType.VARIABLE,
+ { type = snippet.NodeType.Variable, data = { name = 'VAR' } },
+ { type = snippet.NodeType.Variable, data = { name = 'VAR' } },
+ {
+ type = snippet.NodeType.Variable,
+ data = {
name = 'VAR',
+ default = { type = snippet.NodeType.Tabstop, data = { tabstop = 1 } },
},
- {
- type = snippet.NodeType.VARIABLE,
+ },
+ {
+ type = snippet.NodeType.Variable,
+ data = {
name = 'VAR',
- children = {
+ regex = 'regex',
+ options = '',
+ format = {
{
- type = snippet.NodeType.TABSTOP,
- tabstop = 1,
- },
- },
- },
- {
- type = snippet.NodeType.VARIABLE,
- name = 'VAR',
- transform = {
- type = snippet.NodeType.TRANSFORM,
- pattern = 'regex',
- format = {
- {
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- modifier = 'upcase',
- },
+ type = snippet.NodeType.Format,
+ data = { capture = 1, modifier = 'upcase' },
},
},
},
@@ -132,105 +72,82 @@ describe('vim.lsp._snippet', function()
}, parse('$VAR${VAR}${VAR:$1}${VAR/regex/${1:/upcase}/}'))
end)
- it('should parse choice', function()
+ it('parses choice', function()
eq({
- type = snippet.NodeType.SNIPPET,
- children = {
- {
- type = snippet.NodeType.CHOICE,
- tabstop = 1,
- items = {
- ',',
- '|',
- },
- },
+ {
+ type = snippet.NodeType.Choice,
+ data = { tabstop = 1, values = { ',', '|' } },
},
}, parse('${1|\\,,\\||}'))
end)
- it('should parse format', function()
- eq({
- type = snippet.NodeType.SNIPPET,
- children = {
+ it('parses format', function()
+ eq(
+ {
{
- type = snippet.NodeType.VARIABLE,
- name = 'VAR',
- transform = {
- type = snippet.NodeType.TRANSFORM,
- pattern = 'regex',
+ type = snippet.NodeType.Variable,
+ data = {
+ name = 'VAR',
+ regex = 'regex',
+ options = '',
format = {
{
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- modifier = 'upcase',
+ type = snippet.NodeType.Format,
+ data = { capture = 1, modifier = 'upcase' },
},
{
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- if_text = 'if_text',
- else_text = '',
+ type = snippet.NodeType.Format,
+ data = { capture = 1, if_text = 'if_text' },
},
{
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- if_text = '',
- else_text = 'else_text',
+ type = snippet.NodeType.Format,
+ data = { capture = 1, else_text = 'else_text' },
},
{
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- else_text = 'else_text',
- if_text = 'if_text',
+ type = snippet.NodeType.Format,
+ data = { capture = 1, if_text = 'if_text', else_text = 'else_text' },
},
{
- type = snippet.NodeType.FORMAT,
- capture_index = 1,
- if_text = '',
- else_text = 'else_text',
+ type = snippet.NodeType.Format,
+ data = { capture = 1, else_text = 'else_text' },
},
},
},
},
},
- }, parse('${VAR/regex/${1:/upcase}${1:+if_text}${1:-else_text}${1:?if_text:else_text}${1:else_text}/}'))
+ parse(
+ '${VAR/regex/${1:/upcase}${1:+if_text}${1:-else_text}${1:?if_text:else_text}${1:else_text}/}'
+ )
+ )
end)
- it('should parse empty strings', function()
+ it('parses empty strings', function()
eq({
- children = {
- {
- children = { {
- esc = '',
- raw = '',
- type = 7,
- } },
+ {
+ type = snippet.NodeType.Placeholder,
+ data = {
tabstop = 1,
- type = 2,
- },
- {
- esc = ' ',
- raw = ' ',
- type = 7,
+ value = { type = snippet.NodeType.Text, data = { text = '' } },
},
- {
+ },
+ {
+ type = snippet.NodeType.Text,
+ data = { text = ' ' },
+ },
+ {
+ type = snippet.NodeType.Variable,
+ data = {
name = 'VAR',
- transform = {
- format = {
- {
- capture_index = 1,
- else_text = '',
- if_text = '',
- type = 6,
- },
+ regex = 'erg',
+ format = {
+ {
+ type = snippet.NodeType.Format,
+ data = { capture = 1, if_text = '' },
},
- option = 'g',
- pattern = 'erg',
- type = 5,
},
- type = 3,
+ options = 'g',
},
},
- type = 0,
- }, parse('${1:} ${VAR/erg/${1:?:}/g}'))
+ }, parse('${1:} ${VAR/erg/${1:+}/g}'))
end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 155c9ad96c..73e05d8d11 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -2301,7 +2301,7 @@ describe('LSP', function()
{ label='foocar', sortText="g", insertText='foodar', insertTextFormat=2, textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} },
{ label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', insertTextFormat=2, textEdit={} },
-- nested snippet tokens
- { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', insertTextFormat=2, textEdit={} },
+ { label='foocar', sortText="i", insertText='foodar(${1:${2|typ1,typ2|}}) {$0\\}', insertTextFormat=2, textEdit={} },
-- braced tabstop
{ label='foocar', sortText="j", insertText='foodar()${0}', insertTextFormat=2, textEdit={} },
-- plain text
@@ -2317,7 +2317,7 @@ describe('LSP', function()
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foobar', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="f", textEdit={newText='foobar'} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foobar(place holder, more ...holder{})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="g", insertText='foodar', insertTextFormat=2, textEdit={newText='foobar(${1:place holder}, ${2:more ...holder{\\}})'} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foodar(var1 typ1, var2 *typ2) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="h", insertText='foodar(${1:var1} typ1, ${2:var2} *typ2) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
- { abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foodar(var1 typ2 tail) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="i", insertText='foodar(${1:var1 ${2|typ2,typ3|} ${3:tail}}) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
+ { abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foodar(typ1) {}', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="i", insertText='foodar(${1:${2|typ1,typ2|}}) {$0\\}', insertTextFormat=2, textEdit={} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foodar()', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="j", insertText='foodar()${0}', insertTextFormat=2, textEdit={} } } } } },
{ abbr = 'foocar', dup = 1, empty = 1, icase = 1, kind = 'Unknown', menu = '', word = 'foodar(${1:var1})', user_data = { nvim = { lsp = { completion_item = { label='foocar', sortText="k", insertText='foodar(${1:var1})', insertTextFormat=1, textEdit={} } } } } },
}
@@ -3483,6 +3483,50 @@ describe('LSP', function()
end
}
end)
+ it("Fallback to command execution on resolve error", function()
+ clear()
+ exec_lua(create_server_definition)
+ local result = exec_lua([[
+ local server = _create_server({
+ capabilities = {
+ executeCommandProvider = {
+ commands = {"command:1"},
+ },
+ codeActionProvider = {
+ resolveProvider = true
+ }
+ },
+ handlers = {
+ ["textDocument/codeAction"] = function()
+ return {
+ {
+ title = "Code Action 1",
+ command = {
+ title = "Command 1",
+ command = "command:1",
+ }
+ }
+ }
+ end,
+ ["codeAction/resolve"] = function()
+ return nil, "resolve failed"
+ end,
+ }
+ })
+
+ local client_id = vim.lsp.start({
+ name = "dummy",
+ cmd = server.cmd,
+ })
+
+ vim.lsp.buf.code_action({ apply = true })
+ vim.lsp.stop_client(client_id)
+ return server.messages
+ ]])
+ eq("codeAction/resolve", result[4].method)
+ eq("workspace/executeCommand", result[5].method)
+ eq("command:1", result[5].params.command)
+ end)
end)
describe('vim.lsp.commands', function()
it('Accepts only string keys', function()
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index f90e4f7e9d..39fc2c2562 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -44,7 +44,7 @@ describe(':terminal window', function()
{7:6 } |
{3:-- TERMINAL --} |
]])
- feed_data({'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'})
+ feed_data('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
screen:expect([[
{7:1 }tty ready |
{7:2 }rows: 6, cols: 48 |
@@ -55,8 +55,6 @@ describe(':terminal window', function()
{3:-- TERMINAL --} |
]])
- skip(is_os('win'), 'win: :terminal resize is unreliable #7007')
-
-- numberwidth=9
feed([[<C-\><C-N>]])
feed([[:set numberwidth=9 number<CR>i]])
@@ -69,7 +67,7 @@ describe(':terminal window', function()
{7: 6 } |
{3:-- TERMINAL --} |
]])
- feed_data({' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'})
+ feed_data(' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
screen:expect([[
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 48 |
@@ -82,6 +80,41 @@ describe(':terminal window', function()
end)
end)
+ describe("with 'statuscolumn'", function()
+ it('wraps text', function()
+ command([[set number statuscolumn=++%l\ \ ]])
+ screen:expect([[
+ {7:++1 }tty ready |
+ {7:++2 }rows: 6, cols: 45 |
+ {7:++3 }{1: } |
+ {7:++4 } |
+ {7:++5 } |
+ {7:++6 } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\n\n\n\n\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ screen:expect([[
+ {7:++4 } |
+ {7:++5 } |
+ {7:++6 } |
+ {7:++7 } |
+ {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS|
+ {7:++9 }TUVWXYZ{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\nabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ screen:expect([[
+ {7:++7 } |
+ {7:++8 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
+ {7:++9 }STUVWXYZ |
+ {7:++10 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR|
+ {7:++11 }STUVWXYZrows: 6, cols: 44 |
+ {7:++12 }{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+ end)
+
describe("with 'colorcolumn'", function()
before_each(function()
feed([[<C-\><C-N>]])
diff --git a/test/functional/treesitter/fold_spec.lua b/test/functional/treesitter/fold_spec.lua
index 9ed86e87f1..a8abbc002b 100644
--- a/test/functional/treesitter/fold_spec.lua
+++ b/test/functional/treesitter/fold_spec.lua
@@ -359,3 +359,116 @@ void ui_refresh(void)
end)
end)
+
+describe('treesitter foldtext', function()
+ local test_text = [[
+void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
+{
+ int width = INT_MAX, height = INT_MAX;
+ bool ext_widgets[kUIExtCount];
+ for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
+ ext_widgets[i] = true;
+ }
+
+ bool inclusive = ui_override();
+ for (size_t i = 0; i < ui_count; i++) {
+ UI *ui = uis[i];
+ width = MIN(ui->width, width);
+ height = MIN(ui->height, height);
+ foo = BAR(ui->bazaar, bazaar);
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
+ ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ }
+ }
+}]]
+ local screen
+
+ before_each(function()
+ screen = Screen.new(60, 5)
+ screen:set_default_attr_ids({
+ [0] = {foreground = Screen.colors.Blue, bold = true},
+ [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
+ [2] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.SeaGreen};
+ [3] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGray};
+ [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGray};
+ [5] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.Brown};
+ [6] = {background = Screen.colors.Red1};
+ [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Red};
+ [8] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red};
+ [9] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Red};
+ [10] = {bold = true};
+ })
+ screen:attach()
+ end)
+
+ it('displays highlighted content', function()
+ command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
+ insert(test_text)
+ exec_lua([[vim.treesitter.get_parser(0, "c")]])
+
+ feed('ggVGzf')
+ screen:expect{grid=[[
+ {2:^void}{1: }{3:qsort}{4:(}{2:void}{1: }{5:*}{3:base}{4:,}{1: }{2:size_t}{1: }{3:nel}{4:,}{1: }{2:size_t}{1: }{3:width}{4:,}{1: }{2:int}{1: }{4:(}{5:*}{3:compa}|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end)
+
+ it('handles deep nested captures', function()
+ command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
+ insert([[
+function FoldInfo.new()
+ return setmetatable({
+ start_counts = {},
+ stop_counts = {},
+ levels0 = {},
+ levels = {},
+ }, FoldInfo)
+end]])
+ exec_lua([[vim.treesitter.get_parser(0, "lua")]])
+
+ feed('ggjVGkzfgg')
+ screen:expect{grid=[[
+ ^function FoldInfo.new() |
+ {1: }{5:return}{1: }{4:setmetatable({}{1:·····································}|
+ end |
+ {0:~ }|
+ |
+ ]]}
+
+ command('hi! Visual guibg=Red')
+ feed('GVgg')
+ screen:expect{grid=[[
+ ^f{6:unction FoldInfo.new()} |
+ {7: }{8:return}{7: }{9:setmetatable({}{7:·····································}|
+ {6:end} |
+ {0:~ }|
+ {10:-- VISUAL LINE --} |
+ ]]}
+
+ feed('10l<C-V>')
+ screen:expect{grid=[[
+ {6:function F}^oldInfo.new() |
+ {7: }{8:return}{7: }{9:se}{4:tmetatable({}{1:·····································}|
+ {6:end} |
+ {0:~ }|
+ {10:-- VISUAL BLOCK --} |
+ ]]}
+ end)
+
+ it('falls back to default', function()
+ command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext()]])
+ insert(test_text)
+
+ feed('ggVGzf')
+ screen:expect{grid=[[
+ {1:^+-- 19 lines: void qsort(void *base, size_t nel, size_t widt}|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ end)
+end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 17e6855ee4..e4766103c2 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -577,10 +577,10 @@ describe('Command-line coloring', function()
|
{EOB:~ }|
{EOB:~ }|
+ {EOB:~ }|
{MSEP: }|
:+ |
{ERR:E5404: Chunk 1 end 3 not in range (1, 2]}|
- |
:++^ |
]])
end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 931e1f9985..7776e024b0 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -2523,6 +2523,8 @@ describe('highlight namespaces', function()
[6] = {bold = true, reverse = true};
[7] = {reverse = true};
[8] = {foreground = Screen.colors.Gray20};
+ [9] = {foreground = Screen.colors.Blue};
+ [10] = {bold = true, foreground = Screen.colors.SeaGreen};
}
ns1 = meths.create_namespace 'grungy'
@@ -2655,4 +2657,21 @@ describe('highlight namespaces', function()
"Normal:Visual",
},res)
end)
+
+ it('Normal in set_hl #25474', function()
+ meths.set_hl(0, 'Normal', {bg='#333333'})
+ command('highlight Ignore')
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {6: }|
+ |
+ Ignore {8:xxx} {9:ctermf}|
+ {9:g=}15 {9:guifg=}|
+ bg |
+ {10:Press ENTER or type comma}|
+ {10:nd to continue}^ |
+ ]]}
+ end)
end)
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 46a42e5beb..8a13796c04 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1366,7 +1366,7 @@ describe('ui/ext_messages', function()
feed(":intro<cr>")
screen:expect{grid=[[
- |
+ ^ |
|
|
|
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index ea65cf35bd..38649a2be3 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -2439,14 +2439,14 @@ describe('builtin popupmenu', function()
prefix |
bef{n: word } |
tex{n: }^ |
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
-- can't draw the pum, but check we don't crash
screen:try_resize(12,2)
screen:expect([[
{1:<<<}t^ |
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
-- but state is preserved, pum reappears
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index bc9517aa60..7cc1accd3f 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -795,7 +795,7 @@ local function screen_tests(linegrid)
screen:try_resize(1, 1)
screen:expect([[
resize^ |
- {2:-- INSERT -} |
+ {2:-- INSERT --}|
]])
feed('<esc>:ls')
diff --git a/test/old/testdir/setup.vim b/test/old/testdir/setup.vim
index 4e8859a33e..b0c2a15a3f 100644
--- a/test/old/testdir/setup.vim
+++ b/test/old/testdir/setup.vim
@@ -26,6 +26,9 @@ if exists('s:did_load')
set sessionoptions+=options
set viewoptions+=options
set switchbuf=
+ if has('win32')
+ set isfname+=:
+ endif
if g:testname !~ 'test_mapping.vim$'
" Make "Q" switch to Ex mode.
" This does not work for all tests.
@@ -50,6 +53,9 @@ tlunmenu *
" roughly equivalent to test_setmouse() in Vim
func Ntest_setmouse(row, col)
call nvim_input_mouse('move', '', '', 0, a:row - 1, a:col - 1)
+ if state('m') == ''
+ call getchar(0)
+ endif
endfunc
" Prevent Nvim log from writing to stderr.
diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim
index d6d9f351fc..a06411883c 100644
--- a/test/old/testdir/test_diffmode.vim
+++ b/test/old/testdir/test_diffmode.vim
@@ -1616,6 +1616,42 @@ func Test_diff_scroll_wrap_on()
call assert_equal(1, winsaveview().topline)
normal! j
call assert_equal(2, winsaveview().topline)
+
+ bwipe!
+ bwipe!
+endfunc
+
+func Test_diff_scroll_many_filler()
+ 20new
+ vnew
+ call setline(1, ['^^^', '^^^', '$$$', '$$$'])
+ diffthis
+ setlocal scrolloff=0
+ wincmd p
+ call setline(1, ['^^^', '^^^'] + repeat(['###'], 41) + ['$$$', '$$$'])
+ diffthis
+ setlocal scrolloff=0
+ wincmd p
+ redraw
+
+ " Note: need a redraw after each scroll, otherwise the test always passes.
+ normal! G
+ redraw
+ call assert_equal(3, winsaveview().topline)
+ call assert_equal(18, winsaveview().topfill)
+ exe "normal! \<C-B>"
+ redraw
+ call assert_equal(3, winsaveview().topline)
+ call assert_equal(19, winsaveview().topfill)
+ exe "normal! \<C-B>"
+ redraw
+ call assert_equal(2, winsaveview().topline)
+ call assert_equal(0, winsaveview().topfill)
+ exe "normal! \<C-B>"
+ redraw
+ call assert_equal(1, winsaveview().topline)
+ call assert_equal(0, winsaveview().topfill)
+
bwipe!
bwipe!
endfunc
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index e5d7085d71..c3002b6747 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -340,6 +340,7 @@ func s:GetFilenameChecks() abort
\ 'jsonnet': ['file.jsonnet', 'file.libsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
+ \ 'just': ['justfile', 'Justfile', '.justfile', 'config.just'],
\ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
\ 'kdl': ['file.kdl'],
\ 'kivy': ['file.kv'],
diff --git a/test/old/testdir/test_fold.vim b/test/old/testdir/test_fold.vim
index ccd1bfecf8..e529a94174 100644
--- a/test/old/testdir/test_fold.vim
+++ b/test/old/testdir/test_fold.vim
@@ -1569,4 +1569,13 @@ func Test_foldcolumn_linebreak_control_char()
bwipe!
endfunc
+" This used to cause invalid memory access
+func Test_foldexpr_return_empty_string()
+ new
+ setlocal foldexpr='' foldmethod=expr
+ redraw
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index 7b20f47f7a..b27b0be802 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -3303,4 +3303,22 @@ func Test_glob_extended_bash()
let &shell=_shell
endfunc
+" Test for glob() with extended patterns (MS-Windows)
+" Vim doesn't use 'shell' to expand wildcards on MS-Windows.
+" Unlike bash, it doesn't support {,} expansion.
+func Test_glob_extended_mswin()
+ CheckMSWindows
+
+ call mkdir('Xtestglob/foo/bar/src', 'p')
+ call writefile([], 'Xtestglob/foo/bar/src/foo.sh')
+ call writefile([], 'Xtestglob/foo/bar/src/foo.h')
+ call writefile([], 'Xtestglob/foo/bar/src/foo.cpp')
+
+ " Sort output of glob() otherwise we end up with different
+ " ordering depending on whether file system is case-sensitive.
+ let expected = ['Xtestglob/foo/bar/src/foo.cpp', 'Xtestglob/foo/bar/src/foo.h', 'Xtestglob/foo/bar/src/foo.sh']
+ call assert_equal(expected, sort(glob('Xtestglob/**/foo.*', 0, 1)))
+ call delete('Xtestglob', 'rf')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_history.vim b/test/old/testdir/test_history.vim
index f1c31dee04..bb6d671725 100644
--- a/test/old/testdir/test_history.vim
+++ b/test/old/testdir/test_history.vim
@@ -244,8 +244,13 @@ endfunc
" Test for making sure the key value is not stored in history
func Test_history_crypt_key()
CheckFeature cryptv
+
call feedkeys(":set bs=2 key=abc ts=8\<CR>", 'xt')
call assert_equal('set bs=2 key= ts=8', histget(':'))
+
+ call assert_fails("call feedkeys(':set bs=2 key-=abc ts=8\<CR>', 'xt')")
+ call assert_equal('set bs=2 key-= ts=8', histget(':'))
+
set key& bs& ts&
endfunc
diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim
index c56efe8786..76b7cc920b 100644
--- a/test/old/testdir/test_options.vim
+++ b/test/old/testdir/test_options.vim
@@ -299,11 +299,11 @@ func Test_set_completion()
call assert_equal('"set tabstop thesaurus thesaurusfunc', @:)
" Expand current value
- call feedkeys(":set fileencodings=\<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"set fileencodings=ucs-bom,utf-8,default,latin1', @:)
+ call feedkeys(":set suffixes=\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set suffixes=.bak,~,.o,.h,.info,.swp,.obj', @:)
- call feedkeys(":set fileencodings:\<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"set fileencodings:ucs-bom,utf-8,default,latin1', @:)
+ call feedkeys(":set suffixes:\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set suffixes:.bak,~,.o,.h,.info,.swp,.obj', @:)
" Expand key codes.
" call feedkeys(":set <H\<C-A>\<C-B>\"\<CR>", 'tx')
@@ -364,14 +364,20 @@ func Test_set_completion()
call assert_equal("\"set invtabstop=", @:)
" Expand options for 'spellsuggest'
- call feedkeys(":set spellsuggest=best,file:xyz\<Tab>\<C-B>\"\<CR>", 'xt')
- call assert_equal("\"set spellsuggest=best,file:xyz", @:)
-
- " Expand value for 'key'
- " set key=abcd
- " call feedkeys(":set key=\<Tab>\<C-B>\"\<CR>", 'xt')
- " call assert_equal('"set key=*****', @:)
- " set key=
+ call feedkeys(":set spellsuggest=file:test_options.v\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"set spellsuggest=file:test_options.vim", @:)
+ call feedkeys(":set spellsuggest=best,file:test_options.v\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"set spellsuggest=best,file:test_options.vim", @:)
+
+ " Expanding value for 'key' is disallowed
+ if exists('+key')
+ set key=abcd
+ call feedkeys(":set key=\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set key=', @:)
+ call feedkeys(":set key-=\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set key-=', @:)
+ set key=
+ endif
" Expand values for 'filetype'
call feedkeys(":set filetype=sshdconfi\<Tab>\<C-B>\"\<CR>", 'xt')
@@ -386,6 +392,286 @@ func Test_set_completion()
call assert_equal('"set syntax=' .. getcompletion('a*', 'syntax')->join(), @:)
endfunc
+" Test handling of expanding individual string option values
+func Test_set_completion_string_values()
+ "
+ " Test basic enum string options that have well-defined enum names
+ "
+
+ " call assert_equal(['lastline', 'truncate', 'uhex'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['lastline', 'truncate', 'uhex', 'msgsep'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['truncate'], getcompletion('set display=t', 'cmdline'))
+ call assert_equal(['uhex'], getcompletion('set display=*ex*', 'cmdline'))
+
+ " Test that if a value is set, it will populate the results, but only if
+ " typed value is empty.
+ set display=uhex,lastline
+ " call assert_equal(['uhex,lastline', 'lastline', 'truncate', 'uhex'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['uhex,lastline', 'lastline', 'truncate', 'uhex', 'msgsep'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['uhex'], getcompletion('set display=u', 'cmdline'))
+ " If the set value is part of the enum list, it will show as the first
+ " result with no duplicate.
+ set display=uhex
+ " call assert_equal(['uhex', 'lastline', 'truncate'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['uhex', 'lastline', 'truncate', 'msgsep'], getcompletion('set display=', 'cmdline'))
+ " If empty value, will just show the normal list without an empty item
+ set display=
+ " call assert_equal(['lastline', 'truncate', 'uhex'], getcompletion('set display=', 'cmdline'))
+ call assert_equal(['lastline', 'truncate', 'uhex', 'msgsep'], getcompletion('set display=', 'cmdline'))
+ " Test escaping of the values
+ " call assert_equal('vert:\|,fold:-,eob:~,lastline:@', getcompletion('set fillchars=', 'cmdline')[0])
+ call assert_equal('vert:\|,foldsep:\|,fold:-', getcompletion('set fillchars=', 'cmdline')[0])
+
+ " Test comma-separated lists will expand after a comma.
+ call assert_equal(['uhex'], getcompletion('set display=truncate,*ex*', 'cmdline'))
+ " Also test the positioning of the expansion is correct
+ call feedkeys(":set display=truncate,l\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set display=truncate,lastline', @:)
+ set display&
+
+ " Test single-value options will not expand after a comma
+ call assert_equal([], getcompletion('set ambw=single,', 'cmdline'))
+
+ " Test the other simple options to make sure they have basic auto-complete,
+ " but don't exhaustively validate their results.
+ call assert_equal('single', getcompletion('set ambw=', 'cmdline')[0])
+ call assert_match('light\|dark', getcompletion('set bg=', 'cmdline')[1])
+ call assert_equal('indent', getcompletion('set backspace=', 'cmdline')[0])
+ call assert_equal('yes', getcompletion('set backupcopy=', 'cmdline')[1])
+ call assert_equal('backspace', getcompletion('set belloff=', 'cmdline')[1])
+ call assert_equal('min:', getcompletion('set briopt=', 'cmdline')[1])
+ if exists('+browsedir')
+ call assert_equal('current', getcompletion('set browsedir=', 'cmdline')[1])
+ endif
+ call assert_equal('unload', getcompletion('set bufhidden=', 'cmdline')[1])
+ call assert_equal('nowrite', getcompletion('set buftype=', 'cmdline')[1])
+ call assert_equal('internal', getcompletion('set casemap=', 'cmdline')[1])
+ if exists('+clipboard')
+ " call assert_match('unnamed', getcompletion('set clipboard=', 'cmdline')[1])
+ call assert_match('unnamed', getcompletion('set clipboard=', 'cmdline')[0])
+ endif
+ call assert_equal('.', getcompletion('set complete=', 'cmdline')[1])
+ call assert_equal('menu', getcompletion('set completeopt=', 'cmdline')[1])
+ if exists('+completeslash')
+ call assert_equal('backslash', getcompletion('set completeslash=', 'cmdline')[1])
+ endif
+ if exists('+cryptmethod')
+ call assert_equal('zip', getcompletion('set cryptmethod=', 'cmdline')[1])
+ endif
+ if exists('+cursorlineopt')
+ call assert_equal('line', getcompletion('set cursorlineopt=', 'cmdline')[1])
+ endif
+ call assert_equal('throw', getcompletion('set debug=', 'cmdline')[1])
+ call assert_equal('ver', getcompletion('set eadirection=', 'cmdline')[1])
+ call assert_equal('mac', getcompletion('set fileformat=', 'cmdline')[2])
+ if exists('+foldclose')
+ call assert_equal('all', getcompletion('set foldclose=', 'cmdline')[0])
+ endif
+ if exists('+foldmethod')
+ call assert_equal('expr', getcompletion('set foldmethod=', 'cmdline')[1])
+ endif
+ if exists('+foldopen')
+ call assert_equal('all', getcompletion('set foldopen=', 'cmdline')[1])
+ endif
+ call assert_equal('stack', getcompletion('set jumpoptions=', 'cmdline')[0])
+ call assert_equal('stopsel', getcompletion('set keymodel=', 'cmdline')[1])
+ call assert_equal('expr:1', getcompletion('set lispoptions=', 'cmdline')[1])
+ call assert_match('popup', getcompletion('set mousemodel=', 'cmdline')[2])
+ call assert_equal('bin', getcompletion('set nrformats=', 'cmdline')[1])
+ if exists('+rightleftcmd')
+ call assert_equal('search', getcompletion('set rightleftcmd=', 'cmdline')[0])
+ endif
+ call assert_equal('ver', getcompletion('set scrollopt=', 'cmdline')[1])
+ call assert_equal('exclusive', getcompletion('set selection=', 'cmdline')[1])
+ call assert_equal('key', getcompletion('set selectmode=', 'cmdline')[1])
+ if exists('+ssop')
+ call assert_equal('buffers', getcompletion('set ssop=', 'cmdline')[1])
+ endif
+ call assert_equal('statusline', getcompletion('set showcmdloc=', 'cmdline')[1])
+ if exists('+signcolumn')
+ call assert_equal('yes', getcompletion('set signcolumn=', 'cmdline')[1])
+ endif
+ if exists('+spelloptions')
+ call assert_equal('camel', getcompletion('set spelloptions=', 'cmdline')[0])
+ endif
+ if exists('+spellsuggest')
+ call assert_equal('best', getcompletion('set spellsuggest+=', 'cmdline')[0])
+ endif
+ call assert_equal('screen', getcompletion('set splitkeep=', 'cmdline')[1])
+ " call assert_equal('sync', getcompletion('set swapsync=', 'cmdline')[1])
+ call assert_equal('usetab', getcompletion('set switchbuf=', 'cmdline')[1])
+ call assert_equal('ignore', getcompletion('set tagcase=', 'cmdline')[1])
+ if exists('+termwintype')
+ call assert_equal('conpty', getcompletion('set termwintype=', 'cmdline')[1])
+ endif
+ if exists('+toolbar')
+ call assert_equal('text', getcompletion('set toolbar=', 'cmdline')[1])
+ endif
+ if exists('+tbis')
+ call assert_equal('medium', getcompletion('set tbis=', 'cmdline')[2])
+ endif
+ if exists('+ttymouse')
+ set ttymouse=
+ call assert_equal('xterm2', getcompletion('set ttymouse=', 'cmdline')[1])
+ set ttymouse&
+ endif
+ call assert_equal('insert', getcompletion('set virtualedit=', 'cmdline')[1])
+ call assert_equal('longest', getcompletion('set wildmode=', 'cmdline')[1])
+ call assert_equal('full', getcompletion('set wildmode=list,longest:', 'cmdline')[0])
+ call assert_equal('tagfile', getcompletion('set wildoptions=', 'cmdline')[1])
+ if exists('+winaltkeys')
+ call assert_equal('yes', getcompletion('set winaltkeys=', 'cmdline')[1])
+ endif
+
+ " Other string options that queries the system rather than fixed enum names
+ call assert_equal(['all', 'BufAdd'], getcompletion('set eventignore=', 'cmdline')[0:1])
+ call assert_equal('latin1', getcompletion('set fileencodings=', 'cmdline')[1])
+ " call assert_equal('top', getcompletion('set printoptions=', 'cmdline')[0])
+ " call assert_equal('SpecialKey', getcompletion('set wincolor=', 'cmdline')[0])
+
+ call assert_equal('eol', getcompletion('set listchars+=', 'cmdline')[0])
+ call assert_equal(['multispace', 'leadmultispace'], getcompletion('set listchars+=', 'cmdline')[-2:])
+ call assert_equal('eol', getcompletion('setl listchars+=', 'cmdline')[0])
+ call assert_equal(['multispace', 'leadmultispace'], getcompletion('setl listchars+=', 'cmdline')[-2:])
+ call assert_equal('stl', getcompletion('set fillchars+=', 'cmdline')[0])
+ call assert_equal('stl', getcompletion('setl fillchars+=', 'cmdline')[0])
+
+ "
+ " Unique string options below
+ "
+
+ " keyprotocol: only auto-complete when after ':' with known protocol types
+ " call assert_equal([&keyprotocol], getcompletion('set keyprotocol=', 'cmdline'))
+ " call feedkeys(":set keyprotocol+=someterm:m\<Tab>\<C-B>\"\<CR>", 'xt')
+ " call assert_equal('"set keyprotocol+=someterm:mok2', @:)
+ " set keyprotocol&
+
+ " previewpopup / completepopup
+ " call assert_equal('height:', getcompletion('set previewpopup=', 'cmdline')[0])
+ " call assert_equal('EndOfBuffer', getcompletion('set previewpopup=highlight:End*Buffer', 'cmdline')[0])
+ " call feedkeys(":set previewpopup+=border:\<Tab>\<C-B>\"\<CR>", 'xt')
+ " call assert_equal('"set previewpopup+=border:on', @:)
+ " call feedkeys(":set completepopup=height:10,align:\<Tab>\<C-B>\"\<CR>", 'xt')
+ " call assert_equal('"set completepopup=height:10,align:item', @:)
+ " call assert_equal([], getcompletion('set completepopup=bogusname:', 'cmdline'))
+ " set previewpopup& completepopup&
+
+ " diffopt: special handling of algorithm:<alg_list>
+ call assert_equal('filler', getcompletion('set diffopt+=', 'cmdline')[0])
+ call assert_equal([], getcompletion('set diffopt+=iblank,foldcolumn:', 'cmdline'))
+ call assert_equal('patience', getcompletion('set diffopt+=iblank,algorithm:pat*', 'cmdline')[0])
+
+ " highlight: special parsing, including auto-completing highlight groups
+ " after ':'
+ " call assert_equal([&hl, '8'], getcompletion('set hl=', 'cmdline')[0:1])
+ " call assert_equal('8', getcompletion('set hl+=', 'cmdline')[0])
+ " call assert_equal(['8:', '8b', '8i'], getcompletion('set hl+=8', 'cmdline')[0:2])
+ " call assert_equal('8bi', getcompletion('set hl+=8b', 'cmdline')[0])
+ " call assert_equal('NonText', getcompletion('set hl+=8:No*ext', 'cmdline')[0])
+ " If all the display modes are used up we should be suggesting nothing. Make
+ " a hl typed option with all the modes which will look like '8bi-nrsuc2d=t',
+ " and make sure nothing is suggested from that.
+ " let hl_display_modes = join(
+ " \ filter(map(getcompletion('set hl+=8', 'cmdline'),
+ " \ {idx, val -> val[1]}),
+ " \ {idx, val -> val != ':'}),
+ " \ '')
+ " call assert_equal([], getcompletion('set hl+=8'..hl_display_modes, 'cmdline'))
+
+ "
+ " Test flag lists
+ "
+
+ " Test set=. Show the original value if nothing is typed after '='.
+ " Otherwise, the list should avoid showing what's already typed.
+ set mouse=v
+ call assert_equal(['v','a','n','i','c','h','r'], getcompletion('set mouse=', 'cmdline'))
+ set mouse=nvi
+ call assert_equal(['nvi','a','n','v','i','c','h','r'], getcompletion('set mouse=', 'cmdline'))
+ call assert_equal(['a','v','i','c','r'], getcompletion('set mouse=hn', 'cmdline'))
+
+ " Test set+=. Never show original value, and it also tries to avoid listing
+ " flags that's already in the option value.
+ call assert_equal(['a','c','h','r'], getcompletion('set mouse+=', 'cmdline'))
+ call assert_equal(['a','c','r'], getcompletion('set mouse+=hn', 'cmdline'))
+ call assert_equal([], getcompletion('set mouse+=acrhn', 'cmdline'))
+
+ " Test that the position of the expansion is correct (even if there are
+ " additional values after the current cursor)
+ call feedkeys(":set mouse=hn\<Left>\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set mouse=han', @:)
+ set mouse&
+
+ " Test that other flag list options have auto-complete, but don't
+ " exhaustively validate their results.
+ if exists('+concealcursor')
+ call assert_equal('n', getcompletion('set cocu=', 'cmdline')[0])
+ endif
+ call assert_equal('a', getcompletion('set cpo=', 'cmdline')[1])
+ call assert_equal('t', getcompletion('set fo=', 'cmdline')[1])
+ if exists('+guioptions')
+ call assert_equal('!', getcompletion('set go=', 'cmdline')[1])
+ endif
+ call assert_equal('r', getcompletion('set shortmess=', 'cmdline')[1])
+ call assert_equal('b', getcompletion('set whichwrap=', 'cmdline')[1])
+
+ "
+ "Test set-=
+ "
+
+ " Normal single-value option just shows the existing value
+ set ambiwidth=double
+ call assert_equal(['double'], getcompletion('set ambw-=', 'cmdline'))
+ set ambiwidth&
+
+ " Works on numbers and term options as well
+ call assert_equal([string(&laststatus)], getcompletion('set laststatus-=', 'cmdline'))
+ set t_Ce=testCe
+ " call assert_equal(['testCe'], getcompletion('set t_Ce-=', 'cmdline'))
+ set t_Ce&
+
+ " Comma-separated lists should present each option
+ set diffopt=context:123,,,,,iblank,iwhiteall
+ call assert_equal(['context:123', 'iblank', 'iwhiteall'], getcompletion('set diffopt-=', 'cmdline'))
+ call assert_equal(['context:123', 'iblank'], getcompletion('set diffopt-=*n*', 'cmdline'))
+ call assert_equal(['iblank', 'iwhiteall'], getcompletion('set diffopt-=i', 'cmdline'))
+ " Don't present more than one option as it doesn't make sense in set-=
+ call assert_equal([], getcompletion('set diffopt-=iblank,', 'cmdline'))
+ " Test empty option
+ set diffopt=
+ call assert_equal([], getcompletion('set diffopt-=', 'cmdline'))
+ set diffopt&
+
+ " Test escaping output
+ call assert_equal('vert:\|', getcompletion('set fillchars-=', 'cmdline')[0])
+
+ " Test files with commas in name are being parsed and escaped properly
+ set path=has\\\ space,file\\,with\\,comma,normal_file
+ if exists('+completeslash')
+ call assert_equal(['has\\\ space', 'file\,with\,comma', 'normal_file'], getcompletion('set path-=', 'cmdline'))
+ else
+ call assert_equal(['has\\\ space', 'file\\,with\\,comma', 'normal_file'], getcompletion('set path-=', 'cmdline'))
+ endif
+ set path&
+
+ " Flag list should present orig value, then individual flags
+ set mouse=v
+ call assert_equal(['v'], getcompletion('set mouse-=', 'cmdline'))
+ set mouse=avn
+ call assert_equal(['avn','a','v','n'], getcompletion('set mouse-=', 'cmdline'))
+ " Don't auto-complete when we have at least one flags already
+ call assert_equal([], getcompletion('set mouse-=n', 'cmdline'))
+ " Test empty option
+ set mouse=
+ call assert_equal([], getcompletion('set mouse-=', 'cmdline'))
+ set mouse&
+
+ " 'whichwrap' is an odd case where it's both flag list and comma-separated
+ set ww=b,h
+ call assert_equal(['b','h'], getcompletion('set ww-=', 'cmdline'))
+ set ww&
+endfunc
+
func Test_set_option_errors()
call assert_fails('set scroll=-1', 'E49:')
call assert_fails('set backupcopy=', 'E474:')
@@ -1433,7 +1719,7 @@ func Test_opt_cdhome()
set cdhome&
endfunc
-func Test_set_completion_2()
+func Test_set_completion_fuzzy()
CheckOption termguicolors
" Test default option completion
diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim
index f60c0ddb59..80f73ba5d9 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -1,4 +1,4 @@
-" Test for reset 'scroll' and 'smoothscroll'
+" Test for 'scroll', 'scrolloff', 'smoothscroll', etc.
source check.vim
source screendump.vim
@@ -39,20 +39,74 @@ func Test_reset_scroll()
endfunc
func Test_scolloff_even_line_count()
- new
- resize 6
- setlocal scrolloff=3
- call setline(1, range(20))
- normal 2j
- call assert_equal(1, getwininfo(win_getid())[0].topline)
- normal j
- call assert_equal(1, getwininfo(win_getid())[0].topline)
- normal j
- call assert_equal(2, getwininfo(win_getid())[0].topline)
- normal j
- call assert_equal(3, getwininfo(win_getid())[0].topline)
-
- bwipe!
+ new
+ resize 6
+ setlocal scrolloff=3
+ call setline(1, range(20))
+ normal 2j
+ call assert_equal(1, getwininfo(win_getid())[0].topline)
+ normal j
+ call assert_equal(1, getwininfo(win_getid())[0].topline)
+ normal j
+ call assert_equal(2, getwininfo(win_getid())[0].topline)
+ normal j
+ call assert_equal(3, getwininfo(win_getid())[0].topline)
+
+ bwipe!
+endfunc
+
+func Test_mouse_scroll_inactive_with_cursorbind()
+ for scb in [0, 1]
+ for so in [0, 1, 2]
+ let msg = $'scb={scb} so={so}'
+
+ new | only
+ let w1 = win_getid()
+ setlocal cursorbind
+ let &l:scb = scb
+ let &l:so = so
+ call setline(1, range(101, 109))
+ rightbelow vnew
+ let w2 = win_getid()
+ setlocal cursorbind
+ let &l:scb = scb
+ let &l:so = so
+ call setline(1, range(101, 109))
+
+ normal! $
+ call assert_equal(3, col('.', w1), msg)
+ call assert_equal(3, col('.', w2), msg)
+ call Ntest_setmouse(1, 1)
+ call feedkeys("\<ScrollWheelDown>", 'xt')
+ call assert_equal(4, line('w0', w1), msg)
+ call assert_equal(4 + so, line('.', w1), msg)
+ call assert_equal(1, line('w0', w2), msg)
+ call assert_equal(1, line('.', w2), msg)
+ call feedkeys("\<ScrollWheelDown>", 'xt')
+ call assert_equal(7, line('w0', w1), msg)
+ call assert_equal(7 + so, line('.', w1), msg)
+ call assert_equal(1, line('w0', w2), msg)
+ call assert_equal(1, line('.', w2), msg)
+ call feedkeys("\<ScrollWheelUp>", 'xt')
+ call assert_equal(4, line('w0', w1), msg)
+ call assert_equal(7 + so, line('.', w1), msg)
+ call assert_equal(1, line('w0', w2), msg)
+ call assert_equal(1, line('.', w2), msg)
+ call feedkeys("\<ScrollWheelUp>", 'xt')
+ call assert_equal(1, line('w0', w1), msg)
+ call assert_equal(7 + so, line('.', w1), msg)
+ call assert_equal(1, line('w0', w2), msg)
+ call assert_equal(1, line('.', w2), msg)
+ normal! 0
+ call assert_equal(1, line('.', w1), msg)
+ call assert_equal(1, col('.', w1), msg)
+ call assert_equal(1, line('.', w2), msg)
+ call assert_equal(1, col('.', w2), msg)
+
+ bwipe!
+ bwipe!
+ endfor
+ endfor
endfunc
func Test_CtrlE_CtrlY_stop_at_end()