mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	refactor: format test/*
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -16,61 +16,164 @@ 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', preview=false, 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='?', preview=false, range=NIL, register=false, keepscript=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', | ||||
|     preview = false, | ||||
|     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 = '?', | ||||
|     preview = false, | ||||
|     range = NIL, | ||||
|     register = false, | ||||
|     keepscript = false, | ||||
|     script_id = 0, | ||||
|   } | ||||
|   before_each(clear) | ||||
|  | ||||
|   it('gets empty list if no commands were defined', function() | ||||
|     eq({}, meths.get_commands({builtin=false})) | ||||
|     eq({}, meths.get_commands({ builtin = false })) | ||||
|   end) | ||||
|  | ||||
|   it('validation', function() | ||||
|     eq('builtin=true not implemented', pcall_err(meths.get_commands, | ||||
|       {builtin=true})) | ||||
|     eq("Invalid key: 'foo'", pcall_err(meths.get_commands, | ||||
|       {foo='blah'})) | ||||
|     eq('builtin=true not implemented', pcall_err(meths.get_commands, { builtin = true })) | ||||
|     eq("Invalid key: 'foo'", pcall_err(meths.get_commands, { foo = 'blah' })) | ||||
|   end) | ||||
|  | ||||
|   it('gets global user-defined commands', function() | ||||
|     -- Define a command. | ||||
|     command('command -nargs=1 Hello echo "Hello World"') | ||||
|     eq({Hello=cmd_dict}, meths.get_commands({builtin=false})) | ||||
|     eq({ Hello = cmd_dict }, meths.get_commands({ builtin = false })) | ||||
|     -- Define another command. | ||||
|     command('command -nargs=? Pwd pwd'); | ||||
|     eq({Hello=cmd_dict, Pwd=cmd_dict2}, meths.get_commands({builtin=false})) | ||||
|     command('command -nargs=? Pwd pwd') | ||||
|     eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, meths.get_commands({ builtin = false })) | ||||
|     -- Delete a command. | ||||
|     command('delcommand Pwd') | ||||
|     eq({Hello=cmd_dict}, meths.get_commands({builtin=false})) | ||||
|     eq({ Hello = cmd_dict }, meths.get_commands({ builtin = false })) | ||||
|   end) | ||||
|  | ||||
|   it('gets buffer-local user-defined commands', function() | ||||
|     -- Define a buffer-local command. | ||||
|     command('command -buffer -nargs=1 Hello echo "Hello World"') | ||||
|     eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false})) | ||||
|     eq({ Hello = cmd_dict }, curbufmeths.get_commands({ builtin = false })) | ||||
|     -- Define another buffer-local command. | ||||
|     command('command -buffer -nargs=? Pwd pwd') | ||||
|     eq({Hello=cmd_dict, Pwd=cmd_dict2}, curbufmeths.get_commands({builtin=false})) | ||||
|     eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, curbufmeths.get_commands({ builtin = false })) | ||||
|     -- Delete a command. | ||||
|     command('delcommand Pwd') | ||||
|     eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false})) | ||||
|     eq({ Hello = cmd_dict }, curbufmeths.get_commands({ builtin = false })) | ||||
|  | ||||
|     -- {builtin=true} always returns empty for buffer-local case. | ||||
|     eq({}, curbufmeths.get_commands({builtin=true})) | ||||
|     eq({}, curbufmeths.get_commands({ builtin = true })) | ||||
|   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', preview=false, 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='+', preview=false, 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='*', preview=false, 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', preview=false, 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', preview=false, range=NIL,  register=true,  keepscript=false, 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', | ||||
|       preview = false, | ||||
|       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 = '+', | ||||
|       preview = false, | ||||
|       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 = '*', | ||||
|       preview = false, | ||||
|       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', | ||||
|       preview = false, | ||||
|       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', | ||||
|       preview = false, | ||||
|       range = NIL, | ||||
|       register = true, | ||||
|       keepscript = false, | ||||
|       script_id = 4, | ||||
|     } | ||||
|     source([[ | ||||
|       let s:foo = 1 | ||||
|       command -complete=custom,ListUsers -nargs=+ Finger !finger <args> | ||||
|     ]]) | ||||
|     eq({Finger=cmd1}, meths.get_commands({builtin=false})) | ||||
|     eq({ Finger = cmd1 }, meths.get_commands({ builtin = false })) | ||||
|     command('command -nargs=1 -complete=dir -addr=arguments -count=10 TestCmd pwd <args>') | ||||
|     eq({Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false})) | ||||
|     eq({ Finger = cmd1, TestCmd = cmd0 }, meths.get_commands({ builtin = false })) | ||||
|  | ||||
|     source([[ | ||||
|       function! s:foo() abort | ||||
| @@ -88,7 +191,10 @@ describe('nvim_get_commands', function() | ||||
|       command -register Cmd4 call <SID>just_great() | ||||
|     ]]) | ||||
|     -- TODO(justinmk): Order is stable but undefined. Sort before return? | ||||
|     eq({Cmd2=cmd2, Cmd3=cmd3, Cmd4=cmd4, Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false})) | ||||
|     eq( | ||||
|       { Cmd2 = cmd2, Cmd3 = cmd3, Cmd4 = cmd4, Finger = cmd1, TestCmd = cmd0 }, | ||||
|       meths.get_commands({ builtin = false }) | ||||
|     ) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -96,7 +202,7 @@ describe('nvim_create_user_command', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   it('works with strings', function() | ||||
|     meths.create_user_command('SomeCommand', 'let g:command_fired = <args>', {nargs = 1}) | ||||
|     meths.create_user_command('SomeCommand', 'let g:command_fired = <args>', { nargs = 1 }) | ||||
|     meths.command('SomeCommand 42') | ||||
|     eq(42, meths.eval('g:command_fired')) | ||||
|   end) | ||||
| @@ -113,14 +219,15 @@ describe('nvim_create_user_command', function() | ||||
|       }) | ||||
|     ]] | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = [[this\  is    a\ test]], | ||||
|       fargs = {"this ", "is", "a test"}, | ||||
|         fargs = { 'this ', 'is', 'a test' }, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -136,7 +243,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -144,20 +251,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [=[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [=[ | ||||
|       vim.api.nvim_command([[CommandWithLuaCallback this\  is    a\ test]]) | ||||
|       return result | ||||
|     ]=]) | ||||
|     ]=] | ||||
|     ) | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = [[this   includes\ a backslash: \\]], | ||||
|       fargs = {"this", "includes a", "backslash:", "\\"}, | ||||
|         fargs = { 'this', 'includes a', 'backslash:', '\\' }, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -173,7 +283,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -181,20 +291,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [=[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [=[ | ||||
|       vim.api.nvim_command([[CommandWithLuaCallback this   includes\ a backslash: \\]]) | ||||
|       return result | ||||
|     ]=]) | ||||
|     ]=] | ||||
|     ) | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|       args = "a\\b", | ||||
|       fargs = {"a\\b"}, | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = 'a\\b', | ||||
|         fargs = { 'a\\b' }, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -210,7 +323,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -218,20 +331,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [=[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [=[ | ||||
|       vim.api.nvim_command('CommandWithLuaCallback a\\b') | ||||
|       return result | ||||
|     ]=]) | ||||
|     ]=] | ||||
|     ) | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = 'h\tey ', | ||||
|       fargs = {[[h]], [[ey]]}, | ||||
|         fargs = { [[h]], [[ey]] }, | ||||
|         bang = true, | ||||
|         line1 = 10, | ||||
|         line2 = 10, | ||||
|       mods = "confirm unsilent botright horizontal", | ||||
|         mods = 'confirm unsilent botright horizontal', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = true, | ||||
| @@ -247,7 +363,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "botright", | ||||
|           split = 'botright', | ||||
|           tab = -1, | ||||
|           unsilent = true, | ||||
|           verbose = -1, | ||||
| @@ -255,20 +371,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 1, | ||||
|         count = 10, | ||||
|       reg = "", | ||||
|     }, exec_lua [=[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [=[ | ||||
|       vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ') | ||||
|       return result | ||||
|     ]=]) | ||||
|     ]=] | ||||
|     ) | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|       args = "h", | ||||
|       fargs = {"h"}, | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = 'h', | ||||
|         fargs = { 'h' }, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 42, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -284,7 +403,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -292,20 +411,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 1, | ||||
|         count = 42, | ||||
|       reg = "", | ||||
|     }, exec_lua [[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.api.nvim_command('CommandWithLuaCallback 42 h') | ||||
|       return result | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithLuaCallback", | ||||
|       args = "", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithLuaCallback', | ||||
|         args = '', | ||||
|         fargs = {}, -- fargs works without args | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -321,7 +443,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -329,11 +451,13 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.api.nvim_command('CommandWithLuaCallback') | ||||
|       return result | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     -- f-args doesn't split when command nargs is 1 or "?" | ||||
|     exec_lua [[ | ||||
| @@ -347,14 +471,15 @@ describe('nvim_create_user_command', function() | ||||
|       }) | ||||
|     ]] | ||||
|  | ||||
|     eq({ | ||||
|       name = "CommandWithOneOrNoArg", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithOneOrNoArg', | ||||
|         args = "hello I'm one argument", | ||||
|       fargs = {"hello I'm one argument"},  -- Doesn't split args | ||||
|         fargs = { "hello I'm one argument" }, -- Doesn't split args | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -370,7 +495,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -378,21 +503,24 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.api.nvim_command('CommandWithOneOrNoArg hello I\'m one argument') | ||||
|       return result | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     -- f-args is an empty table if no args were passed | ||||
|     eq({ | ||||
|       name = "CommandWithOneOrNoArg", | ||||
|       args = "", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithOneOrNoArg', | ||||
|         args = '', | ||||
|         fargs = {}, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -408,7 +536,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -416,11 +544,13 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.api.nvim_command('CommandWithOneOrNoArg') | ||||
|       return result | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     -- f-args is an empty table when the command nargs=0 | ||||
|     exec_lua [[ | ||||
| @@ -434,14 +564,15 @@ describe('nvim_create_user_command', function() | ||||
|         register = true, | ||||
|       }) | ||||
|     ]] | ||||
|     eq({ | ||||
|       name = "CommandWithNoArgs", | ||||
|       args = "", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithNoArgs', | ||||
|         args = '', | ||||
|         fargs = {}, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -457,7 +588,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -465,20 +596,23 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "", | ||||
|     }, exec_lua [[ | ||||
|         reg = '', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.cmd('CommandWithNoArgs') | ||||
|       return result | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|     -- register can be specified | ||||
|     eq({ | ||||
|       name = "CommandWithNoArgs", | ||||
|       args = "", | ||||
|     eq( | ||||
|       { | ||||
|         name = 'CommandWithNoArgs', | ||||
|         args = '', | ||||
|         fargs = {}, | ||||
|         bang = false, | ||||
|         line1 = 1, | ||||
|         line2 = 1, | ||||
|       mods = "", | ||||
|         mods = '', | ||||
|         smods = { | ||||
|           browse = false, | ||||
|           confirm = false, | ||||
| @@ -494,7 +628,7 @@ describe('nvim_create_user_command', function() | ||||
|           noswapfile = false, | ||||
|           sandbox = false, | ||||
|           silent = false, | ||||
|         split = "", | ||||
|           split = '', | ||||
|           tab = -1, | ||||
|           unsilent = false, | ||||
|           verbose = -1, | ||||
| @@ -502,20 +636,21 @@ describe('nvim_create_user_command', function() | ||||
|         }, | ||||
|         range = 0, | ||||
|         count = 2, | ||||
|       reg = "+", | ||||
|     }, exec_lua [[ | ||||
|         reg = '+', | ||||
|       }, | ||||
|       exec_lua [[ | ||||
|       vim.cmd('CommandWithNoArgs +') | ||||
|       return result | ||||
|     ]]) | ||||
|  | ||||
|     ]] | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('can define buffer-local commands', function() | ||||
|     local bufnr = meths.create_buf(false, false) | ||||
|     bufmeths.create_user_command(bufnr, "Hello", "", {}) | ||||
|     matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) | ||||
|     bufmeths.create_user_command(bufnr, 'Hello', '', {}) | ||||
|     matches('Not an editor command: Hello', pcall_err(meths.command, 'Hello')) | ||||
|     meths.set_current_buf(bufnr) | ||||
|     meths.command("Hello") | ||||
|     meths.command('Hello') | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
| @@ -543,33 +678,63 @@ describe('nvim_create_user_command', function() | ||||
|   end) | ||||
|  | ||||
|   it('does not allow invalid command names', function() | ||||
|     eq("Invalid command name (must start with uppercase): 'test'", pcall_err(exec_lua, [[ | ||||
|     eq( | ||||
|       "Invalid command name (must start with uppercase): 'test'", | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_create_user_command('test', 'echo "hi"', {}) | ||||
|     ]])) | ||||
|     eq("Invalid command name: 't@'", pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid command name: 't@'", | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_create_user_command('t@', 'echo "hi"', {}) | ||||
|     ]])) | ||||
|     eq("Invalid command name: 'T@st'", pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid command name: 'T@st'", | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_create_user_command('T@st', 'echo "hi"', {}) | ||||
|     ]])) | ||||
|     eq("Invalid command name: 'Test!'", pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid command name: 'Test!'", | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_create_user_command('Test!', 'echo "hi"', {}) | ||||
|     ]])) | ||||
|     eq("Invalid command name: '💩'", pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid command name: '💩'", | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_create_user_command('💩', 'echo "hi"', {}) | ||||
|     ]])) | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('smods can be used with nvim_cmd', function() | ||||
|     exec_lua[[ | ||||
|     exec_lua [[ | ||||
|       vim.api.nvim_create_user_command('MyEcho', function(opts) | ||||
|         vim.api.nvim_cmd({ cmd = 'echo', args = { '&verbose' }, mods = opts.smods }, {}) | ||||
|       end, {}) | ||||
|     ]] | ||||
|     eq("3", meths.cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true })) | ||||
|     eq('3', meths.cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true })) | ||||
|  | ||||
|     eq(1, #meths.list_tabpages()) | ||||
|     exec_lua[[ | ||||
|     exec_lua [[ | ||||
|       vim.api.nvim_create_user_command('MySplit', function(opts) | ||||
|         vim.api.nvim_cmd({ cmd = 'split', mods = opts.smods }, {}) | ||||
|       end, {}) | ||||
| @@ -599,13 +764,13 @@ describe('nvim_del_user_command', function() | ||||
|     meths.create_user_command('Hello', 'echo "Hi"', {}) | ||||
|     meths.command('Hello') | ||||
|     meths.del_user_command('Hello') | ||||
|     matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) | ||||
|     matches('Not an editor command: Hello', pcall_err(meths.command, 'Hello')) | ||||
|   end) | ||||
|  | ||||
|   it('can delete buffer-local commands', function() | ||||
|     bufmeths.create_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")) | ||||
|     matches('Not an editor command: Hello', pcall_err(meths.command, 'Hello')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,7 +10,7 @@ local pcall_err = helpers.pcall_err | ||||
| local ok = helpers.ok | ||||
| local assert_alive = helpers.assert_alive | ||||
|  | ||||
| describe('API: highlight',function() | ||||
| describe('API: highlight', function() | ||||
|   clear() | ||||
|   Screen.new() -- initialize Screen.colors | ||||
|  | ||||
| @@ -45,31 +45,35 @@ describe('API: highlight',function() | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     command("hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold") | ||||
|     command( | ||||
|       'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it("nvim_get_hl_by_id", function() | ||||
|   it('nvim_get_hl_by_id', function() | ||||
|     local hl_id = eval("hlID('NewHighlight')") | ||||
|     eq(expected_cterm, nvim("get_hl_by_id", hl_id, false)) | ||||
|     eq(expected_cterm, nvim('get_hl_by_id', hl_id, false)) | ||||
|  | ||||
|     hl_id = eval("hlID('NewHighlight')") | ||||
|     -- Test valid id. | ||||
|     eq(expected_rgb, nvim("get_hl_by_id", hl_id, true)) | ||||
|     eq(expected_rgb, nvim('get_hl_by_id', hl_id, true)) | ||||
|  | ||||
|     -- Test invalid id. | ||||
|     eq('Invalid highlight id: 30000', pcall_err(meths.get_hl_by_id, 30000, false)) | ||||
|  | ||||
|     -- Test all highlight properties. | ||||
|     command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') | ||||
|     eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true)) | ||||
|     eq(expected_rgb2, nvim('get_hl_by_id', hl_id, true)) | ||||
|  | ||||
|     -- Test undercurl | ||||
|     command('hi NewHighlight gui=undercurl') | ||||
|     eq(expected_undercurl, nvim("get_hl_by_id", hl_id, true)) | ||||
|     eq(expected_undercurl, nvim('get_hl_by_id', hl_id, true)) | ||||
|  | ||||
|     -- Test nil argument. | ||||
|     eq('Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer', | ||||
|        pcall_err(meths.get_hl_by_id, { nil }, false)) | ||||
|     eq( | ||||
|       'Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer', | ||||
|       pcall_err(meths.get_hl_by_id, { nil }, false) | ||||
|     ) | ||||
|  | ||||
|     -- Test 0 argument. | ||||
|     eq('Invalid highlight id: 0', pcall_err(meths.get_hl_by_id, 0, false)) | ||||
| @@ -81,76 +85,83 @@ describe('API: highlight',function() | ||||
|     command('hi Normal ctermfg=red ctermbg=yellow') | ||||
|     command('hi NewConstant ctermfg=green guifg=white guibg=blue') | ||||
|     hl_id = eval("hlID('NewConstant')") | ||||
|     eq({foreground = 10,}, meths.get_hl_by_id(hl_id, false)) | ||||
|     eq({ foreground = 10 }, meths.get_hl_by_id(hl_id, false)) | ||||
|  | ||||
|     -- Test highlight group without ctermfg value. | ||||
|     command('hi clear NewConstant') | ||||
|     command('hi NewConstant ctermbg=Magenta guifg=white guibg=blue') | ||||
|     eq({background = 13,}, meths.get_hl_by_id(hl_id, false)) | ||||
|     eq({ background = 13 }, meths.get_hl_by_id(hl_id, false)) | ||||
|  | ||||
|     -- Test highlight group with ctermfg and ctermbg values. | ||||
|     command('hi clear NewConstant') | ||||
|     command('hi NewConstant ctermfg=green ctermbg=Magenta guifg=white guibg=blue') | ||||
|     eq({foreground = 10, background = 13,}, meths.get_hl_by_id(hl_id, false)) | ||||
|     eq({ foreground = 10, background = 13 }, meths.get_hl_by_id(hl_id, false)) | ||||
|   end) | ||||
|  | ||||
|   it("nvim_get_hl_by_name", function() | ||||
|     local expected_normal = { background = Screen.colors.Yellow, | ||||
|                               foreground = Screen.colors.Red } | ||||
|   it('nvim_get_hl_by_name', function() | ||||
|     local expected_normal = { background = Screen.colors.Yellow, foreground = Screen.colors.Red } | ||||
|  | ||||
|     -- Test `Normal` default values. | ||||
|     eq({}, nvim("get_hl_by_name", 'Normal', true)) | ||||
|     eq({}, nvim('get_hl_by_name', 'Normal', true)) | ||||
|  | ||||
|     eq(expected_cterm, nvim("get_hl_by_name", 'NewHighlight', false)) | ||||
|     eq(expected_rgb, nvim("get_hl_by_name", 'NewHighlight', true)) | ||||
|     eq(expected_cterm, nvim('get_hl_by_name', 'NewHighlight', false)) | ||||
|     eq(expected_rgb, nvim('get_hl_by_name', 'NewHighlight', true)) | ||||
|  | ||||
|     -- Test `Normal` modified values. | ||||
|     command('hi Normal guifg=red guibg=yellow') | ||||
|     eq(expected_normal, nvim("get_hl_by_name", 'Normal', true)) | ||||
|     eq(expected_normal, nvim('get_hl_by_name', 'Normal', true)) | ||||
|  | ||||
|     -- Test invalid name. | ||||
|     eq("Invalid highlight name: 'unknown_highlight'", | ||||
|        pcall_err(meths.get_hl_by_name , 'unknown_highlight', false)) | ||||
|     eq( | ||||
|       "Invalid highlight name: 'unknown_highlight'", | ||||
|       pcall_err(meths.get_hl_by_name, 'unknown_highlight', false) | ||||
|     ) | ||||
|  | ||||
|     -- Test nil argument. | ||||
|     eq('Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String', | ||||
|        pcall_err(meths.get_hl_by_name , { nil }, false)) | ||||
|     eq( | ||||
|       'Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String', | ||||
|       pcall_err(meths.get_hl_by_name, { nil }, false) | ||||
|     ) | ||||
|  | ||||
|     -- Test empty string argument. | ||||
|     eq('Invalid highlight name', | ||||
|        pcall_err(meths.get_hl_by_name , '', false)) | ||||
|     eq('Invalid highlight name', pcall_err(meths.get_hl_by_name, '', false)) | ||||
|  | ||||
|     -- Test "standout" attribute. #8054 | ||||
|     eq({ underline = true, }, | ||||
|        meths.get_hl_by_name('cursorline', 0)); | ||||
|     eq({ underline = true }, meths.get_hl_by_name('cursorline', 0)) | ||||
|     command('hi CursorLine cterm=standout,underline term=standout,underline gui=standout,underline') | ||||
|     command('set cursorline') | ||||
|     eq({ underline = true, standout = true, }, | ||||
|        meths.get_hl_by_name('cursorline', 0)); | ||||
|     eq({ underline = true, standout = true }, meths.get_hl_by_name('cursorline', 0)) | ||||
|  | ||||
|     -- Test cterm & Normal values. #18024 (tail) & #18980 | ||||
|     -- Ensure Normal, and groups that match Normal return their fg & bg cterm values | ||||
|     meths.set_hl(0, 'Normal', {ctermfg = 17, ctermbg = 213}) | ||||
|     meths.set_hl(0, 'NotNormal', {ctermfg = 17, ctermbg = 213, nocombine = true}) | ||||
|     meths.set_hl(0, 'Normal', { ctermfg = 17, ctermbg = 213 }) | ||||
|     meths.set_hl(0, 'NotNormal', { ctermfg = 17, ctermbg = 213, nocombine = true }) | ||||
|     -- Note colors are "cterm" values, not rgb-as-ints | ||||
|     eq({foreground = 17, background = 213}, nvim("get_hl_by_name", 'Normal', false)) | ||||
|     eq({foreground = 17, background = 213, nocombine = true}, nvim("get_hl_by_name", 'NotNormal', false)) | ||||
|     eq({ foreground = 17, background = 213 }, nvim('get_hl_by_name', 'Normal', false)) | ||||
|     eq( | ||||
|       { foreground = 17, background = 213, nocombine = true }, | ||||
|       nvim('get_hl_by_name', 'NotNormal', false) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('nvim_get_hl_id_by_name', function() | ||||
|     -- precondition: use a hl group that does not yet exist | ||||
|     eq("Invalid highlight name: 'Shrubbery'", pcall_err(meths.get_hl_by_name, "Shrubbery", true)) | ||||
|     eq(0, funcs.hlID("Shrubbery")) | ||||
|     eq("Invalid highlight name: 'Shrubbery'", pcall_err(meths.get_hl_by_name, 'Shrubbery', true)) | ||||
|     eq(0, funcs.hlID('Shrubbery')) | ||||
|  | ||||
|     local hl_id = meths.get_hl_id_by_name("Shrubbery") | ||||
|     local hl_id = meths.get_hl_id_by_name('Shrubbery') | ||||
|     ok(hl_id > 0) | ||||
|     eq(hl_id, funcs.hlID("Shrubbery")) | ||||
|     eq(hl_id, funcs.hlID('Shrubbery')) | ||||
|  | ||||
|     command('hi Shrubbery guifg=#888888 guibg=#888888') | ||||
|     eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, | ||||
|        meths.get_hl_by_id(hl_id, true)) | ||||
|     eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, | ||||
|        meths.get_hl_by_name("Shrubbery", true)) | ||||
|     eq( | ||||
|       { foreground = tonumber('0x888888'), background = tonumber('0x888888') }, | ||||
|       meths.get_hl_by_id(hl_id, true) | ||||
|     ) | ||||
|     eq( | ||||
|       { foreground = tonumber('0x888888'), background = tonumber('0x888888') }, | ||||
|       meths.get_hl_by_name('Shrubbery', true) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function() | ||||
| @@ -165,7 +176,7 @@ describe('API: highlight',function() | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe("API: set highlight", function() | ||||
| describe('API: set highlight', function() | ||||
|   local highlight_color = { | ||||
|     fg = tonumber('0xff0000'), | ||||
|     bg = tonumber('0x0032aa'), | ||||
| @@ -207,7 +218,7 @@ describe("API: set highlight", function() | ||||
|       strikethrough = true, | ||||
|       altfont = true, | ||||
|       nocombine = true, | ||||
|     } | ||||
|     }, | ||||
|   } | ||||
|   local highlight3_result_gui = { | ||||
|     background = highlight_color.bg, | ||||
| @@ -238,31 +249,35 @@ describe("API: set highlight", function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   it('validation', function() | ||||
|     eq("Invalid 'blend': out of range", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend=999})) | ||||
|     eq("Invalid 'blend': expected Integer, got Array", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend={}})) | ||||
|     eq( | ||||
|       "Invalid 'blend': out of range", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = 999 }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'blend': expected Integer, got Array", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = {} }) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it("can set gui highlight", function() | ||||
|   it('can set gui highlight', function() | ||||
|     local ns = get_ns() | ||||
|     meths.set_hl(ns, 'Test_hl', highlight1) | ||||
|     eq(highlight1, meths.get_hl_by_name('Test_hl', true)) | ||||
|   end) | ||||
|  | ||||
|   it("can set cterm highlight", function() | ||||
|   it('can set cterm highlight', function() | ||||
|     local ns = get_ns() | ||||
|     meths.set_hl(ns, 'Test_hl', highlight2_config) | ||||
|     eq(highlight2_result, meths.get_hl_by_name('Test_hl', false)) | ||||
|   end) | ||||
|  | ||||
|   it("can set empty cterm attr", function() | ||||
|   it('can set empty 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() | ||||
|   it('cterm attr defaults to gui attr', function() | ||||
|     local ns = get_ns() | ||||
|     meths.set_hl(ns, 'Test_hl', highlight1) | ||||
|     eq({ | ||||
| @@ -271,14 +286,14 @@ describe("API: set highlight", function() | ||||
|     }, meths.get_hl_by_name('Test_hl', false)) | ||||
|   end) | ||||
|  | ||||
|   it("can overwrite attr for cterm", function() | ||||
|   it('can overwrite attr for cterm', function() | ||||
|     local ns = get_ns() | ||||
|     meths.set_hl(ns, 'Test_hl', highlight3_config) | ||||
|     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("only allows one underline attribute #22371", function() | ||||
|   it('only allows one underline attribute #22371', function() | ||||
|     local ns = get_ns() | ||||
|     meths.set_hl(ns, 'Test_hl', { | ||||
|       underdouble = true, | ||||
| @@ -292,80 +307,76 @@ describe("API: set highlight", function() | ||||
|     eq({ underdotted = true }, meths.get_hl_by_name('Test_hl', true)) | ||||
|   end) | ||||
|  | ||||
|   it("can set a highlight in the global namespace", function() | ||||
|   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')) | ||||
|     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')) | ||||
|     eq('Test_hl        xxx guibg=#0032aa', exec_capture('highlight Test_hl')) | ||||
|  | ||||
|     meths.set_hl(0, 'Test_hl2', highlight3_config) | ||||
|     eq('Test_hl2       xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa', | ||||
|       exec_capture('highlight Test_hl2')) | ||||
|     eq( | ||||
|       'Test_hl2       xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa', | ||||
|       exec_capture('highlight Test_hl2') | ||||
|     ) | ||||
|  | ||||
|     -- Colors are stored with the name they are defined, but | ||||
|     -- with canonical casing | ||||
|     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', 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')) | ||||
|   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')) | ||||
|     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 = 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 = '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('Test_hl3       xxx ctermbg=9', exec_capture('highlight Test_hl3')) | ||||
|  | ||||
|     eq("Invalid highlight color: 'redd'", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'})) | ||||
|     eq("Invalid highlight color: 'redd'", pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = 'redd' })) | ||||
|  | ||||
|     eq("Invalid highlight color: 'bleu'", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'})) | ||||
|     eq( | ||||
|       "Invalid highlight color: 'bleu'", | ||||
|       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')) | ||||
|     meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF' }) | ||||
|     eq('Test_hl3       xxx guifg=#ff00ff', exec_capture('highlight Test_hl3')) | ||||
|  | ||||
|     eq("Invalid highlight color: '#FF00FF'", | ||||
|       pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'})) | ||||
|     eq( | ||||
|       "Invalid highlight color: '#FF00FF'", | ||||
|       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')) | ||||
|     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')) | ||||
|  | ||||
|     meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 }) | ||||
|     eq('Test_hl3       xxx guifg=#ff00ff blend=50', exec_capture('highlight Test_hl3')) | ||||
|   end) | ||||
|  | ||||
|   it("correctly sets 'Normal' internal properties", function() | ||||
|     -- Normal has some special handling internally. #18024 | ||||
|     meths.set_hl(0, 'Normal', {fg='#000083', bg='#0000F3'}) | ||||
|     eq({foreground = 131, background = 243}, nvim("get_hl_by_name", 'Normal', true)) | ||||
|     meths.set_hl(0, 'Normal', { fg = '#000083', bg = '#0000F3' }) | ||||
|     eq({ foreground = 131, background = 243 }, nvim('get_hl_by_name', 'Normal', true)) | ||||
|   end) | ||||
|  | ||||
|   it('does not segfault on invalid group name #20009', function() | ||||
|     eq("Invalid highlight name: 'foo bar'", pcall_err(meths.set_hl, 0, 'foo bar', {bold = true})) | ||||
|     eq("Invalid highlight name: 'foo bar'", pcall_err(meths.set_hl, 0, 'foo bar', { bold = true })) | ||||
|     assert_alive() | ||||
|   end) | ||||
| end) | ||||
| @@ -380,14 +391,16 @@ describe('API: get highlight', function() | ||||
|   local highlight1 = { | ||||
|     bg = highlight_color.bg, | ||||
|     fg = highlight_color.fg, | ||||
|     bold = true, italic = true, | ||||
|     cterm = {bold = true, italic = true}, | ||||
|     bold = true, | ||||
|     italic = true, | ||||
|     cterm = { bold = true, italic = true }, | ||||
|   } | ||||
|   local highlight2 = { | ||||
|     ctermbg = highlight_color.ctermbg, | ||||
|     ctermfg = highlight_color.ctermfg, | ||||
|     underline = true, reverse = true, | ||||
|     cterm = {underline = true, reverse = true}, | ||||
|     underline = true, | ||||
|     reverse = true, | ||||
|     cterm = { underline = true, reverse = true }, | ||||
|   } | ||||
|   local highlight3_config = { | ||||
|     bg = highlight_color.bg, | ||||
| @@ -413,8 +426,19 @@ describe('API: get highlight', function() | ||||
|     fg = highlight_color.fg, | ||||
|     ctermbg = highlight_color.ctermbg, | ||||
|     ctermfg = highlight_color.ctermfg, | ||||
|     bold = true, italic = true, reverse = true, underdashed = true, strikethrough = true, altfont = true, | ||||
|     cterm = {italic = true, nocombine = true, reverse = true, strikethrough = true, altfont = true} | ||||
|     bold = true, | ||||
|     italic = true, | ||||
|     reverse = true, | ||||
|     underdashed = true, | ||||
|     strikethrough = true, | ||||
|     altfont = true, | ||||
|     cterm = { | ||||
|       italic = true, | ||||
|       nocombine = true, | ||||
|       reverse = true, | ||||
|       strikethrough = true, | ||||
|       altfont = true, | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   local function get_ns() | ||||
| @@ -434,17 +458,16 @@ describe('API: get highlight', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   it('validation', function() | ||||
|     eq("Invalid 'name': expected String, got Integer", | ||||
|        pcall_err(meths.get_hl, 0, { name = 177 })) | ||||
|     eq("Invalid 'name': expected String, got Integer", pcall_err(meths.get_hl, 0, { name = 177 })) | ||||
|     eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' })) | ||||
|   end) | ||||
|  | ||||
|   it('nvim_get_hl with create flag', function() | ||||
|     eq({}, nvim("get_hl", 0, {name = 'Foo', create = false})) | ||||
|     eq({}, nvim('get_hl', 0, { name = 'Foo', create = false })) | ||||
|     eq(0, funcs.hlexists('Foo')) | ||||
|     meths.get_hl(0, {name = 'Bar', create = true}) | ||||
|     meths.get_hl(0, { name = 'Bar', create = true }) | ||||
|     eq(1, funcs.hlexists('Bar')) | ||||
|     meths.get_hl(0, {name = 'FooBar'}) | ||||
|     meths.get_hl(0, { name = 'FooBar' }) | ||||
|     eq(1, funcs.hlexists('FooBar')) | ||||
|   end) | ||||
|  | ||||
| @@ -454,11 +477,11 @@ describe('API: get highlight', function() | ||||
|     meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' }) | ||||
|     eq({ | ||||
|       Test_hl = { | ||||
|         bg = 11845374 | ||||
|         bg = 11845374, | ||||
|       }, | ||||
|       Test_hl_link = { | ||||
|         link = 'Test_hl' | ||||
|       } | ||||
|         link = 'Test_hl', | ||||
|       }, | ||||
|     }, meths.get_hl(ns, {})) | ||||
|   end) | ||||
|  | ||||
| @@ -502,8 +525,7 @@ describe('API: get highlight', function() | ||||
|         undercurl = true, | ||||
|       }, | ||||
|     }) | ||||
|     eq({ underdotted = true, cterm = { undercurl = true} }, | ||||
|        meths.get_hl(ns, { name = 'Test_hl' })) | ||||
|     eq({ underdotted = true, cterm = { undercurl = true } }, meths.get_hl(ns, { name = 'Test_hl' })) | ||||
|   end) | ||||
|  | ||||
|   it('can get a highlight in the global namespace', function() | ||||
| @@ -533,8 +555,13 @@ describe('API: get highlight', function() | ||||
|     command( | ||||
|       'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' | ||||
|     ) | ||||
|     eq({ fg = 16711680, bg = 16776960, sp = 255, bold = true, | ||||
|          ctermbg = 10, cterm = { underline = true }, | ||||
|     eq({ | ||||
|       fg = 16711680, | ||||
|       bg = 16776960, | ||||
|       sp = 255, | ||||
|       bold = true, | ||||
|       ctermbg = 10, | ||||
|       cterm = { underline = true }, | ||||
|     }, meths.get_hl(0, { id = hl_id })) | ||||
|  | ||||
|     -- Test 0 argument | ||||
| @@ -547,16 +574,30 @@ describe('API: get highlight', function() | ||||
|  | ||||
|     -- Test all highlight properties. | ||||
|     command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') | ||||
|     eq({ fg = 16711680, bg = 16776960, sp = 255, | ||||
|          altfont = true, bold = true, italic = true, nocombine = true, reverse = true, strikethrough = true, underline = true, | ||||
|          ctermbg = 10, cterm = {underline = true}, | ||||
|     eq({ | ||||
|       fg = 16711680, | ||||
|       bg = 16776960, | ||||
|       sp = 255, | ||||
|       altfont = true, | ||||
|       bold = true, | ||||
|       italic = true, | ||||
|       nocombine = true, | ||||
|       reverse = true, | ||||
|       strikethrough = true, | ||||
|       underline = true, | ||||
|       ctermbg = 10, | ||||
|       cterm = { underline = true }, | ||||
|     }, meths.get_hl(0, { id = hl_id })) | ||||
|  | ||||
|     -- Test undercurl | ||||
|     command('hi NewHighlight gui=undercurl') | ||||
|     eq({ fg = 16711680, bg = 16776960, sp = 255, undercurl = true, | ||||
|     eq({ | ||||
|       fg = 16711680, | ||||
|       bg = 16776960, | ||||
|       sp = 255, | ||||
|       undercurl = true, | ||||
|       ctermbg = 10, | ||||
|          cterm = {underline = true}, | ||||
|       cterm = { underline = true }, | ||||
|     }, meths.get_hl(0, { id = hl_id })) | ||||
|   end) | ||||
|  | ||||
| @@ -573,7 +614,10 @@ describe('API: get highlight', function() | ||||
|     command('hi Bar guifg=red') | ||||
|     command('hi Foo guifg=#00ff00 gui=bold,underline') | ||||
|     command('hi! link Foo Bar') | ||||
|     eq({ link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true }, meths.get_hl(0, { name = 'Foo', link = true })) | ||||
|     eq( | ||||
|       { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true }, | ||||
|       meths.get_hl(0, { name = 'Foo', link = true }) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('can set link as well as other attributes', function() | ||||
| @@ -584,57 +628,57 @@ describe('API: get highlight', function() | ||||
|   end) | ||||
|  | ||||
|   it("doesn't contain unset groups", function() | ||||
|     local id = meths.get_hl_id_by_name "@foobar.hubbabubba" | ||||
|     local id = meths.get_hl_id_by_name '@foobar.hubbabubba' | ||||
|     ok(id > 0) | ||||
|  | ||||
|     local data = meths.get_hl(0, {}) | ||||
|     eq(nil, data["@foobar.hubbabubba"]) | ||||
|     eq(nil, data["@foobar"]) | ||||
|     eq(nil, data['@foobar.hubbabubba']) | ||||
|     eq(nil, data['@foobar']) | ||||
|  | ||||
|     command 'hi @foobar.hubbabubba gui=bold' | ||||
|     data = meths.get_hl(0, {}) | ||||
|     eq({bold = true}, data["@foobar.hubbabubba"]) | ||||
|     eq(nil, data["@foobar"]) | ||||
|     eq({ bold = true }, data['@foobar.hubbabubba']) | ||||
|     eq(nil, data['@foobar']) | ||||
|  | ||||
|     -- @foobar.hubbabubba was explicitly cleared and thus shows up | ||||
|     -- but @foobar was never touched, and thus doesn't | ||||
|     command 'hi clear @foobar.hubbabubba' | ||||
|     data = meths.get_hl(0, {}) | ||||
|     eq({}, data["@foobar.hubbabubba"]) | ||||
|     eq(nil, data["@foobar"]) | ||||
|     eq({}, data['@foobar.hubbabubba']) | ||||
|     eq(nil, data['@foobar']) | ||||
|   end) | ||||
|  | ||||
|   it('should return default flag', function() | ||||
|     meths.set_hl(0, 'Tried', { fg = "#00ff00", default = true }) | ||||
|     meths.set_hl(0, 'Tried', { fg = '#00ff00', default = true }) | ||||
|     eq({ fg = tonumber('00ff00', 16), default = true }, meths.get_hl(0, { name = 'Tried' })) | ||||
|   end) | ||||
|  | ||||
|   it('should not output empty gui and cterm #23474', function() | ||||
|     meths.set_hl(0, 'Foo', {default = true}) | ||||
|     meths.set_hl(0, 'Foo', { default = true }) | ||||
|     meths.set_hl(0, 'Bar', { default = true, fg = '#ffffff' }) | ||||
|     meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = {bold = true} }) | ||||
|     meths.set_hl(0, 'FooBarA', { default = true, fg = '#ffffff', cterm = {bold = true,italic = true}}) | ||||
|     meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } }) | ||||
|     meths.set_hl( | ||||
|       0, | ||||
|       'FooBarA', | ||||
|       { default = true, fg = '#ffffff', cterm = { bold = true, italic = true } } | ||||
|     ) | ||||
|  | ||||
|     eq('Foo            xxx cleared', | ||||
|       exec_capture('highlight Foo')) | ||||
|     eq({default = true}, meths.get_hl(0, {name = 'Foo'})) | ||||
|     eq('Bar            xxx guifg=#ffffff', | ||||
|       exec_capture('highlight Bar')) | ||||
|     eq('FooBar         xxx cterm=bold guifg=#ffffff', | ||||
|       exec_capture('highlight FooBar')) | ||||
|     eq('FooBarA        xxx cterm=bold,italic guifg=#ffffff', | ||||
|       exec_capture('highlight FooBarA')) | ||||
|     eq('Foo            xxx cleared', exec_capture('highlight Foo')) | ||||
|     eq({ default = true }, meths.get_hl(0, { name = 'Foo' })) | ||||
|     eq('Bar            xxx guifg=#ffffff', exec_capture('highlight Bar')) | ||||
|     eq('FooBar         xxx cterm=bold guifg=#ffffff', exec_capture('highlight FooBar')) | ||||
|     eq('FooBarA        xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA')) | ||||
|   end) | ||||
|  | ||||
|   it('can override exist highlight group by force #20323', function() | ||||
|     local white = tonumber('ffffff', 16) | ||||
|     local green = tonumber('00ff00', 16) | ||||
|     meths.set_hl(0, 'Foo', { fg=white }) | ||||
|     meths.set_hl(0, 'Foo', { fg=green, force = true }) | ||||
|     eq({ fg = green },meths.get_hl(0, {name = 'Foo'})) | ||||
|     meths.set_hl(0, 'Bar', {link = 'Comment', default = true}) | ||||
|     meths.set_hl(0, 'Bar', {link = 'Foo',default = true, force = true}) | ||||
|     eq({link ='Foo', default = true}, meths.get_hl(0, {name = 'Bar'})) | ||||
|     meths.set_hl(0, 'Foo', { fg = white }) | ||||
|     meths.set_hl(0, 'Foo', { fg = green, force = true }) | ||||
|     eq({ fg = green }, meths.get_hl(0, { name = 'Foo' })) | ||||
|     meths.set_hl(0, 'Bar', { link = 'Comment', default = true }) | ||||
|     meths.set_hl(0, 'Bar', { link = 'Foo', default = true, force = true }) | ||||
|     eq({ link = 'Foo', default = true }, meths.get_hl(0, { name = 'Bar' })) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -647,9 +691,9 @@ describe('API: set/get highlight namespace', function() | ||||
|   end) | ||||
|  | ||||
|   it('set/get window highlight namespace', function() | ||||
|     eq(-1, meths.get_hl_ns({winid = 0})) | ||||
|     eq(-1, meths.get_hl_ns({ winid = 0 })) | ||||
|     local ns = meths.create_namespace('') | ||||
|     meths.win_set_hl_ns(0, ns) | ||||
|     eq(ns, meths.get_hl_ns({winid = 0})) | ||||
|     eq(ns, meths.get_hl_ns({ winid = 0 })) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -5,8 +5,7 @@ local clear = helpers.clear | ||||
| local command = helpers.command | ||||
| local feed = helpers.feed | ||||
|  | ||||
| describe("update_menu notification", function() | ||||
|  | ||||
| describe('update_menu notification', function() | ||||
|   local screen | ||||
|  | ||||
|   before_each(function() | ||||
| @@ -16,7 +15,8 @@ describe("update_menu notification", function() | ||||
|   end) | ||||
|  | ||||
|   local function expect_sent(expected) | ||||
|     screen:expect{condition=function() | ||||
|     screen:expect { | ||||
|       condition = function() | ||||
|         if screen.update_menu ~= expected then | ||||
|           if expected then | ||||
|             error('update_menu was expected but not sent') | ||||
| @@ -24,15 +24,17 @@ describe("update_menu notification", function() | ||||
|             error('update_menu was sent unexpectedly') | ||||
|           end | ||||
|         end | ||||
|     end, unchanged=(not expected)} | ||||
|       end, | ||||
|       unchanged = not expected, | ||||
|     } | ||||
|   end | ||||
|  | ||||
|   it("should be sent when adding a menu", function() | ||||
|   it('should be sent when adding a menu', function() | ||||
|     command('menu Test.Test :') | ||||
|     expect_sent(true) | ||||
|   end) | ||||
|  | ||||
|   it("should be sent when deleting a menu", function() | ||||
|   it('should be sent when deleting a menu', function() | ||||
|     command('menu Test.Test :') | ||||
|     screen.update_menu = false | ||||
|  | ||||
| @@ -40,9 +42,8 @@ describe("update_menu notification", function() | ||||
|     expect_sent(true) | ||||
|   end) | ||||
|  | ||||
|   it("should not be sent unnecessarily", function() | ||||
|   it('should not be sent unnecessarily', function() | ||||
|     feed('i12345<ESC>:redraw<CR>') | ||||
|     expect_sent(false) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -43,16 +43,16 @@ describe('API', function() | ||||
|     end) | ||||
|  | ||||
|     it('validation', function() | ||||
|       local status, rv = pcall(request, "nvim_get_proc_children", -1) | ||||
|       local status, rv = pcall(request, 'nvim_get_proc_children', -1) | ||||
|       eq(false, status) | ||||
|       eq("Invalid 'pid': -1", string.match(rv, "Invalid.*")) | ||||
|       eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*')) | ||||
|  | ||||
|       status, rv = pcall(request, "nvim_get_proc_children", 0) | ||||
|       status, rv = pcall(request, 'nvim_get_proc_children', 0) | ||||
|       eq(false, status) | ||||
|       eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) | ||||
|       eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*')) | ||||
|  | ||||
|       -- Assume PID 99999 does not exist. | ||||
|       status, rv = pcall(request, "nvim_get_proc_children", 99999) | ||||
|       status, rv = pcall(request, 'nvim_get_proc_children', 99999) | ||||
|       eq(true, status) | ||||
|       eq({}, rv) | ||||
|     end) | ||||
| @@ -69,16 +69,16 @@ describe('API', function() | ||||
|     end) | ||||
|  | ||||
|     it('validation', function() | ||||
|       local status, rv = pcall(request, "nvim_get_proc", -1) | ||||
|       local status, rv = pcall(request, 'nvim_get_proc', -1) | ||||
|       eq(false, status) | ||||
|       eq("Invalid 'pid': -1", string.match(rv, "Invalid.*")) | ||||
|       eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*')) | ||||
|  | ||||
|       status, rv = pcall(request, "nvim_get_proc", 0) | ||||
|       status, rv = pcall(request, 'nvim_get_proc', 0) | ||||
|       eq(false, status) | ||||
|       eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) | ||||
|       eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*')) | ||||
|  | ||||
|       -- Assume PID 99999 does not exist. | ||||
|       status, rv = pcall(request, "nvim_get_proc", 99999) | ||||
|       status, rv = pcall(request, 'nvim_get_proc', 99999) | ||||
|       eq(true, status) | ||||
|       eq(NIL, rv) | ||||
|     end) | ||||
|   | ||||
| @@ -4,8 +4,8 @@ | ||||
| package.path = arg[1] | ||||
| package.cpath = arg[2] | ||||
|  | ||||
| local StdioStream = require'test.client.uv_stream'.StdioStream | ||||
| local Session = require'test.client.session' | ||||
| local StdioStream = require 'test.client.uv_stream'.StdioStream | ||||
| local Session = require 'test.client.session' | ||||
|  | ||||
| local stdio_stream = StdioStream.open() | ||||
| local session = Session.new(stdio_stream) | ||||
| @@ -15,8 +15,8 @@ local function on_request(method, args) | ||||
|     return 'ok' | ||||
|   elseif method == 'write_stderr' then | ||||
|     io.stderr:write(args[1]) | ||||
|     return "done!" | ||||
|   elseif method == "exit" then | ||||
|     return 'done!' | ||||
|   elseif method == 'exit' then | ||||
|     session:stop() | ||||
|     return vim.NIL | ||||
|   end | ||||
| @@ -24,7 +24,7 @@ end | ||||
|  | ||||
| local function on_notification(event, args) | ||||
|   if event == 'ping' and #args == 0 then | ||||
|     session:notify("nvim_eval", "rpcnotify(g:channel, 'pong')") | ||||
|     session:notify('nvim_eval', "rpcnotify(g:channel, 'pong')") | ||||
|   end | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local assert_log = helpers.assert_log | ||||
| local eq, clear, eval, command, nvim, next_msg = | ||||
|   helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, | ||||
|   helpers.next_msg | ||||
|   helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, helpers.next_msg | ||||
| local meths = helpers.meths | ||||
| local exec_lua = helpers.exec_lua | ||||
| local retry = helpers.retry | ||||
| @@ -24,11 +23,11 @@ describe('notify', function() | ||||
|  | ||||
|   describe('passing a valid channel id', function() | ||||
|     it('sends the notification/args to the corresponding channel', function() | ||||
|       eval('rpcnotify('..channel..', "test-event", 1, 2, 3)') | ||||
|       eq({'notification', 'test-event', {1, 2, 3}}, next_msg()) | ||||
|       command('au FileType lua call rpcnotify('..channel..', "lua!")') | ||||
|       eval('rpcnotify(' .. channel .. ', "test-event", 1, 2, 3)') | ||||
|       eq({ 'notification', 'test-event', { 1, 2, 3 } }, next_msg()) | ||||
|       command('au FileType lua call rpcnotify(' .. channel .. ', "lua!")') | ||||
|       command('set filetype=lua') | ||||
|       eq({'notification', 'lua!', {}}, next_msg()) | ||||
|       eq({ 'notification', 'lua!', {} }, next_msg()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -38,20 +37,20 @@ describe('notify', function() | ||||
|       eval('rpcnotify(0, "event1", 1, 2, 3)') | ||||
|       eval('rpcnotify(0, "event2", 4, 5, 6)') | ||||
|       eval('rpcnotify(0, "event2", 7, 8, 9)') | ||||
|       eq({'notification', 'event2', {4, 5, 6}}, next_msg()) | ||||
|       eq({'notification', 'event2', {7, 8, 9}}, next_msg()) | ||||
|       eq({ 'notification', 'event2', { 4, 5, 6 } }, next_msg()) | ||||
|       eq({ 'notification', 'event2', { 7, 8, 9 } }, next_msg()) | ||||
|       nvim('unsubscribe', 'event2') | ||||
|       nvim('subscribe', 'event1') | ||||
|       eval('rpcnotify(0, "event2", 10, 11, 12)') | ||||
|       eval('rpcnotify(0, "event1", 13, 14, 15)') | ||||
|       eq({'notification', 'event1', {13, 14, 15}}, next_msg()) | ||||
|       eq({ 'notification', 'event1', { 13, 14, 15 } }, next_msg()) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash for deeply nested variable', function() | ||||
|       meths.set_var('l', {}) | ||||
|       local nest_level = 1000 | ||||
|       meths.command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1)) | ||||
|       eval('rpcnotify('..channel..', "event", g:l)') | ||||
|       eval('rpcnotify(' .. channel .. ', "event", g:l)') | ||||
|       local msg = next_msg() | ||||
|       eq('notification', msg[1]) | ||||
|       eq('event', msg[2]) | ||||
| @@ -77,9 +76,9 @@ describe('notify', function() | ||||
|   end) | ||||
|  | ||||
|   it('unsubscribe non-existing event #8745', function() | ||||
|     clear{env={ | ||||
|       NVIM_LOG_FILE=testlog, | ||||
|     }} | ||||
|     clear { env = { | ||||
|       NVIM_LOG_FILE = testlog, | ||||
|     } } | ||||
|     nvim('subscribe', 'event1') | ||||
|     nvim('unsubscribe', 'doesnotexist') | ||||
|     assert_log("tried to unsubscribe unknown event 'doesnotexist'", testlog, 10) | ||||
| @@ -90,14 +89,24 @@ describe('notify', function() | ||||
|   it('cancels stale events on channel close', function() | ||||
|     local catchan = eval("jobstart(['cat'], {'rpc': v:true})") | ||||
|     local catpath = eval('exepath("cat")') | ||||
|     eq({id=catchan, argv={catpath}, stream='job', mode='rpc', client = {}}, exec_lua ([[ | ||||
|     eq( | ||||
|       { id = catchan, argv = { catpath }, stream = 'job', mode = 'rpc', client = {} }, | ||||
|       exec_lua( | ||||
|         [[ | ||||
|       vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'}) | ||||
|       vim.rpcnotify(..., "nvim_subscribe", "daily_rant") | ||||
|       return vim.api.nvim_get_chan_info(...) | ||||
|     ]], catchan)) | ||||
|     ]], | ||||
|         catchan | ||||
|       ) | ||||
|     ) | ||||
|     assert_alive() | ||||
|     eq({false, 'Invalid channel: '..catchan}, | ||||
|       exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan)) | ||||
|     retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :( | ||||
|     eq( | ||||
|       { false, 'Invalid channel: ' .. catchan }, | ||||
|       exec_lua([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan) | ||||
|     ) | ||||
|     retry(nil, 3000, function() | ||||
|       eq({}, meths.get_chan_info(catchan)) | ||||
|     end) -- cat be dead :( | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -40,13 +40,13 @@ describe('server -> client', function() | ||||
|   describe('simple call', function() | ||||
|     it('works', function() | ||||
|       local function on_setup() | ||||
|         eq({4, 5, 6}, eval('rpcrequest('..cid..', "scall", 1, 2, 3)')) | ||||
|         eq({ 4, 5, 6 }, eval('rpcrequest(' .. cid .. ', "scall", 1, 2, 3)')) | ||||
|         stop() | ||||
|       end | ||||
|  | ||||
|       local function on_request(method, args) | ||||
|         eq('scall', method) | ||||
|         eq({1, 2, 3}, args) | ||||
|         eq({ 1, 2, 3 }, args) | ||||
|         nvim('command', 'let g:result = [4, 5, 6]') | ||||
|         return eval('g:result') | ||||
|       end | ||||
| @@ -61,14 +61,14 @@ describe('server -> client', function() | ||||
|     -- elements following the empty string. | ||||
|     it('works', function() | ||||
|       local function on_setup() | ||||
|         eq({1, 2, '', 3, 'asdf'}, eval('rpcrequest('..cid..', "nstring")')) | ||||
|         eq({ 1, 2, '', 3, 'asdf' }, eval('rpcrequest(' .. cid .. ', "nstring")')) | ||||
|         stop() | ||||
|       end | ||||
|  | ||||
|       local function on_request() | ||||
|         -- No need to evaluate the args, we are only interested in | ||||
|         -- a response that contains an array with an empty string. | ||||
|         return {1, 2, '', 3, 'asdf'} | ||||
|         return { 1, 2, '', 3, 'asdf' } | ||||
|       end | ||||
|       run(on_request, nil, on_setup) | ||||
|     end) | ||||
| @@ -81,7 +81,7 @@ describe('server -> client', function() | ||||
|         nvim('set_var', 'result2', 0) | ||||
|         nvim('set_var', 'result3', 0) | ||||
|         nvim('set_var', 'result4', 0) | ||||
|         nvim('command', 'let g:result1 = rpcrequest('..cid..', "rcall", 2)') | ||||
|         nvim('command', 'let g:result1 = rpcrequest(' .. cid .. ', "rcall", 2)') | ||||
|         eq(4, nvim('get_var', 'result1')) | ||||
|         eq(8, nvim('get_var', 'result2')) | ||||
|         eq(16, nvim('get_var', 'result3')) | ||||
| @@ -95,11 +95,11 @@ describe('server -> client', function() | ||||
|         if n <= 16 then | ||||
|           local cmd | ||||
|           if n == 4 then | ||||
|             cmd = 'let g:result2 = rpcrequest('..cid..', "rcall", '..n..')' | ||||
|             cmd = 'let g:result2 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' | ||||
|           elseif n == 8 then | ||||
|             cmd = 'let g:result3 = rpcrequest('..cid..', "rcall", '..n..')' | ||||
|             cmd = 'let g:result3 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' | ||||
|           elseif n == 16 then | ||||
|             cmd = 'let g:result4 = rpcrequest('..cid..', "rcall", '..n..')' | ||||
|             cmd = 'let g:result4 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' | ||||
|           end | ||||
|           nvim('command', cmd) | ||||
|         end | ||||
| @@ -113,18 +113,18 @@ describe('server -> client', function() | ||||
|     it('does not delay notifications during pending request', function() | ||||
|       local received = false | ||||
|       local function on_setup() | ||||
|         eq("retval", funcs.rpcrequest(cid, "doit")) | ||||
|         eq('retval', funcs.rpcrequest(cid, 'doit')) | ||||
|         stop() | ||||
|       end | ||||
|       local function on_request(method) | ||||
|         if method == "doit" then | ||||
|           funcs.rpcnotify(cid, "headsup") | ||||
|           eq(true,received) | ||||
|           return "retval" | ||||
|         if method == 'doit' then | ||||
|           funcs.rpcnotify(cid, 'headsup') | ||||
|           eq(true, received) | ||||
|           return 'retval' | ||||
|         end | ||||
|       end | ||||
|       local function on_notification(method) | ||||
|         if method == "headsup" then | ||||
|         if method == 'headsup' then | ||||
|           received = true | ||||
|         end | ||||
|       end | ||||
| @@ -148,28 +148,28 @@ describe('server -> client', function() | ||||
|     -- of nvim's request stack). | ||||
|     pending('will close connection if not properly synchronized', function() | ||||
|       local function on_setup() | ||||
|         eq('notified!', eval('rpcrequest('..cid..', "notify")')) | ||||
|         eq('notified!', eval('rpcrequest(' .. cid .. ', "notify")')) | ||||
|       end | ||||
|  | ||||
|       local function on_request(method) | ||||
|         if method == "notify" then | ||||
|           eq(1, eval('rpcnotify('..cid..', "notification")')) | ||||
|         if method == 'notify' then | ||||
|           eq(1, eval('rpcnotify(' .. cid .. ', "notification")')) | ||||
|           return 'notified!' | ||||
|         elseif method == "nested" then | ||||
|         elseif method == 'nested' then | ||||
|           -- do some busywork, so the first request will return | ||||
|           -- before this one | ||||
|           for _ = 1, 5 do | ||||
|             assert_alive() | ||||
|           end | ||||
|           eq(1, eval('rpcnotify('..cid..', "nested_done")')) | ||||
|           eq(1, eval('rpcnotify(' .. cid .. ', "nested_done")')) | ||||
|           return 'done!' | ||||
|         end | ||||
|       end | ||||
|  | ||||
|       local function on_notification(method) | ||||
|         if method == "notification" then | ||||
|           eq('done!', eval('rpcrequest('..cid..', "nested")')) | ||||
|         elseif method == "nested_done" then | ||||
|         if method == 'notification' then | ||||
|           eq('done!', eval('rpcrequest(' .. cid .. ', "nested")')) | ||||
|         elseif method == 'nested_done' then | ||||
|           ok(false, 'never sent', 'sent') | ||||
|         end | ||||
|       end | ||||
| @@ -182,11 +182,17 @@ describe('server -> client', function() | ||||
|  | ||||
|   describe('recursive (child) nvim client', function() | ||||
|     before_each(function() | ||||
|       command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])") | ||||
|       command( | ||||
|         "let vim = rpcstart('" | ||||
|           .. nvim_prog | ||||
|           .. "', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])" | ||||
|       ) | ||||
|       neq(0, eval('vim')) | ||||
|     end) | ||||
|  | ||||
|     after_each(function() command('call rpcstop(vim)') end) | ||||
|     after_each(function() | ||||
|       command('call rpcstop(vim)') | ||||
|     end) | ||||
|  | ||||
|     it('can send/receive notifications and make requests', function() | ||||
|       nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')") | ||||
| @@ -198,25 +204,27 @@ describe('server -> client', function() | ||||
|     end) | ||||
|  | ||||
|     it('can communicate buffers, tabpages, and windows', function() | ||||
|       eq({1}, eval("rpcrequest(vim, 'nvim_list_tabpages')")) | ||||
|       eq({ 1 }, eval("rpcrequest(vim, 'nvim_list_tabpages')")) | ||||
|       -- Window IDs start at 1000 (LOWEST_WIN_ID in window.h) | ||||
|       eq({1000}, eval("rpcrequest(vim, 'nvim_list_wins')")) | ||||
|       eq({ 1000 }, eval("rpcrequest(vim, 'nvim_list_wins')")) | ||||
|  | ||||
|       local buf = eval("rpcrequest(vim, 'nvim_list_bufs')")[1] | ||||
|       eq(1, buf) | ||||
|  | ||||
|       eval("rpcnotify(vim, 'buffer_set_line', "..buf..", 0, 'SOME TEXT')") | ||||
|       eval("rpcnotify(vim, 'buffer_set_line', " .. buf .. ", 0, 'SOME TEXT')") | ||||
|       nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait | ||||
|  | ||||
|       eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', "..buf..", 0)")) | ||||
|       eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', " .. buf .. ', 0)')) | ||||
|  | ||||
|       -- Call get_lines(buf, range [0,0], strict_indexing) | ||||
|       eq({'SOME TEXT'}, eval("rpcrequest(vim, 'buffer_get_lines', "..buf..", 0, 1, 1)")) | ||||
|       eq({ 'SOME TEXT' }, eval("rpcrequest(vim, 'buffer_get_lines', " .. buf .. ', 0, 1, 1)')) | ||||
|     end) | ||||
|  | ||||
|     it('returns an error if the request failed', function() | ||||
|       eq("Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist", | ||||
|          pcall_err(eval, "rpcrequest(vim, 'does-not-exist')")) | ||||
|       eq( | ||||
|         "Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist", | ||||
|         pcall_err(eval, "rpcrequest(vim, 'does-not-exist')") | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -236,13 +244,14 @@ describe('server -> client', function() | ||||
|         \ 'rpc': v:true | ||||
|         \ } | ||||
|       ]]) | ||||
|       meths.set_var("args", { | ||||
|         nvim_prog, '-ll', | ||||
|       meths.set_var('args', { | ||||
|         nvim_prog, | ||||
|         '-ll', | ||||
|         'test/functional/api/rpc_fixture.lua', | ||||
|         package.path, | ||||
|         package.cpath, | ||||
|       }) | ||||
|       jobid = eval("jobstart(g:args, g:job_opts)") | ||||
|       jobid = eval('jobstart(g:args, g:job_opts)') | ||||
|       neq(0, jobid) | ||||
|     end) | ||||
|  | ||||
| @@ -250,7 +259,9 @@ describe('server -> client', function() | ||||
|       pcall(funcs.jobstop, jobid) | ||||
|     end) | ||||
|  | ||||
|     if helpers.skip(helpers.is_os('win')) then return end | ||||
|     if helpers.skip(helpers.is_os('win')) then | ||||
|       return | ||||
|     end | ||||
|  | ||||
|     it('rpc and text stderr can be combined', function() | ||||
|       local status, rv = pcall(funcs.rpcrequest, jobid, 'poll') | ||||
| @@ -258,18 +269,18 @@ describe('server -> client', function() | ||||
|         error(string.format('missing nvim Lua module? (%s)', rv)) | ||||
|       end | ||||
|       eq('ok', rv) | ||||
|       funcs.rpcnotify(jobid, "ping") | ||||
|       eq({'notification', 'pong', {}}, next_msg()) | ||||
|       eq("done!",funcs.rpcrequest(jobid, "write_stderr", "fluff\n")) | ||||
|       eq({'notification', 'stderr', {0, {'fluff', ''}}}, next_msg()) | ||||
|       pcall(funcs.rpcrequest, jobid, "exit") | ||||
|       eq({'notification', 'stderr', {0, {''}}}, next_msg()) | ||||
|       eq({'notification', 'exit', {0, 0}}, next_msg()) | ||||
|       funcs.rpcnotify(jobid, 'ping') | ||||
|       eq({ 'notification', 'pong', {} }, next_msg()) | ||||
|       eq('done!', funcs.rpcrequest(jobid, 'write_stderr', 'fluff\n')) | ||||
|       eq({ 'notification', 'stderr', { 0, { 'fluff', '' } } }, next_msg()) | ||||
|       pcall(funcs.rpcrequest, jobid, 'exit') | ||||
|       eq({ 'notification', 'stderr', { 0, { '' } } }, next_msg()) | ||||
|       eq({ 'notification', 'exit', { 0, 0 } }, next_msg()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   describe('connecting to another (peer) nvim', function() | ||||
|     local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'}) | ||||
|     local nvim_argv = merge_args(helpers.nvim_argv, { '--headless' }) | ||||
|     local function connect_test(server, mode, address) | ||||
|       local serverpid = funcs.getpid() | ||||
|       local client = spawn(nvim_argv, false, nil, true) | ||||
| @@ -277,7 +288,7 @@ describe('server -> client', function() | ||||
|  | ||||
|       local clientpid = funcs.getpid() | ||||
|       neq(serverpid, clientpid) | ||||
|       local id = funcs.sockconnect(mode, address, {rpc=true}) | ||||
|       local id = funcs.sockconnect(mode, address, { rpc = true }) | ||||
|       ok(id > 0) | ||||
|  | ||||
|       funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') | ||||
| @@ -303,7 +314,7 @@ describe('server -> client', function() | ||||
|       local server = spawn(nvim_argv) | ||||
|       set_session(server) | ||||
|       local address = funcs.serverlist()[1] | ||||
|       local first = string.sub(address,1,1) | ||||
|       local first = string.sub(address, 1, 1) | ||||
|       ok(first == '/' or first == '\\') | ||||
|       connect_test(server, 'pipe', address) | ||||
|     end) | ||||
| @@ -311,11 +322,11 @@ describe('server -> client', function() | ||||
|     it('via ipv4 address', function() | ||||
|       local server = spawn(nvim_argv) | ||||
|       set_session(server) | ||||
|       local status, address = pcall(funcs.serverstart, "127.0.0.1:") | ||||
|       local status, address = pcall(funcs.serverstart, '127.0.0.1:') | ||||
|       if not status then | ||||
|         pending('no ipv4 stack') | ||||
|       end | ||||
|       eq('127.0.0.1:', string.sub(address,1,10)) | ||||
|       eq('127.0.0.1:', string.sub(address, 1, 10)) | ||||
|       connect_test(server, 'tcp', address) | ||||
|     end) | ||||
|  | ||||
| @@ -326,15 +337,15 @@ describe('server -> client', function() | ||||
|       if not status then | ||||
|         pending('no ipv6 stack') | ||||
|       end | ||||
|       eq('::1:', string.sub(address,1,4)) | ||||
|       eq('::1:', string.sub(address, 1, 4)) | ||||
|       connect_test(server, 'tcp', address) | ||||
|     end) | ||||
|  | ||||
|     it('via hostname', function() | ||||
|       local server = spawn(nvim_argv) | ||||
|       set_session(server) | ||||
|       local address = funcs.serverstart("localhost:") | ||||
|       eq('localhost:', string.sub(address,1,10)) | ||||
|       local address = funcs.serverstart('localhost:') | ||||
|       eq('localhost:', string.sub(address, 1, 10)) | ||||
|       connect_test(server, 'tcp', address) | ||||
|     end) | ||||
|  | ||||
| @@ -345,7 +356,7 @@ describe('server -> client', function() | ||||
|       local client = spawn(nvim_argv, false, nil, true) | ||||
|       set_session(client) | ||||
|  | ||||
|       local id = funcs.sockconnect('pipe', address, {rpc=true}) | ||||
|       local id = funcs.sockconnect('pipe', address, { rpc = true }) | ||||
|       funcs.rpcrequest(id, 'nvim_ui_attach', 80, 24, {}) | ||||
|       assert_alive() | ||||
|  | ||||
| @@ -357,15 +368,15 @@ describe('server -> client', function() | ||||
|   describe('connecting to its own pipe address', function() | ||||
|     it('does not deadlock', function() | ||||
|       local address = funcs.serverlist()[1] | ||||
|       local first = string.sub(address,1,1) | ||||
|       local first = string.sub(address, 1, 1) | ||||
|       ok(first == '/' or first == '\\') | ||||
|       local serverpid = funcs.getpid() | ||||
|  | ||||
|       local id = funcs.sockconnect('pipe', address, {rpc=true}) | ||||
|       local id = funcs.sockconnect('pipe', address, { rpc = true }) | ||||
|  | ||||
|       funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') | ||||
|       eq('hello', meths.get_current_line()) | ||||
|       eq(serverpid, funcs.rpcrequest(id, "nvim_eval", "getpid()")) | ||||
|       eq(serverpid, funcs.rpcrequest(id, 'nvim_eval', 'getpid()')) | ||||
|  | ||||
|       eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1]) | ||||
|     end) | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local clear, nvim, tabpage, curtab, eq, ok = | ||||
|   helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, | ||||
|   helpers.ok | ||||
|   helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, helpers.ok | ||||
| local curtabmeths = helpers.curtabmeths | ||||
| local funcs = helpers.funcs | ||||
| local request = helpers.request | ||||
| @@ -18,8 +17,8 @@ describe('api/tabpage', function() | ||||
|       nvim('command', 'vsplit') | ||||
|       local tab1, tab2 = unpack(nvim('list_tabpages')) | ||||
|       local win1, win2, win3 = unpack(nvim('list_wins')) | ||||
|       eq({win1},  tabpage('list_wins', tab1)) | ||||
|       eq({win2, win3},  tabpage('list_wins', tab2)) | ||||
|       eq({ win1 }, tabpage('list_wins', tab1)) | ||||
|       eq({ win2, win3 }, tabpage('list_wins', tab2)) | ||||
|       eq(win2, tabpage('get_win', tab2)) | ||||
|       nvim('set_current_win', win3) | ||||
|       eq(win3, tabpage('get_win', tab2)) | ||||
| @@ -32,9 +31,9 @@ describe('api/tabpage', function() | ||||
|  | ||||
|   describe('{get,set,del}_var', function() | ||||
|     it('works', function() | ||||
|       curtab('set_var', 'lua', {1, 2, {['3'] = 1}}) | ||||
|       eq({1, 2, {['3'] = 1}}, curtab('get_var', 'lua')) | ||||
|       eq({1, 2, {['3'] = 1}}, nvim('eval', 't:lua')) | ||||
|       curtab('set_var', 'lua', { 1, 2, { ['3'] = 1 } }) | ||||
|       eq({ 1, 2, { ['3'] = 1 } }, curtab('get_var', 'lua')) | ||||
|       eq({ 1, 2, { ['3'] = 1 } }, nvim('eval', 't:lua')) | ||||
|       eq(1, funcs.exists('t:lua')) | ||||
|       curtabmeths.del_var('lua') | ||||
|       eq(0, funcs.exists('t:lua')) | ||||
| @@ -46,15 +45,15 @@ describe('api/tabpage', function() | ||||
|     end) | ||||
|  | ||||
|     it('tabpage_set_var returns the old value', function() | ||||
|       local val1 = {1, 2, {['3'] = 1}} | ||||
|       local val2 = {4, 7} | ||||
|       local val1 = { 1, 2, { ['3'] = 1 } } | ||||
|       local val2 = { 4, 7 } | ||||
|       eq(NIL, request('tabpage_set_var', 0, 'lua', val1)) | ||||
|       eq(val1, request('tabpage_set_var', 0, 'lua', val2)) | ||||
|     end) | ||||
|  | ||||
|     it('tabpage_del_var returns the old value', function() | ||||
|       local val1 = {1, 2, {['3'] = 1}} | ||||
|       local val2 = {4, 7} | ||||
|       local val1 = { 1, 2, { ['3'] = 1 } } | ||||
|       local val2 = { 4, 7 } | ||||
|       eq(NIL, request('tabpage_set_var', 0, 'lua', val1)) | ||||
|       eq(val1, request('tabpage_set_var', 0, 'lua', val2)) | ||||
|       eq(val2, request('tabpage_del_var', 0, 'lua')) | ||||
|   | ||||
| @@ -23,42 +23,56 @@ describe('nvim_ui_attach()', function() | ||||
|   end) | ||||
|  | ||||
|   it('validation', function() | ||||
|     eq('No such UI option: foo', | ||||
|       pcall_err(meths.ui_attach, 80, 24, { foo={'foo'} })) | ||||
|     eq('No such UI option: foo', pcall_err(meths.ui_attach, 80, 24, { foo = { 'foo' } })) | ||||
|  | ||||
|     eq("Invalid 'ext_linegrid': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { ext_linegrid={} })) | ||||
|     eq("Invalid 'override': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { override={} })) | ||||
|     eq("Invalid 'rgb': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { rgb={} })) | ||||
|     eq("Invalid 'term_name': expected String, got Boolean", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { term_name=true })) | ||||
|     eq("Invalid 'term_colors': expected Integer, got Boolean", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { term_colors=true })) | ||||
|     eq("Invalid 'stdin_fd': expected Integer, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdin_fd='foo' })) | ||||
|     eq("Invalid 'stdin_tty': expected Boolean, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdin_tty='foo' })) | ||||
|     eq("Invalid 'stdout_tty': expected Boolean, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdout_tty='foo' })) | ||||
|     eq( | ||||
|       "Invalid 'ext_linegrid': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { ext_linegrid = {} }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'override': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { override = {} }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'rgb': expected Boolean, got Array", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { rgb = {} }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'term_name': expected String, got Boolean", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { term_name = true }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'term_colors': expected Integer, got Boolean", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { term_colors = true }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'stdin_fd': expected Integer, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdin_fd = 'foo' }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'stdin_tty': expected Boolean, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdin_tty = 'foo' }) | ||||
|     ) | ||||
|     eq( | ||||
|       "Invalid 'stdout_tty': expected Boolean, got String", | ||||
|       pcall_err(meths.ui_attach, 80, 24, { stdout_tty = 'foo' }) | ||||
|     ) | ||||
|  | ||||
|     eq('UI not attached to channel: 1', | ||||
|       pcall_err(request, 'nvim_ui_try_resize', 40, 10)) | ||||
|     eq('UI not attached to channel: 1', | ||||
|       pcall_err(request, 'nvim_ui_set_option', 'rgb', true)) | ||||
|     eq('UI not attached to channel: 1', | ||||
|       pcall_err(request, 'nvim_ui_detach')) | ||||
|     eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_try_resize', 40, 10)) | ||||
|     eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_set_option', 'rgb', true)) | ||||
|     eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_detach')) | ||||
|  | ||||
|     local screen = Screen.new() | ||||
|     screen:attach({rgb=false}) | ||||
|     eq('UI already attached to channel: 1', | ||||
|       pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb=false })) | ||||
|     screen:attach({ rgb = false }) | ||||
|     eq( | ||||
|       'UI already attached to channel: 1', | ||||
|       pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false }) | ||||
|     ) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| it('autocmds UIEnter/UILeave', function() | ||||
|   clear{args_rm={'--headless'}} | ||||
|   clear { args_rm = { '--headless' } } | ||||
|   exec([[ | ||||
|     let g:evs = [] | ||||
|     autocmd UIEnter * call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event) | ||||
| @@ -67,9 +81,9 @@ it('autocmds UIEnter/UILeave', function() | ||||
|   ]]) | ||||
|   local screen = Screen.new() | ||||
|   screen:attach() | ||||
|   eq({chan=1}, eval('g:uienter_ev')) | ||||
|   eq({ chan = 1 }, eval('g:uienter_ev')) | ||||
|   screen:detach() | ||||
|   eq({chan=1}, eval('g:uileave_ev')) | ||||
|   eq({ chan = 1 }, eval('g:uileave_ev')) | ||||
|   eq({ | ||||
|     'VimEnter', | ||||
|     'UIEnter', | ||||
| @@ -89,21 +103,27 @@ it('autocmds VimSuspend/VimResume #22041', function() | ||||
|  | ||||
|   eq(false, screen.suspended) | ||||
|   feed('<C-Z>') | ||||
|   screen:expect(function() eq(true, screen.suspended) end) | ||||
|   screen:expect(function() | ||||
|     eq(true, screen.suspended) | ||||
|   end) | ||||
|   eq({ 's' }, eval('g:ev')) | ||||
|   screen.suspended = false | ||||
|   feed('<Ignore>') | ||||
|   eq({ 's', 'r' }, eval('g:ev')) | ||||
|  | ||||
|   command('suspend') | ||||
|   screen:expect(function() eq(true, screen.suspended) end) | ||||
|   screen:expect(function() | ||||
|     eq(true, screen.suspended) | ||||
|   end) | ||||
|   eq({ 's', 'r', 's' }, eval('g:ev')) | ||||
|   screen.suspended = false | ||||
|   meths.input_mouse('move', '', '', 0, 0, 0) | ||||
|   eq({ 's', 'r', 's', 'r' }, eval('g:ev')) | ||||
|  | ||||
|   feed('<C-Z><C-Z><C-Z>') | ||||
|   screen:expect(function() eq(true, screen.suspended) end) | ||||
|   screen:expect(function() | ||||
|     eq(true, screen.suspended) | ||||
|   end) | ||||
|   meths.ui_set_focus(false) | ||||
|   eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev')) | ||||
|   screen.suspended = false | ||||
| @@ -111,7 +131,9 @@ it('autocmds VimSuspend/VimResume #22041', function() | ||||
|   eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev')) | ||||
|  | ||||
|   command('suspend | suspend | suspend') | ||||
|   screen:expect(function() eq(true, screen.suspended) end) | ||||
|   screen:expect(function() | ||||
|     eq(true, screen.suspended) | ||||
|   end) | ||||
|   screen:detach() | ||||
|   eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev')) | ||||
|   screen.suspended = false | ||||
|   | ||||
| @@ -19,41 +19,40 @@ end | ||||
| describe("api_info()['version']", function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   it("returns API level", function() | ||||
|   it('returns API level', function() | ||||
|     local version = call('api_info')['version'] | ||||
|     local current = version['api_level'] | ||||
|     local compat = version['api_compatible'] | ||||
|     eq("number", type(current)) | ||||
|     eq("number", type(compat)) | ||||
|     eq('number', type(current)) | ||||
|     eq('number', type(compat)) | ||||
|     assert(current >= compat) | ||||
|   end) | ||||
|  | ||||
|   it("returns Nvim version", function() | ||||
|   it('returns Nvim version', function() | ||||
|     local version = call('api_info')['version'] | ||||
|     local major = version['major'] | ||||
|     local minor = version['minor'] | ||||
|     local patch = version['patch'] | ||||
|     local prerelease = version['prerelease'] | ||||
|     local build = version['build'] | ||||
|     eq("number", type(major)) | ||||
|     eq("number", type(minor)) | ||||
|     eq("number", type(patch)) | ||||
|     eq("boolean", type(prerelease)) | ||||
|     eq(1, funcs.has("nvim-"..major.."."..minor.."."..patch)) | ||||
|     eq(0, funcs.has("nvim-"..major.."."..minor.."."..(patch + 1))) | ||||
|     eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch)) | ||||
|     eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch)) | ||||
|     eq('number', type(major)) | ||||
|     eq('number', type(minor)) | ||||
|     eq('number', type(patch)) | ||||
|     eq('boolean', type(prerelease)) | ||||
|     eq(1, funcs.has('nvim-' .. major .. '.' .. minor .. '.' .. patch)) | ||||
|     eq(0, funcs.has('nvim-' .. major .. '.' .. minor .. '.' .. (patch + 1))) | ||||
|     eq(0, funcs.has('nvim-' .. major .. '.' .. (minor + 1) .. '.' .. patch)) | ||||
|     eq(0, funcs.has('nvim-' .. (major + 1) .. '.' .. minor .. '.' .. patch)) | ||||
|     assert(build == nil or type(build) == 'string') | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|  | ||||
| describe("api metadata", function() | ||||
| describe('api metadata', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   local function name_table(entries) | ||||
|     local by_name = {} | ||||
|     for _,e in ipairs(entries) do | ||||
|     for _, e in ipairs(entries) do | ||||
|       by_name[e.name] = e | ||||
|     end | ||||
|     return by_name | ||||
| @@ -66,7 +65,7 @@ describe("api metadata", function() | ||||
|       f.parameters[idx][2] = '' -- Remove parameter name. | ||||
|     end | ||||
|  | ||||
|     if string.sub(f.name, 1, 4) ~= "nvim" then | ||||
|     if string.sub(f.name, 1, 4) ~= 'nvim' then | ||||
|       f.method = nil | ||||
|     end | ||||
|     return f | ||||
| @@ -76,7 +75,7 @@ describe("api metadata", function() | ||||
|     -- check types of existing params are the same | ||||
|     -- adding parameters is ok, but removing params is not (gives nil error) | ||||
|     eq(old_e.since, new_e.since, old_e.name) | ||||
|     for i,p in ipairs(old_e.parameters) do | ||||
|     for i, p in ipairs(old_e.parameters) do | ||||
|       eq(new_e.parameters[i][1], p[1], old_e.name) | ||||
|     end | ||||
|   end | ||||
| @@ -100,20 +99,22 @@ describe("api metadata", function() | ||||
|     compat = api.version.api_compatible | ||||
|     api_level = api.version.api_level | ||||
|     if api.version.api_prerelease then | ||||
|       stable = api_level-1 | ||||
|       stable = api_level - 1 | ||||
|     else | ||||
|       stable = api_level | ||||
|     end | ||||
|  | ||||
|     for level = compat, stable do | ||||
|       local path = ('test/functional/fixtures/api_level_'.. | ||||
|                    tostring(level)..'.mpack') | ||||
|       local path = ('test/functional/fixtures/api_level_' .. tostring(level) .. '.mpack') | ||||
|       old_api[level] = read_mpack_file(path) | ||||
|       if old_api[level] == nil then | ||||
|         local errstr = "missing metadata fixture for stable level "..level..". " | ||||
|         local errstr = 'missing metadata fixture for stable level ' .. level .. '. ' | ||||
|         if level == api_level and not api.version.api_prerelease then | ||||
|           errstr = (errstr.."If NVIM_API_CURRENT was bumped, ".. | ||||
|                     "don't forget to set NVIM_API_PRERELEASE to true.") | ||||
|           errstr = ( | ||||
|             errstr | ||||
|             .. 'If NVIM_API_CURRENT was bumped, ' | ||||
|             .. "don't forget to set NVIM_API_PRERELEASE to true." | ||||
|           ) | ||||
|         end | ||||
|         error(errstr) | ||||
|       end | ||||
| @@ -124,60 +125,76 @@ describe("api metadata", function() | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   it("functions are compatible with old metadata or have new level", function() | ||||
|   it('functions are compatible with old metadata or have new level', function() | ||||
|     local funcs_new = name_table(api.functions) | ||||
|     local funcs_compat = {} | ||||
|     for level = compat, stable do | ||||
|       for _,f in ipairs(old_api[level].functions) do | ||||
|       for _, f in ipairs(old_api[level].functions) do | ||||
|         if funcs_new[f.name] == nil then | ||||
|           if f.since >= compat then | ||||
|             error('function '..f.name..' was removed but exists in level '.. | ||||
|                   f.since..' which nvim should be compatible with') | ||||
|             error( | ||||
|               'function ' | ||||
|                 .. f.name | ||||
|                 .. ' was removed but exists in level ' | ||||
|                 .. f.since | ||||
|                 .. ' which nvim should be compatible with' | ||||
|             ) | ||||
|           end | ||||
|         else | ||||
|           eq(filter_function_metadata(f), | ||||
|              filter_function_metadata(funcs_new[f.name])) | ||||
|           eq(filter_function_metadata(f), filter_function_metadata(funcs_new[f.name])) | ||||
|         end | ||||
|       end | ||||
|       funcs_compat[level] = name_table(old_api[level].functions) | ||||
|     end | ||||
|  | ||||
|     for _,f in ipairs(api.functions) do | ||||
|     for _, f in ipairs(api.functions) do | ||||
|       if f.since <= stable then | ||||
|         local f_old = funcs_compat[f.since][f.name] | ||||
|         if f_old == nil then | ||||
|           if string.sub(f.name, 1, 4) == "nvim" then | ||||
|             local errstr = ("function "..f.name.." has too low since value. ".. | ||||
|                             "For new functions set it to "..(stable+1)..".") | ||||
|           if string.sub(f.name, 1, 4) == 'nvim' then | ||||
|             local errstr = ( | ||||
|               'function ' | ||||
|               .. f.name | ||||
|               .. ' has too low since value. ' | ||||
|               .. 'For new functions set it to ' | ||||
|               .. (stable + 1) | ||||
|               .. '.' | ||||
|             ) | ||||
|             if not api.version.api_prerelease then | ||||
|               errstr = (errstr.." Also bump NVIM_API_CURRENT and set ".. | ||||
|                         "NVIM_API_PRERELEASE to true in CMakeLists.txt.") | ||||
|               errstr = ( | ||||
|                 errstr | ||||
|                 .. ' Also bump NVIM_API_CURRENT and set ' | ||||
|                 .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' | ||||
|               ) | ||||
|             end | ||||
|             error(errstr) | ||||
|           else | ||||
|             error("function name '"..f.name.."' doesn't begin with 'nvim_'") | ||||
|             error("function name '" .. f.name .. "' doesn't begin with 'nvim_'") | ||||
|           end | ||||
|         end | ||||
|       elseif f.since > api_level then | ||||
|         if api.version.api_prerelease then | ||||
|           error("New function "..f.name.." should use since value ".. | ||||
|                api_level) | ||||
|           error('New function ' .. f.name .. ' should use since value ' .. api_level) | ||||
|         else | ||||
|           error("function "..f.name.." has since value > api_level. ".. | ||||
|                "Bump NVIM_API_CURRENT and set ".. | ||||
|                "NVIM_API_PRERELEASE to true in CMakeLists.txt.") | ||||
|           error( | ||||
|             'function ' | ||||
|               .. f.name | ||||
|               .. ' has since value > api_level. ' | ||||
|               .. 'Bump NVIM_API_CURRENT and set ' | ||||
|               .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' | ||||
|           ) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   it("UI events are compatible with old metadata or have new level", function() | ||||
|   it('UI events are compatible with old metadata or have new level', function() | ||||
|     local ui_events_new = name_table(api.ui_events) | ||||
|     local ui_events_compat = {} | ||||
|  | ||||
|     -- UI events were formalized in level 3 | ||||
|     for level = 3, stable do | ||||
|       for _,e in ipairs(old_api[level].ui_events) do | ||||
|       for _, e in ipairs(old_api[level].ui_events) do | ||||
|         local new_e = ui_events_new[e.name] | ||||
|         if new_e ~= nil then | ||||
|           check_ui_event_compatible(e, new_e) | ||||
| @@ -186,32 +203,44 @@ describe("api metadata", function() | ||||
|       ui_events_compat[level] = name_table(old_api[level].ui_events) | ||||
|     end | ||||
|  | ||||
|     for _,e in ipairs(api.ui_events) do | ||||
|     for _, e in ipairs(api.ui_events) do | ||||
|       if e.since <= stable then | ||||
|         local e_old = ui_events_compat[e.since][e.name] | ||||
|         if e_old == nil then | ||||
|           local errstr = ("UI event "..e.name.." has too low since value. ".. | ||||
|                           "For new events set it to "..(stable+1)..".") | ||||
|           local errstr = ( | ||||
|             'UI event ' | ||||
|             .. e.name | ||||
|             .. ' has too low since value. ' | ||||
|             .. 'For new events set it to ' | ||||
|             .. (stable + 1) | ||||
|             .. '.' | ||||
|           ) | ||||
|           if not api.version.api_prerelease then | ||||
|             errstr = (errstr.." Also bump NVIM_API_CURRENT and set ".. | ||||
|                       "NVIM_API_PRERELEASE to true in CMakeLists.txt.") | ||||
|             errstr = ( | ||||
|               errstr | ||||
|               .. ' Also bump NVIM_API_CURRENT and set ' | ||||
|               .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' | ||||
|             ) | ||||
|           end | ||||
|           error(errstr) | ||||
|         end | ||||
|       elseif e.since > api_level then | ||||
|         if api.version.api_prerelease then | ||||
|           error("New UI event "..e.name.." should use since value ".. | ||||
|                api_level) | ||||
|           error('New UI event ' .. e.name .. ' should use since value ' .. api_level) | ||||
|         else | ||||
|           error("UI event "..e.name.." has since value > api_level. ".. | ||||
|                "Bump NVIM_API_CURRENT and set ".. | ||||
|                "NVIM_API_PRERELEASE to true in CMakeLists.txt.") | ||||
|           error( | ||||
|             'UI event ' | ||||
|               .. e.name | ||||
|               .. ' has since value > api_level. ' | ||||
|               .. 'Bump NVIM_API_CURRENT and set ' | ||||
|               .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' | ||||
|           ) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   it("ui_options are preserved from older levels", function() | ||||
|   it('ui_options are preserved from older levels', function() | ||||
|     local available_options = {} | ||||
|     for _, option in ipairs(api.ui_options) do | ||||
|       available_options[option] = true | ||||
| @@ -220,7 +249,7 @@ describe("api metadata", function() | ||||
|     for level = 4, stable do | ||||
|       for _, option in ipairs(old_api[level].ui_options) do | ||||
|         if not available_options[option] then | ||||
|           error("UI option "..option.." from stable metadata is missing") | ||||
|           error('UI option ' .. option .. ' from stable metadata is missing') | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -12,7 +12,7 @@ describe('oldtests', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   local exec_lines = function(str) | ||||
|     return funcs.split(funcs.execute(str), "\n") | ||||
|     return funcs.split(funcs.execute(str), '\n') | ||||
|   end | ||||
|  | ||||
|   local add_an_autocmd = function() | ||||
| @@ -38,7 +38,6 @@ describe('oldtests', function() | ||||
|     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 ]] | ||||
| @@ -50,8 +49,8 @@ describe('oldtests', function() | ||||
|   end) | ||||
|  | ||||
|   it('should fire on unload buf', function() | ||||
|     funcs.writefile({'Test file Xxx1'}, 'Xxx1') | ||||
|     funcs.writefile({'Test file Xxx2'}, 'Xxx2') | ||||
|     funcs.writefile({ 'Test file Xxx1' }, 'Xxx1') | ||||
|     funcs.writefile({ 'Test file Xxx2' }, 'Xxx2') | ||||
|     local fname = 'Xtest_functional_autocmd_unload' | ||||
|  | ||||
|     local content = [[ | ||||
| @@ -72,7 +71,7 @@ describe('oldtests', function() | ||||
|       q | ||||
|     ]] | ||||
|  | ||||
|     funcs.writefile(funcs.split(content, "\n"), fname) | ||||
|     funcs.writefile(funcs.split(content, '\n'), fname) | ||||
|  | ||||
|     funcs.delete('Xout') | ||||
|     funcs.system(string.format('%s --clean -N -S %s', meths.get_vvar('progpath'), fname)) | ||||
| @@ -89,7 +88,7 @@ describe('oldtests', function() | ||||
|     local screen = Screen.new(75, 10) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {background = Screen.colors.Cyan}; | ||||
|       [1] = { background = Screen.colors.Cyan }, | ||||
|     }) | ||||
|     exec([[ | ||||
|       set noshowcmd noruler scrolloff=0 | ||||
| @@ -97,7 +96,8 @@ describe('oldtests', function() | ||||
|       edit test/old/testdir/samples/box.txt | ||||
|     ]]) | ||||
|     feed('249GV<C-End>d') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|               const auto themeEmoji = _forPeer->themeEmoji();                    | | ||||
|               if (themeEmoji.isEmpty()) {                                        | | ||||
|                       return nonCustom;                                          | | ||||
| @@ -108,9 +108,11 @@ describe('oldtests', function() | ||||
|                       return nonCustom;                                          | | ||||
|               {1:^}}                                                                  | | ||||
|       353 fewer lines                                                            | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed('<PageUp>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|                                                                                  | | ||||
|       auto BackgroundBox::Inner::resolveResetCustomPaper() const                 | | ||||
|       -> std::optional<Data::WallPaper> {                                        | | ||||
| @@ -121,6 +123,7 @@ describe('oldtests', function() | ||||
|               const auto themeEmoji = _forPeer->themeEmoji();                    | | ||||
|               ^if (themeEmoji.isEmpty()) {                                        | | ||||
|       353 fewer lines                                                            | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -26,23 +26,23 @@ describe('autocmd', function() | ||||
|  | ||||
|   it(':tabnew, :split, :close events order, <afile>', function() | ||||
|     local expected = { | ||||
|       {'WinLeave', ''}, | ||||
|       {'TabLeave', ''}, | ||||
|       {'WinEnter', ''}, | ||||
|       {'TabNew', 'testfile1'},    -- :tabnew | ||||
|       {'TabEnter', ''}, | ||||
|       {'BufLeave', ''}, | ||||
|       {'BufEnter', 'testfile1'},  -- :split | ||||
|       {'WinLeave', 'testfile1'}, | ||||
|       {'WinEnter', 'testfile1'}, | ||||
|       {'WinLeave', 'testfile1'}, | ||||
|       {'WinClosed', '1002'},      -- :close, WinClosed <afile> = window-id | ||||
|       {'WinEnter', 'testfile1'}, | ||||
|       {'WinLeave', 'testfile1'},  -- :bdelete | ||||
|       {'WinEnter', 'testfile1'}, | ||||
|       {'BufLeave', 'testfile1'}, | ||||
|       {'BufEnter', 'testfile2'}, | ||||
|       {'WinClosed', '1000'}, | ||||
|       { 'WinLeave', '' }, | ||||
|       { 'TabLeave', '' }, | ||||
|       { 'WinEnter', '' }, | ||||
|       { 'TabNew', 'testfile1' }, -- :tabnew | ||||
|       { 'TabEnter', '' }, | ||||
|       { 'BufLeave', '' }, | ||||
|       { 'BufEnter', 'testfile1' }, -- :split | ||||
|       { 'WinLeave', 'testfile1' }, | ||||
|       { 'WinEnter', 'testfile1' }, | ||||
|       { 'WinLeave', 'testfile1' }, | ||||
|       { 'WinClosed', '1002' }, -- :close, WinClosed <afile> = window-id | ||||
|       { 'WinEnter', 'testfile1' }, | ||||
|       { 'WinLeave', 'testfile1' }, -- :bdelete | ||||
|       { 'WinEnter', 'testfile1' }, | ||||
|       { 'BufLeave', 'testfile1' }, | ||||
|       { 'BufEnter', 'testfile2' }, | ||||
|       { 'WinClosed', '1000' }, | ||||
|     } | ||||
|     command('let g:evs = []') | ||||
|     command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])') | ||||
| @@ -63,10 +63,10 @@ describe('autocmd', function() | ||||
|  | ||||
|   it('first edit causes BufUnload on NoName', function() | ||||
|     local expected = { | ||||
|       {'BufUnload', ''}, | ||||
|       {'BufDelete', ''}, | ||||
|       {'BufWipeout', ''}, | ||||
|       {'BufEnter', 'testfile1'}, | ||||
|       { 'BufUnload', '' }, | ||||
|       { 'BufDelete', '' }, | ||||
|       { 'BufWipeout', '' }, | ||||
|       { 'BufEnter', 'testfile1' }, | ||||
|     } | ||||
|     command('let g:evs = []') | ||||
|     command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])') | ||||
| @@ -106,20 +106,23 @@ describe('autocmd', function() | ||||
|     local buf1 = eval("bufnr('%')") | ||||
|     command('new') | ||||
|     local buf2 = eval("bufnr('%')") | ||||
|     command('autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])' | ||||
|     command( | ||||
|       'autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])' | ||||
|         -- Attempt recursion. | ||||
|       ..' | bdelete '..buf2) | ||||
|         .. ' | bdelete ' | ||||
|         .. buf2 | ||||
|     ) | ||||
|     command('tabedit testfile2') | ||||
|     command('tabedit testfile3') | ||||
|     command('bdelete '..buf2) | ||||
|     command('bdelete ' .. buf2) | ||||
|     -- Non-recursive: only triggered once. | ||||
|     eq({ | ||||
|       {'WinClosed', '2'}, | ||||
|       { 'WinClosed', '2' }, | ||||
|     }, eval('g:evs')) | ||||
|     command('bdelete '..buf1) | ||||
|     command('bdelete ' .. buf1) | ||||
|     eq({ | ||||
|       {'WinClosed', '2'}, | ||||
|       {'WinClosed', '1'}, | ||||
|       { 'WinClosed', '2' }, | ||||
|       { 'WinClosed', '1' }, | ||||
|     }, eval('g:evs')) | ||||
|   end) | ||||
|  | ||||
| @@ -130,7 +133,7 @@ describe('autocmd', function() | ||||
|     command('new') | ||||
|     command('close') | ||||
|     eq({ | ||||
|       {'WinClosed', '1001'}, | ||||
|       { 'WinClosed', '1001' }, | ||||
|     }, eval('g:evs')) | ||||
|   end) | ||||
|  | ||||
| @@ -139,16 +142,15 @@ describe('autocmd', function() | ||||
|   end) | ||||
|  | ||||
|   describe('BufLeave autocommand', function() | ||||
|     it('can wipe out the buffer created by :edit which triggered autocmd', | ||||
|     function() | ||||
|     it('can wipe out the buffer created by :edit which triggered autocmd', function() | ||||
|       meths.set_option_value('hidden', true, {}) | ||||
|       curbufmeths.set_lines(0, 1, false, { | ||||
|         'start of test file xx', | ||||
|         'end of test file xx'}) | ||||
|         'end of test file xx', | ||||
|       }) | ||||
|  | ||||
|       command('autocmd BufLeave * bwipeout yy') | ||||
|       eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', | ||||
|          exc_exec('edit yy')) | ||||
|       eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy')) | ||||
|  | ||||
|       expect([[ | ||||
|         start of test file xx | ||||
| @@ -177,7 +179,8 @@ describe('autocmd', function() | ||||
|     command('autocmd TabNew * ++once :call add(g:foo, "Once2")') | ||||
|     command('autocmd TabNew * :call add(g:foo, "Many2")') | ||||
|     command('autocmd TabNew * ++once :call add(g:foo, "Once3")') | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|        --- Autocommands --- | ||||
|        TabNew | ||||
| @@ -186,18 +189,21 @@ describe('autocmd', function() | ||||
|                      :call add(g:foo, "Once2") | ||||
|                      :call add(g:foo, "Many2") | ||||
|                      :call add(g:foo, "Once3")]]), | ||||
|        funcs.execute('autocmd Tabnew')) | ||||
|       funcs.execute('autocmd Tabnew') | ||||
|     ) | ||||
|     command('tabnew') | ||||
|     command('tabnew') | ||||
|     command('tabnew') | ||||
|     eq(expected, eval('g:foo')) | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|        --- Autocommands --- | ||||
|        TabNew | ||||
|            *         :call add(g:foo, "Many1") | ||||
|                      :call add(g:foo, "Many2")]]), | ||||
|        funcs.execute('autocmd Tabnew')) | ||||
|       funcs.execute('autocmd Tabnew') | ||||
|     ) | ||||
|  | ||||
|     -- | ||||
|     -- ":autocmd ... ++once" handlers can be deleted. | ||||
| @@ -218,7 +224,9 @@ describe('autocmd', function() | ||||
|     } | ||||
|     command('let g:foo = []') | ||||
|     command('autocmd OptionSet binary ++nested ++once :call add(g:foo, "OptionSet-Once")') | ||||
|     command('autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")') | ||||
|     command( | ||||
|       'autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")' | ||||
|     ) | ||||
|     command("put ='foo bar baz'") | ||||
|     feed('0llhlh') | ||||
|     eq(expected, eval('g:foo')) | ||||
| @@ -236,10 +244,12 @@ describe('autocmd', function() | ||||
|     command('autocmd TabNew * ++once :call add(g:foo, "Once2")') | ||||
|     command('tabnew') | ||||
|     eq(expected, eval('g:foo')) | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|        --- Autocommands ---]]), | ||||
|        funcs.execute('autocmd Tabnew')) | ||||
|       funcs.execute('autocmd Tabnew') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('internal `aucmd_win` window', function() | ||||
| @@ -250,9 +260,13 @@ describe('autocmd', function() | ||||
|     local screen = Screen.new(50, 10) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {background = Screen.colors.LightMagenta}, | ||||
|       [3] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { background = Screen.colors.LightMagenta }, | ||||
|       [3] = { | ||||
|         background = Screen.colors.LightMagenta, | ||||
|         bold = true, | ||||
|         foreground = Screen.colors.Blue1, | ||||
|       }, | ||||
|     }) | ||||
|  | ||||
|     source([[ | ||||
| @@ -276,7 +290,7 @@ describe('autocmd', function() | ||||
|                                                         | | ||||
|     ]]) | ||||
|  | ||||
|     feed(":enew | doautoall User<cr>") | ||||
|     feed(':enew | doautoall User<cr>') | ||||
|     screen:expect([[ | ||||
|       {2:bb                                                }| | ||||
|       {3:~                                                 }|*4 | ||||
| @@ -293,14 +307,16 @@ describe('autocmd', function() | ||||
|     eq(7, eval('g:test')) | ||||
|  | ||||
|     -- API calls are blocked when aucmd_win is not in scope | ||||
|     eq('Vim(call):E5555: API call: Invalid window id: 1001', | ||||
|       pcall_err(command, "call nvim_set_current_win(g:winid)")) | ||||
|     eq( | ||||
|       'Vim(call):E5555: API call: Invalid window id: 1001', | ||||
|       pcall_err(command, 'call nvim_set_current_win(g:winid)') | ||||
|     ) | ||||
|  | ||||
|     -- second time aucmd_win is needed, a different code path is invoked | ||||
|     -- to reuse the same window, so check again | ||||
|     command("let g:test = v:null") | ||||
|     command("let g:had_value = v:null") | ||||
|     feed(":doautoall User<cr>") | ||||
|     command('let g:test = v:null') | ||||
|     command('let g:had_value = v:null') | ||||
|     feed(':doautoall User<cr>') | ||||
|     screen:expect([[ | ||||
|       {2:bb                                                }| | ||||
|       {3:~                                                 }|*4 | ||||
| @@ -318,17 +334,19 @@ describe('autocmd', function() | ||||
|     eq(0, eval('g:had_value')) | ||||
|     eq(7, eval('g:test')) | ||||
|  | ||||
|     eq('Vim(call):E5555: API call: Invalid window id: 1001', | ||||
|       pcall_err(command, "call nvim_set_current_win(g:winid)")) | ||||
|     eq( | ||||
|       'Vim(call):E5555: API call: Invalid window id: 1001', | ||||
|       pcall_err(command, 'call nvim_set_current_win(g:winid)') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it("`aucmd_win` cannot be changed into a normal window #13699", function() | ||||
|   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}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { reverse = true }, | ||||
|       [3] = { bold = true, reverse = true }, | ||||
|     } | ||||
|  | ||||
|     -- Create specific layout and ensure it's left unchanged. | ||||
| @@ -371,13 +389,16 @@ describe('autocmd', function() | ||||
|  | ||||
|     -- 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 [[ | ||||
|     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) | ||||
|  | ||||
|   describe('closing last non-floating window in tab from `aucmd_win`', function() | ||||
| @@ -388,14 +409,18 @@ describe('autocmd', function() | ||||
|     end) | ||||
|  | ||||
|     it('gives E814 when there are no other floating windows', function() | ||||
|       eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain', | ||||
|          pcall_err(command, 'doautoall BufAdd')) | ||||
|       eq( | ||||
|         'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain', | ||||
|         pcall_err(command, 'doautoall BufAdd') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('gives E814 when there are other floating windows', function() | ||||
|       meths.open_win(0, true, {width = 10, height = 10, relative = 'editor', row = 10, col = 10}) | ||||
|       eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain', | ||||
|          pcall_err(command, 'doautoall BufAdd')) | ||||
|       meths.open_win(0, true, { width = 10, height = 10, relative = 'editor', row = 10, col = 10 }) | ||||
|       eq( | ||||
|         'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain', | ||||
|         pcall_err(command, 'doautoall BufAdd') | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -404,60 +429,88 @@ describe('autocmd', function() | ||||
|       vim.cmd('tabnew') | ||||
|       _G.buf = vim.api.nvim_create_buf(true, true) | ||||
|     ]]) | ||||
|     matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[ | ||||
|     matches( | ||||
|       'Vim:E813: Cannot close autocmd window$', | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_buf_call(_G.buf, function() | ||||
|         local win = vim.api.nvim_get_current_win() | ||||
|         vim.api.nvim_win_close(win, true) | ||||
|       end) | ||||
|     ]])) | ||||
|     matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     matches( | ||||
|       'Vim:E813: Cannot close autocmd window$', | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_buf_call(_G.buf, function() | ||||
|         local win = vim.api.nvim_get_current_win() | ||||
|         vim.cmd('tabnext') | ||||
|         vim.api.nvim_win_close(win, true) | ||||
|       end) | ||||
|     ]])) | ||||
|     matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     matches( | ||||
|       'Vim:E813: Cannot close autocmd window$', | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_buf_call(_G.buf, function() | ||||
|         local win = vim.api.nvim_get_current_win() | ||||
|         vim.api.nvim_win_hide(win) | ||||
|       end) | ||||
|     ]])) | ||||
|     matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[ | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|     matches( | ||||
|       'Vim:E813: Cannot close autocmd window$', | ||||
|       pcall_err( | ||||
|         exec_lua, | ||||
|         [[ | ||||
|       vim.api.nvim_buf_call(_G.buf, function() | ||||
|         local win = vim.api.nvim_get_current_win() | ||||
|         vim.cmd('tabnext') | ||||
|         vim.api.nvim_win_hide(win) | ||||
|       end) | ||||
|     ]])) | ||||
|     ]] | ||||
|       ) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it(':doautocmd does not warn "No matching autocommands" #10689', function() | ||||
|     local screen = Screen.new(32, 3) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|     }) | ||||
|  | ||||
|     feed(':doautocmd User Foo<cr>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       ^                                | | ||||
|       {1:~                               }| | ||||
|       :doautocmd User Foo             | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed(':autocmd! SessionLoadPost<cr>') | ||||
|     feed(':doautocmd SessionLoadPost<cr>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       ^                                | | ||||
|       {1:~                               }| | ||||
|       :doautocmd SessionLoadPost      | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
|  | ||||
|   describe('v:event is readonly #18063', function() | ||||
|     it('during ChanOpen event', function() | ||||
|       command('autocmd ChanOpen * let v:event.info.id = 0') | ||||
|       funcs.jobstart({'cat'}) | ||||
|       funcs.jobstart({ 'cat' }) | ||||
|       retry(nil, nil, function() | ||||
|         eq('E46: Cannot change read-only variable "v:event.info"', meths.get_vvar('errmsg')) | ||||
|       end) | ||||
| @@ -473,15 +526,19 @@ describe('autocmd', function() | ||||
|  | ||||
|     it('during RecordingLeave event', function() | ||||
|       command([[autocmd RecordingLeave * let v:event.regname = '']]) | ||||
|       eq('RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"', | ||||
|          pcall_err(command, 'normal! qqq')) | ||||
|       eq( | ||||
|         'RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"', | ||||
|         pcall_err(command, 'normal! qqq') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('during TermClose event', function() | ||||
|       command('autocmd TermClose * let v:event.status = 0') | ||||
|       command('terminal') | ||||
|       eq('TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"', | ||||
|          pcall_err(command, 'bdelete!')) | ||||
|       eq( | ||||
|         'TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"', | ||||
|         pcall_err(command, 'bdelete!') | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -549,9 +606,12 @@ describe('autocmd', function() | ||||
|       eq(0, funcs.exists('#WinNew')) | ||||
|  | ||||
|       -- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') | ||||
|       local ok, msg = pcall(source, [[ | ||||
|       local ok, msg = pcall( | ||||
|         source, | ||||
|         [[ | ||||
|         au WinNew * ++once ++once echo bad | ||||
|       ]]) | ||||
|       ]] | ||||
|       ) | ||||
|  | ||||
|       eq(false, ok) | ||||
|       eq(true, not not string.find(msg, 'E983:')) | ||||
| @@ -559,7 +619,7 @@ describe('autocmd', function() | ||||
|  | ||||
|     it('should have autocmds in filetypedetect group', function() | ||||
|       source [[filetype on]] | ||||
|       neq({}, meths.get_autocmds { group = "filetypedetect" }) | ||||
|       neq({}, meths.get_autocmds { group = 'filetypedetect' }) | ||||
|     end) | ||||
|  | ||||
|     it('should allow comma-separated patterns', function() | ||||
| @@ -571,7 +631,7 @@ describe('autocmd', function() | ||||
|         augroup END | ||||
|       ]] | ||||
|  | ||||
|       eq(4, #meths.get_autocmds { event = "BufReadCmd", group = "TestingPatterns" }) | ||||
|       eq(4, #meths.get_autocmds { event = 'BufReadCmd', group = 'TestingPatterns' }) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,7 @@ describe('autocmd BufEnter', function() | ||||
|  | ||||
|   it("triggered by nvim_command('edit <dir>')", function() | ||||
|     command("autocmd BufEnter * if isdirectory(expand('<afile>')) | let g:dir_bufenter = 1 | endif") | ||||
|     request("nvim_command", "split .") | ||||
|     request('nvim_command', 'split .') | ||||
|     eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory. | ||||
|     eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. | ||||
|   end) | ||||
| @@ -27,21 +27,20 @@ describe('autocmd BufEnter', function() | ||||
|         endtry | ||||
|       endfunction | ||||
|     ]]) | ||||
|     command("call Test()") | ||||
|     command('call Test()') | ||||
|     eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory. | ||||
|     eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. | ||||
|   end) | ||||
|  | ||||
|   it('triggered by ":split normal|:help|:bw"', function() | ||||
|     helpers.add_builddir_to_rtp() | ||||
|     command("split normal") | ||||
|     command("wincmd j") | ||||
|     command("help") | ||||
|     command("wincmd L") | ||||
|     command("autocmd BufEnter normal let g:bufentered = 1") | ||||
|     command("bw") | ||||
|     command('split normal') | ||||
|     command('wincmd j') | ||||
|     command('help') | ||||
|     command('wincmd L') | ||||
|     command('autocmd BufEnter normal let g:bufentered = 1') | ||||
|     command('bw') | ||||
|     eq(1, eval('bufnr("%")')) -- The cursor is back to the bottom window | ||||
|     eq(0, eval("exists('g:bufentered')")) -- The autocmd hasn't been triggered | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -14,9 +14,9 @@ describe('BufModified', function() | ||||
|     let g:modified = 0 | ||||
|     autocmd BufModifiedSet * let g:modified += 1 | ||||
|     ]]) | ||||
|     request("nvim_command", [[normal! aa\<Esc>]]) | ||||
|     request('nvim_command', [[normal! aa\<Esc>]]) | ||||
|     eq(1, eval('g:modified')) | ||||
|     request("nvim_command", [[normal! u]]) | ||||
|     request('nvim_command', [[normal! u]]) | ||||
|     eq(2, eval('g:modified')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -15,7 +15,7 @@ describe('cmdline autocommands', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     channel = meths.get_api_info()[1] | ||||
|     meths.set_var("channel",channel) | ||||
|     meths.set_var('channel', channel) | ||||
|     command("autocmd CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)") | ||||
|     command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)") | ||||
|     command("autocmd CmdWinEnter * call rpcnotify(g:channel, 'CmdWinEnter', v:event)") | ||||
| @@ -24,23 +24,27 @@ describe('cmdline autocommands', function() | ||||
|  | ||||
|   it('works', function() | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) | ||||
|     feed('redraw<cr>') | ||||
|     eq({'notification', 'CmdlineLeave', | ||||
|         {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|  | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) | ||||
|  | ||||
|     -- note: feed('bork<c-c>') might not consume 'bork' | ||||
|     -- due to out-of-band interrupt handling | ||||
|     feed('bork<esc>') | ||||
|     eq({'notification', 'CmdlineLeave', | ||||
|         {{cmdtype=':', cmdlevel=1, abort=true}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = true } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('can abort cmdline', function() | ||||
|     command("autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15") | ||||
|     command('autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15') | ||||
|     feed(":put! ='ok'<cr>") | ||||
|     expect([[ | ||||
|       ok | ||||
| @@ -57,10 +61,10 @@ describe('cmdline autocommands', function() | ||||
|     local screen = Screen.new(72, 8) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, | ||||
|       [3] = {bold = true, foreground = Screen.colors.SeaGreen4}, | ||||
|       [4] = {bold = true, reverse = true}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, | ||||
|       [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, | ||||
|       [4] = { bold = true, reverse = true }, | ||||
|     }) | ||||
|     command("autocmd CmdlineEnter * echoerr 'FAIL'") | ||||
|     command("autocmd CmdlineLeave * echoerr 'very error'") | ||||
| @@ -99,7 +103,7 @@ describe('cmdline autocommands', function() | ||||
|     command("autocmd CmdlineChanged * echoerr 'change erreor'") | ||||
|  | ||||
|     -- history recall still works | ||||
|     feed(":<c-p>") | ||||
|     feed(':<c-p>') | ||||
|     screen:expect([[ | ||||
|                                                                               | | ||||
|       lorem ipsum                                                             | | ||||
| @@ -111,7 +115,7 @@ describe('cmdline autocommands', function() | ||||
|       :put ='lorem ipsum'^                                                     | | ||||
|     ]]) | ||||
|  | ||||
|     feed("<left>") | ||||
|     feed('<left>') | ||||
|     screen:expect([[ | ||||
|                                                                               | | ||||
|       lorem ipsum                                                             | | ||||
| @@ -124,7 +128,7 @@ describe('cmdline autocommands', function() | ||||
|     ]]) | ||||
|  | ||||
|     -- edit still works | ||||
|     feed(".") | ||||
|     feed('.') | ||||
|     screen:expect([[ | ||||
|       {4:                                                                        }| | ||||
|       :                                                                       | | ||||
| @@ -161,62 +165,97 @@ describe('cmdline autocommands', function() | ||||
|  | ||||
|   it('works with nested cmdline', function() | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) | ||||
|     feed('<c-r>=') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg()) | ||||
|     feed('<c-f>') | ||||
|     eq({'notification', 'CmdWinEnter', {{}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdWinEnter', { {} } }, next_msg()) | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=3}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg()) | ||||
|     feed('<c-c>') | ||||
|     eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=3, abort=true}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 3, abort = true } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('<c-c>') | ||||
|     eq({'notification', 'CmdWinLeave', {{}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdWinLeave', { {} } }, next_msg()) | ||||
|     feed('1+2<cr>') | ||||
|     eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('no crash with recursive use of v:event #19484', function() | ||||
|     command('autocmd CmdlineEnter * normal :') | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) | ||||
|     feed('<CR>') | ||||
|     eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('supports CmdlineChanged' ,function() | ||||
|     command("autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())") | ||||
|   it('supports CmdlineChanged', function() | ||||
|     command( | ||||
|       "autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())" | ||||
|     ) | ||||
|     feed(':') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) | ||||
|     feed('l') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'l' } }, next_msg()) | ||||
|     feed('e') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'le' } }, next_msg()) | ||||
|     feed('t') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let' } }, next_msg()) | ||||
|     feed('<space>') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let ' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('x') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('<space>') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x ' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('=') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x =' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('<space>') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = ' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('<c-r>=') | ||||
|     eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg()) | ||||
|     feed('1') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1' } }, next_msg()) | ||||
|     feed('+') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+' } }, next_msg()) | ||||
|     feed('1') | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg()) | ||||
|     eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+1' } }, next_msg()) | ||||
|     feed('<cr>') | ||||
|     eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg()) | ||||
|     eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = 2' } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     feed('<cr>') | ||||
|     eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) | ||||
|     eq( | ||||
|       { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } }, | ||||
|       next_msg() | ||||
|     ) | ||||
|     eq(2, eval('x')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -44,10 +44,18 @@ describe('CursorHold', function() | ||||
|  | ||||
|     local ignore_key = meths.replace_termcodes('<Ignore>', true, true, true) | ||||
|     test_cursorhold(function() end, 1) | ||||
|     test_cursorhold(function() feed('') end, 1) | ||||
|     test_cursorhold(function() meths.feedkeys('', 'n', true) end, 1) | ||||
|     test_cursorhold(function() feed('<Ignore>') end, 0) | ||||
|     test_cursorhold(function() meths.feedkeys(ignore_key, 'n', true) end, 0) | ||||
|     test_cursorhold(function() | ||||
|       feed('') | ||||
|     end, 1) | ||||
|     test_cursorhold(function() | ||||
|       meths.feedkeys('', 'n', true) | ||||
|     end, 1) | ||||
|     test_cursorhold(function() | ||||
|       feed('<Ignore>') | ||||
|     end, 0) | ||||
|     test_cursorhold(function() | ||||
|       meths.feedkeys(ignore_key, 'n', true) | ||||
|     end, 0) | ||||
|   end) | ||||
|  | ||||
|   it("reducing 'updatetime' while waiting for CursorHold #20241", function() | ||||
|   | ||||
| @@ -19,9 +19,9 @@ describe('CursorMoved', function() | ||||
|     ]]) | ||||
|     eq({}, eval('g:log')) | ||||
|     command('new') | ||||
|     eq({'BufEnter2', 'CursorMoved2'}, eval('g:log')) | ||||
|     eq({ 'BufEnter2', 'CursorMoved2' }, eval('g:log')) | ||||
|     command('wincmd w') | ||||
|     eq({'BufEnter2', 'CursorMoved2', 'BufEnter1', 'CursorMoved1'}, eval('g:log')) | ||||
|     eq({ 'BufEnter2', 'CursorMoved2', 'BufEnter1', 'CursorMoved1' }, eval('g:log')) | ||||
|   end) | ||||
|  | ||||
|   it('is not triggered by temporarily switching window', function() | ||||
| @@ -41,13 +41,13 @@ describe('CursorMoved', function() | ||||
|       vsplit foo | ||||
|       autocmd CursorMoved * let g:cursormoved += 1 | ||||
|     ]]) | ||||
|     meths.buf_set_lines(eval('g:buf'), 0, -1, true, {'aaa'}) | ||||
|     meths.buf_set_lines(eval('g:buf'), 0, -1, true, { 'aaa' }) | ||||
|     eq(0, eval('g:cursormoved')) | ||||
|     eq({'aaa'}, meths.buf_get_lines(eval('g:buf'), 0, -1, true)) | ||||
|     eq({ 'aaa' }, meths.buf_get_lines(eval('g:buf'), 0, -1, true)) | ||||
|     eq(0, eval('g:cursormoved')) | ||||
|   end) | ||||
|  | ||||
|   it("is not triggered by cursor movement prior to first CursorMoved instantiation", function() | ||||
|   it('is not triggered by cursor movement prior to first CursorMoved instantiation', function() | ||||
|     source([[ | ||||
|       let g:cursormoved = 0 | ||||
|       autocmd! CursorMoved | ||||
|   | ||||
| @@ -21,41 +21,55 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3', | ||||
|   } | ||||
|  | ||||
|   setup(function()    for _, dir in pairs(dirs) do helpers.mkdir(dir) end end) | ||||
|   teardown(function() for _, dir in pairs(dirs) do helpers.rmdir(dir) end end) | ||||
|   setup(function() | ||||
|     for _, dir in pairs(dirs) do | ||||
|       helpers.mkdir(dir) | ||||
|     end | ||||
|   end) | ||||
|   teardown(function() | ||||
|     for _, dir in pairs(dirs) do | ||||
|       helpers.rmdir(dir) | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   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)]') | ||||
|     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)]' | ||||
|     ) | ||||
|     -- Normalize path separators. | ||||
|     command([[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]]) | ||||
|     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')]]) | ||||
|   end) | ||||
|  | ||||
|   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')) | ||||
|     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')) | ||||
|     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')) | ||||
|     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')) | ||||
| @@ -63,22 +77,22 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|   end) | ||||
|  | ||||
|   it('DirChanged set getcwd() during event #6260', function() | ||||
|     command('lcd '..dirs[1]) | ||||
|     command('lcd ' .. dirs[1]) | ||||
|     eq(dirs[1], eval('g:getcwd')) | ||||
|  | ||||
|     command('tcd '..dirs[2]) | ||||
|     command('tcd ' .. dirs[2]) | ||||
|     eq(dirs[2], eval('g:getcwd')) | ||||
|  | ||||
|     command('cd '..dirs[3]) | ||||
|     command('cd ' .. dirs[3]) | ||||
|     eq(dirs[3], eval('g:getcwd')) | ||||
|   end) | ||||
|  | ||||
|   it('disallow recursion', function() | ||||
|     command('set shellslash') | ||||
|     -- Set up a _nested_ handler. | ||||
|     command('autocmd DirChanged * nested lcd '..dirs[3]) | ||||
|     command('lcd '..dirs[1]) | ||||
|     eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev')) | ||||
|     command('autocmd DirChanged * nested lcd ' .. dirs[3]) | ||||
|     command('lcd ' .. dirs[1]) | ||||
|     eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev')) | ||||
|     eq(1, eval('g:cdcount')) | ||||
|     -- autocmd changed to dirs[3], but did NOT trigger another DirChanged. | ||||
|     eq(dirs[3], eval('getcwd()')) | ||||
| @@ -89,27 +103,36 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     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( | ||||
|       { 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( | ||||
|       { 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( | ||||
|       { 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')) | ||||
| @@ -119,93 +142,93 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     eq(false, status2) | ||||
|     eq(false, status3) | ||||
|  | ||||
|     eq('E344:', string.match(err1, "E%d*:")) | ||||
|     eq('E344:', string.match(err2, "E%d*:")) | ||||
|     eq('E344:', string.match(err3, "E%d*:")) | ||||
|     eq('E344:', string.match(err1, 'E%d*:')) | ||||
|     eq('E344:', string.match(err2, 'E%d*:')) | ||||
|     eq('E344:', string.match(err3, 'E%d*:')) | ||||
|   end) | ||||
|  | ||||
|   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')) | ||||
|     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')) | ||||
|     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('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')) | ||||
|     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]) | ||||
|     command('lcd ' .. dirs[1]) | ||||
|     eq({}, eval('g:evpre')) | ||||
|     eq({}, eval('g:ev')) | ||||
|     eq(1, eval('g:cdprecount')) | ||||
|     eq(1, eval('g:cdcount')) | ||||
|  | ||||
|     if is_os('win') then | ||||
|       command('lcd '..win_dirs[1]) | ||||
|       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')) | ||||
|     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]) | ||||
|     command('tcd ' .. dirs[2]) | ||||
|     eq({}, eval('g:evpre')) | ||||
|     eq({}, eval('g:ev')) | ||||
|     eq(2, eval('g:cdprecount')) | ||||
|     eq(2, eval('g:cdcount')) | ||||
|  | ||||
|     if is_os('win') then | ||||
|       command('tcd '..win_dirs[2]) | ||||
|       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')) | ||||
|     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]) | ||||
|     command('cd ' .. dirs[3]) | ||||
|     eq({}, eval('g:evpre')) | ||||
|     eq({}, eval('g:ev')) | ||||
|     eq(3, eval('g:cdprecount')) | ||||
|     eq(3, eval('g:cdcount')) | ||||
|  | ||||
|     if is_os('win') then | ||||
|       command('cd '..win_dirs[3]) | ||||
|       command('cd ' .. win_dirs[3]) | ||||
|       eq({}, eval('g:evpre')) | ||||
|       eq({}, eval('g:ev')) | ||||
|       eq(3, eval('g:cdprecount')) | ||||
| @@ -214,23 +237,23 @@ describe('autocmd DirChanged and DirChangedPre', 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')) | ||||
|     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') | ||||
|     command('split ' .. dirs[1] .. '/bar') | ||||
|     eq({}, eval('g:evpre')) | ||||
|     eq({}, eval('g:ev')) | ||||
|     eq(4, eval('g:cdprecount')) | ||||
|     eq(4, eval('g:cdcount')) | ||||
|  | ||||
|     if is_os('win') then | ||||
|       command('split '..win_dirs[1]..'/baz') | ||||
|       command('split ' .. win_dirs[1] .. '/baz') | ||||
|       eq({}, eval('g:evpre')) | ||||
|       eq({}, eval('g:ev')) | ||||
|       eq(4, eval('g:cdprecount')) | ||||
| @@ -238,16 +261,16 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   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]) | ||||
|     command('split '..dirs[1]..'/bar')  -- window 1 | ||||
|     command('lcd '..dirs[1]) | ||||
|   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]) | ||||
|     command('split ' .. dirs[1] .. '/bar') -- window 1 | ||||
|     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({ 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')) | ||||
|  | ||||
| @@ -256,15 +279,15 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     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('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({ 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({ 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')) | ||||
| @@ -282,7 +305,7 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|       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]) | ||||
|       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 | ||||
| @@ -297,7 +320,7 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|       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 | ||||
|       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 | ||||
| @@ -317,14 +340,14 @@ describe('autocmd DirChanged and DirChangedPre', 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({ 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({ 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')) | ||||
|  | ||||
| @@ -333,7 +356,7 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     end) | ||||
|     eq(false, status) | ||||
|     eq('Failed to change directory', string.match(err, ': (.*)')) | ||||
|     eq({directory='/doesnotexist', scope='global', changed_window=false}, eval('g:evpre')) | ||||
|     eq({ directory = '/doesnotexist', scope = 'global', changed_window = false }, eval('g:evpre')) | ||||
|     eq(3, eval('g:cdprecount')) | ||||
|     eq(2, eval('g:cdcount')) | ||||
|   end) | ||||
| @@ -343,7 +366,7 @@ describe('autocmd DirChanged and DirChangedPre', function() | ||||
|     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]) | ||||
|     command('cd ' .. dirs[1]) | ||||
|     eq(1, eval('g:triggeredpre')) | ||||
|     eq(1, eval('g:triggered')) | ||||
|   end) | ||||
|   | ||||
| @@ -7,11 +7,11 @@ local command = helpers.command | ||||
| describe('autocmd FileType', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|     it("is triggered by :help only once", function() | ||||
|   it('is triggered by :help only once', function() | ||||
|     helpers.add_builddir_to_rtp() | ||||
|         command("let g:foo = 0") | ||||
|         command("autocmd FileType help let g:foo = g:foo + 1") | ||||
|         command("help help") | ||||
|     command('let g:foo = 0') | ||||
|     command('autocmd FileType help let g:foo = g:foo + 1') | ||||
|     command('help help') | ||||
|     assert.same(1, eval('g:foo')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -5,7 +5,9 @@ local clear = helpers.clear | ||||
| local feed_command = helpers.feed_command | ||||
| local feed_data = thelpers.feed_data | ||||
|  | ||||
| if helpers.skip(helpers.is_os('win')) then return end | ||||
| if helpers.skip(helpers.is_os('win')) then | ||||
|   return | ||||
| end | ||||
|  | ||||
| describe('autoread TUI FocusGained/FocusLost', function() | ||||
|   local f1 = 'xtest-foo' | ||||
| @@ -14,10 +16,14 @@ describe('autoread TUI FocusGained/FocusLost', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     screen = thelpers.setup_child_nvim({ | ||||
|       '-u', 'NONE', | ||||
|       '-i', 'NONE', | ||||
|       '--cmd', 'colorscheme vim', | ||||
|       '--cmd', 'set noswapfile noshowcmd noruler notermguicolors', | ||||
|       '-u', | ||||
|       'NONE', | ||||
|       '-i', | ||||
|       'NONE', | ||||
|       '--cmd', | ||||
|       'colorscheme vim', | ||||
|       '--cmd', | ||||
|       'set noswapfile noshowcmd noruler notermguicolors', | ||||
|     }) | ||||
|   end) | ||||
|  | ||||
| @@ -38,36 +44,44 @@ describe('autoread TUI FocusGained/FocusLost', function() | ||||
|     local atime = os.time() - 10 | ||||
|     luv.fs_utime(path, atime, atime) | ||||
|  | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       {1: }                                                 | | ||||
|       {4:~                                                 }|*3 | ||||
|       {5:[No Name]                                         }| | ||||
|                                                         | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]} | ||||
|     feed_command('edit '..path) | ||||
|     screen:expect{grid=[[ | ||||
|     ]], | ||||
|     } | ||||
|     feed_command('edit ' .. path) | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       {1: }                                                 | | ||||
|       {4:~                                                 }|*3 | ||||
|       {5:xtest-foo                                         }| | ||||
|       :edit xtest-foo                                   | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed_data('\027[O') | ||||
|     feed_data('\027[O') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       {1: }                                                 | | ||||
|       {4:~                                                 }|*3 | ||||
|       {5:xtest-foo                                         }| | ||||
|       :edit xtest-foo                                   | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]], unchanged=true} | ||||
|     ]], | ||||
|       unchanged = true, | ||||
|     } | ||||
|  | ||||
|     helpers.write_file(path, expected_addition) | ||||
|  | ||||
|     feed_data('\027[I') | ||||
|  | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       {1:l}ine 1                                            | | ||||
|       line 2                                            | | ||||
|       line 3                                            | | ||||
| @@ -75,6 +89,7 @@ describe('autoread TUI FocusGained/FocusLost', function() | ||||
|       {5:xtest-foo                                         }| | ||||
|       "xtest-foo" 4L, 28B                               | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -17,15 +17,15 @@ describe('ModeChanged', function() | ||||
|     feed('i') | ||||
|     eq({ | ||||
|       old_mode = 'nt', | ||||
|       new_mode = 't' | ||||
|       new_mode = 't', | ||||
|     }, eval('g:event')) | ||||
|     feed('<c-\\><c-n>') | ||||
|     eq({ | ||||
|       old_mode = 't', | ||||
|       new_mode = 'nt' | ||||
|       new_mode = 'nt', | ||||
|     }, eval('g:event')) | ||||
|     eq(3, eval('g:count')) | ||||
|     command("bd!") | ||||
|     command('bd!') | ||||
|  | ||||
|     -- v:event is cleared after the autocommand is done | ||||
|     eq({}, eval('v:event')) | ||||
|   | ||||
| @@ -15,7 +15,8 @@ describe('autocmd SearchWrapped', function() | ||||
|     command('autocmd! SearchWrapped * let g:test += 1') | ||||
|     curbufmeths.set_lines(0, 1, false, { | ||||
|       'The quick brown fox', | ||||
|       'jumps over the lazy dog'}) | ||||
|       'jumps over the lazy dog', | ||||
|     }) | ||||
|   end) | ||||
|  | ||||
|   it('gets triggered when search wraps the end', function() | ||||
|   | ||||
| @@ -10,24 +10,25 @@ local eval = helpers.eval | ||||
| local exec = helpers.exec | ||||
| local feed = helpers.feed | ||||
|  | ||||
| describe(":autocmd", function() | ||||
| describe(':autocmd', function() | ||||
|   before_each(function() | ||||
|     clear({'-u', 'NONE'}) | ||||
|     clear({ '-u', 'NONE' }) | ||||
|   end) | ||||
|  | ||||
|   it("should not segfault when you just do autocmd", function() | ||||
|     command ":autocmd" | ||||
|   it('should not segfault when you just do autocmd', function() | ||||
|     command ':autocmd' | ||||
|   end) | ||||
|  | ||||
|   it("should filter based on ++once", function() | ||||
|     command "autocmd! BufEnter" | ||||
|   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([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|        --- Autocommands --- | ||||
|        BufEnter | ||||
| @@ -35,15 +36,16 @@ describe(":autocmd", function() | ||||
|        TestingOne  BufEnter | ||||
|            *         :echo "Line 1" | ||||
|                      :echo "Line 2"]]), | ||||
|        funcs.execute('autocmd BufEnter')) | ||||
|       funcs.execute('autocmd BufEnter') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('should not show group information if interrupted', function() | ||||
|     local screen = Screen.new(50, 6) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1},  -- NonText | ||||
|       [2] = {bold = true, foreground = Screen.colors.SeaGreen},  -- MoreMsg | ||||
|       [3] = {bold = true, foreground = Screen.colors.Magenta},  -- Title | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText | ||||
|       [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg | ||||
|       [3] = { bold = true, foreground = Screen.colors.Magenta }, -- Title | ||||
|     }) | ||||
|     screen:attach() | ||||
|     exec([[ | ||||
| @@ -109,7 +111,8 @@ describe(":autocmd", function() | ||||
|       autocmd User foo call Func() | ||||
|       doautocmd User foo | ||||
|     ]]) | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|       --- Autocommands --- | ||||
|       test_1  BufEnter | ||||
| @@ -119,7 +122,9 @@ describe(":autocmd", function() | ||||
|       test_3  BufEnter | ||||
|           D         echo 'D' | ||||
|           E         echo 'E' | ||||
|           F         echo 'F']]), eval('g:output')) | ||||
|           F         echo 'F']]), | ||||
|       eval('g:output') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('can filter by pattern #17973', function() | ||||
| @@ -145,7 +150,8 @@ describe(":autocmd", function() | ||||
|         autocmd User B echo "B3" | ||||
|       augroup END | ||||
|     ]]) | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|       --- Autocommands --- | ||||
|       test_1  User | ||||
| @@ -153,8 +159,11 @@ describe(":autocmd", function() | ||||
|       test_2  User | ||||
|           A         echo "A2" | ||||
|       test_3  User | ||||
|           A         echo "A3"]]), funcs.execute('autocmd User A')) | ||||
|     eq(dedent([[ | ||||
|           A         echo "A3"]]), | ||||
|       funcs.execute('autocmd User A') | ||||
|     ) | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|       --- Autocommands --- | ||||
|       test_1  BufEnter | ||||
| @@ -168,14 +177,19 @@ describe(":autocmd", function() | ||||
|       test_2  User | ||||
|           B         echo "B2" | ||||
|       test_3  User | ||||
|           B         echo "B3"]]), funcs.execute('autocmd * B')) | ||||
|     eq(dedent([[ | ||||
|           B         echo "B3"]]), | ||||
|       funcs.execute('autocmd * B') | ||||
|     ) | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|       --- Autocommands --- | ||||
|       test_3  BufEnter | ||||
|           B         echo "B3" | ||||
|       test_3  User | ||||
|           B         echo "B3"]]), funcs.execute('autocmd test_3 * B')) | ||||
|           B         echo "B3"]]), | ||||
|       funcs.execute('autocmd test_3 * B') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('should skip consecutive patterns', function() | ||||
| @@ -200,7 +214,8 @@ describe(":autocmd", function() | ||||
|  | ||||
|       let g:output = execute('autocmd BufEnter') | ||||
|     ]]) | ||||
|     eq(dedent([[ | ||||
|     eq( | ||||
|       dedent([[ | ||||
|  | ||||
|       --- Autocommands --- | ||||
|       test_1  BufEnter | ||||
| @@ -216,6 +231,8 @@ describe(":autocmd", function() | ||||
|                     echo 'C' | ||||
|           D         echo 'D' | ||||
|                     echo 'E' | ||||
|                     echo 'F']]), eval('g:output')) | ||||
|                     echo 'F']]), | ||||
|       eval('g:output') | ||||
|     ) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -8,10 +8,12 @@ local next_msg = helpers.next_msg | ||||
| local is_os = helpers.is_os | ||||
| local skip = helpers.skip | ||||
|  | ||||
| if skip(is_os('win'), 'Only applies to POSIX systems') then return end | ||||
| if skip(is_os('win'), 'Only applies to POSIX systems') then | ||||
|   return | ||||
| end | ||||
|  | ||||
| local function posix_kill(signame, pid) | ||||
|   os.execute('kill -s '..signame..' -- '..pid..' >/dev/null') | ||||
|   os.execute('kill -s ' .. signame .. ' -- ' .. pid .. ' >/dev/null') | ||||
| end | ||||
|  | ||||
| describe('autocmd Signal', function() | ||||
| @@ -20,19 +22,19 @@ describe('autocmd Signal', function() | ||||
|   it('matches *', function() | ||||
|     command('autocmd Signal * call rpcnotify(1, "foo")') | ||||
|     posix_kill('USR1', funcs.getpid()) | ||||
|     eq({'notification', 'foo', {}}, next_msg()) | ||||
|     eq({ 'notification', 'foo', {} }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('matches SIGUSR1', function() | ||||
|     command('autocmd Signal SIGUSR1 call rpcnotify(1, "foo")') | ||||
|     posix_kill('USR1', funcs.getpid()) | ||||
|     eq({'notification', 'foo', {}}, next_msg()) | ||||
|     eq({ 'notification', 'foo', {} }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('matches SIGWINCH', function() | ||||
|     command('autocmd Signal SIGWINCH call rpcnotify(1, "foo")') | ||||
|     posix_kill('WINCH', funcs.getpid()) | ||||
|     eq({'notification', 'foo', {}}, next_msg()) | ||||
|     eq({ 'notification', 'foo', {} }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('does not match unknown patterns', function() | ||||
|   | ||||
| @@ -7,62 +7,76 @@ describe('TabClosed', function() | ||||
|   describe('au TabClosed', function() | ||||
|     describe('with * as <afile>', function() | ||||
|       it('matches when closing any tab', function() | ||||
|         nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()') | ||||
|         nvim( | ||||
|           'command', | ||||
|           'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()' | ||||
|         ) | ||||
|         repeat | ||||
|           nvim('command', 'tabnew') | ||||
|         until nvim('eval', 'tabpagenr()') == 6 -- current tab is now 6 | ||||
|         eq("tabclosed:6:6:5", nvim('exec', 'tabclose', true)) -- close last 6, current tab is now 5 | ||||
|         eq("tabclosed:5:5:4", nvim('exec', 'close', true)) -- close last window on tab, closes tab | ||||
|         eq("tabclosed:2:2:3", nvim('exec', '2tabclose', true)) -- close tab 2, current tab is now 3 | ||||
|         eq("tabclosed:1:1:2\ntabclosed:1:1:1", nvim('exec', 'tabonly', true)) -- close tabs 1 and 2 | ||||
|         eq('tabclosed:6:6:5', nvim('exec', 'tabclose', true)) -- close last 6, current tab is now 5 | ||||
|         eq('tabclosed:5:5:4', nvim('exec', 'close', true)) -- close last window on tab, closes tab | ||||
|         eq('tabclosed:2:2:3', nvim('exec', '2tabclose', true)) -- close tab 2, current tab is now 3 | ||||
|         eq('tabclosed:1:1:2\ntabclosed:1:1:1', nvim('exec', 'tabonly', true)) -- close tabs 1 and 2 | ||||
|       end) | ||||
|  | ||||
|       it('is triggered when closing a window via bdelete from another tab', function() | ||||
|         nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()') | ||||
|         nvim( | ||||
|           'command', | ||||
|           'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()' | ||||
|         ) | ||||
|         nvim('command', '1tabedit Xtestfile') | ||||
|         nvim('command', '1tabedit Xtestfile') | ||||
|         nvim('command', 'normal! 1gt') | ||||
|         eq({1, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq("tabclosed:2:2:1\ntabclosed:2:2:1", nvim('exec', 'bdelete Xtestfile', true)) | ||||
|         eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq({ 1, 3 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq('tabclosed:2:2:1\ntabclosed:2:2:1', nvim('exec', 'bdelete Xtestfile', true)) | ||||
|         eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|       end) | ||||
|  | ||||
|       it('is triggered when closing a window via bdelete from current tab', function() | ||||
|         nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()') | ||||
|         nvim( | ||||
|           'command', | ||||
|           'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()' | ||||
|         ) | ||||
|         nvim('command', 'file Xtestfile1') | ||||
|         nvim('command', '1tabedit Xtestfile2') | ||||
|         nvim('command', '1tabedit Xtestfile2') | ||||
|  | ||||
|         -- Only one tab is closed, and the alternate file is used for the other. | ||||
|         eq({2, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq("tabclosed:2:2:2", nvim('exec', 'bdelete Xtestfile2', true)) | ||||
|         eq({ 2, 3 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq('tabclosed:2:2:2', nvim('exec', 'bdelete Xtestfile2', true)) | ||||
|         eq('Xtestfile1', nvim('eval', 'bufname("")')) | ||||
|       end) | ||||
|     end) | ||||
|  | ||||
|     describe('with NR as <afile>', function() | ||||
|       it('matches when closing a tab whose index is NR', function() | ||||
|         nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()') | ||||
|         nvim( | ||||
|           'command', | ||||
|           'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()' | ||||
|         ) | ||||
|         nvim('command', 'au! TabClosed 2 echom "tabclosed:match"') | ||||
|         repeat | ||||
|           nvim('command', 'tabnew') | ||||
|         until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7 | ||||
|         -- sanity check, we shouldn't match on tabs with numbers other than 2 | ||||
|         eq("tabclosed:7:7:6", nvim('exec', 'tabclose', true)) | ||||
|         eq('tabclosed:7:7:6', nvim('exec', 'tabclose', true)) | ||||
|         -- close tab page 2, current tab is now 5 | ||||
|         eq("tabclosed:2:2:5\ntabclosed:match", nvim('exec', '2tabclose', true)) | ||||
|         eq('tabclosed:2:2:5\ntabclosed:match', nvim('exec', '2tabclose', true)) | ||||
|       end) | ||||
|     end) | ||||
|  | ||||
|     describe('with close', function() | ||||
|       it('is triggered', function() | ||||
|         nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()') | ||||
|         nvim( | ||||
|           'command', | ||||
|           'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()' | ||||
|         ) | ||||
|         nvim('command', 'tabedit Xtestfile') | ||||
|         eq({2, 2}, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq("tabclosed:2:2:1", nvim('exec', 'close', true)) | ||||
|         eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq({ 2, 2 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|         eq('tabclosed:2:2:1', nvim('exec', 'close', true)) | ||||
|         eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) | ||||
|       end) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -15,8 +15,8 @@ describe('TabNewEntered', function() | ||||
|       it('matches when entering any new tab', function() | ||||
|         clear() | ||||
|         nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")') | ||||
|         eq("tabnewentered:2:2", nvim('exec', 'tabnew', true)) | ||||
|         eq("tabnewentered:3:3", nvim('exec', 'tabnew test.x2', true)) | ||||
|         eq('tabnewentered:2:2', nvim('exec', 'tabnew', true)) | ||||
|         eq('tabnewentered:3:3', nvim('exec', 'tabnew test.x2', true)) | ||||
|       end) | ||||
|     end) | ||||
|     describe('with FILE as <afile>', function() | ||||
| @@ -52,8 +52,8 @@ describe('TabEnter', function() | ||||
|     command('augroup TEMP') | ||||
|     nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')') | ||||
|     command('augroup END') | ||||
|      eq("tabenter:2:1", nvim('exec', 'tabnew', true)) | ||||
|      eq("tabenter:3:2", nvim('exec', 'tabnew test.x2', true)) | ||||
|     eq('tabenter:2:1', nvim('exec', 'tabnew', true)) | ||||
|     eq('tabenter:3:2', nvim('exec', 'tabnew test.x2', true)) | ||||
|     command('augroup! TEMP') | ||||
|   end) | ||||
|   it('has correct previous tab when entering any preexisting tab', function() | ||||
| @@ -62,8 +62,8 @@ describe('TabEnter', function() | ||||
|     command('augroup TEMP') | ||||
|     nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')') | ||||
|     command('augroup END') | ||||
|      eq("tabenter:1:3", nvim('exec', 'tabnext', true)) | ||||
|      eq("tabenter:2:1", nvim('exec', 'tabnext', true)) | ||||
|     eq('tabenter:1:3', nvim('exec', 'tabnext', true)) | ||||
|     eq('tabenter:2:1', nvim('exec', 'tabnext', true)) | ||||
|     command('augroup! TEMP') | ||||
|   end) | ||||
| end) | ||||
| @@ -78,12 +78,13 @@ describe('tabpage/previous', function() | ||||
|       command('tabnew') | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|         eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (third) tab | ||||
|       feed(characters) | ||||
|  | ||||
|         eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|           Tab page 1 | ||||
|               [No Name] | ||||
| @@ -97,14 +98,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|         eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after new tab creation at end', | ||||
|     switches_to_previous_after_new_tab_creation_at_end('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after new tab creation at end', | ||||
|     switches_to_previous_after_new_tab_creation_at_end('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab>. after new tab creation at end', | ||||
|     switches_to_previous_after_new_tab_creation_at_end('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab>. after new tab creation at end', | ||||
|     switches_to_previous_after_new_tab_creation_at_end('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR>. after new tab creation at end', | ||||
|     switches_to_previous_after_new_tab_creation_at_end(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_new_tab_creation_in_middle(characters) | ||||
|     return function() | ||||
| @@ -118,11 +130,12 @@ describe('tabpage/previous', function() | ||||
|       command('tabnew') | ||||
|  | ||||
|       -- The previous tab is now the second. | ||||
|       eq(2, eval('tabpagenr(\'#\')')) | ||||
|       eq(2, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (second) tab | ||||
|       feed(characters) | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
| @@ -138,17 +151,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after new tab creation in middle', | ||||
|     switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_switching_to_next_tab(characters) | ||||
|     return function() | ||||
| @@ -160,12 +181,13 @@ describe('tabpage/previous', function() | ||||
|       command('tabnext') | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|       eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (fourth) tab | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|          #   [No Name] | ||||
| @@ -179,17 +201,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the first. | ||||
|       eq(1, eval('tabpagenr(\'#\')')) | ||||
|       eq(1, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to next tab', | ||||
|     switches_to_previous_after_switching_to_next_tab(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_switching_to_last_tab(characters) | ||||
|     return function() | ||||
| @@ -203,12 +233,13 @@ describe('tabpage/previous', function() | ||||
|       command('tablast') | ||||
|  | ||||
|       -- The previous tab is now the second. | ||||
|       eq(1, eval('tabpagenr(\'#\')')) | ||||
|       eq(1, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (second) tab | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|          >   [No Name] | ||||
| @@ -222,17 +253,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|       eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('g<Tab>')) | ||||
|   it('switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>')) | ||||
|   it('switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('<C-Tab>')) | ||||
|   it('switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous after switching to last tab', | ||||
|     switches_to_previous_after_switching_to_last_tab(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_switching_to_previous_tab(characters) | ||||
|     return function() | ||||
| @@ -244,12 +283,13 @@ describe('tabpage/previous', function() | ||||
|       command('tabprevious') | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|       eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (fourth) tab | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
| @@ -263,17 +303,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to previous tab', | ||||
|     switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_switching_to_first_tab(characters) | ||||
|     return function() | ||||
| @@ -287,12 +335,13 @@ describe('tabpage/previous', function() | ||||
|       command('tabfirst') | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (third) tab | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|          #   [No Name] | ||||
| @@ -306,17 +355,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the first. | ||||
|       eq(1, eval('tabpagenr(\'#\')')) | ||||
|       eq(1, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to first tab', | ||||
|     switches_to_previous_after_switching_to_first_tab(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_numbered_tab_switch(characters) | ||||
|     return function() | ||||
| @@ -328,12 +385,13 @@ describe('tabpage/previous', function() | ||||
|       command('tabnext 2') | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|       eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (fourth) tab | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
| @@ -347,17 +405,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the second. | ||||
|       eq(2, eval('tabpagenr(\'#\')')) | ||||
|       eq(2, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch(':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after numbered tab switch', | ||||
|     switches_to_previous_after_numbered_tab_switch(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function switches_to_previous_after_switching_to_previous(characters1, characters2) | ||||
|     return function() | ||||
| @@ -371,12 +437,13 @@ describe('tabpage/previous', function() | ||||
|       feed(characters1) | ||||
|  | ||||
|       -- The previous tab is now the second. | ||||
|       eq(2, eval('tabpagenr(\'#\')')) | ||||
|       eq(2, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Switch to the previous (second) tab | ||||
|       feed(characters2) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
| @@ -390,41 +457,73 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the fourth. | ||||
|       eq(4, eval('tabpagenr(\'#\')')) | ||||
|       eq(4, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('switches to previous via g<Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', 'g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>')) | ||||
|   it('switches to previous via g<Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':tabn #<CR>')) | ||||
|   it('switches to previous via g<Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', ':tabn #<CR>')) | ||||
|   it('switches to previous via g<Tab> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>')) | ||||
|   it('switches to previous via <C-W>g<Tab> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-W>g<Tab>')) | ||||
|   it('switches to previous via <C-Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>')) | ||||
|   it('switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', ':tabn #<CR>')) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', 'g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to previous via g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':tabn #<CR>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous('<C-Tab>', ':tabn #<CR>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via g<Tab> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-W>g<Tab> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via <C-Tab> after switching to previous via <C-Tab>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>', | ||||
|     switches_to_previous_after_switching_to_previous(':tabn #<CR>', ':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function does_not_switch_to_previous_after_closing_current_tab(characters) | ||||
|     return function() | ||||
| @@ -436,13 +535,14 @@ describe('tabpage/previous', function() | ||||
|       command('wincmd c') | ||||
|  | ||||
|       -- The previous tab is now the "zeroth" -- there isn't one. | ||||
|       eq(0, eval('tabpagenr(\'#\')')) | ||||
|       eq(0, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- At this point, switching to the "previous" (i.e. fourth) tab would mean | ||||
|       -- switching to either a dangling or a null pointer. | ||||
|       feed(characters) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|       eq( | ||||
|         dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
| @@ -454,17 +554,25 @@ describe('tabpage/previous', function() | ||||
|       ) | ||||
|  | ||||
|       -- The previous tab is now the "zero". | ||||
|       eq(0, eval('tabpagenr(\'#\')')) | ||||
|       eq(0, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('does not switch to previous via g<Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('g<Tab>')) | ||||
|   it('does not switch to previous via <C-W>g<Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>')) | ||||
|   it('does not switch to previous via <C-Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('<C-Tab>')) | ||||
|   it('does not switch to previous via :tabn #<CR> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>')) | ||||
|   it( | ||||
|     'does not switch to previous via g<Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'does not switch to previous via <C-W>g<Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'does not switch to previous via <C-Tab> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab('<C-Tab>') | ||||
|   ) | ||||
|   it( | ||||
|     'does not switch to previous via :tabn #<CR> after closing current tab', | ||||
|     does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>') | ||||
|   ) | ||||
|  | ||||
|   local function does_not_switch_to_previous_after_entering_operator_pending(characters) | ||||
|     return function() | ||||
| @@ -474,7 +582,7 @@ describe('tabpage/previous', function() | ||||
|       command('tabnew') | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Enter operator pending mode. | ||||
|       feed('d') | ||||
| @@ -491,11 +599,13 @@ describe('tabpage/previous', function() | ||||
|       eq(4, eval('tabpagenr()')) | ||||
|  | ||||
|       -- The previous tab is still the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('does not switch to previous via g<Tab> after entering operator pending', | ||||
|     does_not_switch_to_previous_after_entering_operator_pending('g<Tab>')) | ||||
|   it( | ||||
|     'does not switch to previous via g<Tab> after entering operator pending', | ||||
|     does_not_switch_to_previous_after_entering_operator_pending('g<Tab>') | ||||
|   ) | ||||
|   -- NOTE: When in operator pending mode, attempting to switch to previous has | ||||
|   --       the following effect: | ||||
|   --       - Ctrl-W exits operator pending mode | ||||
| @@ -506,8 +616,10 @@ describe('tabpage/previous', function() | ||||
|   --       be the same as the normal mode command to switch to the previous tab. | ||||
|   -- it('does not switch to previous via <C-W>g<Tab> after entering operator pending', | ||||
|   --   does_not_switch_to_previous_after_entering_operator_pending('<C-W>g<Tab>')) | ||||
|   it('does not switch to previous via <C-Tab> after entering operator pending', | ||||
|     does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>')) | ||||
|   it( | ||||
|     'does not switch to previous via <C-Tab> after entering operator pending', | ||||
|     does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>') | ||||
|   ) | ||||
|   -- NOTE: When in operator pending mode, pressing : leaves operator pending | ||||
|   --       mode and enters command mode, so :tabn #<CR> does in fact switch | ||||
|   --       tabs. | ||||
| @@ -522,7 +634,7 @@ describe('tabpage/previous', function() | ||||
|       command('tabnew') | ||||
|  | ||||
|       -- The previous tab is now the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|  | ||||
|       -- Edit : command line in command-line window | ||||
|       feed('q:') | ||||
| @@ -540,17 +652,19 @@ describe('tabpage/previous', function() | ||||
|       eq(4, eval('tabpagenr()')) | ||||
|  | ||||
|       -- The previous tab is still the third. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|       eq(3, eval("tabpagenr('#')")) | ||||
|     end | ||||
|   end | ||||
|   it('cmdline-win prevents tab switch via g<Tab>', | ||||
|     cmdline_win_prevents_tab_switch('g<Tab>', 0)) | ||||
|   it('cmdline-win prevents tab switch via <C-W>g<Tab>', | ||||
|     cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1)) | ||||
|   it('cmdline-win prevents tab switch via <C-Tab>', | ||||
|     cmdline_win_prevents_tab_switch('<C-Tab>', 0)) | ||||
|   it('cmdline-win prevents tab switch via :tabn #<CR>', | ||||
|     cmdline_win_prevents_tab_switch(':tabn #<CR>', 0)) | ||||
|   it('cmdline-win prevents tab switch via g<Tab>', cmdline_win_prevents_tab_switch('g<Tab>', 0)) | ||||
|   it( | ||||
|     'cmdline-win prevents tab switch via <C-W>g<Tab>', | ||||
|     cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1) | ||||
|   ) | ||||
|   it('cmdline-win prevents tab switch via <C-Tab>', cmdline_win_prevents_tab_switch('<C-Tab>', 0)) | ||||
|   it( | ||||
|     'cmdline-win prevents tab switch via :tabn #<CR>', | ||||
|     cmdline_win_prevents_tab_switch(':tabn #<CR>', 0) | ||||
|   ) | ||||
|  | ||||
|   it(':tabs indicates correct prevtab curwin', function() | ||||
|     -- Add three tabs for a total of four | ||||
| @@ -562,9 +676,10 @@ describe('tabpage/previous', function() | ||||
|     command('tabnew') | ||||
|  | ||||
|     -- The previous tab is now the three. | ||||
|       eq(3, eval('tabpagenr(\'#\')')) | ||||
|     eq(3, eval("tabpagenr('#')")) | ||||
|  | ||||
|       eq(dedent([=[ | ||||
|     eq( | ||||
|       dedent([=[ | ||||
|  | ||||
|          Tab page 1 | ||||
|              [No Name] | ||||
|   | ||||
| @@ -2,10 +2,8 @@ local luv = require('luv') | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local thelpers = require('test.functional.terminal.helpers') | ||||
|  | ||||
| local clear, command, nvim, testprg = | ||||
|   helpers.clear, helpers.command, helpers.nvim, helpers.testprg | ||||
| local eval, eq, neq, retry = | ||||
|   helpers.eval, helpers.eq, helpers.neq, helpers.retry | ||||
| local clear, command, nvim, testprg = helpers.clear, helpers.command, helpers.nvim, helpers.testprg | ||||
| local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry | ||||
| local matches = helpers.matches | ||||
| local ok = helpers.ok | ||||
| local feed = helpers.feed | ||||
| @@ -27,8 +25,10 @@ describe('autocmd TermClose', function() | ||||
|     nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {}) | ||||
|     command('autocmd TermClose * bdelete!') | ||||
|     command('terminal') | ||||
|     matches('^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://', | ||||
|             pcall_err(command, 'bdelete!')) | ||||
|     matches( | ||||
|       '^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://', | ||||
|       pcall_err(command, 'bdelete!') | ||||
|     ) | ||||
|     assert_alive() | ||||
|   end | ||||
|  | ||||
| @@ -46,8 +46,12 @@ describe('autocmd TermClose', function() | ||||
|     command('autocmd TermClose * let g:test_termclose = 23') | ||||
|     command('terminal') | ||||
|     -- shell-test exits immediately. | ||||
|     retry(nil, nil, function() neq(-1, eval('jobwait([&channel], 0)[0]')) end) | ||||
|     retry(nil, nil, function() eq(23, eval('g:test_termclose')) end) | ||||
|     retry(nil, nil, function() | ||||
|       neq(-1, eval('jobwait([&channel], 0)[0]')) | ||||
|     end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(23, eval('g:test_termclose')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('triggers when long-running terminal job gets stopped', function() | ||||
| @@ -56,22 +60,30 @@ describe('autocmd TermClose', function() | ||||
|     command('autocmd TermClose * let g:test_termclose = 23') | ||||
|     command('terminal') | ||||
|     command('call jobstop(b:terminal_job_id)') | ||||
|     retry(nil, nil, function() eq(23, eval('g:test_termclose')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(23, eval('g:test_termclose')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('kills job trapping SIGTERM', function() | ||||
|     skip(is_os('win')) | ||||
|     nvim('set_option_value', 'shell', 'sh', {}) | ||||
|     nvim('set_option_value', 'shellcmdflag', '-c', {}) | ||||
|     command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]] | ||||
|     command( | ||||
|       [[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]] | ||||
|         .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]] | ||||
|       .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) | ||||
|     retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) | ||||
|         .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]] | ||||
|     ) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, eval('get(g:, "test_job_started", 0)')) | ||||
|     end) | ||||
|  | ||||
|     luv.update_time() | ||||
|     local start = luv.now() | ||||
|     command('call jobstop(g:test_job)') | ||||
|     retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, eval('get(g:, "test_job_exited", 0)')) | ||||
|     end) | ||||
|     luv.update_time() | ||||
|     local duration = luv.now() - start | ||||
|     -- Nvim begins SIGTERM after KILL_TIMEOUT_MS. | ||||
| @@ -83,16 +95,22 @@ describe('autocmd TermClose', function() | ||||
|     skip(is_os('win')) | ||||
|     nvim('set_option_value', 'shell', 'sh', {}) | ||||
|     nvim('set_option_value', 'shellcmdflag', '-c', {}) | ||||
|     command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]] | ||||
|     command( | ||||
|       [[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]] | ||||
|         .. [[ 'pty': 1,]] | ||||
|         .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]] | ||||
|       .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) | ||||
|     retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) | ||||
|         .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]] | ||||
|     ) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, eval('get(g:, "test_job_started", 0)')) | ||||
|     end) | ||||
|  | ||||
|     luv.update_time() | ||||
|     local start = luv.now() | ||||
|     command('call jobstop(g:test_job)') | ||||
|     retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, eval('get(g:, "test_job_exited", 0)')) | ||||
|     end) | ||||
|     luv.update_time() | ||||
|     local duration = luv.now() - start | ||||
|     -- Nvim begins SIGKILL after (2 * KILL_TIMEOUT_MS). | ||||
| @@ -109,13 +127,19 @@ describe('autocmd TermClose', function() | ||||
|     eq(2, eval('bufnr("%")')) | ||||
|  | ||||
|     command('terminal ls') | ||||
|     retry(nil, nil, function() eq(3, eval('bufnr("%")')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(3, eval('bufnr("%")')) | ||||
|     end) | ||||
|  | ||||
|     command('buffer 1') | ||||
|     retry(nil, nil, function() eq(1, eval('bufnr("%")')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, eval('bufnr("%")')) | ||||
|     end) | ||||
|  | ||||
|     command('3bdelete!') | ||||
|     retry(nil, nil, function() eq('3', eval('g:abuf')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq('3', eval('g:abuf')) | ||||
|     end) | ||||
|     feed('<c-c>:qa!<cr>') | ||||
|   end) | ||||
|  | ||||
| @@ -124,10 +148,14 @@ describe('autocmd TermClose', function() | ||||
|     command('autocmd TermClose * let g:status = v:event.status') | ||||
|  | ||||
|     command('terminal 0') | ||||
|     retry(nil, nil, function() eq(0, eval('g:status')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(0, eval('g:status')) | ||||
|     end) | ||||
|  | ||||
|     command('terminal 42') | ||||
|     retry(nil, nil, function() eq(42, eval('g:status')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(42, eval('g:status')) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -141,10 +169,13 @@ it('autocmd TermEnter, TermLeave', function() | ||||
|   command('terminal') | ||||
|  | ||||
|   feed('i') | ||||
|   eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, }, eval('g:evs')) | ||||
|   eq({ { 'TermOpen', 'n' }, { 'TermEnter', 't' } }, eval('g:evs')) | ||||
|   feed([[<C-\><C-n>]]) | ||||
|   feed('A') | ||||
|   eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, {'TermLeave', 'n'}, {'TermEnter', 't'}, }, eval('g:evs')) | ||||
|   eq( | ||||
|     { { 'TermOpen', 'n' }, { 'TermEnter', 't' }, { 'TermLeave', 'n' }, { 'TermEnter', 't' } }, | ||||
|     eval('g:evs') | ||||
|   ) | ||||
|  | ||||
|   -- TermLeave is also triggered by :quit. | ||||
|   command('split foo') | ||||
| @@ -154,14 +185,14 @@ it('autocmd TermEnter, TermLeave', function() | ||||
|   command('q!') | ||||
|   feed('<Ignore>') -- Add input to separate two RPC requests | ||||
|   eq({ | ||||
|     {'TermOpen',  'n'}, | ||||
|     {'TermEnter', 't'}, | ||||
|     {'TermLeave', 'n'}, | ||||
|     {'TermEnter', 't'}, | ||||
|     {'TermLeave', 'n'}, | ||||
|     {'TermEnter', 't'}, | ||||
|     {'TermClose', 't'}, | ||||
|     {'TermLeave', 'n'}, | ||||
|     { 'TermOpen', 'n' }, | ||||
|     { 'TermEnter', 't' }, | ||||
|     { 'TermLeave', 'n' }, | ||||
|     { 'TermEnter', 't' }, | ||||
|     { 'TermLeave', 'n' }, | ||||
|     { 'TermEnter', 't' }, | ||||
|     { 'TermClose', 't' }, | ||||
|     { 'TermLeave', 'n' }, | ||||
|   }, eval('g:evs')) | ||||
| end) | ||||
|  | ||||
| @@ -172,13 +203,15 @@ describe('autocmd TextChangedT', function() | ||||
|   it('works', function() | ||||
|     command('autocmd TextChangedT * ++once let g:called = 1') | ||||
|     thelpers.feed_data('a') | ||||
|     retry(nil, nil, function() eq(1, meths.get_var('called')) end) | ||||
|     retry(nil, nil, function() | ||||
|       eq(1, meths.get_var('called')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('cannot delete terminal buffer', function() | ||||
|     command([[autocmd TextChangedT * call nvim_input('<CR>') | bwipe!]]) | ||||
|     thelpers.feed_data('a') | ||||
|     screen:expect({any = 'E937: '}) | ||||
|     screen:expect({ any = 'E937: ' }) | ||||
|     matches('^E937: Attempt to delete a buffer that is in use: term://', meths.get_vvar('errmsg')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -88,7 +88,7 @@ it('TextChangedI and TextChangedP autocommands', function() | ||||
|   eq('IIPPPP', eval('g:autocmd')) | ||||
|   feed('<esc>') | ||||
|  | ||||
|   eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) | ||||
|   eq({ 'foo', 'bar', 'foobar', 'foo' }, eval('getline(1, "$")')) | ||||
| end) | ||||
|  | ||||
| -- oldtest: Test_TextChangedI_with_setline() | ||||
| @@ -172,11 +172,11 @@ it('TextChangedI and TextChanged', function() | ||||
|     eq('', eval('g:autocmd_n')) | ||||
|   end | ||||
|  | ||||
|   validate_mixed_textchangedi({'o', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'O', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'ciw', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'cc', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'C', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'s', '<esc>'}) | ||||
|   validate_mixed_textchangedi({'S', '<esc>'}) | ||||
|   validate_mixed_textchangedi({ 'o', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 'O', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 'ciw', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 'cc', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 'C', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 's', '<esc>' }) | ||||
|   validate_mixed_textchangedi({ 'S', '<esc>' }) | ||||
| end) | ||||
|   | ||||
| @@ -28,7 +28,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(1, eval('g:count')) | ||||
|  | ||||
| @@ -42,7 +42,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'baz ' }, | ||||
|       regname = '', | ||||
|       regtype = 'v', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(2, eval('g:count')) | ||||
|  | ||||
| @@ -52,8 +52,8 @@ describe('TextYankPost', function() | ||||
|       operator = 'y', | ||||
|       regcontents = { 'foo', 'baz' }, | ||||
|       regname = '', | ||||
|       regtype = "\0223", -- ^V + block width | ||||
|       visual = true | ||||
|       regtype = '\0223', -- ^V + block width | ||||
|       visual = true, | ||||
|     }, eval('g:event')) | ||||
|     eq(3, eval('g:count')) | ||||
|   end) | ||||
| @@ -66,25 +66,25 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|  | ||||
|     command('set debug=msg') | ||||
|     -- the regcontents should not be changed without copy. | ||||
|     local status, err = pcall(command,'call extend(g:event.regcontents, ["more text"])') | ||||
|     eq(status,false) | ||||
|     local status, err = pcall(command, 'call extend(g:event.regcontents, ["more text"])') | ||||
|     eq(status, false) | ||||
|     neq(nil, string.find(err, ':E742:')) | ||||
|  | ||||
|     -- can't mutate keys inside the autocommand | ||||
|     command('autocmd! TextYankPost * let v:event.regcontents = 0') | ||||
|     status, err = pcall(command,'normal yy') | ||||
|     eq(status,false) | ||||
|     status, err = pcall(command, 'normal yy') | ||||
|     eq(status, false) | ||||
|     neq(nil, string.find(err, ':E46:')) | ||||
|  | ||||
|     -- can't add keys inside the autocommand | ||||
|     command('autocmd! TextYankPost * let v:event.mykey = 0') | ||||
|     status, err = pcall(command,'normal yy') | ||||
|     eq(status,false) | ||||
|     status, err = pcall(command, 'normal yy') | ||||
|     eq(status, false) | ||||
|     neq(nil, string.find(err, ':E742:')) | ||||
|   end) | ||||
|  | ||||
| @@ -97,10 +97,10 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(1, eval('g:count')) | ||||
|     eq({ 'foo\nbar' }, funcs.getreg('+',1,1)) | ||||
|     eq({ 'foo\nbar' }, funcs.getreg('+', 1, 1)) | ||||
|   end) | ||||
|  | ||||
|   it('is executed after delete and change', function() | ||||
| @@ -111,7 +111,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo' }, | ||||
|       regname = '', | ||||
|       regtype = 'v', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(1, eval('g:count')) | ||||
|  | ||||
| @@ -122,7 +122,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { '\nbar' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(2, eval('g:count')) | ||||
|  | ||||
| @@ -133,7 +133,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'baz' }, | ||||
|       regname = '', | ||||
|       regtype = 'v', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(3, eval('g:count')) | ||||
|   end) | ||||
| @@ -162,7 +162,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'bar' }, | ||||
|       regname = 'b', | ||||
|       regtype = 'v', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|  | ||||
|     feed('"*yy') | ||||
| @@ -172,10 +172,10 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '*', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|  | ||||
|     command("set clipboard=unnamed") | ||||
|     command('set clipboard=unnamed') | ||||
|  | ||||
|     -- regname still shows the name the user requested | ||||
|     feed('yy') | ||||
| @@ -185,7 +185,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|  | ||||
|     feed('"*yy') | ||||
| @@ -195,7 +195,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '*', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|   end) | ||||
|  | ||||
| @@ -207,7 +207,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'foo\nbar' }, | ||||
|       regname = '+', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(1, eval('g:count')) | ||||
|  | ||||
| @@ -218,7 +218,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'baz text' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(2, eval('g:count')) | ||||
|  | ||||
| @@ -229,7 +229,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'baz ' }, | ||||
|       regname = '', | ||||
|       regtype = 'v', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(3, eval('g:count')) | ||||
|  | ||||
| @@ -240,7 +240,7 @@ describe('TextYankPost', function() | ||||
|       regcontents = { 'baz text' }, | ||||
|       regname = '', | ||||
|       regtype = 'V', | ||||
|       visual = false | ||||
|       visual = false, | ||||
|     }, eval('g:event')) | ||||
|     eq(4, eval('g:count')) | ||||
|   end) | ||||
|   | ||||
| @@ -32,12 +32,12 @@ describe('WinResized', function() | ||||
|     -- increase window height, two windows will be reported | ||||
|     feed('<C-W>+') | ||||
|     eq(1, eval('g:resized')) | ||||
|     eq({windows = {1002, 1001}}, eval('g:v_event')) | ||||
|     eq({ windows = { 1002, 1001 } }, eval('g:v_event')) | ||||
|  | ||||
|     -- increase window width, three windows will be reported | ||||
|     feed('<C-W>>') | ||||
|     eq(2, eval('g:resized')) | ||||
|     eq({windows = {1002, 1001, 1000}}, eval('g:v_event')) | ||||
|     eq({ windows = { 1002, 1001, 1000 } }, eval('g:v_event')) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -63,22 +63,22 @@ describe('WinScrolled', function() | ||||
|   end) | ||||
|  | ||||
|   it('is triggered by scrolling vertically', function() | ||||
|     local lines = {'123', '123'} | ||||
|     local lines = { '123', '123' } | ||||
|     meths.buf_set_lines(0, 0, -1, true, lines) | ||||
|     eq(0, eval('g:scrolled')) | ||||
|  | ||||
|     feed('<C-E>') | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('<C-Y>') | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
|  | ||||
| @@ -86,58 +86,58 @@ describe('WinScrolled', function() | ||||
|     command('set nowrap') | ||||
|     local width = meths.win_get_width(0) | ||||
|     local line = '123' .. ('*'):rep(width * 2) | ||||
|     local lines = {line, line} | ||||
|     local lines = { line, line } | ||||
|     meths.buf_set_lines(0, 0, -1, true, lines) | ||||
|     eq(0, eval('g:scrolled')) | ||||
|  | ||||
|     feed('zl') | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('zh') | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
|  | ||||
|   it('is triggered by horizontal scrolling from cursor move', function() | ||||
|     command('set nowrap') | ||||
|     local lines = {'', '', 'Foo'} | ||||
|     local lines = { '', '', 'Foo' } | ||||
|     meths.buf_set_lines(0, 0, -1, true, lines) | ||||
|     meths.win_set_cursor(0, {3, 0}) | ||||
|     meths.win_set_cursor(0, { 3, 0 }) | ||||
|     eq(0, eval('g:scrolled')) | ||||
|  | ||||
|     feed('zl') | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('zl') | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('h') | ||||
|     eq(3, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('zh') | ||||
|     eq(4, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
|  | ||||
| @@ -145,22 +145,22 @@ describe('WinScrolled', function() | ||||
|   it('is triggered by scrolling on a long wrapped line #19968', function() | ||||
|     local height = meths.win_get_height(0) | ||||
|     local width = meths.win_get_width(0) | ||||
|     meths.buf_set_lines(0, 0, -1, true, {('foo'):rep(height * width)}) | ||||
|     meths.win_set_cursor(0, {1, height * width - 1}) | ||||
|     meths.buf_set_lines(0, 0, -1, true, { ('foo'):rep(height * width) }) | ||||
|     meths.win_set_cursor(0, { 1, height * width - 1 }) | ||||
|     eq(0, eval('g:scrolled')) | ||||
|  | ||||
|     feed('gj') | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width}, | ||||
|       ['1000'] = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width}, | ||||
|       all = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width }, | ||||
|       ['1000'] = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('0') | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width}, | ||||
|       ['1000'] = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = -width}, | ||||
|       all = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width }, | ||||
|       ['1000'] = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = -width }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('$') | ||||
| @@ -181,15 +181,15 @@ describe('WinScrolled', function() | ||||
|     feed('i<C-X><C-E><Esc>') | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('i<C-X><C-Y><Esc>') | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('L') | ||||
| @@ -198,8 +198,8 @@ describe('WinScrolled', function() | ||||
|     feed('A<CR><Esc>') | ||||
|     eq(3, eval('g:scrolled')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
| end) | ||||
| @@ -257,30 +257,30 @@ describe('WinScrolled', function() | ||||
|  | ||||
|     feed('<C-E>') | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 1, topfill = 1, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1001'] = {leftcol = 0, topline = 0, topfill = -1, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 1, topfill = 1, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1001'] = { leftcol = 0, topline = 0, topfill = -1, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('2<C-E>') | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 2, topfill = 2, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1001'] = {leftcol = 0, topline = 0, topfill = -2, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 2, topfill = 2, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1001'] = { leftcol = 0, topline = 0, topfill = -2, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('<C-E>') | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1001'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1001'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     feed('2<C-Y>') | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 3, topfill = 1, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1000'] = {leftcol = 0, topline = -2, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       ['1001'] = {leftcol = 0, topline = -1, topfill = 1, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 3, topfill = 1, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1000'] = { leftcol = 0, topline = -2, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       ['1001'] = { leftcol = 0, topline = -1, topfill = 1, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
|  | ||||
| @@ -297,14 +297,20 @@ describe('WinScrolled', function() | ||||
|     eq(0, eval('g:scrolled')) | ||||
|  | ||||
|     local buf = meths.create_buf(true, true) | ||||
|     meths.buf_set_lines(buf, 0, -1, false, {'@', 'b', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}) | ||||
|     meths.buf_set_lines( | ||||
|       buf, | ||||
|       0, | ||||
|       -1, | ||||
|       false, | ||||
|       { '@', 'b', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n' } | ||||
|     ) | ||||
|     local win = meths.open_win(buf, false, { | ||||
|       height = 5, | ||||
|       width = 10, | ||||
|       col = 0, | ||||
|       row = 1, | ||||
|       relative = 'editor', | ||||
|       style = 'minimal' | ||||
|       style = 'minimal', | ||||
|     }) | ||||
|     screen:expect({ any = '@' }) | ||||
|     local winid_str = tostring(win.id) | ||||
| @@ -315,16 +321,16 @@ describe('WinScrolled', function() | ||||
|     eq(1, eval('g:scrolled')) | ||||
|     eq(winid_str, eval('g:amatch')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       [winid_str] = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       [winid_str] = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|  | ||||
|     meths.input_mouse('wheel', 'up', '', 0, 3, 3) | ||||
|     eq(2, eval('g:scrolled')) | ||||
|     eq(tostring(win.id), eval('g:amatch')) | ||||
|     eq({ | ||||
|       all = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       [winid_str] = {leftcol = 0, topline = -3, topfill = 0, width = 0, height = 0, skipcol = 0}, | ||||
|       all = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|       [winid_str] = { leftcol = 0, topline = -3, topfill = 0, width = 0, height = 0, skipcol = 0 }, | ||||
|     }, eval('g:v_event')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local clear, eq, eval, next_msg, ok, source = helpers.clear, helpers.eq, | ||||
|    helpers.eval, helpers.next_msg, helpers.ok, helpers.source | ||||
| local clear, eq, eval, next_msg, ok, source = | ||||
|   helpers.clear, helpers.eq, helpers.eval, helpers.next_msg, helpers.ok, helpers.source | ||||
| local command, funcs, meths = helpers.command, helpers.funcs, helpers.meths | ||||
| local sleep = helpers.sleep | ||||
| local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv | ||||
| @@ -40,7 +40,7 @@ describe('channels', function() | ||||
|  | ||||
|     meths.set_var('address', address) | ||||
|     command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})") | ||||
|     local id = eval("g:id") | ||||
|     local id = eval('g:id') | ||||
|     ok(id > 0) | ||||
|  | ||||
|     command("call chansend(g:id, msgpackdump([[2,'nvim_set_var',['code',23]]]))") | ||||
| @@ -52,12 +52,11 @@ describe('channels', function() | ||||
|  | ||||
|     command("call chansend(g:id, msgpackdump([[0,0,'nvim_eval',['2+3']]]))") | ||||
|  | ||||
|  | ||||
|     local res = eval("msgpackdump([[1,0,v:null,5]])") | ||||
|     eq({"\148\001\n\192\005"}, res) | ||||
|     eq({'notification', 'data', {id, res}}, next_msg()) | ||||
|     local res = eval('msgpackdump([[1,0,v:null,5]])') | ||||
|     eq({ '\148\001\n\192\005' }, res) | ||||
|     eq({ 'notification', 'data', { id, res } }, next_msg()) | ||||
|     command("call chansend(g:id, msgpackdump([[2,'nvim_command',['quit']]]))") | ||||
|     eq({'notification', 'data', {id, {''}}}, next_msg()) | ||||
|     eq({ 'notification', 'data', { id, { '' } } }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('can use stdio channel', function() | ||||
| @@ -68,8 +67,10 @@ describe('channels', function() | ||||
|       \ 'on_exit': function('OnEvent'), | ||||
|       \ } | ||||
|     ]]) | ||||
|     meths.set_var("nvim_prog", nvim_prog) | ||||
|     meths.set_var("code", [[ | ||||
|     meths.set_var('nvim_prog', nvim_prog) | ||||
|     meths.set_var( | ||||
|       'code', | ||||
|       [[ | ||||
|       function! OnEvent(id, data, event) dict | ||||
|         let text = string([a:id, a:data, a:event]) | ||||
|         call chansend(g:x, text) | ||||
| @@ -81,25 +82,31 @@ describe('channels', function() | ||||
|       endfunction | ||||
|       let g:x = stdioopen({'on_stdin':'OnEvent'}) | ||||
|       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") | ||||
|     ]] | ||||
|     ) | ||||
|     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()) | ||||
|     eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg()) | ||||
|  | ||||
|     command("call chansend(id, 'howdy')") | ||||
|     eq({"notification", "stdout", {id, {"[1, ['howdy'], 'stdin']"}}}, next_msg()) | ||||
|     eq({ 'notification', 'stdout', { id, { "[1, ['howdy'], 'stdin']" } } }, next_msg()) | ||||
|  | ||||
|     command("call chansend(id, 0z686f6c61)") | ||||
|     eq({"notification", "stdout", {id, {"[1, ['hola'], 'stdin']"}}}, next_msg()) | ||||
|     command('call chansend(id, 0z686f6c61)') | ||||
|     eq({ 'notification', 'stdout', { id, { "[1, ['hola'], 'stdin']" } } }, next_msg()) | ||||
|  | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|     expect_twostreams({{"notification", "stdout", {id, {"[1, [''], 'stdin']"}}}, | ||||
|                        {'notification', 'stdout', {id, {''}}}}, | ||||
|                       {{"notification", "stderr", {id, {"*dies*"}}}, | ||||
|                        {'notification', 'stderr', {id, {''}}}}) | ||||
|     eq({"notification", "exit", {3,0}}, next_msg()) | ||||
|     expect_twostreams({ | ||||
|       { 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } }, | ||||
|       { 'notification', 'stdout', { id, { '' } } }, | ||||
|     }, { | ||||
|       { 'notification', 'stderr', { id, { '*dies*' } } }, | ||||
|       { 'notification', 'stderr', { id, { '' } } }, | ||||
|     }) | ||||
|     eq({ 'notification', 'exit', { 3, 0 } }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('can use stdio channel and on_print callback', function() | ||||
| @@ -110,8 +117,10 @@ describe('channels', function() | ||||
|       \ 'on_exit': function('OnEvent'), | ||||
|       \ } | ||||
|     ]]) | ||||
|     meths.set_var("nvim_prog", nvim_prog) | ||||
|     meths.set_var("code", [[ | ||||
|     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 == [''] | ||||
| @@ -123,24 +132,27 @@ describe('channels', function() | ||||
|       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") | ||||
|     ]] | ||||
|     ) | ||||
|     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()) | ||||
|     eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg()) | ||||
|  | ||||
|     command("call chansend(id, 'howdy')") | ||||
|     eq({"notification", "stdout", {id, {"OnPrint:[1, ['howdy'], 'stdin']"}}}, next_msg()) | ||||
|     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} | ||||
|     if not pcall(eq, {"notification", stream, {id, joined}}, msg) then | ||||
|       local sep = (not nobr) and "" or nil | ||||
|       eq({"notification", stream, {id, {line1, sep}}}, msg) | ||||
|       eq({"notification", stream, {id, {line2}}}, next_msg()) | ||||
|     local joined = nobr and { line1 .. line2 } or { line1, line2 } | ||||
|     if not pcall(eq, { 'notification', stream, { id, joined } }, msg) then | ||||
|       local sep = (not nobr) and '' or nil | ||||
|       eq({ 'notification', stream, { id, { line1, sep } } }, msg) | ||||
|       eq({ 'notification', stream, { id, { line2 } } }, next_msg()) | ||||
|     end | ||||
|   end | ||||
|  | ||||
| @@ -153,50 +165,52 @@ describe('channels', function() | ||||
|       \ 'pty': v:true, | ||||
|       \ } | ||||
|     ]]) | ||||
|     meths.set_var("nvim_prog", nvim_prog) | ||||
|     meths.set_var("code", [[ | ||||
|     meths.set_var('nvim_prog', nvim_prog) | ||||
|     meths.set_var( | ||||
|       'code', | ||||
|       [[ | ||||
|       function! OnEvent(id, data, event) dict | ||||
|         let text = string([a:id, a:data, a:event]) | ||||
|         call chansend(g:x, text) | ||||
|       endfunction | ||||
|       let g:x = stdioopen({'on_stdin':'OnEvent'}) | ||||
|     ]]) | ||||
|     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") | ||||
|     ]] | ||||
|     ) | ||||
|     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) | ||||
|  | ||||
|     command("call chansend(id, 'TEXT\n')") | ||||
|     expect_twoline(id, "stdout", "TEXT\r", "[1, ['TEXT', ''], 'stdin']") | ||||
|     expect_twoline(id, 'stdout', 'TEXT\r', "[1, ['TEXT', ''], 'stdin']") | ||||
|  | ||||
|     command("call chansend(id, 0z426c6f6273210a)") | ||||
|     expect_twoline(id, "stdout", "Blobs!\r", "[1, ['Blobs!', ''], 'stdin']") | ||||
|     command('call chansend(id, 0z426c6f6273210a)') | ||||
|     expect_twoline(id, 'stdout', 'Blobs!\r', "[1, ['Blobs!', ''], 'stdin']") | ||||
|  | ||||
|     command("call chansend(id, 'neovan')") | ||||
|     eq({"notification", "stdout", {id, {"neovan"}}}, next_msg()) | ||||
|     eq({ 'notification', 'stdout', { id, { 'neovan' } } }, next_msg()) | ||||
|     command("call chansend(id, '\127\127im\n')") | ||||
|     expect_twoline(id, "stdout", "\b \b\b \bim\r", "[1, ['neovim', ''], 'stdin']") | ||||
|     expect_twoline(id, 'stdout', '\b \b\b \bim\r', "[1, ['neovim', ''], 'stdin']") | ||||
|  | ||||
|     command("call chansend(id, 'incomplet\004')") | ||||
|  | ||||
|     local bsdlike = is_os('bsd') or is_os('mac') | ||||
|     local extra = bsdlike and "^D\008\008" or "" | ||||
|     expect_twoline(id, "stdout", | ||||
|                    "incomplet"..extra, "[1, ['incomplet'], 'stdin']", true) | ||||
|  | ||||
|     local extra = bsdlike and '^D\008\008' or '' | ||||
|     expect_twoline(id, 'stdout', 'incomplet' .. extra, "[1, ['incomplet'], 'stdin']", true) | ||||
|  | ||||
|     command("call chansend(id, '\004')") | ||||
|     if bsdlike then | ||||
|       expect_twoline(id, "stdout", extra, "[1, [''], 'stdin']", true) | ||||
|       expect_twoline(id, 'stdout', extra, "[1, [''], 'stdin']", true) | ||||
|     else | ||||
|       eq({"notification", "stdout", {id, {"[1, [''], 'stdin']"}}}, next_msg()) | ||||
|       eq({ 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } }, next_msg()) | ||||
|     end | ||||
|  | ||||
|     -- channel is still open | ||||
|     command("call chansend(id, 'hi again!\n')") | ||||
|     eq({"notification", "stdout", {id, {"hi again!\r", ""}}}, next_msg()) | ||||
|     eq({ 'notification', 'stdout', { id, { 'hi again!\r', '' } } }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   it('stdio channel can use rpc and stderr simultaneously', function() | ||||
|     skip(is_os('win')) | ||||
|     source([[ | ||||
| @@ -206,27 +220,33 @@ describe('channels', function() | ||||
|       \ 'rpc': v:true, | ||||
|       \ } | ||||
|     ]]) | ||||
|     meths.set_var("nvim_prog", nvim_prog) | ||||
|     meths.set_var("code", [[ | ||||
|     meths.set_var('nvim_prog', nvim_prog) | ||||
|     meths.set_var( | ||||
|       'code', | ||||
|       [[ | ||||
|       let id = stdioopen({'rpc':v:true}) | ||||
|       call rpcnotify(id,"nvim_call_function", "rpcnotify", [1, "message", "hi there!", id]) | ||||
|       call chansend(v:stderr, "trouble!") | ||||
|     ]]) | ||||
|     command("let id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)") | ||||
|     eq({"notification", "message", {"hi there!", 1}}, next_msg()) | ||||
|     eq({"notification", "stderr", {3, {"trouble!"}}}, next_msg()) | ||||
|     ]] | ||||
|     ) | ||||
|     command( | ||||
|       "let id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)" | ||||
|     ) | ||||
|     eq({ 'notification', 'message', { 'hi there!', 1 } }, next_msg()) | ||||
|     eq({ 'notification', 'stderr', { 3, { 'trouble!' } } }, next_msg()) | ||||
|  | ||||
|     eq(30, eval("rpcrequest(id, 'nvim_eval', '[chansend(v:stderr, \"math??\"), 5*6][1]')")) | ||||
|     eq({"notification", "stderr", {3, {"math??"}}}, next_msg()) | ||||
|     eq({ 'notification', 'stderr', { 3, { 'math??' } } }, next_msg()) | ||||
|  | ||||
|     local _, err = pcall(command,"call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')") | ||||
|     ok(string.find(err,"E906: invalid stream for channel") ~= nil) | ||||
|     local _, err = | ||||
|       pcall(command, "call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')") | ||||
|     ok(string.find(err, 'E906: invalid stream for channel') ~= nil) | ||||
|  | ||||
|     eq(1, eval("rpcrequest(id, 'nvim_eval', 'chanclose(v:stderr, \"stderr\")')")) | ||||
|     eq({"notification", "stderr", {3, {""}}}, next_msg()) | ||||
|     eq({ 'notification', 'stderr', { 3, { '' } } }, next_msg()) | ||||
|  | ||||
|     command("call rpcnotify(id, 'nvim_command', 'quit')") | ||||
|     eq({"notification", "exit", {3, 0}}, next_msg()) | ||||
|     eq({ 'notification', 'exit', { 3, 0 } }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('can use buffered output mode', function() | ||||
| @@ -239,27 +259,29 @@ describe('channels', function() | ||||
|       \ } | ||||
|     ]]) | ||||
|     command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") | ||||
|     local id = eval("g:id") | ||||
|     local id = eval('g:id') | ||||
|  | ||||
|     command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]]) | ||||
|     sleep(10) | ||||
|     command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]]) | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|  | ||||
|     eq({"notification", "stdout", {id, {'10 PRINT "NVIM"', | ||||
|                                        '20 GOTO 10', ''}}}, next_msg()) | ||||
|     eq({"notification", "exit", {id, 0}}, next_msg()) | ||||
|     eq({ | ||||
|       'notification', | ||||
|       'stdout', | ||||
|       { id, { '10 PRINT "NVIM"', '20 GOTO 10', '' } }, | ||||
|     }, next_msg()) | ||||
|     eq({ 'notification', 'exit', { id, 0 } }, next_msg()) | ||||
|  | ||||
|     command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") | ||||
|     id = eval("g:id") | ||||
|     id = eval('g:id') | ||||
|  | ||||
|     command([[call chansend(id, "is no number\nnot at all")]]) | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|  | ||||
|     -- works correctly with no output | ||||
|     eq({"notification", "stdout", {id, {''}}}, next_msg()) | ||||
|     eq({"notification", "exit", {id, 1}}, next_msg()) | ||||
|  | ||||
|     eq({ 'notification', 'stdout', { id, { '' } } }, next_msg()) | ||||
|     eq({ 'notification', 'exit', { id, 1 } }, next_msg()) | ||||
|   end) | ||||
|  | ||||
|   it('can use buffered output mode with no stream callback', function() | ||||
| @@ -274,31 +296,40 @@ describe('channels', function() | ||||
|       \ } | ||||
|     ]]) | ||||
|     command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") | ||||
|     local id = eval("g:id") | ||||
|     local id = eval('g:id') | ||||
|  | ||||
|     command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]]) | ||||
|     sleep(10) | ||||
|     command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]]) | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|  | ||||
|     eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"', | ||||
|                                          '20 GOTO 10', ''}}}, next_msg()) | ||||
|     eq({ | ||||
|       'notification', | ||||
|       'exit', | ||||
|       { id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } }, | ||||
|     }, next_msg()) | ||||
|  | ||||
|     -- if dict is reused the new value is not stored, | ||||
|     -- but nvim also does not crash | ||||
|     command("let id = jobstart(['cat'], g:job_opts)") | ||||
|     id = eval("g:id") | ||||
|     id = eval('g:id') | ||||
|  | ||||
|     command([[call chansend(id, "cat text\n")]]) | ||||
|     sleep(10) | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|  | ||||
|     -- old value was not overwritten | ||||
|     eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"', | ||||
|                                          '20 GOTO 10', ''}}}, next_msg()) | ||||
|     eq({ | ||||
|       'notification', | ||||
|       'exit', | ||||
|       { id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } }, | ||||
|     }, next_msg()) | ||||
|  | ||||
|     -- and an error was thrown. | ||||
|     eq("E5210: dict key 'stdout' already set for buffered stream in channel "..id, eval('v:errmsg')) | ||||
|     eq( | ||||
|       "E5210: dict key 'stdout' already set for buffered stream in channel " .. id, | ||||
|       eval('v:errmsg') | ||||
|     ) | ||||
|  | ||||
|     -- reset dictionary | ||||
|     source([[ | ||||
| @@ -308,13 +339,13 @@ describe('channels', function() | ||||
|       \ } | ||||
|     ]]) | ||||
|     command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") | ||||
|     id = eval("g:id") | ||||
|     id = eval('g:id') | ||||
|  | ||||
|     command([[call chansend(id, "is no number\nnot at all")]]) | ||||
|     command("call chanclose(id, 'stdin')") | ||||
|  | ||||
|     -- works correctly with no output | ||||
|     eq({"notification", "exit", {id, 1, {''}}}, next_msg()) | ||||
|     eq({ 'notification', 'exit', { id, 1, { '' } } }, next_msg()) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -325,8 +356,10 @@ describe('loopback', function() | ||||
|   end) | ||||
|  | ||||
|   it('does not crash when sending raw data', function() | ||||
|     eq("Vim(call):Can't send raw data to rpc channel", | ||||
|        pcall_err(command, "call chansend(chan, 'test')")) | ||||
|     eq( | ||||
|       "Vim(call):Can't send raw data to rpc channel", | ||||
|       pcall_err(command, "call chansend(chan, 'test')") | ||||
|     ) | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
|   | ||||
| @@ -27,8 +27,8 @@ describe('v:exiting', function() | ||||
|  | ||||
|   local function test_exiting(setup_fn) | ||||
|     local function on_setup() | ||||
|       command('autocmd VimLeavePre * call rpcrequest('..cid..', "exit", "VimLeavePre")') | ||||
|       command('autocmd VimLeave    * call rpcrequest('..cid..', "exit", "VimLeave")') | ||||
|       command('autocmd VimLeavePre * call rpcrequest(' .. cid .. ', "exit", "VimLeavePre")') | ||||
|       command('autocmd VimLeave    * call rpcrequest(' .. cid .. ', "exit", "VimLeave")') | ||||
|       setup_fn() | ||||
|     end | ||||
|     local requests_args = {} | ||||
| @@ -39,7 +39,7 @@ describe('v:exiting', function() | ||||
|       return '' | ||||
|     end | ||||
|     run(on_request, nil, on_setup) | ||||
|     eq({{'VimLeavePre'}, {'VimLeave'}}, requests_args) | ||||
|     eq({ { 'VimLeavePre' }, { 'VimLeave' } }, requests_args) | ||||
|   end | ||||
|  | ||||
|   it('is 0 on normal exit', function() | ||||
| @@ -59,11 +59,16 @@ end) | ||||
| describe(':cquit', function() | ||||
|   local function test_cq(cmdline, exit_code, redir_msg) | ||||
|     if redir_msg then | ||||
|       eq(redir_msg, pcall_err(function() return exec_capture(cmdline) end)) | ||||
|       eq( | ||||
|         redir_msg, | ||||
|         pcall_err(function() | ||||
|           return exec_capture(cmdline) | ||||
|         end) | ||||
|       ) | ||||
|       poke_eventloop() | ||||
|       assert_alive() | ||||
|     else | ||||
|       funcs.system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline}) | ||||
|       funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline }) | ||||
|       eq(exit_code, eval('v:shell_error')) | ||||
|     end | ||||
|   end | ||||
|   | ||||
| @@ -34,8 +34,7 @@ local spawn = helpers.spawn | ||||
| local set_session = helpers.set_session | ||||
|  | ||||
| describe('fileio', function() | ||||
|   before_each(function() | ||||
|   end) | ||||
|   before_each(function() end) | ||||
|   after_each(function() | ||||
|     check_close() | ||||
|     os.remove('Xtest_startup_shada') | ||||
| @@ -51,25 +50,25 @@ describe('fileio', function() | ||||
|     rmdir('Xtest_backupdir with spaces') | ||||
|   end) | ||||
|  | ||||
|   local args = { nvim_prog, '--clean', '--cmd', 'set nofsync directory=Xtest_startup_swapdir', } | ||||
|   local args = { nvim_prog, '--clean', '--cmd', 'set nofsync directory=Xtest_startup_swapdir' } | ||||
|   --- Starts a new nvim session and returns an attached screen. | ||||
|   local function startup(extra_args) | ||||
|     extra_args = extra_args or {} | ||||
|     local argv = vim.tbl_flatten({args, '--embed', extra_args}) | ||||
|     local argv = vim.tbl_flatten({ args, '--embed', extra_args }) | ||||
|     local screen_nvim = spawn(argv) | ||||
|     set_session(screen_nvim) | ||||
|     local screen = Screen.new(70, 10) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {foreground = Screen.colors.NvimDarkGrey4}; | ||||
|       [2] = {background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3}; | ||||
|       [3] = {foreground = Screen.colors.NvimLightCyan}; | ||||
|       [1] = { foreground = Screen.colors.NvimDarkGrey4 }, | ||||
|       [2] = { background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3 }, | ||||
|       [3] = { foreground = Screen.colors.NvimLightCyan }, | ||||
|     }) | ||||
|     return screen | ||||
|   end | ||||
|  | ||||
|   it("fsync() with 'nofsync' #8304", function() | ||||
|     clear({ args={ '--cmd', 'set nofsync directory=Xtest_startup_swapdir', } }) | ||||
|     clear({ args = { '--cmd', 'set nofsync directory=Xtest_startup_swapdir' } }) | ||||
|  | ||||
|     -- These cases ALWAYS force fsync (regardless of 'fsync' option): | ||||
|  | ||||
| @@ -101,21 +100,26 @@ describe('fileio', function() | ||||
|     eq('foozubbaz', trim(read_file('Xtest_startup_file1'))) | ||||
|  | ||||
|     -- 4. Exit caused by deadly signal (+ 'swapfile'). | ||||
|     local j = funcs.jobstart(vim.tbl_flatten({args, '--embed'}), {rpc=true}) | ||||
|     funcs.rpcrequest(j, 'nvim_exec2', [[ | ||||
|     local j = funcs.jobstart(vim.tbl_flatten({ args, '--embed' }), { rpc = true }) | ||||
|     funcs.rpcrequest( | ||||
|       j, | ||||
|       'nvim_exec2', | ||||
|       [[ | ||||
|       set nofsync directory=Xtest_startup_swapdir | ||||
|       edit Xtest_startup_file2 | ||||
|       write | ||||
|       put ='fsyncd text' | ||||
|     ]], {}) | ||||
|     ]], | ||||
|       {} | ||||
|     ) | ||||
|     eq('Xtest_startup_swapdir', funcs.rpcrequest(j, 'nvim_eval', '&directory')) | ||||
|     funcs.jobstop(j) -- Send deadly signal. | ||||
|  | ||||
|     local screen = startup() | ||||
|     feed(':recover Xtest_startup_file2<cr>') | ||||
|     screen:expect({any = [[Using swap file "Xtest_startup_swapdir[/\]Xtest_startup_file2%.swp"]]}) | ||||
|     screen:expect({ any = [[Using swap file "Xtest_startup_swapdir[/\]Xtest_startup_file2%.swp"]] }) | ||||
|     feed('<cr>') | ||||
|     screen:expect({any = 'fsyncd text'}) | ||||
|     screen:expect({ any = 'fsyncd text' }) | ||||
|  | ||||
|     -- 5. SIGPWR signal. | ||||
|     -- oldtest: Test_signal_PWR() | ||||
| @@ -123,8 +127,14 @@ describe('fileio', function() | ||||
|  | ||||
|   it('backup #9709', function() | ||||
|     skip(is_ci('cirrus')) | ||||
|     clear({ args={ '-i', 'Xtest_startup_shada', | ||||
|                    '--cmd', 'set directory=Xtest_startup_swapdir' } }) | ||||
|     clear({ | ||||
|       args = { | ||||
|         '-i', | ||||
|         'Xtest_startup_shada', | ||||
|         '--cmd', | ||||
|         'set directory=Xtest_startup_swapdir', | ||||
|       }, | ||||
|     }) | ||||
|  | ||||
|     command('write Xtest_startup_file1') | ||||
|     feed('ifoo<esc>') | ||||
| @@ -137,8 +147,8 @@ describe('fileio', function() | ||||
|     local foobar_contents = trim(read_file('Xtest_startup_file1')) | ||||
|     local bar_contents = trim(read_file('Xtest_startup_file1~')) | ||||
|  | ||||
|     eq('foobar', foobar_contents); | ||||
|     eq('foo', bar_contents); | ||||
|     eq('foobar', foobar_contents) | ||||
|     eq('foo', bar_contents) | ||||
|   end) | ||||
|  | ||||
|   it('backup with full path #11214', function() | ||||
| @@ -154,13 +164,16 @@ describe('fileio', function() | ||||
|     command('write') | ||||
|  | ||||
|     -- Backup filename = fullpath, separators replaced with "%". | ||||
|     local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1', | ||||
|       is_os('win') and '[:/\\]' or '/', '%%') .. '~' | ||||
|     local foo_contents = trim(read_file('Xtest_backupdir/'..backup_file_name)) | ||||
|     local backup_file_name = string.gsub( | ||||
|       currentdir() .. '/Xtest_startup_file1', | ||||
|       is_os('win') and '[:/\\]' or '/', | ||||
|       '%%' | ||||
|     ) .. '~' | ||||
|     local foo_contents = trim(read_file('Xtest_backupdir/' .. backup_file_name)) | ||||
|     local foobar_contents = trim(read_file('Xtest_startup_file1')) | ||||
|  | ||||
|     eq('foobar', foobar_contents); | ||||
|     eq('foo', foo_contents); | ||||
|     eq('foobar', foobar_contents) | ||||
|     eq('foo', foo_contents) | ||||
|   end) | ||||
|  | ||||
|   it('backup with full path with spaces', function() | ||||
| @@ -176,13 +189,16 @@ describe('fileio', function() | ||||
|     command('write') | ||||
|  | ||||
|     -- Backup filename = fullpath, separators replaced with "%". | ||||
|     local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1', | ||||
|       is_os('win') and '[:/\\]' or '/', '%%') .. '~' | ||||
|     local foo_contents = trim(read_file('Xtest_backupdir with spaces/'..backup_file_name)) | ||||
|     local backup_file_name = string.gsub( | ||||
|       currentdir() .. '/Xtest_startup_file1', | ||||
|       is_os('win') and '[:/\\]' or '/', | ||||
|       '%%' | ||||
|     ) .. '~' | ||||
|     local foo_contents = trim(read_file('Xtest_backupdir with spaces/' .. backup_file_name)) | ||||
|     local foobar_contents = trim(read_file('Xtest_startup_file1')) | ||||
|  | ||||
|     eq('foobar', foobar_contents); | ||||
|     eq('foo', foo_contents); | ||||
|     eq('foobar', foobar_contents) | ||||
|     eq('foo', foo_contents) | ||||
|   end) | ||||
|  | ||||
|   it('backup symlinked files #11349', function() | ||||
| @@ -202,11 +218,10 @@ describe('fileio', function() | ||||
|     command('write') | ||||
|  | ||||
|     local backup_raw = read_file(backup_file_name) | ||||
|     neq(nil, backup_raw, "Expected backup file " .. backup_file_name .. "to exist but did not") | ||||
|     neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. 'to exist but did not') | ||||
|     eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents') | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   it('backup symlinked files in first available backupdir #11349', function() | ||||
|     skip(is_ci('cirrus')) | ||||
|     clear() | ||||
| @@ -228,7 +243,7 @@ describe('fileio', function() | ||||
|     command('write') | ||||
|  | ||||
|     local backup_raw = read_file(backup_file_name) | ||||
|     neq(nil, backup_raw, "Expected backup file " .. backup_file_name .. " to exist but did not") | ||||
|     neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. ' to exist but did not') | ||||
|     eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents') | ||||
|   end) | ||||
|  | ||||
| @@ -247,7 +262,7 @@ describe('fileio', function() | ||||
|     table.insert(text, '') | ||||
|     eq(text, funcs.readfile(fname, 'b')) | ||||
|   end) | ||||
|   it('read invalid u8 over INT_MAX doesn\'t segfault', function() | ||||
|   it("read invalid u8 over INT_MAX doesn't segfault", function() | ||||
|     clear() | ||||
|     command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")') | ||||
|     -- This should not segfault | ||||
| @@ -257,18 +272,18 @@ describe('fileio', function() | ||||
|  | ||||
|   it(':w! does not show "file has been changed" warning', function() | ||||
|     clear() | ||||
|     write_file("Xtest-overwrite-forced", 'foobar') | ||||
|     write_file('Xtest-overwrite-forced', 'foobar') | ||||
|     command('set nofixendofline') | ||||
|     local screen = Screen.new(40,4) | ||||
|     local screen = Screen.new(40, 4) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, | ||||
|       [3] = {bold = true, foreground = Screen.colors.SeaGreen4} | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, | ||||
|       [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|     command("set shortmess-=F") | ||||
|     command('set shortmess-=F') | ||||
|  | ||||
|     command("e Xtest-overwrite-forced") | ||||
|     command('e Xtest-overwrite-forced') | ||||
|     screen:expect([[ | ||||
|       ^foobar                                  | | ||||
|       {1:~                                       }|*2 | ||||
| @@ -276,14 +291,14 @@ describe('fileio', function() | ||||
|     ]]) | ||||
|  | ||||
|     -- Get current unix time. | ||||
|     local cur_unix_time = os.time(os.date("!*t")) | ||||
|     local cur_unix_time = os.time(os.date('!*t')) | ||||
|     local future_time = cur_unix_time + 999999 | ||||
|     -- Set the file's access/update time to be | ||||
|     -- greater than the time at which it was created. | ||||
|     local uv = require("luv") | ||||
|     local uv = require('luv') | ||||
|     uv.fs_utime('Xtest-overwrite-forced', future_time, future_time) | ||||
|     -- use async feed_command because nvim basically hangs on the prompt | ||||
|     feed_command("w") | ||||
|     feed_command('w') | ||||
|     screen:expect([[ | ||||
|       {2:WARNING: The file has been changed since}| | ||||
|       {2: reading it!!!}                          | | ||||
| @@ -291,15 +306,15 @@ describe('fileio', function() | ||||
|       ^                                        | | ||||
|     ]]) | ||||
|  | ||||
|     feed("n") | ||||
|     feed("<cr>") | ||||
|     feed('n') | ||||
|     feed('<cr>') | ||||
|     screen:expect([[ | ||||
|       ^foobar                                  | | ||||
|       {1:~                                       }|*2 | ||||
|                                               | | ||||
|     ]]) | ||||
|     -- Use a screen test because the warning does not set v:errmsg. | ||||
|     command("w!") | ||||
|     command('w!') | ||||
|     screen:expect([[ | ||||
|       ^foobar                                  | | ||||
|       {1:~                                       }|*2 | ||||
| @@ -333,7 +348,7 @@ describe('tmpdir', function() | ||||
|   end | ||||
|  | ||||
|   it('failure modes', function() | ||||
|     clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } }) | ||||
|     clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } }) | ||||
|     assert_nolog('tempdir is not a directory', testlog) | ||||
|     assert_nolog('tempdir has invalid permissions', testlog) | ||||
|  | ||||
| @@ -345,7 +360,7 @@ describe('tmpdir', function() | ||||
|     expect_exit(command, ':qall!') | ||||
|     rmdir(tmproot) | ||||
|     write_file(tmproot, '') -- Not a directory, vim_mktempdir() should skip it. | ||||
|     clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } }) | ||||
|     clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } }) | ||||
|     matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir(). | ||||
|     -- Assert that broken tmpdir root was handled. | ||||
|     assert_log('tempdir root not a directory', testlog, 100) | ||||
| @@ -356,7 +371,7 @@ describe('tmpdir', function() | ||||
|     os.remove(tmproot) | ||||
|     mkdir(tmproot) | ||||
|     funcs.setfperm(tmproot, 'rwxr--r--') -- Invalid permissions, vim_mktempdir() should skip it. | ||||
|     clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } }) | ||||
|     clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } }) | ||||
|     matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir(). | ||||
|     -- Assert that broken tmpdir root was handled. | ||||
|     assert_log('tempdir root has invalid permissions', testlog, 100) | ||||
| @@ -365,14 +380,14 @@ describe('tmpdir', function() | ||||
|   it('too long', function() | ||||
|     local bigname = ('%s/%s'):format(os_tmpdir, ('x'):rep(666)) | ||||
|     mkdir(bigname) | ||||
|     clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=bigname, } }) | ||||
|     clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = bigname } }) | ||||
|     matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir(). | ||||
|     local len = (funcs.tempname()):len() | ||||
|     ok(len > 4 and len < 256, '4 < len < 256', tostring(len)) | ||||
|   end) | ||||
|  | ||||
|   it('disappeared #1432', function() | ||||
|     clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } }) | ||||
|     clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } }) | ||||
|     assert_nolog('tempdir disappeared', testlog) | ||||
|  | ||||
|     local function rm_tmpdir() | ||||
| @@ -406,12 +421,13 @@ describe('tmpdir', function() | ||||
|   end) | ||||
|  | ||||
|   it('$NVIM_APPNAME relative path', function() | ||||
|     clear({ env={ | ||||
|       NVIM_APPNAME='a/b', | ||||
|       NVIM_LOG_FILE=testlog, | ||||
|       TMPDIR=os_tmpdir, | ||||
|     } }) | ||||
|     clear({ | ||||
|       env = { | ||||
|         NVIM_APPNAME = 'a/b', | ||||
|         NVIM_LOG_FILE = testlog, | ||||
|         TMPDIR = os_tmpdir, | ||||
|       }, | ||||
|     }) | ||||
|     matches([=[.*[/\\]a%%b%.[^/\\]+]=], funcs.tempname()) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -23,7 +23,7 @@ describe('log', function() | ||||
|     -- calls, that needs investigation. | ||||
|     clear() | ||||
|     eq(0, request('nvim__stats').log_skip) | ||||
|     clear{env={CDPATH='~doesnotexist'}} | ||||
|     clear { env = { CDPATH = '~doesnotexist' } } | ||||
|     assert(request('nvim__stats').log_skip <= 13) | ||||
|   end) | ||||
|  | ||||
| @@ -32,14 +32,16 @@ describe('log', function() | ||||
|     --    ERR 2022-05-29T12:30:03.800 T2         log_init:110: test log message | ||||
|     --    ERR 2022-05-29T12:30:03.814 T2/child   log_init:110: test log message | ||||
|  | ||||
|     clear({env={ | ||||
|       NVIM_LOG_FILE=testlog, | ||||
|     clear({ | ||||
|       env = { | ||||
|         NVIM_LOG_FILE = testlog, | ||||
|         -- TODO: remove this after nvim_log #7062 is merged. | ||||
|       __NVIM_TEST_LOG='1' | ||||
|       }}) | ||||
|         __NVIM_TEST_LOG = '1', | ||||
|       }, | ||||
|     }) | ||||
|  | ||||
|     local tid = _G._nvim_test_id | ||||
|     assert_log(tid..'%.%d+%.%d +server_init:%d+: test log message', testlog, 100) | ||||
|     assert_log(tid .. '%.%d+%.%d +server_init:%d+: test log message', testlog, 100) | ||||
|  | ||||
|     exec_lua([[ | ||||
|       local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict()) | ||||
|   | ||||
| @@ -33,27 +33,44 @@ describe('command-line option', function() | ||||
|  | ||||
|     it('treats - as stdin', function() | ||||
|       eq(nil, luv.fs_stat(fname)) | ||||
|       funcs.system( | ||||
|         {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', | ||||
|          '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|          '-s', '-', fname}, | ||||
|         {':call setline(1, "42")', ':wqall!', ''}) | ||||
|       funcs.system({ | ||||
|         nvim_prog_abs(), | ||||
|         '-u', | ||||
|         'NONE', | ||||
|         '-i', | ||||
|         'NONE', | ||||
|         '--headless', | ||||
|         '--cmd', | ||||
|         'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|         '-s', | ||||
|         '-', | ||||
|         fname, | ||||
|       }, { ':call setline(1, "42")', ':wqall!', '' }) | ||||
|       eq(0, eval('v:shell_error')) | ||||
|       local attrs = luv.fs_stat(fname) | ||||
|       eq(#('42\n'), attrs.size) | ||||
|       eq(#'42\n', attrs.size) | ||||
|     end) | ||||
|  | ||||
|     it('does not expand $VAR', function() | ||||
|       eq(nil, luv.fs_stat(fname)) | ||||
|       eq(true, not not dollar_fname:find('%$%w+')) | ||||
|       write_file(dollar_fname, ':call setline(1, "100500")\n:wqall!\n') | ||||
|       funcs.system( | ||||
|         {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', | ||||
|          '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|          '-s', dollar_fname, fname}) | ||||
|       funcs.system({ | ||||
|         nvim_prog_abs(), | ||||
|         '-u', | ||||
|         'NONE', | ||||
|         '-i', | ||||
|         'NONE', | ||||
|         '--headless', | ||||
|         '--cmd', | ||||
|         'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|         '-s', | ||||
|         dollar_fname, | ||||
|         fname, | ||||
|       }) | ||||
|       eq(0, eval('v:shell_error')) | ||||
|       local attrs = luv.fs_stat(fname) | ||||
|       eq(#('100500\n'), attrs.size) | ||||
|       eq(#'100500\n', attrs.size) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash after reading from stdin in non-headless mode', function() | ||||
| @@ -61,24 +78,33 @@ describe('command-line option', function() | ||||
|       local screen = Screen.new(40, 8) | ||||
|       screen:attach() | ||||
|       local args = { | ||||
|         nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', | ||||
|         '--cmd', '"set noswapfile shortmess+=IFW fileformats=unix notermguicolors"', | ||||
|         '-s', '-' | ||||
|         nvim_prog_abs(), | ||||
|         '-u', | ||||
|         'NONE', | ||||
|         '-i', | ||||
|         'NONE', | ||||
|         '--cmd', | ||||
|         '"set noswapfile shortmess+=IFW fileformats=unix notermguicolors"', | ||||
|         '-s', | ||||
|         '-', | ||||
|       } | ||||
|  | ||||
|       -- Need to explicitly pipe to stdin so that the embedded Nvim instance doesn't try to read | ||||
|       -- data from the terminal #18181 | ||||
|       funcs.termopen(string.format([[echo "" | %s]], table.concat(args, " ")), { | ||||
|         env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } | ||||
|       funcs.termopen(string.format([[echo "" | %s]], table.concat(args, ' ')), { | ||||
|         env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, | ||||
|       }) | ||||
|       screen:expect([[ | ||||
|       screen:expect( | ||||
|         [[ | ||||
|         ^                                        | | ||||
|         ~                                       |*4 | ||||
|         {1:[No Name]             0,0-1          All}| | ||||
|                                                 |*2 | ||||
|       ]], { | ||||
|         [1] = {reverse = true}; | ||||
|       }) | ||||
|       ]], | ||||
|         { | ||||
|           [1] = { reverse = true }, | ||||
|         } | ||||
|       ) | ||||
|       feed('i:cq<CR>') | ||||
|       screen:expect([[ | ||||
|                                                 | | ||||
| @@ -101,12 +127,22 @@ describe('command-line option', function() | ||||
|  | ||||
|     it('errors out when trying to use nonexistent file with -s', function() | ||||
|       eq( | ||||
|         'Cannot open for reading: "'..nonexistent_fname..'": no such file or directory\n', | ||||
|         funcs.system( | ||||
|           {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', | ||||
|            '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|            '--cmd', 'language C', | ||||
|            '-s', nonexistent_fname})) | ||||
|         'Cannot open for reading: "' .. nonexistent_fname .. '": no such file or directory\n', | ||||
|         funcs.system({ | ||||
|           nvim_prog_abs(), | ||||
|           '-u', | ||||
|           'NONE', | ||||
|           '-i', | ||||
|           'NONE', | ||||
|           '--headless', | ||||
|           '--cmd', | ||||
|           'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|           '--cmd', | ||||
|           'language C', | ||||
|           '-s', | ||||
|           nonexistent_fname, | ||||
|         }) | ||||
|       ) | ||||
|       eq(2, eval('v:shell_error')) | ||||
|     end) | ||||
|  | ||||
| @@ -114,12 +150,25 @@ describe('command-line option', function() | ||||
|       write_file(fname, ':call setline(1, "1")\n:wqall!\n') | ||||
|       write_file(dollar_fname, ':call setline(1, "2")\n:wqall!\n') | ||||
|       eq( | ||||
|         'Attempt to open script file again: "-s '..dollar_fname..'"\n', | ||||
|         funcs.system( | ||||
|           {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', | ||||
|            '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|            '--cmd', 'language C', | ||||
|            '-s', fname, '-s', dollar_fname, fname_2})) | ||||
|         'Attempt to open script file again: "-s ' .. dollar_fname .. '"\n', | ||||
|         funcs.system({ | ||||
|           nvim_prog_abs(), | ||||
|           '-u', | ||||
|           'NONE', | ||||
|           '-i', | ||||
|           'NONE', | ||||
|           '--headless', | ||||
|           '--cmd', | ||||
|           'set noswapfile shortmess+=IFW fileformats=unix', | ||||
|           '--cmd', | ||||
|           'language C', | ||||
|           '-s', | ||||
|           fname, | ||||
|           '-s', | ||||
|           dollar_fname, | ||||
|           fname_2, | ||||
|         }) | ||||
|       ) | ||||
|       eq(2, eval('v:shell_error')) | ||||
|       eq(nil, luv.fs_stat(fname_2)) | ||||
|     end) | ||||
| @@ -128,7 +177,7 @@ describe('command-line option', function() | ||||
|   it('nvim -v, :version', function() | ||||
|     matches('Run ":verbose version"', funcs.execute(':version')) | ||||
|     matches('Compilation: .*Run :checkhealth', funcs.execute(':verbose version')) | ||||
|     matches('Run "nvim %-V1 %-v"', funcs.system({nvim_prog_abs(), '-v'})) | ||||
|     matches('Compilation: .*Run :checkhealth', funcs.system({nvim_prog_abs(), '-V1', '-v'})) | ||||
|     matches('Run "nvim %-V1 %-v"', funcs.system({ nvim_prog_abs(), '-v' })) | ||||
|     matches('Compilation: .*Run :checkhealth', funcs.system({ nvim_prog_abs(), '-V1', '-v' })) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ local write_file = helpers.write_file | ||||
|  | ||||
| local function join_path(...) | ||||
|   local pathsep = (is_os('win') and '\\' or '/') | ||||
|   return table.concat({...}, pathsep) | ||||
|   return table.concat({ ... }, pathsep) | ||||
| end | ||||
|  | ||||
| describe('path collapse', function() | ||||
| @@ -23,40 +23,40 @@ describe('path collapse', function() | ||||
|   before_each(function() | ||||
|     targetdir = join_path('test', 'functional', 'fixtures') | ||||
|     clear() | ||||
|     command('edit '..join_path(targetdir, 'tty-test.c')) | ||||
|     command('edit ' .. join_path(targetdir, 'tty-test.c')) | ||||
|     expected_path = eval('expand("%:p")') | ||||
|   end) | ||||
|  | ||||
|   it('with /./ segment #7117', function() | ||||
|     command('edit '..join_path(targetdir, '.', 'tty-test.c')) | ||||
|     command('edit ' .. join_path(targetdir, '.', 'tty-test.c')) | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
|  | ||||
|   it('with ./ prefix #7117', function() | ||||
|     command('edit '..join_path('.', targetdir, 'tty-test.c')) | ||||
|     command('edit ' .. join_path('.', targetdir, 'tty-test.c')) | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
|  | ||||
|   it('with ./ prefix, after directory change #7117', function() | ||||
|     command('edit '..join_path('.', targetdir, 'tty-test.c')) | ||||
|     command('edit ' .. join_path('.', targetdir, 'tty-test.c')) | ||||
|     command('cd test') | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
|  | ||||
|   it('with /../ segment #7117', function() | ||||
|     command('edit '..join_path(targetdir, '..', 'fixtures', 'tty-test.c')) | ||||
|     command('edit ' .. join_path(targetdir, '..', 'fixtures', 'tty-test.c')) | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
|  | ||||
|   it('with ../ and different starting directory #7117', function() | ||||
|     command('cd test') | ||||
|     command('edit '..join_path('..', targetdir, 'tty-test.c')) | ||||
|     command('edit ' .. join_path('..', targetdir, 'tty-test.c')) | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
|  | ||||
|   it('with ./../ and different starting directory #7117', function() | ||||
|     command('cd test') | ||||
|     command('edit '..join_path('.', '..', targetdir, 'tty-test.c')) | ||||
|     command('edit ' .. join_path('.', '..', targetdir, 'tty-test.c')) | ||||
|     eq(expected_path, eval('expand("%:p")')) | ||||
|   end) | ||||
| end) | ||||
| @@ -67,16 +67,16 @@ describe('expand wildcard', function() | ||||
|   it('with special characters #24421', function() | ||||
|     local folders = is_os('win') and { | ||||
|       '{folder}', | ||||
|       'folder$name' | ||||
|       'folder$name', | ||||
|     } or { | ||||
|       'folder-name', | ||||
|       '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..'/*")')) | ||||
|       eq(file, eval('expand("' .. folder .. '/*")')) | ||||
|       rmdir(folder) | ||||
|     end | ||||
|   end) | ||||
| @@ -131,14 +131,30 @@ describe('file search', function() | ||||
|     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]]) | ||||
|     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]]) | ||||
|     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) | ||||
|  | ||||
|   ---@param funcname 'finddir' | 'findfile' | ||||
|   | ||||
| @@ -51,7 +51,10 @@ describe('Remote', function() | ||||
|       local client_starter = spawn(new_argv(), false, nil, true) | ||||
|       set_session(client_starter) | ||||
|       -- Call jobstart() and jobwait() in the same RPC request to reduce flakiness. | ||||
|       eq({ 0 }, exec_lua([[return vim.fn.jobwait({ vim.fn.jobstart({...}, { | ||||
|       eq( | ||||
|         { 0 }, | ||||
|         exec_lua( | ||||
|           [[return vim.fn.jobwait({ vim.fn.jobstart({...}, { | ||||
|         stdout_buffered = true, | ||||
|         stderr_buffered = true, | ||||
|         on_stdout = function(_, data, _) | ||||
| @@ -60,7 +63,15 @@ describe('Remote', function() | ||||
|         on_stderr = function(_, data, _) | ||||
|           _G.Remote_stderr = table.concat(data, '\n') | ||||
|         end, | ||||
|       }) })]], nvim_prog, '--clean', '--headless', '--server', addr, ...)) | ||||
|       }) })]], | ||||
|           nvim_prog, | ||||
|           '--clean', | ||||
|           '--headless', | ||||
|           '--server', | ||||
|           addr, | ||||
|           ... | ||||
|         ) | ||||
|       ) | ||||
|       local res = exec_lua([[return { _G.Remote_stdout, _G.Remote_stderr }]]) | ||||
|       client_starter:close() | ||||
|       set_session(server) | ||||
| @@ -95,7 +106,7 @@ describe('Remote', function() | ||||
|     end) | ||||
|  | ||||
|     it('send keys', function() | ||||
|       eq({ '', '' }, run_remote('--remote-send', ':edit '..fname..'<CR><C-W>v')) | ||||
|       eq({ '', '' }, run_remote('--remote-send', ':edit ' .. fname .. '<CR><C-W>v')) | ||||
|       expect(contents) | ||||
|       eq(2, #funcs.getwininfo()) | ||||
|       -- Only a single buffer as we're using edit and not drop like --remote does | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -30,9 +30,11 @@ describe('K', function() | ||||
|       set keywordprg=echo\ fnord>>]]) | ||||
|  | ||||
|     -- K on the text "K_spec_out" resolves to `!echo fnord >> K_spec_out`. | ||||
|     feed('i'..test_file..'<ESC>K') | ||||
|     retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end) | ||||
|     eq({'fnord'}, eval("readfile('"..test_file.."')")) | ||||
|     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()')) | ||||
| @@ -60,9 +62,8 @@ describe('K', function() | ||||
|  | ||||
|   it('empty string falls back to :help #19298', function() | ||||
|     meths.set_option_value('keywordprg', '', {}) | ||||
|     meths.buf_set_lines(0, 0, -1, true, {'doesnotexist'}) | ||||
|     meths.buf_set_lines(0, 0, -1, true, { 'doesnotexist' }) | ||||
|     feed('K') | ||||
|     eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg')) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -18,17 +18,17 @@ describe('completion', function() | ||||
|     screen = Screen.new(60, 8) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold=true, foreground=Screen.colors.Blue}, | ||||
|       [1] = {background = Screen.colors.LightMagenta}, | ||||
|       [2] = {background = Screen.colors.Grey}, | ||||
|       [3] = {bold = true}, | ||||
|       [4] = {bold = true, foreground = Screen.colors.SeaGreen}, | ||||
|       [5] = {foreground = Screen.colors.Red}, | ||||
|       [6] = {background = Screen.colors.Black}, | ||||
|       [7] = {foreground = Screen.colors.White, background = Screen.colors.Red}, | ||||
|       [8] = {reverse = true}, | ||||
|       [9] = {bold = true, reverse = true}, | ||||
|       [10] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow}, | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, | ||||
|       [1] = { background = Screen.colors.LightMagenta }, | ||||
|       [2] = { background = Screen.colors.Grey }, | ||||
|       [3] = { bold = true }, | ||||
|       [4] = { bold = true, foreground = Screen.colors.SeaGreen }, | ||||
|       [5] = { foreground = Screen.colors.Red }, | ||||
|       [6] = { background = Screen.colors.Black }, | ||||
|       [7] = { foreground = Screen.colors.White, background = Screen.colors.Red }, | ||||
|       [8] = { reverse = true }, | ||||
|       [9] = { bold = true, reverse = true }, | ||||
|       [10] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, | ||||
|     }) | ||||
|   end) | ||||
|  | ||||
| @@ -57,9 +57,10 @@ describe('completion', function() | ||||
|     it('returns expected dict in normal completion', function() | ||||
|       feed('ifoo<ESC>o<C-x><C-n>') | ||||
|       eq('foo', eval('getline(2)')) | ||||
|       eq({word = 'foo', abbr = '', menu = '', | ||||
|           info = '', kind = '', user_data = ''}, | ||||
|         eval('v:completed_item')) | ||||
|       eq( | ||||
|         { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' }, | ||||
|         eval('v:completed_item') | ||||
|       ) | ||||
|     end) | ||||
|     it('is readonly', function() | ||||
|       screen:try_resize(80, 8) | ||||
| @@ -107,9 +108,14 @@ describe('completion', function() | ||||
|         {0:~                                                           }|*4 | ||||
|         {3:-- Omni completion (^O^N^P) }{4:match 1 of 2}                    | | ||||
|       ]]) | ||||
|       eq({word = 'foo', abbr = 'bar', menu = 'baz', | ||||
|           info = 'foobar', kind = 'foobaz', user_data = ''}, | ||||
|         eval('v:completed_item')) | ||||
|       eq({ | ||||
|         word = 'foo', | ||||
|         abbr = 'bar', | ||||
|         menu = 'baz', | ||||
|         info = 'foobar', | ||||
|         kind = 'foobaz', | ||||
|         user_data = '', | ||||
|       }, eval('v:completed_item')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -286,8 +292,8 @@ describe('completion', function() | ||||
|     end) | ||||
|  | ||||
|     local tests = { | ||||
|       ['<up>, <down>, <cr>'] = {'<down><cr>', '<up><cr>'}, | ||||
|       ['<c-n>, <c-p>, <c-y>'] = {'<c-n><c-y>', '<c-p><c-y>'}, | ||||
|       ['<up>, <down>, <cr>'] = { '<down><cr>', '<up><cr>' }, | ||||
|       ['<c-n>, <c-p>, <c-y>'] = { '<c-n><c-y>', '<c-p><c-y>' }, | ||||
|     } | ||||
|  | ||||
|     for name, seq in pairs(tests) do | ||||
| @@ -303,13 +309,13 @@ describe('completion', function() | ||||
|         feed('A<right><esc>A<right><esc>') | ||||
|  | ||||
|         local expected = { | ||||
|           {'foo', 'bar', 'foo'}, | ||||
|           {'foo', 'bar', 'ccc'}, | ||||
|           {'foo', 'bar'}, | ||||
|           {'foo', 'bbb'}, | ||||
|           {'foo'}, | ||||
|           {'aaa'}, | ||||
|           {''}, | ||||
|           { 'foo', 'bar', 'foo' }, | ||||
|           { 'foo', 'bar', 'ccc' }, | ||||
|           { 'foo', 'bar' }, | ||||
|           { 'foo', 'bbb' }, | ||||
|           { 'foo' }, | ||||
|           { 'aaa' }, | ||||
|           { '' }, | ||||
|         } | ||||
|  | ||||
|         for i = 1, #expected do | ||||
| @@ -329,7 +335,7 @@ describe('completion', function() | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   describe("refresh:always", function() | ||||
|   describe('refresh:always', function() | ||||
|     before_each(function() | ||||
|       source([[ | ||||
|         function! TestCompletion(findstart, base) abort | ||||
| @@ -354,9 +360,9 @@ describe('completion', function() | ||||
|         set completeopt=menuone,noselect | ||||
|         set completefunc=TestCompletion | ||||
|       ]]) | ||||
|     end ) | ||||
|     end) | ||||
|  | ||||
|     it('completes on each input char', function () | ||||
|     it('completes on each input char', function() | ||||
|       feed('i<C-x><C-u>') | ||||
|       screen:expect([[ | ||||
|         ^                                                            | | ||||
| @@ -402,7 +408,7 @@ describe('completion', function() | ||||
|       expect('August') | ||||
|     end) | ||||
|  | ||||
|     it("repeats correctly after backspace #2674", function () | ||||
|     it('repeats correctly after backspace #2674', function() | ||||
|       feed('o<C-x><C-u>Ja') | ||||
|       screen:expect([[ | ||||
|                                                                     | | ||||
| @@ -471,10 +477,10 @@ describe('completion', function() | ||||
|         return '' | ||||
|       endfunction | ||||
|       ]]) | ||||
|       feed_command("set completeopt=menuone,noselect") | ||||
|       feed_command('set completeopt=menuone,noselect') | ||||
|     end) | ||||
|  | ||||
|     it("works", function() | ||||
|     it('works', function() | ||||
|       feed('i<C-r>=TestComplete()<CR>') | ||||
|       screen:expect([[ | ||||
|         ^                                                            | | ||||
| @@ -630,7 +636,7 @@ describe('completion', function() | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it("does not indent until an item is selected #8345", function () | ||||
|   it('does not indent until an item is selected #8345', function() | ||||
|     -- Indents on "ind", unindents on "unind". | ||||
|     source([[ | ||||
|       function! TestIndent() | ||||
| @@ -649,14 +655,14 @@ describe('completion', function() | ||||
|     ]]) | ||||
|  | ||||
|     -- Give some words to complete. | ||||
|     feed("iinc uninc indent unindent<CR>") | ||||
|     feed('iinc uninc indent unindent<CR>') | ||||
|  | ||||
|     -- Does not indent when "ind" is typed. | ||||
|     feed("in<C-X><C-N>") | ||||
|     feed('in<C-X><C-N>') | ||||
|     -- Completion list is generated incorrectly if we send everything at once | ||||
|     -- via nvim_input().  So poke_eventloop() before sending <BS>. #8480 | ||||
|     poke_eventloop() | ||||
|     feed("<BS>d") | ||||
|     feed('<BS>d') | ||||
|  | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
| @@ -667,7 +673,7 @@ describe('completion', function() | ||||
|     ]]) | ||||
|  | ||||
|     -- Indents when the item is selected | ||||
|     feed("<C-Y>") | ||||
|     feed('<C-Y>') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent^                                              | | ||||
| @@ -675,7 +681,7 @@ describe('completion', function() | ||||
|       {3:-- INSERT --}                                                | | ||||
|     ]]) | ||||
|     -- Indents when completion is exited using ESC. | ||||
|     feed("<CR>in<C-N><BS>d<Esc>") | ||||
|     feed('<CR>in<C-N><BS>d<Esc>') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent                                              | | ||||
| @@ -684,9 +690,9 @@ describe('completion', function() | ||||
|                                                                   | | ||||
|     ]]) | ||||
|     -- Works for unindenting too. | ||||
|     feed("ounin<C-X><C-N>") | ||||
|     feed('ounin<C-X><C-N>') | ||||
|     helpers.poke_eventloop() | ||||
|     feed("<BS>d") | ||||
|     feed('<BS>d') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent                                              | | ||||
| @@ -697,7 +703,7 @@ describe('completion', function() | ||||
|       {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2}             | | ||||
|     ]]) | ||||
|     -- Works when going back and forth. | ||||
|     feed("<BS>c") | ||||
|     feed('<BS>c') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent                                              | | ||||
| @@ -707,7 +713,7 @@ describe('completion', function() | ||||
|       {0:~                                                           }|*2 | ||||
|       {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2}             | | ||||
|     ]]) | ||||
|     feed("<BS>d") | ||||
|     feed('<BS>d') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent                                              | | ||||
| @@ -717,7 +723,7 @@ describe('completion', function() | ||||
|       {0:~                                                           }|*2 | ||||
|       {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2}             | | ||||
|     ]]) | ||||
|     feed("<C-N><C-N><C-Y><Esc>") | ||||
|     feed('<C-N><C-N><C-Y><Esc>') | ||||
|     screen:expect([[ | ||||
|       inc uninc indent unindent                                   | | ||||
|               indent                                              | | ||||
| @@ -728,8 +734,8 @@ describe('completion', function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('disables folding during completion', function () | ||||
|     feed_command("set foldmethod=indent") | ||||
|   it('disables folding during completion', function() | ||||
|     feed_command('set foldmethod=indent') | ||||
|     feed('i<Tab>foo<CR><Tab>bar<Esc>gg') | ||||
|     screen:expect([[ | ||||
|               ^foo                                                 | | ||||
| @@ -747,8 +753,8 @@ describe('completion', function() | ||||
|     eq(-1, eval('foldclosed(1)')) | ||||
|   end) | ||||
|  | ||||
|   it('popupmenu is not interrupted by events', function () | ||||
|     feed_command("set complete=.") | ||||
|   it('popupmenu is not interrupted by events', function() | ||||
|     feed_command('set complete=.') | ||||
|  | ||||
|     feed('ifoobar fooegg<cr>f<c-p>') | ||||
|     screen:expect([[ | ||||
| @@ -762,14 +768,17 @@ describe('completion', function() | ||||
|  | ||||
|     assert_alive() | ||||
|     -- popupmenu still visible | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       foobar fooegg                                               | | ||||
|       fooegg^                                                      | | ||||
|       {1:foobar         }{0:                                             }| | ||||
|       {2:fooegg         }{0:                                             }| | ||||
|       {0:~                                                           }|*3 | ||||
|       {3:-- Keyword completion (^N^P) }{4:match 1 of 2}                   | | ||||
|     ]], unchanged=true} | ||||
|     ]], | ||||
|       unchanged = true, | ||||
|     } | ||||
|  | ||||
|     feed('<c-p>') | ||||
|     -- Didn't restart completion: old matches still used | ||||
| @@ -787,47 +796,52 @@ describe('completion', function() | ||||
|     it('expands when there is only one match', function() | ||||
|       feed(':lua CURRENT_TESTING_VAR = 1<CR>') | ||||
|       feed(':lua CURRENT_TESTING_<TAB>') | ||||
|       screen:expect{grid=[[ | ||||
|       screen:expect { | ||||
|         grid = [[ | ||||
|                                                                     | | ||||
|         {0:~                                                           }|*6 | ||||
|         :lua CURRENT_TESTING_VAR^                                    | | ||||
|       ]]} | ||||
|       ]], | ||||
|       } | ||||
|     end) | ||||
|  | ||||
|     it('expands when there is only one match', function() | ||||
|       feed(':lua CURRENT_TESTING_FOO = 1<CR>') | ||||
|       feed(':lua CURRENT_TESTING_BAR = 1<CR>') | ||||
|       feed(':lua CURRENT_TESTING_<TAB>') | ||||
|       screen:expect{ grid = [[ | ||||
|       screen:expect { | ||||
|         grid = [[ | ||||
|                                                                     | | ||||
|         {0:~                                                           }|*5 | ||||
|         {10:CURRENT_TESTING_BAR}{9:  CURRENT_TESTING_FOO                    }| | ||||
|         :lua CURRENT_TESTING_BAR^                                    | | ||||
|       ]], unchanged = true } | ||||
|       ]], | ||||
|         unchanged = true, | ||||
|       } | ||||
|     end) | ||||
|  | ||||
|     it('provides completion from `getcompletion()`', function() | ||||
|       eq({'vim'}, funcs.getcompletion('vi', 'lua')) | ||||
|       eq({'api'}, funcs.getcompletion('vim.ap', 'lua')) | ||||
|       eq({'tbl_filter'}, funcs.getcompletion('vim.tbl_fil', 'lua')) | ||||
|       eq({'vim'}, funcs.getcompletion('print(vi', 'lua')) | ||||
|       eq({ 'vim' }, funcs.getcompletion('vi', 'lua')) | ||||
|       eq({ 'api' }, funcs.getcompletion('vim.ap', 'lua')) | ||||
|       eq({ 'tbl_filter' }, funcs.getcompletion('vim.tbl_fil', 'lua')) | ||||
|       eq({ 'vim' }, funcs.getcompletion('print(vi', 'lua')) | ||||
|       -- fuzzy completion is not supported, so the result should be the same | ||||
|       command('set wildoptions+=fuzzy') | ||||
|       eq({'vim'}, funcs.getcompletion('vi', 'lua')) | ||||
|       eq({ 'vim' }, funcs.getcompletion('vi', 'lua')) | ||||
|     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({ '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 () | ||||
|     it('is cleared after CTRL-C', function() | ||||
|       feed('q:') | ||||
|       feed('ifoo faa fee f') | ||||
|       screen:expect([[ | ||||
| @@ -837,7 +851,7 @@ describe('completion', function() | ||||
|         {0:~                                                           }|*3 | ||||
|         {9:[Command Line]                                              }| | ||||
|         {3:-- INSERT --}                                                | | ||||
|       ]] ) | ||||
|       ]]) | ||||
|       feed('<c-x><c-n>') | ||||
|       screen:expect([[ | ||||
|                                                                     | | ||||
| @@ -870,16 +884,18 @@ describe('completion', function() | ||||
|         endfunction | ||||
|       ]]) | ||||
|       meths.set_option_value('completeopt', 'menuone,noselect', {}) | ||||
|       meths.set_var('_complist', {{ | ||||
|         word=0, | ||||
|         abbr=1, | ||||
|         menu=2, | ||||
|         kind=3, | ||||
|         info=4, | ||||
|         icase=5, | ||||
|         dup=6, | ||||
|         empty=7, | ||||
|       }}) | ||||
|       meths.set_var('_complist', { | ||||
|         { | ||||
|           word = 0, | ||||
|           abbr = 1, | ||||
|           menu = 2, | ||||
|           kind = 3, | ||||
|           info = 4, | ||||
|           icase = 5, | ||||
|           dup = 6, | ||||
|           empty = 7, | ||||
|         }, | ||||
|       }) | ||||
|     end) | ||||
|  | ||||
|     it('shows correct variant as word', function() | ||||
| @@ -897,7 +913,8 @@ describe('completion', function() | ||||
|     feed_command('set ignorecase infercase') | ||||
|     feed_command('edit runtime/doc/backers.txt') | ||||
|     feed('oX<C-X><C-N>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       *backers.txt*          Nvim                                 | | ||||
|       Xnull^                                                       | | ||||
|       {2:Xnull          }{6: }                                            | | ||||
| @@ -906,11 +923,12 @@ describe('completion', function() | ||||
|       {1:Xpayn          }{2: }                                            | | ||||
|       {1:Xinity         }{2: }                                            | | ||||
|       {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7}             | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
|  | ||||
|   it('CompleteChanged autocommand', function() | ||||
|     curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', ''}) | ||||
|     curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', '' }) | ||||
|     source([[ | ||||
|       set complete=. completeopt=noinsert,noselect,menuone | ||||
|       function! OnPumChange() | ||||
| @@ -925,39 +943,45 @@ describe('completion', function() | ||||
|     -- v:event.size should be set with ext_popupmenu #20646 | ||||
|     screen:set_option('ext_popupmenu', true) | ||||
|     feed('Sf<C-N>') | ||||
|     screen:expect({grid = [[ | ||||
|     screen:expect({ | ||||
|       grid = [[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       f^                                                           | | ||||
|       {0:~                                                           }|*3 | ||||
|       {3:-- Keyword completion (^N^P) }{5:Back at original}               | | ||||
|     ]], popupmenu = { | ||||
|     ]], | ||||
|       popupmenu = { | ||||
|         anchor = { 1, 3, 0 }, | ||||
|       items = { { "foo", "", "", "" }, { "foobar", "", "", "" } }, | ||||
|       pos = -1 | ||||
|     }}) | ||||
|     eq({completed_item = {}, width = 0, | ||||
|       height = 2, size = 2, | ||||
|       col = 0, row = 4, scrollbar = false}, | ||||
|       eval('g:event')) | ||||
|         items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } }, | ||||
|         pos = -1, | ||||
|       }, | ||||
|     }) | ||||
|     eq( | ||||
|       { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, | ||||
|       eval('g:event') | ||||
|     ) | ||||
|     feed('oob') | ||||
|     screen:expect({grid = [[ | ||||
|     screen:expect({ | ||||
|       grid = [[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       foob^                                                        | | ||||
|       {0:~                                                           }|*3 | ||||
|       {3:-- Keyword completion (^N^P) }{5:Back at original}               | | ||||
|     ]], popupmenu = { | ||||
|     ]], | ||||
|       popupmenu = { | ||||
|         anchor = { 1, 3, 0 }, | ||||
|       items = { { "foobar", "", "", "" } }, | ||||
|       pos = -1 | ||||
|     }}) | ||||
|     eq({completed_item = {}, width = 0, | ||||
|       height = 1, size = 1, | ||||
|       col = 0, row = 4, scrollbar = false}, | ||||
|       eval('g:event')) | ||||
|         items = { { 'foobar', '', '', '' } }, | ||||
|         pos = -1, | ||||
|       }, | ||||
|     }) | ||||
|     eq( | ||||
|       { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false }, | ||||
|       eval('g:event') | ||||
|     ) | ||||
|     feed('<Esc>') | ||||
|     screen:set_option('ext_popupmenu', false) | ||||
|  | ||||
| @@ -972,10 +996,10 @@ describe('completion', function() | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{5:Back at original}               | | ||||
|     ]]) | ||||
|     eq({completed_item = {}, width = 15, | ||||
|       height = 2, size = 2, | ||||
|       col = 0, row = 4, scrollbar = false}, | ||||
|       eval('g:event')) | ||||
|     eq( | ||||
|       { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, | ||||
|       eval('g:event') | ||||
|     ) | ||||
|     feed('<C-N>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
| @@ -1028,7 +1052,7 @@ describe('completion', function() | ||||
|   end) | ||||
|  | ||||
|   it('is stopped by :stopinsert from timer #12976', function() | ||||
|     screen:try_resize(32,14) | ||||
|     screen:try_resize(32, 14) | ||||
|     command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]]) | ||||
|     feed('Gah<c-x><c-n>') | ||||
|     screen:expect([[ | ||||
| @@ -1084,7 +1108,8 @@ describe('completion', function() | ||||
|     screen:try_resize(20, 9) | ||||
|     command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden') | ||||
|     feed('i<C-n>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       foo^                 | | ||||
|       {2:foo            }{0:     }| | ||||
|       {1:bar            }{0:     }| | ||||
| @@ -1092,15 +1117,18 @@ describe('completion', function() | ||||
|       {1:.hidden        }{0:     }| | ||||
|       {0:~                   }|*3 | ||||
|       {3:-- }{4:match 1 of 4}     | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed('<Esc>ccf<C-n>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       foo^                 | | ||||
|       {2:foo            }{0:     }| | ||||
|       {1:foa            }{0:     }| | ||||
|       {0:~                   }|*5 | ||||
|       {3:-- }{4:match 1 of 2}     | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
|  | ||||
|   it('restores extmarks if original text is restored #23653', function() | ||||
|   | ||||
| @@ -5,7 +5,7 @@ local command = helpers.command | ||||
| local poke_eventloop = helpers.poke_eventloop | ||||
| local sleep = helpers.sleep | ||||
|  | ||||
| describe("CTRL-C (mapped)", function() | ||||
| describe('CTRL-C (mapped)', function() | ||||
|   local screen | ||||
|  | ||||
|   before_each(function() | ||||
| @@ -14,7 +14,7 @@ describe("CTRL-C (mapped)", function() | ||||
|     screen:attach() | ||||
|   end) | ||||
|  | ||||
|   it("interrupts :global", function() | ||||
|   it('interrupts :global', function() | ||||
|     -- Crashes luajit. | ||||
|     if helpers.skip_fragile(pending) then | ||||
|       return | ||||
| @@ -25,7 +25,7 @@ describe("CTRL-C (mapped)", function() | ||||
|       nnoremap <C-C> <NOP> | ||||
|     ]]) | ||||
|  | ||||
|     command("silent edit! test/functional/fixtures/bigfile.txt") | ||||
|     command('silent edit! test/functional/fixtures/bigfile.txt') | ||||
|  | ||||
|     screen:expect([[ | ||||
|       ^0000;<control>;Cc;0;BN;;;;;N;NULL;;;;               | | ||||
| @@ -37,18 +37,20 @@ describe("CTRL-C (mapped)", function() | ||||
|     ]]) | ||||
|  | ||||
|     local function test_ctrl_c(ms) | ||||
|       feed(":global/^/p<CR>") | ||||
|       feed(':global/^/p<CR>') | ||||
|       screen:sleep(ms) | ||||
|       feed("<C-C>") | ||||
|       screen:expect{any="Interrupt"} | ||||
|       feed('<C-C>') | ||||
|       screen:expect { any = 'Interrupt' } | ||||
|     end | ||||
|  | ||||
|     -- The test is time-sensitive. Try different sleep values. | ||||
|     local ms_values = {100, 1000, 10000} | ||||
|     local ms_values = { 100, 1000, 10000 } | ||||
|     for i, ms in ipairs(ms_values) do | ||||
|       if i < #ms_values then | ||||
|         local status, _ = pcall(test_ctrl_c, ms) | ||||
|         if status then break end | ||||
|         if status then | ||||
|           break | ||||
|         end | ||||
|       else -- Call the last attempt directly. | ||||
|         test_ctrl_c(ms) | ||||
|       end | ||||
|   | ||||
| @@ -13,8 +13,12 @@ describe('Folds', function() | ||||
|   local tempfname = 'Xtest-fold.txt' | ||||
|  | ||||
|   setup(clear) | ||||
|   before_each(function() command('bwipe! | new') end) | ||||
|   after_each(function() os.remove(tempfname) end) | ||||
|   before_each(function() | ||||
|     command('bwipe! | new') | ||||
|   end) | ||||
|   after_each(function() | ||||
|     os.remove(tempfname) | ||||
|   end) | ||||
|  | ||||
|   it('manual folding adjusts with filter', function() | ||||
|     insert([[ | ||||
| @@ -94,7 +98,8 @@ describe('Folds', function() | ||||
|     end | ||||
|  | ||||
|     it('neither closes nor corrupts folds', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 	a | ||||
| @@ -112,7 +117,9 @@ a | ||||
| 	a | ||||
| 	a | ||||
| 	a | ||||
| 	a]], '7,12m0') | ||||
| 	a]], | ||||
|         '7,12m0' | ||||
|       ) | ||||
|       expect([[ | ||||
| a | ||||
| 	a | ||||
| @@ -133,7 +140,7 @@ a | ||||
| 	a | ||||
| 	a]]) | ||||
|       -- lines are not closed, folds are correct | ||||
|       for i = 1,funcs.line('$') do | ||||
|       for i = 1, funcs.line('$') do | ||||
|         eq(-1, funcs.foldclosed(i)) | ||||
|         if i == 1 or i == 7 or i == 13 then | ||||
|           eq(0, funcs.foldlevel(i)) | ||||
| @@ -151,7 +158,8 @@ a | ||||
|     end) | ||||
|  | ||||
|     it("doesn't split a fold when the move is within it", function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 	a | ||||
| @@ -161,24 +169,30 @@ a | ||||
| 		a | ||||
| 	a | ||||
| 	a | ||||
| a]], '5m6') | ||||
|       eq({0, 1, 1, 2, 2, 2, 2, 1, 1, 0}, get_folds()) | ||||
| a]], | ||||
|         '5m6' | ||||
|       ) | ||||
|       eq({ 0, 1, 1, 2, 2, 2, 2, 1, 1, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('truncates folds that end in the moved range', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 		a | ||||
| 		a | ||||
| 		a | ||||
| a | ||||
| a]], '4,5m6') | ||||
|       eq({0, 1, 2, 0, 0, 0, 0}, get_folds()) | ||||
| a]], | ||||
|         '4,5m6' | ||||
|       ) | ||||
|       eq({ 0, 1, 2, 0, 0, 0, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('moves folds that start between moved range and destination', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 	a | ||||
| @@ -191,12 +205,15 @@ a | ||||
| 	a | ||||
| a | ||||
| a | ||||
| 	a]], '3,4m$') | ||||
|       eq({0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0}, get_folds()) | ||||
| 	a]], | ||||
|         '3,4m$' | ||||
|       ) | ||||
|       eq({ 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('does not affect folds outside changed lines', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| 	a | ||||
| 	a | ||||
| 	a | ||||
| @@ -205,12 +222,15 @@ a | ||||
| a | ||||
| 	a | ||||
| 	a | ||||
| 	a]], '4m5') | ||||
|       eq({1, 1, 1, 0, 0, 0, 1, 1, 1}, get_folds()) | ||||
| 	a]], | ||||
|         '4m5' | ||||
|       ) | ||||
|       eq({ 1, 1, 1, 0, 0, 0, 1, 1, 1 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('moves and truncates folds that start in moved range', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 		a | ||||
| @@ -220,34 +240,43 @@ a | ||||
| a | ||||
| a | ||||
| a | ||||
| a]], '1,3m7') | ||||
|       eq({0, 0, 0, 0, 0, 1, 2, 0, 0, 0}, get_folds()) | ||||
| a]], | ||||
|         '1,3m7' | ||||
|       ) | ||||
|       eq({ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('breaks a fold when moving text into it', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 		a | ||||
| 		a | ||||
| 		a | ||||
| a | ||||
| a]], '$m4') | ||||
|       eq({0, 1, 2, 2, 0, 0, 0}, get_folds()) | ||||
| a]], | ||||
|         '$m4' | ||||
|       ) | ||||
|       eq({ 0, 1, 2, 2, 0, 0, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('adjusts correctly when moving a range backwards', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| a | ||||
| 	a | ||||
| 		a | ||||
| 		a | ||||
| a]], '2,3m0') | ||||
|       eq({1, 2, 0, 0, 0}, get_folds()) | ||||
| a]], | ||||
|         '2,3m0' | ||||
|       ) | ||||
|       eq({ 1, 2, 0, 0, 0 }, get_folds()) | ||||
|     end) | ||||
|  | ||||
|     it('handles shifting all remaining folds', function() | ||||
|       test_move_indent([[ | ||||
|       test_move_indent( | ||||
|         [[ | ||||
| 	a | ||||
| 		a | ||||
| 		a | ||||
| @@ -262,18 +291,23 @@ a]], '2,3m0') | ||||
| 		a | ||||
| 		a | ||||
| 	a | ||||
| a]], '13m7') | ||||
|       eq({1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0}, get_folds()) | ||||
| a]], | ||||
|         '13m7' | ||||
|       ) | ||||
|       eq({ 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0 }, get_folds()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('updates correctly on :read', function() | ||||
|     -- luacheck: ignore 621 | ||||
|     helpers.write_file(tempfname, [[ | ||||
|     helpers.write_file( | ||||
|       tempfname, | ||||
|       [[ | ||||
|     a | ||||
|  | ||||
|  | ||||
|     	a]]) | ||||
|     	a]] | ||||
|     ) | ||||
|     insert([[ | ||||
|     	a | ||||
|     	a | ||||
| @@ -295,13 +329,13 @@ a]], '13m7') | ||||
|     	a | ||||
|     	a | ||||
|     ]]) | ||||
|     for i = 1,2 do | ||||
|     for i = 1, 2 do | ||||
|       eq(1, funcs.foldlevel(i)) | ||||
|     end | ||||
|     for i = 3,5 do | ||||
|     for i = 3, 5 do | ||||
|       eq(0, funcs.foldlevel(i)) | ||||
|     end | ||||
|     for i = 6,8 do | ||||
|     for i = 6, 8 do | ||||
|       eq(1, funcs.foldlevel(i)) | ||||
|     end | ||||
|   end) | ||||
| @@ -356,7 +390,9 @@ a]], '13m7') | ||||
|       return 0 | ||||
|     endfunction | ||||
|     ]]) | ||||
|     helpers.write_file(tempfname, [[ | ||||
|     helpers.write_file( | ||||
|       tempfname, | ||||
|       [[ | ||||
|     b | ||||
|     b | ||||
|     a | ||||
| @@ -364,7 +400,8 @@ a]], '13m7') | ||||
|     d | ||||
|     a | ||||
|     a | ||||
|     c]]) | ||||
|     c]] | ||||
|     ) | ||||
|     insert([[ | ||||
|     a | ||||
|     a | ||||
| @@ -388,7 +425,7 @@ a]], '13m7') | ||||
|  | ||||
|   it('no folds remain if :delete makes buffer empty #19671', function() | ||||
|     command('setlocal foldmethod=manual') | ||||
|     funcs.setline(1, {'foo', 'bar', 'baz'}) | ||||
|     funcs.setline(1, { 'foo', 'bar', 'baz' }) | ||||
|     command('2,3fold') | ||||
|     command('%delete') | ||||
|     eq(0, funcs.foldlevel(1)) | ||||
|   | ||||
| @@ -12,7 +12,7 @@ local curbufmeths = helpers.curbufmeths | ||||
|  | ||||
| describe('jumplist', function() | ||||
|   local fname1 = 'Xtest-functional-normal-jump' | ||||
|   local fname2 = fname1..'2' | ||||
|   local fname2 = fname1 .. '2' | ||||
|   before_each(clear) | ||||
|   after_each(function() | ||||
|     os.remove(fname1) | ||||
| @@ -27,7 +27,7 @@ describe('jumplist', function() | ||||
|     write_file(fname1, 'first file contents') | ||||
|     write_file(fname2, 'second file contents') | ||||
|  | ||||
|     command('args '..fname1..' '..fname2) | ||||
|     command('args ' .. fname1 .. ' ' .. fname2) | ||||
|     local buf1 = funcs.bufnr(fname1) | ||||
|     local buf2 = funcs.bufnr(fname2) | ||||
|  | ||||
| @@ -44,7 +44,7 @@ describe('jumplist', function() | ||||
|     feed('<C-O>') | ||||
|     eq(buf1, funcs.bufnr('%')) | ||||
|  | ||||
|     command('drop '..fname2) | ||||
|     command('drop ' .. fname2) | ||||
|     feed('<C-O>') | ||||
|     eq(buf1, funcs.bufnr('%')) | ||||
|   end) | ||||
| @@ -56,11 +56,12 @@ describe('jumplist', function() | ||||
|     local screen = Screen.new(5, 25) | ||||
|     screen:attach() | ||||
|     command('set number') | ||||
|     command('edit '..fname1) | ||||
|     command('edit ' .. fname1) | ||||
|     feed('35gg') | ||||
|     command('edit '..fname2) | ||||
|     command('edit ' .. fname2) | ||||
|     feed('<C-O>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       {1: 24 }foobar  | | ||||
|       {1: 25 }foobar  | | ||||
|       {1: 26 }foobar  | | ||||
| @@ -86,9 +87,11 @@ describe('jumplist', function() | ||||
|       {1: 46 }foobar  | | ||||
|       {1: 47 }foobar  | | ||||
|                   | | ||||
|     ]], attr_ids={ | ||||
|       [1] = {foreground = Screen.colors.Brown}; | ||||
|     }} | ||||
|     ]], | ||||
|       attr_ids = { | ||||
|         [1] = { foreground = Screen.colors.Brown }, | ||||
|       }, | ||||
|     } | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -98,8 +101,7 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|     feed(':clearjumps<cr>') | ||||
|  | ||||
|     -- Add lines so that we have locations to jump to. | ||||
|     for i = 1,101,1 | ||||
|     do | ||||
|     for i = 1, 101, 1 do | ||||
|       feed('iLine ' .. i .. '<cr><esc>') | ||||
|     end | ||||
|  | ||||
| @@ -122,7 +124,8 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|     feed('<C-O>') | ||||
|     feed('<C-O>') | ||||
|  | ||||
|     eq(   '' | ||||
|     eq( | ||||
|       '' | ||||
|         .. ' jump line  col file/text\n' | ||||
|         .. '   4   102    0 \n' | ||||
|         .. '   3     1    0 Line 1\n' | ||||
| @@ -131,11 +134,13 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|         .. '>  0    30    0 Line 30\n' | ||||
|         .. '   1    40    0 Line 40\n' | ||||
|         .. '   2    50    0 Line 50', | ||||
|        exec_capture('jumps')) | ||||
|       exec_capture('jumps') | ||||
|     ) | ||||
|  | ||||
|     feed('90gg') | ||||
|  | ||||
|     eq(   '' | ||||
|     eq( | ||||
|       '' | ||||
|         .. ' jump line  col file/text\n' | ||||
|         .. '   5   102    0 \n' | ||||
|         .. '   4     1    0 Line 1\n' | ||||
| @@ -143,14 +148,16 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|         .. '   2    20    0 Line 20\n' | ||||
|         .. '   1    30    0 Line 30\n' | ||||
|         .. '>', | ||||
|        exec_capture('jumps')) | ||||
|       exec_capture('jumps') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('does not add the same location twice adjacently', function() | ||||
|     feed('60gg') | ||||
|     feed('60gg') | ||||
|  | ||||
|     eq(   '' | ||||
|     eq( | ||||
|       '' | ||||
|         .. ' jump line  col file/text\n' | ||||
|         .. '   7   102    0 \n' | ||||
|         .. '   6     1    0 Line 1\n' | ||||
| @@ -160,14 +167,16 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|         .. '   2    40    0 Line 40\n' | ||||
|         .. '   1    50    0 Line 50\n' | ||||
|         .. '>', | ||||
|        exec_capture('jumps')) | ||||
|       exec_capture('jumps') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('does add the same location twice nonadjacently', function() | ||||
|     feed('10gg') | ||||
|     feed('20gg') | ||||
|  | ||||
|     eq(   '' | ||||
|     eq( | ||||
|       '' | ||||
|         .. ' jump line  col file/text\n' | ||||
|         .. '   8   102    0 \n' | ||||
|         .. '   7     1    0 Line 1\n' | ||||
| @@ -178,19 +187,20 @@ describe("jumpoptions=stack behaves like 'tagstack'", function() | ||||
|         .. '   2    50    0 Line 50\n' | ||||
|         .. '   1    10    0 Line 10\n' | ||||
|         .. '>', | ||||
|        exec_capture('jumps')) | ||||
|       exec_capture('jumps') | ||||
|     ) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe("jumpoptions=view", function() | ||||
| describe('jumpoptions=view', function() | ||||
|   local file1 = 'Xtestfile-functional-editor-jumps' | ||||
|   local file2 = 'Xtestfile-functional-editor-jumps-2' | ||||
|   local function content() | ||||
|     local c = {} | ||||
|     for i=1,30 do | ||||
|       c[i] = i .. " line" | ||||
|     for i = 1, 30 do | ||||
|       c[i] = i .. ' line' | ||||
|     end | ||||
|     return table.concat(c, "\n") | ||||
|     return table.concat(c, '\n') | ||||
|   end | ||||
|   before_each(function() | ||||
|     clear() | ||||
| @@ -206,9 +216,9 @@ describe("jumpoptions=view", function() | ||||
|   it('restores the view', function() | ||||
|     local screen = Screen.new(5, 8) | ||||
|     screen:attach() | ||||
|     command("edit " .. file1) | ||||
|     feed("12Gztj") | ||||
|     feed("gg<C-o>") | ||||
|     command('edit ' .. file1) | ||||
|     feed('12Gztj') | ||||
|     feed('gg<C-o>') | ||||
|     screen:expect([[ | ||||
|     12 line     | | ||||
|     ^13 line     | | ||||
| @@ -224,10 +234,10 @@ describe("jumpoptions=view", function() | ||||
|   it('restores the view across files', function() | ||||
|     local screen = Screen.new(5, 5) | ||||
|     screen:attach() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("12Gzt") | ||||
|     command("next") | ||||
|     feed("G") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('12Gzt') | ||||
|     command('next') | ||||
|     feed('G') | ||||
|     screen:expect([[ | ||||
|     27 line     | | ||||
|     28 line     | | ||||
| @@ -235,7 +245,7 @@ describe("jumpoptions=view", function() | ||||
|     ^30 line     | | ||||
|                 | | ||||
|     ]]) | ||||
|     feed("<C-o><C-o>") | ||||
|     feed('<C-o><C-o>') | ||||
|     screen:expect([[ | ||||
|     ^12 line     | | ||||
|     13 line     | | ||||
| @@ -248,10 +258,10 @@ describe("jumpoptions=view", function() | ||||
|   it('restores the view across files with <C-^>', function() | ||||
|     local screen = Screen.new(5, 5) | ||||
|     screen:attach() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("12Gzt") | ||||
|     command("next") | ||||
|     feed("G") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('12Gzt') | ||||
|     command('next') | ||||
|     feed('G') | ||||
|     screen:expect([[ | ||||
|     27 line     | | ||||
|     28 line     | | ||||
| @@ -259,7 +269,7 @@ describe("jumpoptions=view", function() | ||||
|     ^30 line     | | ||||
|                 | | ||||
|     ]]) | ||||
|     feed("<C-^>") | ||||
|     feed('<C-^>') | ||||
|     screen:expect([[ | ||||
|     ^12 line     | | ||||
|     13 line     | | ||||
| @@ -269,11 +279,11 @@ describe("jumpoptions=view", function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('falls back to standard behavior when view can\'t be recovered', function() | ||||
|   it("falls back to standard behavior when view can't be recovered", function() | ||||
|     local screen = Screen.new(5, 8) | ||||
|     screen:attach() | ||||
|     command("edit " .. file1) | ||||
|     feed("7GzbG") | ||||
|     command('edit ' .. file1) | ||||
|     feed('7GzbG') | ||||
|     curbufmeths.set_lines(0, 2, true, {}) | ||||
|     -- Move to line 7, and set it as the last line visible on the view with zb, meaning to recover | ||||
|     -- the view it needs to put the cursor 7 lines from the top line. Then go to the end of the | ||||
| @@ -281,7 +291,7 @@ describe("jumpoptions=view", function() | ||||
|     -- Therefore when trying to jump back to it it's not possible to set a 7 line offset from the | ||||
|     -- mark position to the top line, since there's only 5 lines from the mark position to line 0. | ||||
|     -- Therefore falls back to standard behavior which is centering the view/line. | ||||
|     feed("<C-o>") | ||||
|     feed('<C-o>') | ||||
|     screen:expect([[ | ||||
|     4 line      | | ||||
|     5 line      | | ||||
|   | ||||
| @@ -9,11 +9,11 @@ describe('gu and gU', function() | ||||
|  | ||||
|   it('works in any locale with default casemap', function() | ||||
|     eq('internal,keepascii', eval('&casemap')) | ||||
|     insert("iI") | ||||
|     feed("VgU") | ||||
|     expect("II") | ||||
|     feed("Vgu") | ||||
|     expect("ii") | ||||
|     insert('iI') | ||||
|     feed('VgU') | ||||
|     expect('II') | ||||
|     feed('Vgu') | ||||
|     expect('ii') | ||||
|   end) | ||||
|  | ||||
|   describe('works in Turkish locale', function() | ||||
| @@ -21,7 +21,7 @@ describe('gu and gU', function() | ||||
|  | ||||
|     local err = exc_exec('lang ctype tr_TR.UTF-8') | ||||
|     if err ~= 0 then | ||||
|       pending("Locale tr_TR.UTF-8 not supported", function() end) | ||||
|       pending('Locale tr_TR.UTF-8 not supported', function() end) | ||||
|       return | ||||
|     end | ||||
|  | ||||
| @@ -32,29 +32,29 @@ describe('gu and gU', function() | ||||
|     it('with default casemap', function() | ||||
|       eq('internal,keepascii', eval('&casemap')) | ||||
|       -- expect ASCII behavior | ||||
|       insert("iI") | ||||
|       feed("VgU") | ||||
|       expect("II") | ||||
|       feed("Vgu") | ||||
|       expect("ii") | ||||
|       insert('iI') | ||||
|       feed('VgU') | ||||
|       expect('II') | ||||
|       feed('Vgu') | ||||
|       expect('ii') | ||||
|     end) | ||||
|  | ||||
|     it('with casemap=""', function() | ||||
|       command('set casemap=') | ||||
|       -- expect either Turkish locale behavior or ASCII behavior | ||||
|       local iupper = eval("toupper('i')") | ||||
|       if iupper == "İ" then | ||||
|         insert("iI") | ||||
|         feed("VgU") | ||||
|         expect("İI") | ||||
|         feed("Vgu") | ||||
|         expect("iı") | ||||
|       elseif iupper == "I" then | ||||
|         insert("iI") | ||||
|         feed("VgU") | ||||
|         expect("II") | ||||
|         feed("Vgu") | ||||
|         expect("ii") | ||||
|       if iupper == 'İ' then | ||||
|         insert('iI') | ||||
|         feed('VgU') | ||||
|         expect('İI') | ||||
|         feed('Vgu') | ||||
|         expect('iı') | ||||
|       elseif iupper == 'I' then | ||||
|         insert('iI') | ||||
|         feed('VgU') | ||||
|         expect('II') | ||||
|         feed('Vgu') | ||||
|         expect('ii') | ||||
|       else | ||||
|         error("expected toupper('i') to be either 'I' or 'İ'") | ||||
|       end | ||||
|   | ||||
| @@ -14,13 +14,13 @@ describe("'langmap'", function() | ||||
|     feed('gg0') | ||||
|   end) | ||||
|  | ||||
|   it("converts keys in normal mode", function() | ||||
|   it('converts keys in normal mode', function() | ||||
|     feed('ix') | ||||
|     expect('iii ww') | ||||
|     feed('whello<esc>') | ||||
|     expect('iii helloww') | ||||
|   end) | ||||
|   it("gives characters that are mapped by :nmap.", function() | ||||
|   it('gives characters that are mapped by :nmap.', function() | ||||
|     command('map i 0x') | ||||
|     feed('w') | ||||
|     expect('ii www') | ||||
| @@ -32,20 +32,18 @@ describe("'langmap'", function() | ||||
|     it("'langnoremap' is by default ON", function() | ||||
|       eq(1, eval('&langnoremap')) | ||||
|     end) | ||||
|     it("Results of maps are not converted when 'langnoremap' ON.", | ||||
|     function() | ||||
|     it("Results of maps are not converted when 'langnoremap' ON.", function() | ||||
|       command('nmap x i') | ||||
|       feed('xdl<esc>') | ||||
|       expect('dliii www') | ||||
|     end) | ||||
|     it("applies when deciding whether to map recursively", function() | ||||
|     it('applies when deciding whether to map recursively', function() | ||||
|       command('nmap l i') | ||||
|       command('nmap w j') | ||||
|       feed('ll') | ||||
|       expect('liii www') | ||||
|     end) | ||||
|     it("does not stop applying 'langmap' on first character of a mapping", | ||||
|     function() | ||||
|     it("does not stop applying 'langmap' on first character of a mapping", function() | ||||
|       command('1t1') | ||||
|       command('1t1') | ||||
|       command('goto 1') | ||||
| @@ -56,8 +54,7 @@ describe("'langmap'", function() | ||||
|       iii www | ||||
|       ihelloii www]]) | ||||
|     end) | ||||
|     it("Results of maps are converted when 'langnoremap' OFF.", | ||||
|     function() | ||||
|     it("Results of maps are converted when 'langnoremap' OFF.", function() | ||||
|       command('set nolangnoremap') | ||||
|       command('nmap x i') | ||||
|       feed('xdl<esc>') | ||||
| @@ -65,8 +62,7 @@ describe("'langmap'", function() | ||||
|     end) | ||||
|   end) | ||||
|   -- e.g. CTRL-W_j  ,  mj , 'j and "jp | ||||
|   it('conversions are applied to keys in middle of command', | ||||
|   function() | ||||
|   it('conversions are applied to keys in middle of command', function() | ||||
|     -- Works in middle of window command | ||||
|     feed('<C-w>s') | ||||
|     local origwin = curwin() | ||||
| @@ -74,12 +70,12 @@ describe("'langmap'", function() | ||||
|     neq(origwin, curwin()) | ||||
|     -- Works when setting a mark | ||||
|     feed('yy3p3gg0mwgg0mi') | ||||
|     eq({0, 3, 1, 0}, call('getpos', "'i")) | ||||
|     eq({0, 1, 1, 0}, call('getpos', "'w")) | ||||
|     eq({ 0, 3, 1, 0 }, call('getpos', "'i")) | ||||
|     eq({ 0, 1, 1, 0 }, call('getpos', "'w")) | ||||
|     feed('3dd') | ||||
|     -- Works when moving to a mark | ||||
|     feed("'i") | ||||
|     eq({0, 1, 1, 0}, call('getpos', '.')) | ||||
|     eq({ 0, 1, 1, 0 }, call('getpos', '.')) | ||||
|     -- Works when selecting a register | ||||
|     feed('qillqqwhhq') | ||||
|     eq('hh', eval('@i')) | ||||
| @@ -193,8 +189,7 @@ describe("'langmap'", function() | ||||
|       eq(1, eval('gotten_one')) | ||||
|     end) | ||||
|   end) | ||||
|   it('conversions are not applied during setreg()', | ||||
|   function() | ||||
|   it('conversions are not applied during setreg()', function() | ||||
|     call('setreg', 'i', 'ww') | ||||
|     eq('ww', eval('@i')) | ||||
|   end) | ||||
| @@ -214,12 +209,18 @@ describe("'langmap'", function() | ||||
|   end) | ||||
|  | ||||
|   local function testrecording(command_string, expect_string, setup_function, expect_macro) | ||||
|     if setup_function then setup_function() end | ||||
|     if setup_function then | ||||
|       setup_function() | ||||
|     end | ||||
|     feed('qa' .. command_string .. 'q') | ||||
|     expect(expect_string) | ||||
|     eq(expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true), | ||||
|       eval('@a')) | ||||
|     if setup_function then setup_function() end | ||||
|     eq( | ||||
|       expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true), | ||||
|       eval('@a') | ||||
|     ) | ||||
|     if setup_function then | ||||
|       setup_function() | ||||
|     end | ||||
|     -- n.b. may need nvim_replace_termcodes() here. | ||||
|     feed('@a') | ||||
|     expect(expect_string) | ||||
| @@ -276,5 +277,4 @@ describe("'langmap'", function() | ||||
|     testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]])) | ||||
|     testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]])) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -11,10 +11,9 @@ local meths = helpers.meths | ||||
| local insert = helpers.insert | ||||
| local curbufmeths = helpers.curbufmeths | ||||
|  | ||||
|  | ||||
| describe('macros', function() | ||||
|   before_each(function() | ||||
|     clear({args_rm = {'--cmd'}}) | ||||
|     clear({ args_rm = { '--cmd' } }) | ||||
|   end) | ||||
|   it('can be recorded and replayed', function() | ||||
|     feed('qiahello<esc>q') | ||||
| @@ -42,16 +41,16 @@ hello]] | ||||
|     feed [[gg]] | ||||
|  | ||||
|     feed [[qqAFOO<esc>q]] | ||||
|     eq({'helloFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'helloFOO', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[Q]] | ||||
|     eq({'helloFOOFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[Q]] | ||||
|     eq({ 'helloFOOFOO', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[G3Q]] | ||||
|     eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[G3Q]] | ||||
|     eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[ggV3jQ]] | ||||
|     eq({'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[ggV3jQ]] | ||||
|     eq({ 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|   end) | ||||
|  | ||||
|   it('can be replayed with @', function() | ||||
| @@ -61,37 +60,36 @@ hello]] | ||||
|     feed [[gg]] | ||||
|  | ||||
|     feed [[qqAFOO<esc>q]] | ||||
|     eq({'helloFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'helloFOO', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[Q]] | ||||
|     eq({'helloFOOFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[Q]] | ||||
|     eq({ 'helloFOOFOO', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[G3@@]] | ||||
|     eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[G3@@]] | ||||
|     eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[ggV2j@@]] | ||||
|     eq({'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[ggV2j@@]] | ||||
|     eq({ 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|   end) | ||||
|  | ||||
|   it('can be replayed with @q and @w', function() | ||||
|  | ||||
|     insert [[hello | ||||
| hello | ||||
| hello]] | ||||
|     feed [[gg]] | ||||
|  | ||||
|     feed [[qqAFOO<esc>qu]] | ||||
|     eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'hello', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed [[qwA123<esc>qu]] | ||||
|     eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'hello', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[V3j@q]] | ||||
|     eq({'helloFOO', 'helloFOO', 'helloFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[V3j@q]] | ||||
|     eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed [[gg]] | ||||
|     feed[[Vj@w]] | ||||
|     eq({'helloFOO123', 'helloFOO123', 'helloFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[Vj@w]] | ||||
|     eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|   end) | ||||
|  | ||||
|   it('can be replayed with @q and @w visual-block', function() | ||||
| @@ -101,17 +99,17 @@ hello]] | ||||
|     feed [[gg]] | ||||
|  | ||||
|     feed [[qqAFOO<esc>qu]] | ||||
|     eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'hello', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed [[qwA123<esc>qu]] | ||||
|     eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     eq({ 'hello', 'hello', 'hello' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed[[<C-v>3j@q]] | ||||
|     eq({'helloFOO', 'helloFOO', 'helloFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[<C-v>3j@q]] | ||||
|     eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|  | ||||
|     feed [[gg]] | ||||
|     feed[[<C-v>j@w]] | ||||
|     eq({'helloFOO123', 'helloFOO123', 'helloFOO'}, curbufmeths.get_lines(0, -1, false)) | ||||
|     feed [[<C-v>j@w]] | ||||
|     eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, curbufmeths.get_lines(0, -1, false)) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -141,7 +139,7 @@ describe('immediately after a macro has finished executing,', function() | ||||
|  | ||||
|     it('if the macro does not end with a <Nop> mapping', function() | ||||
|       feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op | ||||
|       eq({mode = 'n', blocking = false}, meths.get_mode()) | ||||
|       eq({ mode = 'n', blocking = false }, meths.get_mode()) | ||||
|       expect('') | ||||
|       eq('', eval('@a')) | ||||
|     end) | ||||
| @@ -149,7 +147,7 @@ describe('immediately after a macro has finished executing,', function() | ||||
|     it('if the macro ends with a <Nop> mapping', function() | ||||
|       command('nnoremap 0 <Nop>') | ||||
|       feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op | ||||
|       eq({mode = 'n', blocking = false}, meths.get_mode()) | ||||
|       eq({ mode = 'n', blocking = false }, meths.get_mode()) | ||||
|       expect('') | ||||
|       eq('', eval('@a')) | ||||
|     end) | ||||
|   | ||||
| @@ -9,7 +9,9 @@ local eq = helpers.eq | ||||
| local feed = helpers.feed | ||||
| local write_file = helpers.write_file | ||||
| local pcall_err = helpers.pcall_err | ||||
| local cursor = function() return helpers.meths.win_get_cursor(0) end | ||||
| local cursor = function() | ||||
|   return helpers.meths.win_get_cursor(0) | ||||
| end | ||||
|  | ||||
| describe('named marks', function() | ||||
|   local file1 = 'Xtestfile-functional-editor-marks' | ||||
| @@ -24,153 +26,153 @@ describe('named marks', function() | ||||
|     os.remove(file2) | ||||
|   end) | ||||
|  | ||||
|   it("can be set", function() | ||||
|     command("edit " .. file1) | ||||
|     command("mark a") | ||||
|     eq({1, 0}, curbufmeths.get_mark("a")) | ||||
|     feed("jmb") | ||||
|     eq({2, 0}, curbufmeths.get_mark("b")) | ||||
|     feed("jmB") | ||||
|     eq({3, 0}, curbufmeths.get_mark("B")) | ||||
|     command("4kc") | ||||
|     eq({4, 0}, curbufmeths.get_mark("c")) | ||||
|   it('can be set', function() | ||||
|     command('edit ' .. file1) | ||||
|     command('mark a') | ||||
|     eq({ 1, 0 }, curbufmeths.get_mark('a')) | ||||
|     feed('jmb') | ||||
|     eq({ 2, 0 }, curbufmeths.get_mark('b')) | ||||
|     feed('jmB') | ||||
|     eq({ 3, 0 }, curbufmeths.get_mark('B')) | ||||
|     command('4kc') | ||||
|     eq({ 4, 0 }, curbufmeths.get_mark('c')) | ||||
|   end) | ||||
|  | ||||
|   it("errors when set out of range with :mark", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "1000mark x") | ||||
|     eq("nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x", err) | ||||
|   it('errors when set out of range with :mark', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, '1000mark x') | ||||
|     eq('nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors when set out of range with :k", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "1000kx") | ||||
|     eq("nvim_exec2(): Vim(k):E16: Invalid range: 1000kx", err) | ||||
|   it('errors when set out of range with :k', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, '1000kx') | ||||
|     eq('nvim_exec2(): Vim(k):E16: Invalid range: 1000kx', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors on unknown mark name with :mark", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "mark #") | ||||
|     eq("nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err) | ||||
|   it('errors on unknown mark name with :mark', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, 'mark #') | ||||
|     eq('nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors on unknown mark name with '", function() | ||||
|     command("edit " .. file1) | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! '#") | ||||
|     eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err) | ||||
|     eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors on unknown mark name with `", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! `#") | ||||
|     eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err) | ||||
|   it('errors on unknown mark name with `', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, 'normal! `#') | ||||
|     eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors when moving to a mark that is not set with '", function() | ||||
|     command("edit " .. file1) | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! 'z") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|     err = pcall_err(helpers.exec_capture, "normal! '.") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors when moving to a mark that is not set with `", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! `z") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|     err = pcall_err(helpers.exec_capture, "normal! `>") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|   it('errors when moving to a mark that is not set with `', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, 'normal! `z') | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|     err = pcall_err(helpers.exec_capture, 'normal! `>') | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors when moving to a global mark that is not set with '", function() | ||||
|     command("edit " .. file1) | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! 'Z") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|   end) | ||||
|  | ||||
|   it("errors when moving to a global mark that is not set with `", function() | ||||
|     command("edit " .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! `Z") | ||||
|     eq("nvim_exec2(): Vim(normal):E20: Mark not set", err) | ||||
|   it('errors when moving to a global mark that is not set with `', function() | ||||
|     command('edit ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, 'normal! `Z') | ||||
|     eq('nvim_exec2(): Vim(normal):E20: Mark not set', err) | ||||
|   end) | ||||
|  | ||||
|   it("can move to them using '", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("j") | ||||
|     feed("ma") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('j') | ||||
|     feed('ma') | ||||
|     feed("G'a") | ||||
|     eq({2, 0}, cursor()) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     feed("'A") | ||||
|     eq(1, meths.get_current_buf().id) | ||||
|     eq({2, 0}, cursor()) | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("can move to them using `", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("jll") | ||||
|     feed("ma") | ||||
|     feed("G`a") | ||||
|     eq({2, 2}, cursor()) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     feed("`A") | ||||
|   it('can move to them using `', function() | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('jll') | ||||
|     feed('ma') | ||||
|     feed('G`a') | ||||
|     eq({ 2, 2 }, cursor()) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     feed('`A') | ||||
|     eq(1, meths.get_current_buf().id) | ||||
|     eq({2, 2}, cursor()) | ||||
|     eq({ 2, 2 }, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("can move to them using g'", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("jll") | ||||
|     feed("ma") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('jll') | ||||
|     feed('ma') | ||||
|     feed("Gg'a") | ||||
|     eq({2, 0}, cursor()) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     feed("g'A") | ||||
|     eq(1, meths.get_current_buf().id) | ||||
|     eq({2, 0}, cursor()) | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("can move to them using g`", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("jll") | ||||
|     feed("ma") | ||||
|     feed("Gg`a") | ||||
|     eq({2, 2}, cursor()) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     feed("g`A") | ||||
|   it('can move to them using g`', function() | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('jll') | ||||
|     feed('ma') | ||||
|     feed('Gg`a') | ||||
|     eq({ 2, 2 }, cursor()) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     feed('g`A') | ||||
|     eq(1, meths.get_current_buf().id) | ||||
|     eq({2, 2}, cursor()) | ||||
|     eq({ 2, 2 }, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("can move to them using :'", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("j") | ||||
|     feed("ma") | ||||
|     feed("G") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('j') | ||||
|     feed('ma') | ||||
|     feed('G') | ||||
|     command("'a") | ||||
|     eq({2, 0}, cursor()) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     command("'A") | ||||
|     eq(1, meths.get_current_buf().id) | ||||
|     eq({2, 0}, cursor()) | ||||
|     eq({ 2, 0 }, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("errors when it can't find the buffer", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("mA") | ||||
|     command("next") | ||||
|     command("bw! " .. file1 ) | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('mA') | ||||
|     command('next') | ||||
|     command('bw! ' .. file1) | ||||
|     local err = pcall_err(helpers.exec_capture, "normal! 'A") | ||||
|     eq("nvim_exec2(): Vim(normal):E92: Buffer 1 not found", err) | ||||
|     eq('nvim_exec2(): Vim(normal):E92: Buffer 1 not found', err) | ||||
|     os.remove(file1) | ||||
|   end) | ||||
|  | ||||
|   it("errors when using a mark in another buffer in command range", function() | ||||
|   it('errors when using a mark in another buffer in command range', function() | ||||
|     feed('ifoo<Esc>mA') | ||||
|     command('enew') | ||||
|     feed('ibar<Esc>') | ||||
| @@ -178,147 +180,147 @@ describe('named marks', function() | ||||
|   end) | ||||
|  | ||||
|   it("leave a context mark when moving with '", function() | ||||
|     command("edit " .. file1) | ||||
|     feed("llmamA") | ||||
|     feed("10j0")  -- first col, last line | ||||
|     command('edit ' .. file1) | ||||
|     feed('llmamA') | ||||
|     feed('10j0') -- first col, last line | ||||
|     local pos = cursor() | ||||
|     feed("'a") | ||||
|     feed("<C-o>") | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|     feed("'A") | ||||
|     feed("<C-o>") | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("leave a context mark when moving with `", function() | ||||
|     command("edit " .. file1) | ||||
|     feed("llmamA") | ||||
|     feed("10j0")  -- first col, last line | ||||
|   it('leave a context mark when moving with `', function() | ||||
|     command('edit ' .. file1) | ||||
|     feed('llmamA') | ||||
|     feed('10j0') -- first col, last line | ||||
|     local pos = cursor() | ||||
|     feed("`a") | ||||
|     feed("<C-o>") | ||||
|     feed('`a') | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|     feed("`A") | ||||
|     feed("<C-o>") | ||||
|     feed('`A') | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("leave a context mark when the mark changes buffer with g'", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     local pos | ||||
|     feed("GmA") | ||||
|     command("next") | ||||
|     feed('GmA') | ||||
|     command('next') | ||||
|     pos = cursor() | ||||
|     command("clearjumps") | ||||
|     command('clearjumps') | ||||
|     feed("g'A") -- since the mark is in another buffer, it leaves a context mark | ||||
|     feed("<C-o>") | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("leave a context mark when the mark changes buffer with g`", function() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|   it('leave a context mark when the mark changes buffer with g`', function() | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     local pos | ||||
|     feed("GmA") | ||||
|     command("next") | ||||
|     feed('GmA') | ||||
|     command('next') | ||||
|     pos = cursor() | ||||
|     command("clearjumps") | ||||
|     feed("g`A")  -- since the mark is in another buffer, it leaves a context mark | ||||
|     feed("<C-o>") | ||||
|     command('clearjumps') | ||||
|     feed('g`A') -- since the mark is in another buffer, it leaves a context mark | ||||
|     feed('<C-o>') | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("do not leave a context mark when moving with g'", function() | ||||
|     command("edit " .. file1) | ||||
|     command('edit ' .. file1) | ||||
|     local pos | ||||
|     feed("ma") | ||||
|     feed('ma') | ||||
|     pos = cursor() -- Mark pos | ||||
|     feed("10j0")  -- first col, last line | ||||
|     feed('10j0') -- first col, last line | ||||
|     feed("g'a") | ||||
|     feed("<C-o>") -- should do nothing | ||||
|     feed('<C-o>') -- should do nothing | ||||
|     eq(pos, cursor()) | ||||
|     feed("mA") | ||||
|     feed('mA') | ||||
|     pos = cursor() -- Mark pos | ||||
|     feed("10j0")  -- first col, last line | ||||
|     feed('10j0') -- first col, last line | ||||
|     feed("g'a") | ||||
|     feed("<C-o>") -- should do nothing | ||||
|     feed('<C-o>') -- should do nothing | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("do not leave a context mark when moving with g`", function() | ||||
|     command("edit " .. file1) | ||||
|   it('do not leave a context mark when moving with g`', function() | ||||
|     command('edit ' .. file1) | ||||
|     local pos | ||||
|     feed("ma") | ||||
|     feed('ma') | ||||
|     pos = cursor() -- Mark pos | ||||
|     feed("10j0")  -- first col, last line | ||||
|     feed("g`a") | ||||
|     feed("<C-o>") -- should do nothing | ||||
|     feed('10j0') -- first col, last line | ||||
|     feed('g`a') | ||||
|     feed('<C-o>') -- should do nothing | ||||
|     eq(pos, cursor()) | ||||
|     feed("mA") | ||||
|     feed('mA') | ||||
|     pos = cursor() -- Mark pos | ||||
|     feed("10j0")  -- first col, last line | ||||
|     feed('10j0') -- first col, last line | ||||
|     feed("g'a") | ||||
|     feed("<C-o>") -- should do nothing | ||||
|     feed('<C-o>') -- should do nothing | ||||
|     eq(pos, cursor()) | ||||
|   end) | ||||
|  | ||||
|   it("open folds when moving to them", function() | ||||
|     command("edit " .. file1) | ||||
|     feed("jzfG") -- Fold from the second line to the end | ||||
|     command("3mark a") | ||||
|     feed("G") -- On top of the fold | ||||
|   it('open folds when moving to them', function() | ||||
|     command('edit ' .. file1) | ||||
|     feed('jzfG') -- Fold from the second line to the end | ||||
|     command('3mark a') | ||||
|     feed('G') -- On top of the fold | ||||
|     assert(funcs.foldclosed('.') ~= -1) -- folded | ||||
|     feed("'a") | ||||
|     eq(-1, funcs.foldclosed('.')) | ||||
|  | ||||
|     feed("zc") | ||||
|     feed('zc') | ||||
|     assert(funcs.foldclosed('.') ~= -1) -- folded | ||||
|     -- TODO: remove this workaround after fixing #15873 | ||||
|     feed("k`a") | ||||
|     feed('k`a') | ||||
|     eq(-1, funcs.foldclosed('.')) | ||||
|  | ||||
|     feed("zc") | ||||
|     feed('zc') | ||||
|     assert(funcs.foldclosed('.') ~= -1) -- folded | ||||
|     feed("kg'a") | ||||
|     eq(-1, funcs.foldclosed('.')) | ||||
|  | ||||
|     feed("zc") | ||||
|     feed('zc') | ||||
|     assert(funcs.foldclosed('.') ~= -1) -- folded | ||||
|     feed("kg`a") | ||||
|     feed('kg`a') | ||||
|     eq(-1, funcs.foldclosed('.')) | ||||
|   end) | ||||
|  | ||||
|   it("do not open folds when moving to them doesn't move the cursor", function() | ||||
|     command("edit " .. file1) | ||||
|     feed("jzfG") -- Fold from the second line to the end | ||||
|     command('edit ' .. file1) | ||||
|     feed('jzfG') -- Fold from the second line to the end | ||||
|     assert(funcs.foldclosed('.') == 2) -- folded | ||||
|     feed("ma") | ||||
|     feed('ma') | ||||
|     feed("'a") | ||||
|     feed("`a") | ||||
|     feed('`a') | ||||
|     feed("g'a") | ||||
|     feed("g`a") | ||||
|     feed('g`a') | ||||
|     -- should still be folded | ||||
|     eq(2, funcs.foldclosed('.')) | ||||
|   end) | ||||
|  | ||||
|   it("getting '{ '} '( ') does not move cursor", function() | ||||
|     meths.buf_set_lines(0, 0, 0, true, {'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee'}) | ||||
|     meths.win_set_cursor(0, {2, 0}) | ||||
|     meths.buf_set_lines(0, 0, 0, true, { 'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee' }) | ||||
|     meths.win_set_cursor(0, { 2, 0 }) | ||||
|     funcs.getpos("'{") | ||||
|     eq({2, 0}, meths.win_get_cursor(0)) | ||||
|     eq({ 2, 0 }, meths.win_get_cursor(0)) | ||||
|     funcs.getpos("'}") | ||||
|     eq({2, 0}, meths.win_get_cursor(0)) | ||||
|     eq({ 2, 0 }, meths.win_get_cursor(0)) | ||||
|     funcs.getpos("'(") | ||||
|     eq({2, 0}, meths.win_get_cursor(0)) | ||||
|     eq({ 2, 0 }, meths.win_get_cursor(0)) | ||||
|     funcs.getpos("')") | ||||
|     eq({2, 0}, meths.win_get_cursor(0)) | ||||
|     eq({ 2, 0 }, meths.win_get_cursor(0)) | ||||
|   end) | ||||
|  | ||||
|   it('in command range does not move cursor #19248', function() | ||||
|     meths.create_user_command('Test', ':', {range = true}) | ||||
|     meths.buf_set_lines(0, 0, 0, true, {'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee'}) | ||||
|     meths.win_set_cursor(0, {2, 0}) | ||||
|     meths.create_user_command('Test', ':', { range = true }) | ||||
|     meths.buf_set_lines(0, 0, 0, true, { 'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee' }) | ||||
|     meths.win_set_cursor(0, { 2, 0 }) | ||||
|     command([['{,'}Test]]) | ||||
|     eq({2, 0}, meths.win_get_cursor(0)) | ||||
|     eq({ 2, 0 }, meths.win_get_cursor(0)) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| @@ -327,16 +329,16 @@ describe('named marks view', function() | ||||
|   local file2 = 'Xtestfile-functional-editor-marks-2' | ||||
|   local function content() | ||||
|     local c = {} | ||||
|     for i=1,30 do | ||||
|       c[i] = i .. " line" | ||||
|     for i = 1, 30 do | ||||
|       c[i] = i .. ' line' | ||||
|     end | ||||
|     return table.concat(c, "\n") | ||||
|     return table.concat(c, '\n') | ||||
|   end | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     write_file(file1, content(), false, false) | ||||
|     write_file(file2, content(), false, false) | ||||
|     command("set jumpoptions+=view") | ||||
|     command('set jumpoptions+=view') | ||||
|   end) | ||||
|   after_each(function() | ||||
|     os.remove(file1) | ||||
| @@ -346,8 +348,8 @@ describe('named marks view', function() | ||||
|   it('is restored in normal mode but not op-pending mode', function() | ||||
|     local screen = Screen.new(5, 8) | ||||
|     screen:attach() | ||||
|       command("edit " .. file1) | ||||
|       feed("<C-e>jWma") | ||||
|     command('edit ' .. file1) | ||||
|     feed('<C-e>jWma') | ||||
|     feed("G'a") | ||||
|     local expected = [[ | ||||
|       2 line      | | ||||
| @@ -359,8 +361,8 @@ describe('named marks view', function() | ||||
|       8 line      | | ||||
|                   | | ||||
|       ]] | ||||
|       screen:expect({grid=expected}) | ||||
|       feed("G`a") | ||||
|     screen:expect({ grid = expected }) | ||||
|     feed('G`a') | ||||
|     screen:expect([[ | ||||
|       2 line      | | ||||
|       3 ^line      | | ||||
| @@ -372,7 +374,7 @@ describe('named marks view', function() | ||||
|                   | | ||||
|       ]]) | ||||
|     -- not in op-pending mode #20886 | ||||
|       feed("ggj=`a") | ||||
|     feed('ggj=`a') | ||||
|     screen:expect([[ | ||||
|       1 line      | | ||||
|       ^2 line      | | ||||
| @@ -388,8 +390,8 @@ describe('named marks view', function() | ||||
|   it('is restored across files', function() | ||||
|     local screen = Screen.new(5, 5) | ||||
|     screen:attach() | ||||
|     command("args " .. file1 .. " " .. file2) | ||||
|     feed("<C-e>mA") | ||||
|     command('args ' .. file1 .. ' ' .. file2) | ||||
|     feed('<C-e>mA') | ||||
|     local mark_view = [[ | ||||
|     ^2 line      | | ||||
|     3 line      | | ||||
| @@ -398,7 +400,7 @@ describe('named marks view', function() | ||||
|                 | | ||||
|     ]] | ||||
|     screen:expect(mark_view) | ||||
|     command("next") | ||||
|     command('next') | ||||
|     screen:expect([[ | ||||
|     ^1 line      | | ||||
|     2 line      | | ||||
| @@ -410,12 +412,12 @@ describe('named marks view', function() | ||||
|     screen:expect(mark_view) | ||||
|   end) | ||||
|  | ||||
|   it('fallback to standard behavior when view can\'t be recovered', function() | ||||
|   it("fallback to standard behavior when view can't be recovered", function() | ||||
|     local screen = Screen.new(10, 10) | ||||
|     screen:attach() | ||||
|       command("edit " .. file1) | ||||
|       feed("7GzbmaG") -- Seven lines from the top | ||||
|       command("new") -- Screen size for window is now half the height can't be restored | ||||
|     command('edit ' .. file1) | ||||
|     feed('7GzbmaG') -- Seven lines from the top | ||||
|     command('new') -- Screen size for window is now half the height can't be restored | ||||
|     feed("<C-w>p'a") | ||||
|     screen:expect([[ | ||||
|                   | | ||||
|   | ||||
| @@ -66,11 +66,11 @@ describe('meta-keys #8226 #13042', function() | ||||
|     command('inoremap <A-j> alt-j') | ||||
|     feed('i<M-l> xxx <A-j><M-h>a<A-h>') | ||||
|     expect('meta-l xxx alt-j') | ||||
|     eq({ 0, 1, 14, 0, }, funcs.getpos('.')) | ||||
|     eq({ 0, 1, 14, 0 }, funcs.getpos('.')) | ||||
|     -- Unmapped ALT-chord behaves as ESC+c. | ||||
|     command('iunmap <M-l>') | ||||
|     feed('0i<M-l>') | ||||
|     eq({ 0, 1, 2, 0, }, funcs.getpos('.')) | ||||
|     eq({ 0, 1, 2, 0 }, funcs.getpos('.')) | ||||
|     -- Unmapped ALT-chord has same `undo` characteristics as ESC+<key> | ||||
|     command('0,$d') | ||||
|     feed('ahello<M-.>') | ||||
| @@ -101,7 +101,7 @@ describe('meta-keys #8226 #13042', function() | ||||
|     eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]])) | ||||
|     eq('t', eval('mode(1)')) | ||||
|     feed('<Esc>j') | ||||
|     eq({ 0, 2, 1, 0, }, funcs.getpos('.')) | ||||
|     eq({ 0, 2, 1, 0 }, funcs.getpos('.')) | ||||
|     eq('nt', eval('mode(1)')) | ||||
|   end) | ||||
|  | ||||
|   | ||||
| @@ -48,25 +48,29 @@ describe('cmdline', function() | ||||
|   it('redraws statusline when toggling overstrike', function() | ||||
|     local screen = Screen.new(60, 4) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold = true, foreground = Screen.colors.Blue},  -- NonText | ||||
|       [1] = {reverse = true, bold = true},  -- StatusLine | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|       [1] = { reverse = true, bold = true }, -- StatusLine | ||||
|     }) | ||||
|     screen:attach() | ||||
|     command('set laststatus=2 statusline=%!mode(1)') | ||||
|     feed(':') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|                                                                   | | ||||
|       {0:~                                                           }| | ||||
|       {1:c                                                           }| | ||||
|       :^                                                           | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed('<Insert>') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|                                                                   | | ||||
|       {0:~                                                           }| | ||||
|       {1:cr                                                          }| | ||||
|       :^                                                           | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
|  | ||||
|   describe('history', function() | ||||
|   | ||||
| @@ -53,13 +53,13 @@ describe('insert-mode', function() | ||||
|     it('double quote is removed after hit-enter prompt #22609', function() | ||||
|       local screen = Screen.new(60, 6) | ||||
|       screen:set_default_attr_ids({ | ||||
|         [0] = {bold = true, foreground = Screen.colors.Blue},  -- NonText | ||||
|         [1] = {foreground = Screen.colors.Blue},  -- SpecialKey | ||||
|         [2] = {foreground = Screen.colors.SlateBlue}, | ||||
|         [3] = {bold = true},  -- ModeMsg | ||||
|         [4] = {reverse = true, bold = true},  -- MsgSeparator | ||||
|         [5] = {background = Screen.colors.Red, foreground = Screen.colors.White},  -- ErrorMsg | ||||
|         [6] = {foreground = Screen.colors.SeaGreen, bold = true},  -- MoreMsg | ||||
|         [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|         [1] = { foreground = Screen.colors.Blue }, -- SpecialKey | ||||
|         [2] = { foreground = Screen.colors.SlateBlue }, | ||||
|         [3] = { bold = true }, -- ModeMsg | ||||
|         [4] = { reverse = true, bold = true }, -- MsgSeparator | ||||
|         [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg | ||||
|         [6] = { foreground = Screen.colors.SeaGreen, bold = true }, -- MoreMsg | ||||
|       }) | ||||
|       screen:attach() | ||||
|       feed('i<C-R>') | ||||
| @@ -187,10 +187,10 @@ describe('insert-mode', function() | ||||
|   it('multi-char mapping updates screen properly #25626', function() | ||||
|     local screen = Screen.new(60, 6) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold = true, foreground = Screen.colors.Blue};  -- NonText | ||||
|       [1] = {bold = true, reverse = true};  -- StatusLine | ||||
|       [2] = {reverse = true};  -- StatusLineNC | ||||
|       [3] = {bold = true};  -- ModeMsg | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|       [1] = { bold = true, reverse = true }, -- StatusLine | ||||
|       [2] = { reverse = true }, -- StatusLineNC | ||||
|       [3] = { bold = true }, -- ModeMsg | ||||
|     }) | ||||
|     screen:attach() | ||||
|     command('vnew') | ||||
| @@ -199,22 +199,26 @@ describe('insert-mode', function() | ||||
|     command('set timeoutlen=10000') | ||||
|     command('inoremap jk <Esc>') | ||||
|     feed('i<CR>βββ<Left><Left>j') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       foo                           │                             | | ||||
|       foo                           │β^jβ                          | | ||||
|       foo                           │{0:~                            }| | ||||
|       {0:~                             }│{0:~                            }| | ||||
|       {2:[No Name] [+]                  }{1:[No Name] [+]                }| | ||||
|       {3:-- INSERT --}                                                | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|     feed('k') | ||||
|     screen:expect{grid=[[ | ||||
|     screen:expect { | ||||
|       grid = [[ | ||||
|       foo                           │                             | | ||||
|       foo                           │^βββ                          | | ||||
|       foo                           │{0:~                            }| | ||||
|       {0:~                             }│{0:~                            }| | ||||
|       {2:[No Name] [+]                  }{1:[No Name] [+]                }| | ||||
|                                                                   | | ||||
|     ]]} | ||||
|     ]], | ||||
|     } | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -35,12 +35,12 @@ describe('put command', function() | ||||
|   before_each(reset) | ||||
|  | ||||
|   local function visual_marks_zero() | ||||
|     for _,v in pairs(funcs.getpos("'<")) do | ||||
|     for _, v in pairs(funcs.getpos("'<")) do | ||||
|       if v ~= 0 then | ||||
|         return false | ||||
|       end | ||||
|     end | ||||
|     for _,v in pairs(funcs.getpos("'>")) do | ||||
|     for _, v in pairs(funcs.getpos("'>")) do | ||||
|       if v ~= 0 then | ||||
|         return false | ||||
|       end | ||||
| @@ -51,10 +51,12 @@ describe('put command', function() | ||||
|   -- {{{ Where test definitions are run | ||||
|   local function run_test_variations(test_variations, extra_setup) | ||||
|     reset() | ||||
|     if extra_setup then extra_setup() end | ||||
|     if extra_setup then | ||||
|       extra_setup() | ||||
|     end | ||||
|     local init_contents = curbuf_contents() | ||||
|     local init_cursorpos = funcs.getcurpos() | ||||
|     local assert_no_change = function (exception_table, after_undo) | ||||
|     local assert_no_change = function(exception_table, after_undo) | ||||
|       expect(init_contents) | ||||
|       -- When putting the ". register forwards, undo doesn't move | ||||
|       -- the cursor back to where it was before. | ||||
| @@ -69,7 +71,9 @@ describe('put command', function() | ||||
|  | ||||
|     for _, test in pairs(test_variations) do | ||||
|       it(test.description, function() | ||||
|         if extra_setup then extra_setup() end | ||||
|         if extra_setup then | ||||
|           extra_setup() | ||||
|         end | ||||
|         local orig_dotstr = funcs.getreg('.') | ||||
|         helpers.ok(visual_marks_zero()) | ||||
|         -- Make sure every test starts from the same conditions | ||||
| @@ -115,8 +119,13 @@ describe('put command', function() | ||||
|   end -- run_test_variations() | ||||
|   -- }}} | ||||
|  | ||||
|   local function create_test_defs(test_defs, command_base, command_creator, -- {{{ | ||||
|                                   expect_base, expect_creator) | ||||
|   local function create_test_defs( | ||||
|     test_defs, | ||||
|     command_base, | ||||
|     command_creator, -- {{{ | ||||
|     expect_base, | ||||
|     expect_creator | ||||
|   ) | ||||
|     local rettab = {} | ||||
|     local exceptions | ||||
|     for _, v in pairs(test_defs) do | ||||
| @@ -125,8 +134,7 @@ describe('put command', function() | ||||
|       else | ||||
|         exceptions = {} | ||||
|       end | ||||
|       table.insert(rettab, | ||||
|       { | ||||
|       table.insert(rettab, { | ||||
|         test_action = command_creator(command_base, v[1]), | ||||
|         test_assertions = expect_creator(expect_base, v[2]), | ||||
|         description = v[3], | ||||
| @@ -146,7 +154,7 @@ describe('put command', function() | ||||
|     for linenum, line in pairs(funcs.split(expect_string, '\n', 1)) do | ||||
|       local column = line:find('x') | ||||
|       if column then | ||||
|         return {linenum, column}, expect_string:gsub('x', '') | ||||
|         return { linenum, column }, expect_string:gsub('x', '') | ||||
|       end | ||||
|     end | ||||
|   end -- find_cursor_position() }}} | ||||
| @@ -186,7 +194,7 @@ describe('put command', function() | ||||
|       -- '.' command. | ||||
|       if not (exception_table.redo_position and after_redo) then | ||||
|         local actual_position = funcs.getcurpos() | ||||
|         eq(cursor_position, {actual_position[2], actual_position[5]}) | ||||
|         eq(cursor_position, { actual_position[2], actual_position[5] }) | ||||
|       end | ||||
|     end | ||||
|   end -- expect_creator() }}} | ||||
| @@ -195,13 +203,13 @@ describe('put command', function() | ||||
|   local function copy_def(def) | ||||
|     local rettab = { '', {}, '', nil } | ||||
|     rettab[1] = def[1] | ||||
|     for k,v in pairs(def[2]) do | ||||
|     for k, v in pairs(def[2]) do | ||||
|       rettab[2][k] = v | ||||
|     end | ||||
|     rettab[3] = def[3] | ||||
|     if def[4] then | ||||
|       rettab[4] = {} | ||||
|       for k,v in pairs(def[4]) do | ||||
|       for k, v in pairs(def[4]) do | ||||
|         rettab[4][k] = v | ||||
|       end | ||||
|     end | ||||
| @@ -211,52 +219,52 @@ describe('put command', function() | ||||
|   local normal_command_defs = { | ||||
|     { | ||||
|       'p', | ||||
|       {cursor_after = false, put_backwards = false, dot_register = false}, | ||||
|       { cursor_after = false, put_backwards = false, dot_register = false }, | ||||
|       'pastes after cursor with p', | ||||
|     }, | ||||
|     { | ||||
|       'gp', | ||||
|       {cursor_after = true, put_backwards = false, dot_register = false}, | ||||
|       { cursor_after = true, put_backwards = false, dot_register = false }, | ||||
|       'leaves cursor after text with gp', | ||||
|     }, | ||||
|     { | ||||
|       '".p', | ||||
|       {cursor_after = false, put_backwards = false, dot_register = true}, | ||||
|       { cursor_after = false, put_backwards = false, dot_register = true }, | ||||
|       'works with the ". register', | ||||
|     }, | ||||
|     { | ||||
|       '".gp', | ||||
|       {cursor_after = true, put_backwards = false, dot_register = true}, | ||||
|       { cursor_after = true, put_backwards = false, dot_register = true }, | ||||
|       'gp works with the ". register', | ||||
|       {redo_position = true}, | ||||
|       { redo_position = true }, | ||||
|     }, | ||||
|     { | ||||
|       'P', | ||||
|       {cursor_after = false, put_backwards = true, dot_register = false}, | ||||
|       { cursor_after = false, put_backwards = true, dot_register = false }, | ||||
|       'pastes before cursor with P', | ||||
|     }, | ||||
|     { | ||||
|       'gP', | ||||
|       {cursor_after = true, put_backwards = true, dot_register = false}, | ||||
|       { cursor_after = true, put_backwards = true, dot_register = false }, | ||||
|       'gP pastes before cursor and leaves cursor after text', | ||||
|     }, | ||||
|     { | ||||
|       '".P', | ||||
|       {cursor_after = false, put_backwards = true, dot_register = true}, | ||||
|       { cursor_after = false, put_backwards = true, dot_register = true }, | ||||
|       'P works with ". register', | ||||
|     }, | ||||
|     { | ||||
|       '".gP', | ||||
|       {cursor_after = true, put_backwards = true, dot_register = true}, | ||||
|       { cursor_after = true, put_backwards = true, dot_register = true }, | ||||
|       'gP works with ". register', | ||||
|       {redo_position = true}, | ||||
|       { redo_position = true }, | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   -- Add a definition applying a count for each definition above. | ||||
|   -- Could do this for each transformation (p -> P, p -> gp etc), but I think | ||||
|   -- it's neater this way (balance between being explicit and too verbose). | ||||
|   for i = 1,#normal_command_defs do | ||||
|   for i = 1, #normal_command_defs do | ||||
|     local cur = normal_command_defs[i] | ||||
|  | ||||
|     -- Make modified copy of current definition that includes a count. | ||||
| @@ -279,35 +287,36 @@ describe('put command', function() | ||||
|   local ex_command_defs = { | ||||
|     { | ||||
|       'put', | ||||
|       {put_backwards = false, dot_register = false}, | ||||
|       { put_backwards = false, dot_register = false }, | ||||
|       'pastes linewise forwards with :put', | ||||
|     }, | ||||
|     { | ||||
|       'put!', | ||||
|       {put_backwards = true, dot_register = false}, | ||||
|       { put_backwards = true, dot_register = false }, | ||||
|       'pastes linewise backwards with :put!', | ||||
|     }, | ||||
|     { | ||||
|       'put .', | ||||
|       {put_backwards = false, dot_register = true}, | ||||
|       { put_backwards = false, dot_register = true }, | ||||
|       'pastes linewise with the dot register', | ||||
|     }, | ||||
|     { | ||||
|       'put! .', | ||||
|       {put_backwards = true, dot_register = true}, | ||||
|       { put_backwards = true, dot_register = true }, | ||||
|       'pastes linewise backwards with the dot register', | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   local function non_dotdefs(def_table) | ||||
|     return filter(function(d) return not d[2].dot_register end, def_table) | ||||
|     return filter(function(d) | ||||
|       return not d[2].dot_register | ||||
|     end, def_table) | ||||
|   end | ||||
|  | ||||
|   -- }}} | ||||
|  | ||||
|   -- Conversion functions {{{ | ||||
|   local function convert_charwise(expect_base, conversion_table, | ||||
|                                        virtualedit_end, visual_put) | ||||
|   local function convert_charwise(expect_base, conversion_table, virtualedit_end, visual_put) | ||||
|     expect_base = dedent(expect_base) | ||||
|     -- There is no difference between 'P' and 'p' when VIsual_active | ||||
|     if not visual_put then | ||||
| @@ -420,8 +429,13 @@ describe('put command', function() | ||||
|     return orig_line:sub(1, prev_end - 1) .. 'x' .. orig_line:sub(prev_end) | ||||
|   end | ||||
|  | ||||
|   local function convert_blockwise(expect_base, conversion_table, visual, | ||||
|                                    use_b, trailing_whitespace) | ||||
|   local function convert_blockwise( | ||||
|     expect_base, | ||||
|     conversion_table, | ||||
|     visual, | ||||
|     use_b, | ||||
|     trailing_whitespace | ||||
|   ) | ||||
|     expect_base = dedent(expect_base) | ||||
|     local p_str = 'test_string"' | ||||
|     if use_b then | ||||
| @@ -452,11 +466,9 @@ describe('put command', function() | ||||
|  | ||||
|     if conversion_table.count and conversion_table.count > 1 then | ||||
|       local p_pattern = p_str:gsub('%.', '%%.') | ||||
|       expect_base = expect_base:gsub(p_pattern, | ||||
|                                      p_str:rep(conversion_table.count)) | ||||
|       expect_base = expect_base:gsub('test_stringx([b".])', | ||||
|                                      p_str:rep(conversion_table.count - 1) | ||||
|                                      .. '%0') | ||||
|       expect_base = expect_base:gsub(p_pattern, p_str:rep(conversion_table.count)) | ||||
|       expect_base = | ||||
|         expect_base:gsub('test_stringx([b".])', p_str:rep(conversion_table.count - 1) .. '%0') | ||||
|     end | ||||
|  | ||||
|     if conversion_table.cursor_after then | ||||
| @@ -496,8 +508,13 @@ describe('put command', function() | ||||
|   -- }}} | ||||
|  | ||||
|   -- Convenience functions {{{ | ||||
|   local function run_normal_mode_tests(test_string, base_map, extra_setup, | ||||
|                                        virtualedit_end, selection_string) | ||||
|   local function run_normal_mode_tests( | ||||
|     test_string, | ||||
|     base_map, | ||||
|     extra_setup, | ||||
|     virtualedit_end, | ||||
|     selection_string | ||||
|   ) | ||||
|     local function convert_closure(e, c) | ||||
|       return convert_charwise(e, c, virtualedit_end, selection_string) | ||||
|     end | ||||
| @@ -532,8 +549,12 @@ describe('put command', function() | ||||
|  | ||||
|   local function run_linewise_tests(expect_base, base_command, extra_setup) | ||||
|     local linewise_test_defs = create_test_defs( | ||||
|         ex_command_defs, base_command, | ||||
|         create_put_action, expect_base, convert_linewiseer) | ||||
|       ex_command_defs, | ||||
|       base_command, | ||||
|       create_put_action, | ||||
|       expect_base, | ||||
|       convert_linewiseer | ||||
|     ) | ||||
|     run_test_variations(linewise_test_defs, extra_setup) | ||||
|   end -- run_linewise_tests() | ||||
|   -- }}} | ||||
| @@ -545,7 +566,8 @@ describe('put command', function() | ||||
|     Line of words 2]] | ||||
|     run_normal_mode_tests(expect_string, 'p') | ||||
|  | ||||
|     run_linewise_tests([[ | ||||
|     run_linewise_tests( | ||||
|       [[ | ||||
|       Line of words 1 | ||||
|       xtest_string" | ||||
|       Line of words 2]], | ||||
| @@ -585,11 +607,12 @@ describe('put command', function() | ||||
|     run_test_variations( | ||||
|       create_test_defs( | ||||
|         linewise_put_defs, | ||||
|         'put a', create_put_action, | ||||
|         base_expect_string, convert_linewiseer | ||||
|         'put a', | ||||
|         create_put_action, | ||||
|         base_expect_string, | ||||
|         convert_linewiseer | ||||
|       ) | ||||
|     ) | ||||
|  | ||||
|   end) | ||||
|  | ||||
|   describe('blockwise register', function() | ||||
| @@ -600,18 +623,13 @@ describe('put command', function() | ||||
|      test_stringb]] | ||||
|  | ||||
|     local function expect_block_creator(expect_base, conversion_table) | ||||
|       return expect_creator(function(e,c) return convert_blockwise(e,c,nil,true) end, | ||||
|                     expect_base, conversion_table) | ||||
|       return expect_creator(function(e, c) | ||||
|         return convert_blockwise(e, c, nil, true) | ||||
|       end, expect_base, conversion_table) | ||||
|     end | ||||
|  | ||||
|     run_test_variations( | ||||
|       create_test_defs( | ||||
|         blockwise_put_defs, | ||||
|         '"bp', | ||||
|         create_p_action, | ||||
|         test_base, | ||||
|         expect_block_creator | ||||
|       ) | ||||
|       create_test_defs(blockwise_put_defs, '"bp', create_p_action, test_base, expect_block_creator) | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
| @@ -632,17 +650,17 @@ describe('put command', function() | ||||
|  | ||||
|   describe('linewise paste with autoindent', function() | ||||
|     -- luacheck: ignore | ||||
|     run_linewise_tests([[ | ||||
|     run_linewise_tests( | ||||
|       [[ | ||||
|         Line of words 1 | ||||
|         	Line of words 2 | ||||
|         xtest_string"]], | ||||
|         'put' | ||||
|       , | ||||
|       'put', | ||||
|       function() | ||||
|         funcs.setline('$', '	Line of words 2') | ||||
|         -- Set curswant to '8' to be at the end of the tab character | ||||
|         -- This is where the cursor is put back after the 'u' command. | ||||
|         funcs.setpos('.', {0, 2, 1, 0, 8}) | ||||
|         funcs.setpos('.', { 0, 2, 1, 0, 8 }) | ||||
|         command('set autoindent') | ||||
|       end | ||||
|     ) | ||||
| @@ -655,7 +673,7 @@ describe('put command', function() | ||||
|     run_normal_mode_tests(test_string, 'p', function() | ||||
|       funcs.setline('$', '	Line of words 2') | ||||
|       command('setlocal virtualedit=all') | ||||
|       funcs.setpos('.', {0, 2, 1, 2, 3}) | ||||
|       funcs.setpos('.', { 0, 2, 1, 2, 3 }) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -667,7 +685,7 @@ describe('put command', function() | ||||
|     run_normal_mode_tests(test_string, 'p', function() | ||||
|       funcs.setline('$', '	Line of words 2') | ||||
|       command('setlocal virtualedit=all') | ||||
|       funcs.setpos('.', {0, 1, 16, 1, 17}) | ||||
|       funcs.setpos('.', { 0, 1, 16, 1, 17 }) | ||||
|     end, true) | ||||
|   end) | ||||
|  | ||||
| @@ -681,10 +699,8 @@ describe('put command', function() | ||||
|     describe('over trailing newline', function() | ||||
|       local test_string = 'Line of test_stringx"Line of words 2' | ||||
|       run_normal_mode_tests(test_string, 'v$p', function() | ||||
|         funcs.setpos('.', {0, 1, 9, 0, 9}) | ||||
|       end, | ||||
|       nil, | ||||
|       'words 1\n') | ||||
|         funcs.setpos('.', { 0, 1, 9, 0, 9 }) | ||||
|       end, nil, 'words 1\n') | ||||
|     end) | ||||
|     describe('linewise mode', function() | ||||
|       local test_string = [[ | ||||
| @@ -693,8 +709,7 @@ describe('put command', function() | ||||
|       local function expect_vis_linewise(expect_base, conversion_table) | ||||
|         return expect_creator(function(e, c) | ||||
|           return convert_linewise(e, c, nil, nil) | ||||
|         end, | ||||
|         expect_base, conversion_table) | ||||
|         end, expect_base, conversion_table) | ||||
|       end | ||||
|       run_test_variations( | ||||
|         create_test_defs( | ||||
| @@ -704,15 +719,16 @@ describe('put command', function() | ||||
|           test_string, | ||||
|           expect_vis_linewise | ||||
|         ), | ||||
|         function() funcs.setpos('.', {0, 1, 1, 0, 1}) end | ||||
|         function() | ||||
|           funcs.setpos('.', { 0, 1, 1, 0, 1 }) | ||||
|         end | ||||
|       ) | ||||
|  | ||||
|       describe('with whitespace at bol', function() | ||||
|         local function expect_vis_lineindented(expect_base, conversion_table) | ||||
|           local test_expect = expect_creator(function(e, c) | ||||
|             return convert_linewise(e, c, nil, nil, '    ') | ||||
|             end, | ||||
|             expect_base, conversion_table) | ||||
|           end, expect_base, conversion_table) | ||||
|           return function(exception_table, after_redo) | ||||
|             test_expect(exception_table, after_redo) | ||||
|             if not conversion_table.put_backwards then | ||||
| @@ -737,7 +753,6 @@ describe('put command', function() | ||||
|           end | ||||
|         ) | ||||
|       end) | ||||
|  | ||||
|     end) | ||||
|  | ||||
|     describe('blockwise visual mode', function() | ||||
| @@ -749,8 +764,8 @@ describe('put command', function() | ||||
|         local test_expect = expect_creator(function(e, c) | ||||
|           return convert_blockwise(e, c, true) | ||||
|         end, expect_base, conversion_table) | ||||
|         return function(e,c) | ||||
|           test_expect(e,c) | ||||
|         return function(e, c) | ||||
|           test_expect(e, c) | ||||
|           if not conversion_table.put_backwards then | ||||
|             eq('Lin\nLin', funcs.getreg('"')) | ||||
|           end | ||||
| @@ -766,7 +781,6 @@ describe('put command', function() | ||||
|       ) | ||||
|       run_test_variations(select_down_test_defs) | ||||
|  | ||||
|  | ||||
|       -- Undo and redo of a visual block put leave the cursor in the top | ||||
|       -- left of the visual block area no matter where the cursor was | ||||
|       -- when it started. | ||||
| @@ -778,8 +792,7 @@ describe('put command', function() | ||||
|         rettab[4].undo_position = true | ||||
|         rettab[4].redo_position = true | ||||
|         return rettab | ||||
|         end, | ||||
|         normal_command_defs) | ||||
|       end, normal_command_defs) | ||||
|  | ||||
|       -- Selection direction doesn't matter | ||||
|       run_test_variations( | ||||
| @@ -790,7 +803,9 @@ describe('put command', function() | ||||
|           test_base, | ||||
|           expect_block_creator | ||||
|         ), | ||||
|         function() funcs.setpos('.', {0, 2, 1, 0, 1}) end | ||||
|         function() | ||||
|           funcs.setpos('.', { 0, 2, 1, 0, 1 }) | ||||
|         end | ||||
|       ) | ||||
|  | ||||
|       describe('blockwise cursor after undo', function() | ||||
| @@ -800,62 +815,45 @@ describe('put command', function() | ||||
|         -- the same pattern as everything else. | ||||
|         -- Here we fix this by directly checking the undo/redo position | ||||
|         -- in the test_assertions of our test definitions. | ||||
|         local function assertion_creator(_,_) | ||||
|           return function(_,_) | ||||
|         local function assertion_creator(_, _) | ||||
|           return function(_, _) | ||||
|             feed('u') | ||||
|             -- Have to use feed('u') here to set curswant, because | ||||
|             -- ex_undo() doesn't do that. | ||||
|             eq({0, 1, 1, 0, 1}, funcs.getcurpos()) | ||||
|             eq({ 0, 1, 1, 0, 1 }, funcs.getcurpos()) | ||||
|             feed('<C-r>') | ||||
|             eq({0, 1, 1, 0, 1}, funcs.getcurpos()) | ||||
|             eq({ 0, 1, 1, 0, 1 }, funcs.getcurpos()) | ||||
|           end | ||||
|         end | ||||
|  | ||||
|         run_test_variations( | ||||
|           create_test_defs( | ||||
|             undo_redo_no, | ||||
|             '<C-v>kllp', | ||||
|             create_p_action, | ||||
|             test_base, | ||||
|             assertion_creator | ||||
|           ), | ||||
|           function() funcs.setpos('.', {0, 2, 1, 0, 1}) end | ||||
|           create_test_defs(undo_redo_no, '<C-v>kllp', create_p_action, test_base, assertion_creator), | ||||
|           function() | ||||
|             funcs.setpos('.', { 0, 2, 1, 0, 1 }) | ||||
|           end | ||||
|         ) | ||||
|       end) | ||||
|     end) | ||||
|  | ||||
|  | ||||
|     describe("with 'virtualedit'", function() | ||||
|       describe('splitting a tab character', function() | ||||
|         local base_expect_string = [[ | ||||
|         Line of words 1 | ||||
|           test_stringx"     Line of words 2]] | ||||
|         run_normal_mode_tests( | ||||
|           base_expect_string, | ||||
|           'vp', | ||||
|           function() | ||||
|         run_normal_mode_tests(base_expect_string, 'vp', function() | ||||
|           funcs.setline('$', '	Line of words 2') | ||||
|           command('setlocal virtualedit=all') | ||||
|             funcs.setpos('.', {0, 2, 1, 2, 3}) | ||||
|           end, | ||||
|           nil, | ||||
|           ' ' | ||||
|         ) | ||||
|           funcs.setpos('.', { 0, 2, 1, 2, 3 }) | ||||
|         end, nil, ' ') | ||||
|       end) | ||||
|       describe('after end of line', function() | ||||
|         local base_expect_string = [[ | ||||
|         Line of words 1  test_stringx" | ||||
|         Line of words 2]] | ||||
|         run_normal_mode_tests( | ||||
|           base_expect_string, | ||||
|           'vp', | ||||
|           function() | ||||
|         run_normal_mode_tests(base_expect_string, 'vp', function() | ||||
|           command('setlocal virtualedit=all') | ||||
|             funcs.setpos('.', {0, 1, 16, 2, 18}) | ||||
|           end, | ||||
|           true, | ||||
|           ' ' | ||||
|         ) | ||||
|           funcs.setpos('.', { 0, 1, 16, 2, 18 }) | ||||
|         end, true, ' ') | ||||
|       end) | ||||
|     end) | ||||
|   end) | ||||
| @@ -873,9 +871,12 @@ describe('put command', function() | ||||
|       	Line of words 1 | ||||
|       Line of words 2]]) | ||||
|       feed('u1go<C-v>j".p') | ||||
|       eq([[ | ||||
|       eq( | ||||
|         [[ | ||||
| 	ine of words 1 | ||||
| 	ine of words 2]], curbuf_contents()) | ||||
| 	ine of words 2]], | ||||
|         curbuf_contents() | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     local screen | ||||
| @@ -891,7 +892,8 @@ describe('put command', function() | ||||
|       end | ||||
|       helpers.ok(not screen.bell and not screen.visualbell) | ||||
|       actions() | ||||
|       screen:expect{condition=function() | ||||
|       screen:expect { | ||||
|         condition = function() | ||||
|           if should_ring then | ||||
|             if not screen.bell and not screen.visualbell then | ||||
|               error('Bell was not rung after action') | ||||
| @@ -901,23 +903,31 @@ describe('put command', function() | ||||
|               error('Bell was rung after action') | ||||
|             end | ||||
|           end | ||||
|       end, unchanged=(not should_ring)} | ||||
|         end, | ||||
|         unchanged = not should_ring, | ||||
|       } | ||||
|       screen.bell = false | ||||
|       screen.visualbell = false | ||||
|     end | ||||
|  | ||||
|     it('should not ring the bell with gp at end of line', function() | ||||
|       bell_test(function() feed('$".gp') end) | ||||
|       bell_test(function() | ||||
|         feed('$".gp') | ||||
|       end) | ||||
|  | ||||
|       -- Even if the last character is a multibyte character. | ||||
|       reset() | ||||
|       funcs.setline(1, 'helloม') | ||||
|       bell_test(function() feed('$".gp') end) | ||||
|       bell_test(function() | ||||
|         feed('$".gp') | ||||
|       end) | ||||
|     end) | ||||
|  | ||||
|     it('should not ring the bell with gp and end of file', function() | ||||
|       funcs.setpos('.', {0, 2, 1, 0}) | ||||
|       bell_test(function() feed('$vl".gp') end) | ||||
|       funcs.setpos('.', { 0, 2, 1, 0 }) | ||||
|       bell_test(function() | ||||
|         feed('$vl".gp') | ||||
|       end) | ||||
|     end) | ||||
|  | ||||
|     it('should ring the bell when deleting if not appropriate', function() | ||||
| @@ -926,7 +936,9 @@ describe('put command', function() | ||||
|       expect([[ | ||||
|       ine of words 1 | ||||
|       Line of words 2]]) | ||||
|       bell_test(function() feed('".P') end, true) | ||||
|       bell_test(function() | ||||
|         feed('".P') | ||||
|       end, true) | ||||
|     end) | ||||
|  | ||||
|     it('should restore cursor position after undo of ".p', function() | ||||
| @@ -946,4 +958,3 @@ describe('put command', function() | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -8,10 +8,7 @@ describe('search (/)', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   it('fails with huge column (%c) value #9930', function() | ||||
|     eq([[Vim:E951: \% value too large]], | ||||
|       pcall_err(command, "/\\v%18446744071562067968c")) | ||||
|     eq([[Vim:E951: \% value too large]], | ||||
|       pcall_err(command, "/\\v%2147483648c")) | ||||
|     eq([[Vim:E951: \% value too large]], pcall_err(command, '/\\v%18446744071562067968c')) | ||||
|     eq([[Vim:E951: \% value too large]], pcall_err(command, '/\\v%2147483648c')) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -58,7 +58,9 @@ describe('tabpage', function() | ||||
|   end) | ||||
|  | ||||
|   it('no segfault with strange WinClosed autocommand #20290', function() | ||||
|     pcall(exec, [[ | ||||
|     pcall( | ||||
|       exec, | ||||
|       [[ | ||||
|       set nohidden | ||||
|       edit Xa | ||||
|       split Xb | ||||
| @@ -66,45 +68,46 @@ describe('tabpage', function() | ||||
|       new | ||||
|       autocmd WinClosed * tabprev | bwipe! | ||||
|       close | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
|   it('nvim_win_close and nvim_win_hide update tabline #20285', function() | ||||
|     eq(1, #meths.list_tabpages()) | ||||
|     eq({1, 1}, funcs.win_screenpos(0)) | ||||
|     eq({ 1, 1 }, funcs.win_screenpos(0)) | ||||
|     local win1 = curwin().id | ||||
|  | ||||
|     command('tabnew') | ||||
|     eq(2, #meths.list_tabpages()) | ||||
|     eq({2, 1}, funcs.win_screenpos(0)) | ||||
|     eq({ 2, 1 }, funcs.win_screenpos(0)) | ||||
|     local win2 = curwin().id | ||||
|  | ||||
|     meths.win_close(win1, true) | ||||
|     eq(win2, curwin().id) | ||||
|     eq(1, #meths.list_tabpages()) | ||||
|     eq({1, 1}, funcs.win_screenpos(0)) | ||||
|     eq({ 1, 1 }, funcs.win_screenpos(0)) | ||||
|  | ||||
|     command('tabnew') | ||||
|     eq(2, #meths.list_tabpages()) | ||||
|     eq({2, 1}, funcs.win_screenpos(0)) | ||||
|     eq({ 2, 1 }, funcs.win_screenpos(0)) | ||||
|     local win3 = curwin().id | ||||
|  | ||||
|     meths.win_hide(win2) | ||||
|     eq(win3, curwin().id) | ||||
|     eq(1, #meths.list_tabpages()) | ||||
|     eq({1, 1}, funcs.win_screenpos(0)) | ||||
|     eq({ 1, 1 }, funcs.win_screenpos(0)) | ||||
|   end) | ||||
|  | ||||
|   it('switching tabpage after setting laststatus=3 #19591', function() | ||||
|     local screen = Screen.new(40, 8) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold = true, foreground = Screen.colors.Blue}, | ||||
|       [1] = {bold = true, reverse = true},  -- StatusLine | ||||
|       [2] = {reverse = true},  -- TabLineFill | ||||
|       [3] = {bold = true}, -- TabLineSel | ||||
|       [4] = {background = Screen.colors.LightGrey, underline = true},  -- TabLine | ||||
|       [5] = {bold = true, foreground = Screen.colors.Magenta}, | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, | ||||
|       [1] = { bold = true, reverse = true }, -- StatusLine | ||||
|       [2] = { reverse = true }, -- TabLineFill | ||||
|       [3] = { bold = true }, -- TabLineSel | ||||
|       [4] = { background = Screen.colors.LightGrey, underline = true }, -- TabLine | ||||
|       [5] = { bold = true, foreground = Screen.colors.Magenta }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|  | ||||
| @@ -130,7 +133,7 @@ describe('tabpage', function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it(":tabmove handles modifiers and addr", function() | ||||
|   it(':tabmove handles modifiers and addr', function() | ||||
|     command('tabnew | tabnew | tabnew') | ||||
|     eq(4, funcs.nvim_tabpage_get_number(0)) | ||||
|     command('     silent      :keepalt   :: :::    silent!    -    tabmove') | ||||
|   | ||||
| @@ -21,15 +21,23 @@ describe('u CTRL-R g- g+', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   local function create_history(num_steps) | ||||
|     if num_steps == 0 then return end | ||||
|     if num_steps == 0 then | ||||
|       return | ||||
|     end | ||||
|     insert('1') | ||||
|     if num_steps == 1 then return end | ||||
|     if num_steps == 1 then | ||||
|       return | ||||
|     end | ||||
|     feed('o2<esc>') | ||||
|     feed('o3<esc>') | ||||
|     feed('u') | ||||
|     if num_steps == 2 then return end | ||||
|     if num_steps == 2 then | ||||
|       return | ||||
|     end | ||||
|     feed('o4<esc>') | ||||
|     if num_steps == 3 then return end | ||||
|     if num_steps == 3 then | ||||
|       return | ||||
|     end | ||||
|     feed('u') | ||||
|   end | ||||
|  | ||||
| @@ -57,13 +65,23 @@ describe('u CTRL-R g- g+', function() | ||||
|     undo_and_redo(2, 'g-', 'g+', '1') | ||||
|   end) | ||||
|   it('undoes properly around a branch point', function() | ||||
|     undo_and_redo(3, 'u', '<C-r>', [[ | ||||
|     undo_and_redo( | ||||
|       3, | ||||
|       'u', | ||||
|       '<C-r>', | ||||
|       [[ | ||||
|       1 | ||||
|       2]]) | ||||
|     undo_and_redo(3, 'g-', 'g+', [[ | ||||
|       2]] | ||||
|     ) | ||||
|     undo_and_redo( | ||||
|       3, | ||||
|       'g-', | ||||
|       'g+', | ||||
|       [[ | ||||
|       1 | ||||
|       2 | ||||
|       3]]) | ||||
|       3]] | ||||
|     ) | ||||
|   end) | ||||
|   it('can find the previous sequence after undoing to a branch', function() | ||||
|     undo_and_redo(4, 'u', '<C-r>', '1') | ||||
|   | ||||
| @@ -29,8 +29,7 @@ local cmdtest = function(cmd, prep, ret1) | ||||
|     -- Used to crash because this invokes history processing which uses | ||||
|     -- hist_char2type which after fdb68e35e4c729c7ed097d8ade1da29e5b3f4b31 | ||||
|     -- crashed. | ||||
|     it(cmd .. 's' .. prep .. ' the current line by default when feeding', | ||||
|     function() | ||||
|     it(cmd .. 's' .. prep .. ' the current line by default when feeding', function() | ||||
|       feed(':' .. cmd .. '\nabc\ndef\n.\n') | ||||
|       eq(ret1, buffer_contents()) | ||||
|     end) | ||||
| @@ -63,8 +62,8 @@ describe('the first line is redrawn correctly after inserting text in an empty b | ||||
|     clear() | ||||
|     screen = Screen.new(20, 8) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue}, | ||||
|       [2] = {bold = true, reverse = true}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue }, | ||||
|       [2] = { bold = true, reverse = true }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|   end) | ||||
|   | ||||
| @@ -1,28 +1,28 @@ | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs | ||||
| local ok = helpers.ok | ||||
| local clear = helpers.clear | ||||
|  | ||||
| describe(":argument", function() | ||||
| describe(':argument', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|   end) | ||||
|  | ||||
|   it("does not restart :terminal buffer", function() | ||||
|       command("terminal") | ||||
|   it('does not restart :terminal buffer', function() | ||||
|     command('terminal') | ||||
|     helpers.feed([[<C-\><C-N>]]) | ||||
|       command("argadd") | ||||
|     command('argadd') | ||||
|     helpers.feed([[<C-\><C-N>]]) | ||||
|       local bufname_before = funcs.bufname("%") | ||||
|       local bufnr_before = funcs.bufnr("%") | ||||
|       helpers.ok(nil ~= string.find(bufname_before, "^term://"))  -- sanity | ||||
|     local bufname_before = funcs.bufname('%') | ||||
|     local bufnr_before = funcs.bufnr('%') | ||||
|     helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity | ||||
|  | ||||
|       command("argument 1") | ||||
|     command('argument 1') | ||||
|     helpers.feed([[<C-\><C-N>]]) | ||||
|  | ||||
|       local bufname_after = funcs.bufname("%") | ||||
|       local bufnr_after = funcs.bufnr("%") | ||||
|       eq("["..bufname_before.."]", helpers.eval('trim(execute("args"))')) | ||||
|     local bufname_after = funcs.bufname('%') | ||||
|     local bufnr_after = funcs.bufnr('%') | ||||
|     eq('[' .. bufname_before .. ']', helpers.eval('trim(execute("args"))')) | ||||
|     ok(funcs.line('$') > 1) | ||||
|     eq(bufname_before, bufname_after) | ||||
|     eq(bufnr_before, bufnr_after) | ||||
|   | ||||
| @@ -21,18 +21,30 @@ local directories = { | ||||
| } | ||||
|  | ||||
| -- Shorthand writing to get the current working directory | ||||
| local  cwd = function(...) return call('getcwd', ...) end  -- effective working dir | ||||
| local wcwd = function() return cwd(0) end  -- window dir | ||||
| local tcwd = function() return cwd(-1, 0) end  -- tab dir | ||||
| local cwd = function(...) | ||||
|   return call('getcwd', ...) | ||||
| end -- effective working dir | ||||
| local wcwd = function() | ||||
|   return cwd(0) | ||||
| end -- window dir | ||||
| local tcwd = function() | ||||
|   return cwd(-1, 0) | ||||
| end -- tab dir | ||||
|  | ||||
| -- Same, except these tell us if there is a working directory at all | ||||
| local  lwd = function(...) return call('haslocaldir', ...) end  -- effective working dir | ||||
| local wlwd = function() return lwd(0) end  -- window dir | ||||
| local tlwd = function() return lwd(-1,  0) end  -- tab dir | ||||
| local lwd = function(...) | ||||
|   return call('haslocaldir', ...) | ||||
| end -- effective working dir | ||||
| local wlwd = function() | ||||
|   return lwd(0) | ||||
| end -- window dir | ||||
| local tlwd = function() | ||||
|   return lwd(-1, 0) | ||||
| end -- tab dir | ||||
| --local glwd = function() return eval('haslocaldir(-1, -1)') end  -- global dir | ||||
|  | ||||
| -- Test both the `cd` and `chdir` variants | ||||
| for _, cmd in ipairs {'cd', 'chdir'} do | ||||
| for _, cmd in ipairs { 'cd', 'chdir' } do | ||||
|   describe(':' .. cmd, function() | ||||
|     before_each(function() | ||||
|       clear() | ||||
| @@ -199,7 +211,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do | ||||
|  | ||||
|       -- Change back to initial tab and verify working directory has stayed | ||||
|       command('tabnext') | ||||
|       eq(globalDir, cwd() ) | ||||
|       eq(globalDir, cwd()) | ||||
|       eq(0, tlwd()) | ||||
|       eq(0, wlwd()) | ||||
|  | ||||
| @@ -213,25 +225,25 @@ for _, cmd in ipairs {'cd', 'chdir'} do | ||||
|  | ||||
|       -- Unless the global change happened in a tab with local directory | ||||
|       command('silent ' .. cmd .. ' ..') | ||||
|       eq(globalDir, cwd() ) | ||||
|       eq(0 , tlwd()) | ||||
|       eq(0 , wlwd()) | ||||
|       eq(globalDir, cwd()) | ||||
|       eq(0, tlwd()) | ||||
|       eq(0, wlwd()) | ||||
|       -- Which also affects the first tab | ||||
|       command('tabnext') | ||||
|       eq(globalDir, cwd()) | ||||
|  | ||||
|       -- But not in a window with its own local directory | ||||
|       command('tabnext | wincmd w') | ||||
|       eq(globalDir .. pathsep .. directories.window, cwd() ) | ||||
|       eq(0 , tlwd()) | ||||
|       eq(globalDir .. pathsep .. directories.window, cwd()) | ||||
|       eq(0, tlwd()) | ||||
|       eq(globalDir .. pathsep .. directories.window, wcwd()) | ||||
|     end) | ||||
|   end) | ||||
| end | ||||
|  | ||||
| -- Test legal parameters for 'getcwd' and 'haslocaldir' | ||||
| for _, cmd in ipairs {'getcwd', 'haslocaldir'} do | ||||
|   describe(cmd..'()', function() | ||||
| for _, cmd in ipairs { 'getcwd', 'haslocaldir' } do | ||||
|   describe(cmd .. '()', function() | ||||
|     before_each(function() | ||||
|       clear() | ||||
|     end) | ||||
| @@ -271,7 +283,7 @@ for _, cmd in ipairs {'getcwd', 'haslocaldir'} do | ||||
|   end) | ||||
| end | ||||
|  | ||||
| describe("getcwd()", function () | ||||
| describe('getcwd()', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     mkdir(directories.global) | ||||
| @@ -281,11 +293,11 @@ describe("getcwd()", function () | ||||
|     helpers.rmdir(directories.global) | ||||
|   end) | ||||
|  | ||||
|   it("returns empty string if working directory does not exist", function() | ||||
|   it('returns empty string if working directory does not exist', function() | ||||
|     skip(is_os('win')) | ||||
|     command("cd "..directories.global) | ||||
|     command("call delete('../"..directories.global.."', 'd')") | ||||
|     eq("", helpers.eval("getcwd()")) | ||||
|     command('cd ' .. directories.global) | ||||
|     command("call delete('../" .. directories.global .. "', 'd')") | ||||
|     eq('', helpers.eval('getcwd()')) | ||||
|   end) | ||||
|  | ||||
|   it("works with 'autochdir' after local directory was set (#9892)", function() | ||||
|   | ||||
| @@ -16,24 +16,24 @@ describe('mappings with <Cmd>', function() | ||||
|   local tmpfile = 'X_ex_cmds_cmd_map' | ||||
|  | ||||
|   local function cmdmap(lhs, rhs) | ||||
|     command('noremap '..lhs..' <Cmd>'..rhs..'<cr>') | ||||
|     command('noremap! '..lhs..' <Cmd>'..rhs..'<cr>') | ||||
|     command('noremap ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>') | ||||
|     command('noremap! ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>') | ||||
|   end | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     screen = Screen.new(65, 8) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, | ||||
|       [3] = {bold = true, foreground = Screen.colors.SeaGreen4}, | ||||
|       [4] = {bold = true}, | ||||
|       [5] = {background = Screen.colors.LightGrey}, | ||||
|       [6] = {foreground = Screen.colors.Blue1}, | ||||
|       [7] = {bold = true, reverse = true}, | ||||
|       [8] = {background = Screen.colors.WebGray}, | ||||
|       [9] = {background = Screen.colors.LightMagenta}, | ||||
|       [10] = {foreground = Screen.colors.Red}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, | ||||
|       [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, | ||||
|       [4] = { bold = true }, | ||||
|       [5] = { background = Screen.colors.LightGrey }, | ||||
|       [6] = { foreground = Screen.colors.Blue1 }, | ||||
|       [7] = { bold = true, reverse = true }, | ||||
|       [8] = { background = Screen.colors.WebGray }, | ||||
|       [9] = { background = Screen.colors.LightMagenta }, | ||||
|       [10] = { foreground = Screen.colors.Red }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|  | ||||
| @@ -57,7 +57,7 @@ describe('mappings with <Cmd>', function() | ||||
|     feed('gg') | ||||
|     cmdmap('<F8>', 'startinsert') | ||||
|     cmdmap('<F9>', 'stopinsert') | ||||
|     command("abbr foo <Cmd>let g:y = 17<cr>bar") | ||||
|     command('abbr foo <Cmd>let g:y = 17<cr>bar') | ||||
|   end) | ||||
|  | ||||
|   after_each(function() | ||||
| @@ -121,7 +121,7 @@ describe('mappings with <Cmd>', function() | ||||
|     feed('<F3>') | ||||
|     eq('foo…bar', eval('g:str')) | ||||
|     local str = eval([["foo\<D-…>bar"]]) | ||||
|     command([[noremap <F3> <Cmd>let g:str = ']]..str..[['<CR>]]) | ||||
|     command([[noremap <F3> <Cmd>let g:str = ']] .. str .. [['<CR>]]) | ||||
|     feed('<F3>') | ||||
|     eq(str, eval('g:str')) | ||||
|     command([[noremap <F3> <Cmd>let g:str = 'foo<D-…>bar'<CR>]]) | ||||
| @@ -160,7 +160,7 @@ describe('mappings with <Cmd>', function() | ||||
|     eq('n', eval('mode(1)')) | ||||
|  | ||||
|     -- operator-pending mode | ||||
|     feed("d<F3>") | ||||
|     feed('d<F3>') | ||||
|     eq('no', eval('m')) | ||||
|     -- did leave operator-pending mode | ||||
|     eq('n', eval('mode(1)')) | ||||
| @@ -171,21 +171,21 @@ describe('mappings with <Cmd>', function() | ||||
|     eq('i', eval('mode(1)')) | ||||
|  | ||||
|     -- replace mode | ||||
|     feed("<Ins><F3>") | ||||
|     feed('<Ins><F3>') | ||||
|     eq('R', eval('m')) | ||||
|     eq('R', eval('mode(1)')) | ||||
|     feed('<esc>') | ||||
|     eq('n', eval('mode(1)')) | ||||
|  | ||||
|     -- virtual replace mode | ||||
|     feed("gR<F3>") | ||||
|     feed('gR<F3>') | ||||
|     eq('Rv', eval('m')) | ||||
|     eq('Rv', eval('mode(1)')) | ||||
|     feed('<esc>') | ||||
|     eq('n', eval('mode(1)')) | ||||
|  | ||||
|     -- langmap works, but is not distinguished in mode(1) | ||||
|     feed(":set iminsert=1<cr>i<F3>") | ||||
|     feed(':set iminsert=1<cr>i<F3>') | ||||
|     eq('i', eval('m')) | ||||
|     eq('i', eval('mode(1)')) | ||||
|     feed('<esc>') | ||||
| @@ -212,15 +212,15 @@ describe('mappings with <Cmd>', function() | ||||
|  | ||||
|     -- check v:count and v:register works | ||||
|     feed('<F2>') | ||||
|     eq({'n', 0, '"'}, eval('s')) | ||||
|     eq({ 'n', 0, '"' }, eval('s')) | ||||
|     feed('7<F2>') | ||||
|     eq({'n', 7, '"'}, eval('s')) | ||||
|     eq({ 'n', 7, '"' }, eval('s')) | ||||
|     feed('"e<F2>') | ||||
|     eq({'n', 0, 'e'}, eval('s')) | ||||
|     eq({ 'n', 0, 'e' }, eval('s')) | ||||
|     feed('5"k<F2>') | ||||
|     eq({'n', 5, 'k'}, eval('s')) | ||||
|     eq({ 'n', 5, 'k' }, eval('s')) | ||||
|     feed('"+2<F2>') | ||||
|     eq({'n', 2, '+'}, eval('s')) | ||||
|     eq({ 'n', 2, '+' }, eval('s')) | ||||
|  | ||||
|     -- text object enters visual mode | ||||
|     feed('<F7>') | ||||
| @@ -249,7 +249,7 @@ describe('mappings with <Cmd>', function() | ||||
|       {4:-- INSERT --}                                                     | | ||||
|     ]]) | ||||
|     -- feedkeys were not executed immediately | ||||
|     eq({'n', 'of test text'}, eval('[m,a]')) | ||||
|     eq({ 'n', 'of test text' }, eval('[m,a]')) | ||||
|     eq('i', eval('mode(1)')) | ||||
|     feed('<esc>') | ||||
|  | ||||
| @@ -261,7 +261,7 @@ describe('mappings with <Cmd>', function() | ||||
|                                                                        | | ||||
|     ]]) | ||||
|     -- feedkeys(..., 'x') was executed immediately, but insert mode gets aborted | ||||
|     eq({'n', 'of alphabetatest text'}, eval('[m,b]')) | ||||
|     eq({ 'n', 'of alphabetatest text' }, eval('[m,b]')) | ||||
|     eq('n', eval('mode(1)')) | ||||
|   end) | ||||
|  | ||||
| @@ -270,9 +270,11 @@ describe('mappings with <Cmd>', function() | ||||
|     command('noremap ,f <Cmd>nosuchcommand<cr>') | ||||
|     command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>') | ||||
|     command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>') | ||||
|     command('noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>') | ||||
|     command( | ||||
|       'noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>' | ||||
|     ) | ||||
|  | ||||
|     feed(":normal ,x<cr>") | ||||
|     feed(':normal ,x<cr>') | ||||
|     screen:expect([[ | ||||
|       ^some short lines                                                 | | ||||
|       aa                                                               | | ||||
| @@ -282,9 +284,9 @@ describe('mappings with <Cmd>', function() | ||||
|       :normal ,x                                                       | | ||||
|     ]]) | ||||
|  | ||||
|     eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec("normal ,f")) | ||||
|     eq('very error', exc_exec("normal ,e")) | ||||
|     eq('Vim(echoerr):The message.', exc_exec("normal ,m")) | ||||
|     eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec('normal ,f')) | ||||
|     eq('very error', exc_exec('normal ,e')) | ||||
|     eq('Vim(echoerr):The message.', exc_exec('normal ,m')) | ||||
|     feed('w') | ||||
|     screen:expect([[ | ||||
|       some ^short lines                                                 | | ||||
| @@ -296,7 +298,7 @@ describe('mappings with <Cmd>', function() | ||||
|     ]]) | ||||
|  | ||||
|     command(':%d') | ||||
|     eq('Vim(echoerr):Err', exc_exec("normal ,w")) | ||||
|     eq('Vim(echoerr):Err', exc_exec('normal ,w')) | ||||
|     screen:expect([[ | ||||
|       ^                                                                 | | ||||
|       0                                                                | | ||||
| @@ -332,7 +334,7 @@ describe('mappings with <Cmd>', function() | ||||
|     -- can invoke operator, ending visual mode | ||||
|     feed('<F5>') | ||||
|     eq('n', funcs.mode(1)) | ||||
|     eq({'some short l'}, funcs.getreg('a',1,1)) | ||||
|     eq({ 'some short l' }, funcs.getreg('a', 1, 1)) | ||||
|  | ||||
|     -- error doesn't interrupt visual mode | ||||
|     feed('ggvw<F6>') | ||||
| @@ -393,12 +395,12 @@ describe('mappings with <Cmd>', function() | ||||
|     -- visual mapping in select mode restart select mode after operator | ||||
|     feed('<F5>') | ||||
|     eq('s', funcs.mode(1)) | ||||
|     eq({'some short l'}, funcs.getreg('a',1,1)) | ||||
|     eq({ 'some short l' }, funcs.getreg('a', 1, 1)) | ||||
|  | ||||
|     -- select mode mapping works, and does not restart select mode | ||||
|     feed('<F2>') | ||||
|     eq('n', funcs.mode(1)) | ||||
|     eq({'some short l'}, funcs.getreg('b',1,1)) | ||||
|     eq({ 'some short l' }, funcs.getreg('b', 1, 1)) | ||||
|  | ||||
|     -- error doesn't interrupt temporary visual mode | ||||
|     feed('<esc>ggvw<c-g><F6>') | ||||
| @@ -468,17 +470,16 @@ describe('mappings with <Cmd>', function() | ||||
|     eq('i', eval('mode(1)')) | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   it('works in operator-pending mode', function() | ||||
|     feed('d<F4>') | ||||
|     expect([[ | ||||
|         lines | ||||
|         of test text]]) | ||||
|     eq({'some short '}, funcs.getreg('"',1,1)) | ||||
|     eq({ 'some short ' }, funcs.getreg('"', 1, 1)) | ||||
|     feed('.') | ||||
|     expect([[ | ||||
|         test text]]) | ||||
|     eq({'lines', 'of '}, funcs.getreg('"',1,1)) | ||||
|     eq({ 'lines', 'of ' }, funcs.getreg('"', 1, 1)) | ||||
|     feed('uu') | ||||
|     expect([[ | ||||
|         some short lines | ||||
| @@ -504,7 +505,7 @@ describe('mappings with <Cmd>', function() | ||||
|     feed('"bd<F7>') | ||||
|     expect([[ | ||||
|         soest text]]) | ||||
|     eq(funcs.getreg('b',1,1), {'me short lines', 'of t'}) | ||||
|     eq(funcs.getreg('b', 1, 1), { 'me short lines', 'of t' }) | ||||
|  | ||||
|     -- startinsert aborts operator | ||||
|     feed('d<F8>') | ||||
| @@ -514,7 +515,6 @@ describe('mappings with <Cmd>', function() | ||||
|   end) | ||||
|  | ||||
|   it('works in insert mode', function() | ||||
|  | ||||
|     -- works the same as <c-o>w<c-o>w | ||||
|     feed('iindeed <F4>little ') | ||||
|     screen:expect([[ | ||||
| @@ -535,7 +535,6 @@ describe('mappings with <Cmd>', function() | ||||
|       {3:Press ENTER or type command to continue}^                          | | ||||
|     ]]) | ||||
|  | ||||
|  | ||||
|     feed('<cr>') | ||||
|     eq('E605: Exception not caught: very error', eval('v:errmsg')) | ||||
|     -- still in insert | ||||
| @@ -562,7 +561,7 @@ describe('mappings with <Cmd>', function() | ||||
|       of stuff test text]]) | ||||
|  | ||||
|     feed('<F5>') | ||||
|     eq(funcs.getreg('a',1,1), {'deed some short little lines', 'of stuff t'}) | ||||
|     eq(funcs.getreg('a', 1, 1), { 'deed some short little lines', 'of stuff t' }) | ||||
|  | ||||
|     -- still in insert | ||||
|     screen:expect([[ | ||||
| @@ -704,7 +703,6 @@ describe('mappings with <Cmd>', function() | ||||
|     ]]) | ||||
|     eq('i', eval('mode(1)')) | ||||
|     eq(9, eval('g:y')) | ||||
|  | ||||
|   end) | ||||
|  | ||||
|   it("doesn't crash when invoking cmdline mode recursively #8859", function() | ||||
| @@ -726,18 +724,20 @@ describe('mappings with <Cmd>', function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it("works with <SID> mappings", function() | ||||
|   it('works with <SID> mappings', function() | ||||
|     command('new!') | ||||
|     write_file(tmpfile, [[ | ||||
|     write_file( | ||||
|       tmpfile, | ||||
|       [[ | ||||
|       map <f2> <Cmd>call <SID>do_it()<Cr> | ||||
|       function! s:do_it() | ||||
|         let g:x = 10 | ||||
|       endfunction | ||||
|     ]]) | ||||
|     command('source '..tmpfile) | ||||
|     ]] | ||||
|     ) | ||||
|     command('source ' .. tmpfile) | ||||
|     feed('<f2>') | ||||
|     eq('', eval('v:errmsg')) | ||||
|     eq(10, eval('g:x')) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -9,10 +9,10 @@ describe(':debug', function() | ||||
|     clear() | ||||
|     screen = Screen.new(30, 14) | ||||
|     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}, | ||||
|       [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 }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|   end) | ||||
|   | ||||
| @@ -8,7 +8,6 @@ local exec_lua = helpers.exec_lua | ||||
| local command = helpers.command | ||||
| local eval = helpers.eval | ||||
|  | ||||
|  | ||||
| describe('Vimscript dictionary notifications', function() | ||||
|   local channel | ||||
|  | ||||
| @@ -29,9 +28,9 @@ describe('Vimscript dictionary notifications', function() | ||||
|         key = 'watched' | ||||
|       end | ||||
|       if opval == '' then | ||||
|         command(('unlet %s[\'%s\']'):format(dict_expr, key)) | ||||
|         command(("unlet %s['%s']"):format(dict_expr, key)) | ||||
|       else | ||||
|         command(('let %s[\'%s\'] %s'):format(dict_expr, key, opval)) | ||||
|         command(("let %s['%s'] %s"):format(dict_expr, key, opval)) | ||||
|       end | ||||
|     end | ||||
|  | ||||
| @@ -40,9 +39,9 @@ describe('Vimscript dictionary notifications', function() | ||||
|         key = 'watched' | ||||
|       end | ||||
|       if opval == '' then | ||||
|         exec_lua(('vim.api.nvim_del_var(\'%s\')'):format(key)) | ||||
|         exec_lua(("vim.api.nvim_del_var('%s')"):format(key)) | ||||
|       else | ||||
|         exec_lua(('vim.api.nvim_set_var(\'%s\', %s)'):format(key, opval)) | ||||
|         exec_lua(("vim.api.nvim_set_var('%s', %s)"):format(key, opval)) | ||||
|       end | ||||
|     end | ||||
|  | ||||
| @@ -61,14 +60,14 @@ describe('Vimscript dictionary notifications', function() | ||||
|       -- helper to verify that no notifications are sent after certain change | ||||
|       -- to a dict | ||||
|       nvim('command', "call rpcnotify(g:channel, 'echo')") | ||||
|       eq({'notification', 'echo', {}}, next_msg()) | ||||
|       eq({ 'notification', 'echo', {} }, next_msg()) | ||||
|     end | ||||
|  | ||||
|     local function verify_value(vals, key) | ||||
|       if not key then | ||||
|         key = 'watched' | ||||
|       end | ||||
|       eq({'notification', 'values', {key, vals}}, next_msg()) | ||||
|       eq({ 'notification', 'values', { key, vals } }, next_msg()) | ||||
|     end | ||||
|  | ||||
|     describe(dict_expr .. ' watcher', function() | ||||
| @@ -81,20 +80,20 @@ describe('Vimscript dictionary notifications', function() | ||||
|       before_each(function() | ||||
|         source([[ | ||||
|         function! g:Changed(dict, key, value) | ||||
|           if a:dict isnot ]]..dict_expr..[[ | | ||||
|           if a:dict isnot ]] .. dict_expr .. [[ | | ||||
|             throw 'invalid dict' | ||||
|           endif | ||||
|           call rpcnotify(g:channel, 'values', a:key, a:value) | ||||
|         endfunction | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "watched", "g:Changed") | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "watched2", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "watched", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "watched2", "g:Changed") | ||||
|         ]]) | ||||
|       end) | ||||
|  | ||||
|       after_each(function() | ||||
|         source([[ | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "watched", "g:Changed") | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "watched2", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "watched", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "watched2", "g:Changed") | ||||
|         ]]) | ||||
|         update('= "test"') | ||||
|         update('= "test2"', 'watched2') | ||||
| @@ -134,99 +133,99 @@ describe('Vimscript dictionary notifications', function() | ||||
|  | ||||
|       it('is triggered by remove()', function() | ||||
|         update('= "test"') | ||||
|         verify_value({new = 'test'}) | ||||
|         nvim('command', 'call remove('..dict_expr..', "watched")') | ||||
|         verify_value({old = 'test'}) | ||||
|         verify_value({ new = 'test' }) | ||||
|         nvim('command', 'call remove(' .. dict_expr .. ', "watched")') | ||||
|         verify_value({ old = 'test' }) | ||||
|       end) | ||||
|  | ||||
|       if is_g then | ||||
|         it('is triggered by remove() when updated with nvim_*_var', function() | ||||
|           update_with_api('"test"') | ||||
|           verify_value({new = 'test'}) | ||||
|           nvim('command', 'call remove('..dict_expr..', "watched")') | ||||
|           verify_value({old = 'test'}) | ||||
|           verify_value({ new = 'test' }) | ||||
|           nvim('command', 'call remove(' .. dict_expr .. ', "watched")') | ||||
|           verify_value({ old = 'test' }) | ||||
|         end) | ||||
|  | ||||
|         it('is triggered by remove() when updated with vim.g', function() | ||||
|           update_with_vim_g('= "test"') | ||||
|           verify_value({new = 'test'}) | ||||
|           nvim('command', 'call remove('..dict_expr..', "watched")') | ||||
|           verify_value({old = 'test'}) | ||||
|           verify_value({ new = 'test' }) | ||||
|           nvim('command', 'call remove(' .. dict_expr .. ', "watched")') | ||||
|           verify_value({ old = 'test' }) | ||||
|         end) | ||||
|       end | ||||
|  | ||||
|       it('is triggered by extend()', function() | ||||
|         update('= "xtend"') | ||||
|         verify_value({new = 'xtend'}) | ||||
|         verify_value({ new = 'xtend' }) | ||||
|         nvim('command', [[ | ||||
|           call extend(]]..dict_expr..[[, {'watched': 'xtend2', 'watched2': 5, 'watched3': 'a'}) | ||||
|           call extend(]] .. dict_expr .. [[, {'watched': 'xtend2', 'watched2': 5, 'watched3': 'a'}) | ||||
|         ]]) | ||||
|         verify_value({old = 'xtend', new = 'xtend2'}) | ||||
|         verify_value({new = 5}, 'watched2') | ||||
|         verify_value({ old = 'xtend', new = 'xtend2' }) | ||||
|         verify_value({ new = 5 }, 'watched2') | ||||
|         update('') | ||||
|         verify_value({old = 'xtend2'}) | ||||
|         verify_value({ old = 'xtend2' }) | ||||
|         update('', 'watched2') | ||||
|         verify_value({old = 5}, 'watched2') | ||||
|         verify_value({ old = 5 }, 'watched2') | ||||
|         update('', 'watched3') | ||||
|         verify_echo() | ||||
|       end) | ||||
|  | ||||
|       it('is triggered with key patterns', function() | ||||
|         source([[ | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "wat*", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "wat*", "g:Changed") | ||||
|         ]]) | ||||
|         update('= 1') | ||||
|         verify_value({new = 1}) | ||||
|         verify_value({new = 1}) | ||||
|         verify_value({ new = 1 }) | ||||
|         verify_value({ new = 1 }) | ||||
|         update('= 3', 'watched2') | ||||
|         verify_value({new = 3}, 'watched2') | ||||
|         verify_value({new = 3}, 'watched2') | ||||
|         verify_value({ new = 3 }, 'watched2') | ||||
|         verify_value({ new = 3 }, 'watched2') | ||||
|         verify_echo() | ||||
|         source([[ | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "wat*", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "wat*", "g:Changed") | ||||
|         ]]) | ||||
|         -- watch every key pattern | ||||
|         source([[ | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "*", "g:Changed") | ||||
|         ]]) | ||||
|         update('= 3', 'another_key') | ||||
|         update('= 4', 'another_key') | ||||
|         update('', 'another_key') | ||||
|         update('= 2') | ||||
|         verify_value({new = 3}, 'another_key') | ||||
|         verify_value({old = 3, new = 4}, 'another_key') | ||||
|         verify_value({old = 4}, 'another_key') | ||||
|         verify_value({old = 1, new = 2}) | ||||
|         verify_value({old = 1, new = 2}) | ||||
|         verify_value({ new = 3 }, 'another_key') | ||||
|         verify_value({ old = 3, new = 4 }, 'another_key') | ||||
|         verify_value({ old = 4 }, 'another_key') | ||||
|         verify_value({ old = 1, new = 2 }) | ||||
|         verify_value({ old = 1, new = 2 }) | ||||
|         verify_echo() | ||||
|         source([[ | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "*", "g:Changed") | ||||
|         ]]) | ||||
|       end) | ||||
|  | ||||
|       it('is triggered for empty keys', function() | ||||
|         command([[ | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "", "g:Changed") | ||||
|         ]]) | ||||
|         update('= 1', '') | ||||
|         verify_value({new = 1}, '') | ||||
|         verify_value({ new = 1 }, '') | ||||
|         update('= 2', '') | ||||
|         verify_value({old = 1, new = 2}, '') | ||||
|         verify_value({ old = 1, new = 2 }, '') | ||||
|         command([[ | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "", "g:Changed") | ||||
|         ]]) | ||||
|       end) | ||||
|  | ||||
|       it('is triggered for empty keys when using catch-all *', function() | ||||
|         command([[ | ||||
|         call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed") | ||||
|         call dictwatcheradd(]] .. dict_expr .. [[, "*", "g:Changed") | ||||
|         ]]) | ||||
|         update('= 1', '') | ||||
|         verify_value({new = 1}, '') | ||||
|         verify_value({ new = 1 }, '') | ||||
|         update('= 2', '') | ||||
|         verify_value({old = 1, new = 2}, '') | ||||
|         verify_value({ old = 1, new = 2 }, '') | ||||
|         command([[ | ||||
|         call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed") | ||||
|         call dictwatcherdel(]] .. dict_expr .. [[, "*", "g:Changed") | ||||
|         ]]) | ||||
|       end) | ||||
|  | ||||
| @@ -244,31 +243,31 @@ describe('Vimscript dictionary notifications', function() | ||||
|       end | ||||
|  | ||||
|       test_updates({ | ||||
|         {'= 3', {new = 3}}, | ||||
|         {'= 6', {old = 3, new = 6}}, | ||||
|         {'+= 3', {old = 6, new = 9}}, | ||||
|         {'', {old = 9}} | ||||
|         { '= 3', { new = 3 } }, | ||||
|         { '= 6', { old = 3, new = 6 } }, | ||||
|         { '+= 3', { old = 6, new = 9 } }, | ||||
|         { '', { old = 9 } }, | ||||
|       }) | ||||
|  | ||||
|       test_updates({ | ||||
|         {'= "str"', {new = 'str'}}, | ||||
|         {'= "str2"', {old = 'str', new = 'str2'}}, | ||||
|         {'.= "2str"', {old = 'str2', new = 'str22str'}}, | ||||
|         {'', {old = 'str22str'}} | ||||
|         { '= "str"', { new = 'str' } }, | ||||
|         { '= "str2"', { old = 'str', new = 'str2' } }, | ||||
|         { '.= "2str"', { old = 'str2', new = 'str22str' } }, | ||||
|         { '', { old = 'str22str' } }, | ||||
|       }) | ||||
|  | ||||
|       test_updates({ | ||||
|         {'= [1, 2]', {new = {1, 2}}}, | ||||
|         {'= [1, 2, 3]', {old = {1, 2}, new = {1, 2, 3}}}, | ||||
|         { '= [1, 2]', { new = { 1, 2 } } }, | ||||
|         { '= [1, 2, 3]', { old = { 1, 2 }, new = { 1, 2, 3 } } }, | ||||
|         -- the += will update the list in place, so old and new are the same | ||||
|         {'+= [4, 5]', {old = {1, 2, 3, 4, 5}, new = {1, 2, 3, 4, 5}}}, | ||||
|         {'', {old = {1, 2, 3, 4 ,5}}} | ||||
|         { '+= [4, 5]', { old = { 1, 2, 3, 4, 5 }, new = { 1, 2, 3, 4, 5 } } }, | ||||
|         { '', { old = { 1, 2, 3, 4, 5 } } }, | ||||
|       }) | ||||
|  | ||||
|       test_updates({ | ||||
|         {'= {"k": "v"}', {new = {k = 'v'}}}, | ||||
|         {'= {"k1": 2}', {old = {k = 'v'}, new = {k1 = 2}}}, | ||||
|         {'', {old = {k1 = 2}}}, | ||||
|         { '= {"k": "v"}', { new = { k = 'v' } } }, | ||||
|         { '= {"k1": 2}', { old = { k = 'v' }, new = { k1 = 2 } } }, | ||||
|         { '', { old = { k1 = 2 } } }, | ||||
|       }) | ||||
|     end) | ||||
|   end | ||||
| @@ -295,17 +294,17 @@ describe('Vimscript dictionary notifications', function() | ||||
|  | ||||
|     it('invokes all callbacks when the key is changed', function() | ||||
|       nvim('command', 'let g:key = "value"') | ||||
|       eq({'notification', '1', {'key', {new = 'value'}}}, next_msg()) | ||||
|       eq({'notification', '2', {'key', {new = 'value'}}}, next_msg()) | ||||
|       eq({ 'notification', '1', { 'key', { new = 'value' } } }, next_msg()) | ||||
|       eq({ 'notification', '2', { 'key', { new = 'value' } } }, next_msg()) | ||||
|     end) | ||||
|  | ||||
|     it('only removes watchers that fully match dict, key and callback', function() | ||||
|       nvim('command', 'let g:key = "value"') | ||||
|       eq({'notification', '1', {'key', {new = 'value'}}}, next_msg()) | ||||
|       eq({'notification', '2', {'key', {new = 'value'}}}, next_msg()) | ||||
|       eq({ 'notification', '1', { 'key', { new = 'value' } } }, next_msg()) | ||||
|       eq({ 'notification', '2', { 'key', { new = 'value' } } }, next_msg()) | ||||
|       nvim('command', 'call dictwatcherdel(g:, "key", "g:Watcher1")') | ||||
|       nvim('command', 'let g:key = "v2"') | ||||
|       eq({'notification', '2', {'key', {old = 'value', new = 'v2'}}}, next_msg()) | ||||
|       eq({ 'notification', '2', { 'key', { old = 'value', new = 'v2' } } }, next_msg()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -315,8 +314,10 @@ describe('Vimscript dictionary notifications', function() | ||||
|       call rpcnotify(g:channel, '1', a:key, a:value) | ||||
|     endfunction | ||||
|     ]]) | ||||
|     eq('Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"', | ||||
|        exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')) | ||||
|     eq( | ||||
|       'Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"', | ||||
|       exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   describe('errors', function() | ||||
| @@ -333,13 +334,17 @@ describe('Vimscript dictionary notifications', function() | ||||
|  | ||||
|     -- WARNING: This suite depends on the above tests | ||||
|     it('fails to remove if no watcher with matching callback is found', function() | ||||
|       eq("Vim(call):Couldn't find a watcher matching key and callback", | ||||
|         exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")')) | ||||
|       eq( | ||||
|         "Vim(call):Couldn't find a watcher matching key and callback", | ||||
|         exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('fails to remove if no watcher with matching key is found', function() | ||||
|       eq("Vim(call):Couldn't find a watcher matching key and callback", | ||||
|         exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")')) | ||||
|       eq( | ||||
|         "Vim(call):Couldn't find a watcher matching key and callback", | ||||
|         exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it("does not fail to add/remove if the callback doesn't exist", function() | ||||
| @@ -348,8 +353,10 @@ describe('Vimscript dictionary notifications', function() | ||||
|     end) | ||||
|  | ||||
|     it('fails to remove watcher from v:_null_dict', function() | ||||
|       eq("Vim(call):Couldn't find a watcher matching key and callback", | ||||
|          exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")')) | ||||
|       eq( | ||||
|         "Vim(call):Couldn't find a watcher matching key and callback", | ||||
|         exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     --[[ | ||||
| @@ -373,7 +380,7 @@ describe('Vimscript dictionary notifications', function() | ||||
|       ]]) | ||||
|       command('call g:ReplaceWatcher2()') | ||||
|       command('let g:key = "value"') | ||||
|       eq({'notification', '2b', {'key', {old = 'v2', new = 'value'}}}, next_msg()) | ||||
|       eq({ 'notification', '2b', { 'key', { old = 'v2', new = 'value' } } }, next_msg()) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash when freeing a watched dictionary', function() | ||||
| @@ -400,7 +407,7 @@ describe('Vimscript dictionary notifications', function() | ||||
|       call dictwatcheradd(d, 'foo', {dict, key, value -> rpcnotify(g:channel, '2', key, value)}) | ||||
|       let d.foo = 'bar' | ||||
|       ]]) | ||||
|       eq({'notification', '2', {'foo', {old = 'baz', new = 'bar'}}}, next_msg()) | ||||
|       eq({ 'notification', '2', { 'foo', { old = 'baz', new = 'bar' } } }, next_msg()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -412,12 +419,11 @@ describe('Vimscript dictionary notifications', function() | ||||
|       call dictwatcheradd(b:, 'changedtick', 'OnTickChanged') | ||||
|     ]]) | ||||
|  | ||||
|     insert('t'); | ||||
|     eq({'notification', 'SendChangeTick', {'changedtick', {old = 2, new = 3}}}, | ||||
|        next_msg()) | ||||
|     insert('t') | ||||
|     eq({ 'notification', 'SendChangeTick', { 'changedtick', { old = 2, new = 3 } } }, next_msg()) | ||||
|  | ||||
|     command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]]) | ||||
|     insert('t'); | ||||
|     insert('t') | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
| @@ -479,7 +485,7 @@ describe('Vimscript dictionary notifications', function() | ||||
|       let g:d.foo = 23 | ||||
|     ]]) | ||||
|     eq(23, eval('g:d.foo')) | ||||
|     eq({"W1"}, eval('g:calls')) | ||||
|     eq({ 'W1' }, eval('g:calls')) | ||||
|   end) | ||||
|  | ||||
|   it('calls watcher deleted in callback', function() | ||||
| @@ -507,7 +513,6 @@ describe('Vimscript dictionary notifications', function() | ||||
|       let g:d.foo = 123 | ||||
|     ]]) | ||||
|     eq(123, eval('g:d.foo')) | ||||
|     eq({"W1", "W2", "W2", "W1"}, eval('g:calls')) | ||||
|     eq({ 'W1', 'W2', 'W2', 'W1' }, eval('g:calls')) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -10,13 +10,13 @@ describe(':digraphs', function() | ||||
|     clear() | ||||
|     screen = Screen.new(65, 8) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, | ||||
|       [3] = {bold = true, foreground = Screen.colors.SeaGreen4}, | ||||
|       [4] = {bold = true}, | ||||
|       [5] = {background = Screen.colors.LightGrey}, | ||||
|       [6] = {foreground = Screen.colors.Blue1}, | ||||
|       [7] = {bold = true, reverse = true}, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Blue1 }, | ||||
|       [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, | ||||
|       [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, | ||||
|       [4] = { bold = true }, | ||||
|       [5] = { background = Screen.colors.LightGrey }, | ||||
|       [6] = { foreground = Screen.colors.Blue1 }, | ||||
|       [7] = { bold = true, reverse = true }, | ||||
|     }) | ||||
|     screen:attach() | ||||
|   end) | ||||
|   | ||||
| @@ -3,7 +3,7 @@ local command = helpers.command | ||||
| local Screen = require('test.functional.ui.screen') | ||||
| local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command | ||||
|  | ||||
| describe(":drop", function() | ||||
| describe(':drop', function() | ||||
|   local screen | ||||
|  | ||||
|   before_each(function() | ||||
| @@ -11,16 +11,16 @@ describe(":drop", function() | ||||
|     screen = Screen.new(35, 10) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold=true, foreground=Screen.colors.Blue}, | ||||
|       [1] = {bold = true, reverse = true}, | ||||
|       [2] = {reverse = true}, | ||||
|       [3] = {bold = true}, | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, | ||||
|       [1] = { bold = true, reverse = true }, | ||||
|       [2] = { reverse = true }, | ||||
|       [3] = { bold = true }, | ||||
|     }) | ||||
|     command("set laststatus=2 shortmess-=F") | ||||
|     command('set laststatus=2 shortmess-=F') | ||||
|   end) | ||||
|  | ||||
|   it("works like :e when called with only one window open", function() | ||||
|     feed_command("drop tmp1.vim") | ||||
|   it('works like :e when called with only one window open', function() | ||||
|     feed_command('drop tmp1.vim') | ||||
|     screen:expect([[ | ||||
|       ^                                   | | ||||
|       {0:~                                  }|*7 | ||||
| @@ -29,11 +29,11 @@ describe(":drop", function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it("switches to an open window showing the buffer", function() | ||||
|     feed_command("edit tmp1") | ||||
|     feed_command("vsplit") | ||||
|     feed_command("edit tmp2") | ||||
|     feed_command("drop tmp1") | ||||
|   it('switches to an open window showing the buffer', function() | ||||
|     feed_command('edit tmp1') | ||||
|     feed_command('vsplit') | ||||
|     feed_command('edit tmp2') | ||||
|     feed_command('drop tmp1') | ||||
|     screen:expect([[ | ||||
|                     │^                    | | ||||
|       {0:~             }│{0:~                   }|*7 | ||||
| @@ -43,12 +43,12 @@ describe(":drop", function() | ||||
|   end) | ||||
|  | ||||
|   it("splits off a new window when a buffer can't be abandoned", function() | ||||
|     command("set nohidden") | ||||
|     feed_command("edit tmp1") | ||||
|     feed_command("vsplit") | ||||
|     feed_command("edit tmp2") | ||||
|     feed("iABC<esc>") | ||||
|     feed_command("drop tmp3") | ||||
|     command('set nohidden') | ||||
|     feed_command('edit tmp1') | ||||
|     feed_command('vsplit') | ||||
|     feed_command('edit tmp2') | ||||
|     feed('iABC<esc>') | ||||
|     feed_command('drop tmp3') | ||||
|     screen:expect([[ | ||||
|       ^                    │              | | ||||
|       {0:~                   }│{0:~             }|*3 | ||||
| @@ -59,5 +59,4 @@ describe(":drop", function() | ||||
|       "tmp3" [New]                       | | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -14,15 +14,15 @@ local exec_capture = helpers.exec_capture | ||||
| local matches = helpers.matches | ||||
|  | ||||
| describe(':echo :echon :echomsg :echoerr', function() | ||||
|   local fn_tbl = {'String', 'StringN', 'StringMsg', 'StringErr'} | ||||
|   local fn_tbl = { 'String', 'StringN', 'StringMsg', 'StringErr' } | ||||
|   local function assert_same_echo_dump(expected, input, use_eval) | ||||
|     for _,v in pairs(fn_tbl) do | ||||
|       eq(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) | ||||
|     for _, v in pairs(fn_tbl) do | ||||
|       eq(expected, use_eval and eval(v .. '(' .. input .. ')') or funcs[v](input)) | ||||
|     end | ||||
|   end | ||||
|   local function assert_matches_echo_dump(expected, input, use_eval) | ||||
|     for _,v in pairs(fn_tbl) do | ||||
|       matches(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) | ||||
|     for _, v in pairs(fn_tbl) do | ||||
|       matches(expected, use_eval and eval(v .. '(' .. input .. ')') or funcs[v](input)) | ||||
|     end | ||||
|   end | ||||
|  | ||||
| @@ -85,14 +85,12 @@ describe(':echo :echon :echomsg :echoerr', function() | ||||
|       eq('v:null', funcs.StringErr(NIL)) | ||||
|     end) | ||||
|  | ||||
|     it('dumps values with at most six digits after the decimal point', | ||||
|     function() | ||||
|     it('dumps values with at most six digits after the decimal point', function() | ||||
|       assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020) | ||||
|       assert_same_echo_dump('1.234568', 1.23456789123456789123456789) | ||||
|     end) | ||||
|  | ||||
|     it('dumps values with at most seven digits before the decimal point', | ||||
|     function() | ||||
|     it('dumps values with at most seven digits before the decimal point', function() | ||||
|       assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789) | ||||
|       assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789) | ||||
|     end) | ||||
| @@ -115,8 +113,8 @@ describe(':echo :echon :echomsg :echoerr', function() | ||||
|     end) | ||||
|  | ||||
|     it('dumps large values', function() | ||||
|       assert_same_echo_dump('2147483647', 2^31-1) | ||||
|       assert_same_echo_dump('-2147483648', -2^31) | ||||
|       assert_same_echo_dump('2147483647', 2 ^ 31 - 1) | ||||
|       assert_same_echo_dump('-2147483648', -2 ^ 31) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| @@ -198,75 +196,95 @@ describe(':echo :echon :echomsg :echoerr', function() | ||||
|         let TestDictRef = function('TestDict', d) | ||||
|         let d.tdr = TestDictRef | ||||
|       ]]) | ||||
|       eq(dedent([[ | ||||
|       eq( | ||||
|         dedent([[ | ||||
|           function('TestDict', {'tdr': function('TestDict', {...@1})})]]), | ||||
|          exec_capture('echo String(d.tdr)')) | ||||
|         exec_capture('echo String(d.tdr)') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('dumps automatically created partials', function() | ||||
|       assert_same_echo_dump( | ||||
|         "function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})", | ||||
|         '{"f": Test2_f}.f', | ||||
|         true) | ||||
|         true | ||||
|       ) | ||||
|       assert_same_echo_dump( | ||||
|         "function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})", | ||||
|         '{"f": function(Test2_f, [1])}.f', | ||||
|         true) | ||||
|         true | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('dumps manually created partials', function() | ||||
|       assert_same_echo_dump("function('Test3', [1, 2], {})", | ||||
|                             "function('Test3', [1, 2], {})", true) | ||||
|       assert_same_echo_dump("function('Test3', [1, 2])", | ||||
|                             "function('Test3', [1, 2])", true) | ||||
|       assert_same_echo_dump("function('Test3', {})", | ||||
|                             "function('Test3', {})", true) | ||||
|       assert_same_echo_dump("function('Test3', [1, 2], {})", "function('Test3', [1, 2], {})", true) | ||||
|       assert_same_echo_dump("function('Test3', [1, 2])", "function('Test3', [1, 2])", true) | ||||
|       assert_same_echo_dump("function('Test3', {})", "function('Test3', {})", true) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash or halt when dumping partials with reference cycles in self', | ||||
|     function() | ||||
|       meths.set_var('d', {v=true}) | ||||
|       eq(dedent([[ | ||||
|           {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]), | ||||
|         exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) | ||||
|     it('does not crash or halt when dumping partials with reference cycles in self', function() | ||||
|       meths.set_var('d', { v = true }) | ||||
|       eq( | ||||
|         dedent( | ||||
|           [[ | ||||
|           {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]] | ||||
|         ), | ||||
|         exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('does not show errors when dumping partials referencing the same dictionary', | ||||
|     function() | ||||
|     it('does not show errors when dumping partials referencing the same dictionary', function() | ||||
|       command('let d = {}') | ||||
|       -- Regression for “eval/typval_encode: Dump empty dictionary before | ||||
|       -- checking for refcycle”, results in error. | ||||
|       eq('[function(\'tr\', {}), function(\'tr\', {})]', eval('String([function("tr", d), function("tr", d)])')) | ||||
|       eq( | ||||
|         "[function('tr', {}), function('tr', {})]", | ||||
|         eval('String([function("tr", d), function("tr", d)])') | ||||
|       ) | ||||
|       -- Regression for “eval: Work with reference cycles in partials (self) | ||||
|       -- properly”, results in crash. | ||||
|       eval('extend(d, {"a": 1})') | ||||
|       eq('[function(\'tr\', {\'a\': 1}), function(\'tr\', {\'a\': 1})]', eval('String([function("tr", d), function("tr", d)])')) | ||||
|       eq( | ||||
|         "[function('tr', {'a': 1}), function('tr', {'a': 1})]", | ||||
|         eval('String([function("tr", d), function("tr", d)])') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash or halt when dumping partials with reference cycles in arguments', | ||||
|     function() | ||||
|     it('does not crash or halt when dumping partials with reference cycles in arguments', function() | ||||
|       meths.set_var('l', {}) | ||||
|       eval('add(l, l)') | ||||
|       -- Regression: the below line used to crash (add returns original list and | ||||
|       -- there was error in dumping partials). Tested explicitly in | ||||
|       -- test/unit/api/private_helpers_spec.lua. | ||||
|       eval('add(l, function("Test1", l))') | ||||
|       eq(dedent([=[ | ||||
|           function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]), | ||||
|         exec_capture('echo String(function("Test1", l))')) | ||||
|       eq( | ||||
|         dedent( | ||||
|           [=[ | ||||
|           function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=] | ||||
|         ), | ||||
|         exec_capture('echo String(function("Test1", l))') | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('does not crash or halt when dumping partials with reference cycles in self and arguments', | ||||
|     it( | ||||
|       'does not crash or halt when dumping partials with reference cycles in self and arguments', | ||||
|       function() | ||||
|       meths.set_var('d', {v=true}) | ||||
|         meths.set_var('d', { v = true }) | ||||
|         meths.set_var('l', {}) | ||||
|         eval('add(l, l)') | ||||
|         eval('add(l, function("Test1", l))') | ||||
|         eval('add(l, function("Test1", d))') | ||||
|       eq(dedent([=[ | ||||
|           {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]), | ||||
|         exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) | ||||
|     end) | ||||
|         eq( | ||||
|           dedent( | ||||
|             [=[ | ||||
|           {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=] | ||||
|           ), | ||||
|           exec_capture( | ||||
|             'echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))' | ||||
|           ) | ||||
|         ) | ||||
|       end | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   describe('used to represent lists', function() | ||||
| @@ -275,15 +293,15 @@ describe(':echo :echon :echomsg :echoerr', function() | ||||
|     end) | ||||
|  | ||||
|     it('dumps non-empty list', function() | ||||
|       assert_same_echo_dump('[1, 2]', {1,2}) | ||||
|       assert_same_echo_dump('[1, 2]', { 1, 2 }) | ||||
|     end) | ||||
|  | ||||
|     it('dumps nested lists', function() | ||||
|       assert_same_echo_dump('[[[[[]]]]]', {{{{{}}}}}) | ||||
|       assert_same_echo_dump('[[[[[]]]]]', { { { { {} } } } }) | ||||
|     end) | ||||
|  | ||||
|     it('dumps nested non-empty lists', function() | ||||
|       assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', {1, {{3, {{5}, 4}}, 2}}) | ||||
|       assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', { 1, { { 3, { { 5 }, 4 } }, 2 } }) | ||||
|     end) | ||||
|  | ||||
|     it('does not error when dumping recursive lists', function() | ||||
| @@ -308,27 +326,25 @@ describe(':echo :echon :echomsg :echoerr', function() | ||||
|     it('dumps list with two same empty dictionaries, also in partials', function() | ||||
|       command('let d = {}') | ||||
|       assert_same_echo_dump('[{}, {}]', '[d, d]', true) | ||||
|       eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) | ||||
|       eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) | ||||
|       eq("[function('tr', {}), {}]", eval('String([function("tr", d), d])')) | ||||
|       eq("[{}, function('tr', {})]", eval('String([d, function("tr", d)])')) | ||||
|     end) | ||||
|  | ||||
|     it('dumps non-empty dictionary', function() | ||||
|       assert_same_echo_dump("{'t''est': 1}", {["t'est"]=1}) | ||||
|       assert_same_echo_dump("{'t''est': 1}", { ["t'est"] = 1 }) | ||||
|     end) | ||||
|  | ||||
|     it('does not error when dumping recursive dictionaries', function() | ||||
|       meths.set_var('d', {d=1}) | ||||
|       meths.set_var('d', { d = 1 }) | ||||
|       eval('extend(d, {"d": d})') | ||||
|       eq(0, exc_exec('echo String(d)')) | ||||
|     end) | ||||
|  | ||||
|     it('dumps recursive dictionaries without the error', function() | ||||
|       meths.set_var('d', {d=1}) | ||||
|       meths.set_var('d', { d = 1 }) | ||||
|       eval('extend(d, {"d": d})') | ||||
|       eq('{\'d\': {...@0}}', | ||||
|          exec_capture('echo String(d)')) | ||||
|       eq('{\'out\': {\'d\': {...@1}}}', | ||||
|          exec_capture('echo String({"out": d})')) | ||||
|       eq("{'d': {...@0}}", exec_capture('echo String(d)')) | ||||
|       eq("{'out': {'d': {...@1}}}", exec_capture('echo String({"out": d})')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   | ||||
| @@ -1,25 +1,25 @@ | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs | ||||
| local ok = helpers.ok | ||||
| local clear = helpers.clear | ||||
| local feed = helpers.feed | ||||
|  | ||||
| describe(":edit", function() | ||||
| describe(':edit', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|   end) | ||||
|  | ||||
|   it("without arguments does not restart :terminal buffer", function() | ||||
|       command("terminal") | ||||
|   it('without arguments does not restart :terminal buffer', function() | ||||
|     command('terminal') | ||||
|     feed([[<C-\><C-N>]]) | ||||
|       local bufname_before = funcs.bufname("%") | ||||
|       local bufnr_before = funcs.bufnr("%") | ||||
|       helpers.ok(nil ~= string.find(bufname_before, "^term://"))  -- sanity | ||||
|     local bufname_before = funcs.bufname('%') | ||||
|     local bufnr_before = funcs.bufnr('%') | ||||
|     helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity | ||||
|  | ||||
|       command("edit") | ||||
|     command('edit') | ||||
|  | ||||
|       local bufname_after = funcs.bufname("%") | ||||
|       local bufnr_after = funcs.bufnr("%") | ||||
|     local bufname_after = funcs.bufname('%') | ||||
|     local bufnr_after = funcs.bufnr('%') | ||||
|     ok(funcs.line('$') > 1) | ||||
|     eq(bufname_before, bufname_after) | ||||
|     eq(bufnr_before, bufnr_after) | ||||
|   | ||||
| @@ -3,7 +3,6 @@ local clear, feed_command, feed = helpers.clear, helpers.feed_command, helpers.f | ||||
| local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval | ||||
|  | ||||
| describe('&encoding', function() | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     -- sanity check: tests should run with encoding=utf-8 | ||||
| @@ -32,9 +31,9 @@ describe('&encoding', function() | ||||
|  | ||||
|   it('can be set to utf-8 without error', function() | ||||
|     feed_command('set encoding=utf-8') | ||||
|     eq("", eval('v:errmsg')) | ||||
|     eq('', eval('v:errmsg')) | ||||
|  | ||||
|     clear('--cmd', 'set enc=utf-8') | ||||
|     eq("", eval('v:errmsg')) | ||||
|     eq('', eval('v:errmsg')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local command = helpers.command | ||||
| local eq = helpers.eq | ||||
| local clear = helpers.clear | ||||
| @@ -20,15 +20,25 @@ describe('Ex cmds', function() | ||||
|     command(':later 9999999999999999999999999999999999999999') | ||||
|     command(':echo expand("#<9999999999999999999999999999999999999999")') | ||||
|     command(':lockvar 9999999999999999999999999999999999999999') | ||||
|     command(':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999') | ||||
|     check_excmd_err(':tabnext 9999999999999999999999999999999999999999', | ||||
|                     'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999') | ||||
|     check_excmd_err(':N 9999999999999999999999999999999999999999', | ||||
|                     'Vim(Next):E939: Positive count required') | ||||
|     check_excmd_err(':bdelete 9999999999999999999999999999999999999999', | ||||
|                     'Vim(bdelete):E939: Positive count required') | ||||
|     eq('Vim(menu):E329: No menu "9999999999999999999999999999999999999999"', | ||||
|       pcall_err(command, ':menu 9999999999999999999999999999999999999999')) | ||||
|     command( | ||||
|       ':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999' | ||||
|     ) | ||||
|     check_excmd_err( | ||||
|       ':tabnext 9999999999999999999999999999999999999999', | ||||
|       'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999' | ||||
|     ) | ||||
|     check_excmd_err( | ||||
|       ':N 9999999999999999999999999999999999999999', | ||||
|       'Vim(Next):E939: Positive count required' | ||||
|     ) | ||||
|     check_excmd_err( | ||||
|       ':bdelete 9999999999999999999999999999999999999999', | ||||
|       'Vim(bdelete):E939: Positive count required' | ||||
|     ) | ||||
|     eq( | ||||
|       'Vim(menu):E329: No menu "9999999999999999999999999999999999999999"', | ||||
|       pcall_err(command, ':menu 9999999999999999999999999999999999999999') | ||||
|     ) | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ local rmdir = helpers.rmdir | ||||
| local mkdir = helpers.mkdir | ||||
|  | ||||
| describe(':file', function() | ||||
|   local swapdir = luv.cwd()..'/Xtest-file_spec' | ||||
|   local swapdir = luv.cwd() .. '/Xtest-file_spec' | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     rmdir(swapdir) | ||||
| @@ -19,18 +19,17 @@ describe(':file', function() | ||||
|     rmdir(swapdir) | ||||
|   end) | ||||
|  | ||||
|   it("rename does not lose swapfile #6487", function() | ||||
|   it('rename does not lose swapfile #6487', function() | ||||
|     local testfile = 'test-file_spec' | ||||
|     local testfile_renamed = testfile..'-renamed' | ||||
|     local testfile_renamed = testfile .. '-renamed' | ||||
|     -- Note: `set swapfile` *must* go after `set directory`: otherwise it may | ||||
|     -- attempt to create a swapfile in different directory. | ||||
|     command('set directory^='..swapdir..'//') | ||||
|     command('set directory^=' .. swapdir .. '//') | ||||
|     command('set swapfile fileformat=unix undolevels=-1') | ||||
|  | ||||
|     command('edit! '..testfile) | ||||
|     command('edit! ' .. testfile) | ||||
|     -- Before #6487 this gave "E301: Oops, lost the swap file !!!" on Windows. | ||||
|     command('file '..testfile_renamed) | ||||
|     eq(testfile_renamed..'.swp', | ||||
|        string.match(funcs.execute('swapname'), '[^%%]+$')) | ||||
|     command('file ' .. testfile_renamed) | ||||
|     eq(testfile_renamed .. '.swp', string.match(funcs.execute('swapname'), '[^%%]+$')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| local Screen = require('test.functional.ui.screen') | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local eq, command = helpers.eq, helpers.command | ||||
| local clear = helpers.clear | ||||
| local eval, exc_exec = helpers.eval, helpers.exc_exec | ||||
| @@ -17,15 +17,18 @@ describe(':highlight', function() | ||||
|   end) | ||||
|  | ||||
|   it('invalid color name', function() | ||||
|     eq('Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818', | ||||
|        exc_exec("highlight normal ctermfg=#181818")) | ||||
|     eq('Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818', | ||||
|        exc_exec("highlight normal ctermbg=#181818")) | ||||
|     eq( | ||||
|       'Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818', | ||||
|       exc_exec('highlight normal ctermfg=#181818') | ||||
|     ) | ||||
|     eq( | ||||
|       'Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818', | ||||
|       exc_exec('highlight normal ctermbg=#181818') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('invalid group name', function() | ||||
|     eq('Vim(highlight):E411: Highlight group not found: foo', | ||||
|        exc_exec("highlight foo")) | ||||
|     eq('Vim(highlight):E411: Highlight group not found: foo', exc_exec('highlight foo')) | ||||
|   end) | ||||
|  | ||||
|   it('"Normal" foreground with red', function() | ||||
|   | ||||
| @@ -44,6 +44,4 @@ describe(':ls', function() | ||||
|       eq('\n  3 %aF ', string.match(ls_output, '^\n *3 ... ')) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -8,27 +8,30 @@ local testprg = helpers.testprg | ||||
|  | ||||
| describe(':make', function() | ||||
|   clear() | ||||
|   before_each(function () | ||||
|   before_each(function() | ||||
|     clear() | ||||
|   end) | ||||
|  | ||||
|   describe('with powershell', function() | ||||
|     if not has_powershell() then | ||||
|       pending("not tested; powershell was not found", function() end) | ||||
|       pending('not tested; powershell was not found', function() end) | ||||
|       return | ||||
|     end | ||||
|     before_each(function () | ||||
|     before_each(function() | ||||
|       helpers.set_shell_powershell() | ||||
|     end) | ||||
|  | ||||
|     it('captures stderr & non zero exit code #14349', function () | ||||
|       nvim('set_option_value', 'makeprg', testprg('shell-test')..' foo', {}) | ||||
|     it('captures stderr & non zero exit code #14349', function() | ||||
|       nvim('set_option_value', 'makeprg', testprg('shell-test') .. ' foo', {}) | ||||
|       local out = eval('execute("make")') | ||||
|       -- Error message is captured in the file and printed in the footer | ||||
|       matches('[\r\n]+.*[\r\n]+Unknown first argument%: foo[\r\n]+%(1 of 1%)%: Unknown first argument%: foo', out) | ||||
|       matches( | ||||
|         '[\r\n]+.*[\r\n]+Unknown first argument%: foo[\r\n]+%(1 of 1%)%: Unknown first argument%: foo', | ||||
|         out | ||||
|       ) | ||||
|     end) | ||||
|  | ||||
|     it('captures stderr & zero exit code #14349', function () | ||||
|     it('captures stderr & zero exit code #14349', function() | ||||
|       nvim('set_option_value', 'makeprg', testprg('shell-test'), {}) | ||||
|       local out = eval('execute("make")') | ||||
|       -- Ensure there are no "shell returned X" messages between | ||||
| @@ -36,7 +39,5 @@ describe(':make', function() | ||||
|       matches('LastExitCode%s+ready [$]%s+[(]', out) | ||||
|       matches('\n.*%: ready [$]', out) | ||||
|     end) | ||||
|  | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local Screen = require('test.functional.ui.screen') | ||||
|  | ||||
| local eq = helpers.eq | ||||
| @@ -33,23 +33,27 @@ describe(':*map', function() | ||||
|  | ||||
|   it('shows <Nop> as mapping rhs', function() | ||||
|     command('nmap asdf <Nop>') | ||||
|     eq([[ | ||||
|     eq( | ||||
|       [[ | ||||
|  | ||||
| n  asdf          <Nop>]], | ||||
|        exec_capture('nmap asdf')) | ||||
|       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([[ | ||||
|     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]], | ||||
|        exec_capture('filter the nmap')) | ||||
|       exec_capture('filter the nmap') | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('<Plug> mappings ignore nore', function() | ||||
| @@ -75,7 +79,7 @@ n  asdf1         qwert | ||||
|       nmap increase_x_remap x<Plug>(Increase_x)x | ||||
|       nnoremap increase_x_noremap x<Plug>(Increase_x)x | ||||
|     ]] | ||||
|     insert("Some text") | ||||
|     insert('Some text') | ||||
|     eq('Some text', eval("getline('.')")) | ||||
|  | ||||
|     feed('increase_x_remap') | ||||
|   | ||||
| @@ -4,9 +4,7 @@ local expect, feed = helpers.expect, helpers.feed | ||||
| local eq, eval = helpers.eq, helpers.eval | ||||
| local funcs = helpers.funcs | ||||
|  | ||||
|  | ||||
| describe(':emenu', function() | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     command('nnoremenu Test.Test inormal<ESC>') | ||||
| @@ -60,7 +58,6 @@ describe(':emenu', function() | ||||
| end) | ||||
|  | ||||
| describe('menu_get', function() | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     command([=[ | ||||
| @@ -83,12 +80,12 @@ describe('menu_get', function() | ||||
|   end) | ||||
|  | ||||
|   it("path='', modes='a'", function() | ||||
|     local m = funcs.menu_get("","a"); | ||||
|     local m = funcs.menu_get('', 'a') | ||||
|     -- HINT: To print the expected table and regenerate the tests: | ||||
|     -- print(require('vim.inspect')(m)) | ||||
|     local expected = { | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         submenus = { | ||||
|           { | ||||
| @@ -97,176 +94,45 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "insert", | ||||
|                 silent = 0 | ||||
|                 rhs = 'insert', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               s = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "x", | ||||
|                 silent = 0 | ||||
|                 rhs = 'x', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "inormal<Esc>", | ||||
|                 silent = 0 | ||||
|                 rhs = 'inormal<Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               v = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "x", | ||||
|                 silent = 0 | ||||
|                 rhs = 'x', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               c = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "cmdmode", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'cmdmode', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = "Test", | ||||
|             hidden = 0 | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
|             name = "Nested", | ||||
|             submenus = { | ||||
|               { | ||||
|                 mappings = { | ||||
|                   o = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level1", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   v = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level1", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   s = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level1", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   n = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level1", | ||||
|                     silent = 0 | ||||
|                   } | ||||
|                 }, | ||||
|                 priority = 500, | ||||
|                 name = "test", | ||||
|                 hidden = 0 | ||||
|               }, | ||||
|               { | ||||
|                 mappings = { | ||||
|                   o = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level2", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   v = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level2", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   s = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level2", | ||||
|                     silent = 0 | ||||
|                   }, | ||||
|                   n = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = "level2", | ||||
|                     silent = 0 | ||||
|                   } | ||||
|                 }, | ||||
|                 priority = 500, | ||||
|                 name = "Nested2", | ||||
|                 hidden = 0 | ||||
|               } | ||||
|             }, | ||||
|             hidden = 0 | ||||
|           } | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test" | ||||
|       }, | ||||
|       { | ||||
|         priority = 500, | ||||
|         name = "Export", | ||||
|         submenus = { | ||||
|           { | ||||
|             tooltip = "This is the tooltip", | ||||
|             name = 'Test', | ||||
|             hidden = 0, | ||||
|             name = "Script", | ||||
|             priority = 500, | ||||
|             mappings = { | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "p", | ||||
|                 silent = 0 | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         hidden = 0 | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
|         name = "Edit", | ||||
|         submenus = { | ||||
|           { | ||||
|             mappings = { | ||||
|               c = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "<C-R>\"", | ||||
|                 silent = 0 | ||||
|               }, | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "p", | ||||
|                 silent = 0 | ||||
|               } | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = "Paste", | ||||
|             hidden = 0 | ||||
|           } | ||||
|         }, | ||||
|         hidden = 0 | ||||
|       }, | ||||
|       { | ||||
|         priority = 500, | ||||
|         name = "]Export", | ||||
|             name = 'Nested', | ||||
|             submenus = { | ||||
|               { | ||||
|                 mappings = { | ||||
| @@ -274,72 +140,207 @@ describe('menu_get', function() | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                 rhs = "thisoneshouldbehidden", | ||||
|                 silent = 0 | ||||
|                     rhs = 'level1', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   v = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                 rhs = "thisoneshouldbehidden", | ||||
|                 silent = 0 | ||||
|                     rhs = 'level1', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   s = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                 rhs = "thisoneshouldbehidden", | ||||
|                 silent = 0 | ||||
|                     rhs = 'level1', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   n = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                 rhs = "thisoneshouldbehidden", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                     rhs = 'level1', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                 }, | ||||
|                 priority = 500, | ||||
|             name = "hidden", | ||||
|             hidden = 0 | ||||
|           } | ||||
|                 name = 'test', | ||||
|                 hidden = 0, | ||||
|               }, | ||||
|               { | ||||
|                 mappings = { | ||||
|                   o = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = 'level2', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   v = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = 'level2', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   s = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = 'level2', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                   n = { | ||||
|                     sid = 0, | ||||
|                     noremap = 0, | ||||
|                     enabled = 1, | ||||
|                     rhs = 'level2', | ||||
|                     silent = 0, | ||||
|                   }, | ||||
|                 }, | ||||
|                 priority = 500, | ||||
|                 name = 'Nested2', | ||||
|                 hidden = 0, | ||||
|               }, | ||||
|             }, | ||||
|             hidden = 0, | ||||
|           }, | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = 'Test', | ||||
|       }, | ||||
|       { | ||||
|         priority = 500, | ||||
|         name = 'Export', | ||||
|         submenus = { | ||||
|           { | ||||
|             tooltip = 'This is the tooltip', | ||||
|             hidden = 0, | ||||
|             name = 'Script', | ||||
|             priority = 500, | ||||
|             mappings = { | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'p', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|         }, | ||||
|         hidden = 0, | ||||
|       }, | ||||
|       { | ||||
|         priority = 500, | ||||
|         name = 'Edit', | ||||
|         submenus = { | ||||
|           { | ||||
|             mappings = { | ||||
|               c = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = '<C-R>"', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'p', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = 'Paste', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|         }, | ||||
|         hidden = 0, | ||||
|       }, | ||||
|       { | ||||
|         priority = 500, | ||||
|         name = ']Export', | ||||
|         submenus = { | ||||
|           { | ||||
|             mappings = { | ||||
|               o = { | ||||
|                 sid = 0, | ||||
|                 noremap = 0, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'thisoneshouldbehidden', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               v = { | ||||
|                 sid = 0, | ||||
|                 noremap = 0, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'thisoneshouldbehidden', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               s = { | ||||
|                 sid = 0, | ||||
|                 noremap = 0, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'thisoneshouldbehidden', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               n = { | ||||
|                 sid = 0, | ||||
|                 noremap = 0, | ||||
|                 enabled = 1, | ||||
|                 rhs = 'thisoneshouldbehidden', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = 'hidden', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|         }, | ||||
|         hidden = 1, | ||||
|       }, | ||||
|         hidden = 1 | ||||
|       } | ||||
|     } | ||||
|     eq(expected, m) | ||||
|   end) | ||||
|  | ||||
|   it('matching path, all modes', function() | ||||
|     local m = funcs.menu_get("Export", "a") | ||||
|     local expected = { { | ||||
|     local m = funcs.menu_get('Export', 'a') | ||||
|     local expected = { | ||||
|       { | ||||
|         hidden = 0, | ||||
|       name = "Export", | ||||
|         name = 'Export', | ||||
|         priority = 500, | ||||
|       submenus = { { | ||||
|         tooltip = "This is the tooltip", | ||||
|         submenus = { | ||||
|           { | ||||
|             tooltip = 'This is the tooltip', | ||||
|             hidden = 0, | ||||
|         name = "Script", | ||||
|             name = 'Script', | ||||
|             priority = 500, | ||||
|             mappings = { | ||||
|               n = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|             rhs = "p", | ||||
|             silent = 0 | ||||
|                 rhs = 'p', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     } | ||||
|         } | ||||
|       } } | ||||
|     } } | ||||
|     eq(expected, m) | ||||
|   end) | ||||
|  | ||||
|   it('no path, matching modes', function() | ||||
|     local m = funcs.menu_get("","i") | ||||
|     local m = funcs.menu_get('', 'i') | ||||
|     local expected = { | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         submenus = { | ||||
|           { | ||||
| @@ -348,27 +349,27 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "insert", | ||||
|                 silent = 0 | ||||
|               } | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = "Test", | ||||
|             hidden = 0 | ||||
|                 rhs = 'insert', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             priority = 500, | ||||
|         name = "Test" | ||||
|       } | ||||
|             name = 'Test', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = 'Test', | ||||
|       }, | ||||
|     } | ||||
|     eq(expected, m) | ||||
|   end) | ||||
|  | ||||
|   it('matching path and modes', function() | ||||
|     local m = funcs.menu_get("Test","i") | ||||
|     local m = funcs.menu_get('Test', 'i') | ||||
|     local expected = { | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         submenus = { | ||||
|           { | ||||
|             mappings = { | ||||
| @@ -376,26 +377,25 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "insert", | ||||
|                 silent = 0 | ||||
|                 rhs = 'insert', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             priority = 500, | ||||
|             name = "Test", | ||||
|             hidden = 0 | ||||
|             name = 'Test', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test", | ||||
|         hidden = 0 | ||||
|       } | ||||
|         name = 'Test', | ||||
|         hidden = 0, | ||||
|       }, | ||||
|     } | ||||
|     eq(expected, m) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe('menu_get', function() | ||||
|  | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     command('aunmenu *') | ||||
| @@ -412,10 +412,10 @@ describe('menu_get', function() | ||||
|     command('nnoremenu &Test.Test8 <NoP>') | ||||
|     command('nnoremenu &Test.Test9 ""') | ||||
|  | ||||
|     local m = funcs.menu_get(""); | ||||
|     local m = funcs.menu_get('') | ||||
|     local expected = { | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         submenus = { | ||||
|           { | ||||
| @@ -425,12 +425,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "inormal<Esc>", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'inormal<Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -439,12 +439,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "<Tab><Esc>", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '<Tab><Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test2", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test2', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -453,19 +453,19 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "yA<C-R>0<Tab>xyz<Esc>", | ||||
|                 silent = 0 | ||||
|                 rhs = 'yA<C-R>0<Tab>xyz<Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|               v = { | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "yA<C-R>0<Tab>xyz<Esc>", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'yA<C-R>0<Tab>xyz<Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test3", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test3', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -474,12 +474,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "<C-R>*", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '<C-R>*', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test4", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test4', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -488,12 +488,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "<C-R>+", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '<C-R>+', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test5", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test5', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -502,12 +502,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test6", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test6', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -516,12 +516,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test7", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test7', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -530,12 +530,12 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             name = "Test8", | ||||
|             hidden = 0 | ||||
|             }, | ||||
|             name = 'Test8', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|           { | ||||
|             priority = 500, | ||||
| @@ -544,17 +544,17 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "\"\"", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = '""', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             name = 'Test9', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|             name = "Test9", | ||||
|             hidden = 0 | ||||
|           } | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test" | ||||
|       } | ||||
|         name = 'Test', | ||||
|       }, | ||||
|     } | ||||
|  | ||||
|     eq(m, expected) | ||||
| @@ -565,12 +565,12 @@ describe('menu_get', function() | ||||
|     command('nnoremenu &Test\\ 1.Test\\ 2 Wargl') | ||||
|     command('nnoremenu &Test4.Test<Tab>3 i space<Esc>') | ||||
|  | ||||
|     local m = funcs.menu_get(""); | ||||
|     local m = funcs.menu_get('') | ||||
|     local expected = { | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         actext = "Y", | ||||
|         actext = 'Y', | ||||
|         submenus = { | ||||
|           { | ||||
|             mappings = { | ||||
| @@ -578,21 +578,21 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "inormal<Alt-j>", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'inormal<Alt-j>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             hidden = 0, | ||||
|             actext = "X x", | ||||
|             actext = 'X x', | ||||
|             priority = 500, | ||||
|             name = "Test" | ||||
|           } | ||||
|             name = 'Test', | ||||
|           }, | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test" | ||||
|         name = 'Test', | ||||
|       }, | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         submenus = { | ||||
|           { | ||||
| @@ -602,19 +602,19 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "Wargl", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'Wargl', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             name = 'Test 2', | ||||
|             hidden = 0, | ||||
|           }, | ||||
|             name = "Test 2", | ||||
|             hidden = 0 | ||||
|           } | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test 1" | ||||
|         name = 'Test 1', | ||||
|       }, | ||||
|       { | ||||
|         shortcut = "T", | ||||
|         shortcut = 'T', | ||||
|         hidden = 0, | ||||
|         submenus = { | ||||
|           { | ||||
| @@ -623,19 +623,19 @@ describe('menu_get', function() | ||||
|                 sid = 1, | ||||
|                 noremap = 1, | ||||
|                 enabled = 1, | ||||
|                 rhs = "i space<Esc>", | ||||
|                 silent = 0 | ||||
|               } | ||||
|                 rhs = 'i space<Esc>', | ||||
|                 silent = 0, | ||||
|               }, | ||||
|             }, | ||||
|             hidden = 0, | ||||
|             actext = "3", | ||||
|             actext = '3', | ||||
|             priority = 500, | ||||
|             name = "Test" | ||||
|           } | ||||
|             name = 'Test', | ||||
|           }, | ||||
|         }, | ||||
|         priority = 500, | ||||
|         name = "Test4" | ||||
|       } | ||||
|         name = 'Test4', | ||||
|       }, | ||||
|     } | ||||
|  | ||||
|     eq(m, expected) | ||||
|   | ||||
| @@ -18,7 +18,9 @@ local mkdir = helpers.mkdir | ||||
|  | ||||
| local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' | ||||
|  | ||||
| if helpers.skip(helpers.is_os('win')) then return end | ||||
| if helpers.skip(helpers.is_os('win')) then | ||||
|   return | ||||
| end | ||||
|  | ||||
| describe(':mksession', function() | ||||
|   local session_file = file_prefix .. '.vim' | ||||
|   | ||||
| @@ -29,8 +29,7 @@ describe(':mkview', function() | ||||
|  | ||||
|   it('viewoption curdir restores local current directory', function() | ||||
|     local cwd_dir = funcs.getcwd() | ||||
|     local set_view_dir_command = 'set viewdir=' .. cwd_dir .. | ||||
|           get_pathsep() .. view_dir | ||||
|     local set_view_dir_command = 'set viewdir=' .. cwd_dir .. get_pathsep() .. view_dir | ||||
|  | ||||
|     -- By default the local current directory should save | ||||
|     command(set_view_dir_command) | ||||
| @@ -63,5 +62,4 @@ describe(':mkview', function() | ||||
|     -- The view's local directory should have been saved | ||||
|     eq(cwd_dir .. get_pathsep() .. local_dir, funcs.getcwd()) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|   | ||||
| @@ -12,9 +12,15 @@ local eval = helpers.eval | ||||
| local shada_file = 'Xtest.shada' | ||||
|  | ||||
| local function _clear() | ||||
|   clear{args={'-i', shada_file, -- Need shada for these tests. | ||||
|               '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}, | ||||
|         args_rm={'-i', '--cmd'}} | ||||
|   clear { | ||||
|     args = { | ||||
|       '-i', | ||||
|       shada_file, -- Need shada for these tests. | ||||
|       '--cmd', | ||||
|       'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler', | ||||
|     }, | ||||
|     args_rm = { '-i', '--cmd' }, | ||||
|   } | ||||
| end | ||||
|  | ||||
| describe(':oldfiles', function() | ||||
| @@ -40,8 +46,8 @@ describe(':oldfiles', function() | ||||
|     feed_command('oldfiles') | ||||
|     screen:expect([[ | ||||
|                                                                                                           | | ||||
|       1: ]].. add_padding(oldfiles[1]) ..[[ | | ||||
|       2: ]].. add_padding(oldfiles[2]) ..[[ | | ||||
|       1: ]] .. add_padding(oldfiles[1]) .. [[ | | ||||
|       2: ]] .. add_padding(oldfiles[2]) .. [[ | | ||||
|                                                                                                           | | ||||
|       Press ENTER or type command to continue^                                                             | | ||||
|     ]]) | ||||
| @@ -59,7 +65,7 @@ describe(':oldfiles', function() | ||||
|     feed_command('rshada!') | ||||
|  | ||||
|     local function get_oldfiles(cmd) | ||||
|       local t = eval([[split(execute(']]..cmd..[['), "\n")]]) | ||||
|       local t = eval([[split(execute(']] .. cmd .. [['), "\n")]]) | ||||
|       for i, _ in ipairs(t) do | ||||
|         t[i] = t[i]:gsub('^%d+:%s+', '') | ||||
|       end | ||||
| @@ -68,16 +74,16 @@ describe(':oldfiles', function() | ||||
|     end | ||||
|  | ||||
|     local oldfiles = get_oldfiles('oldfiles') | ||||
|     eq({another, file1, file2}, oldfiles) | ||||
|     eq({ another, file1, file2 }, oldfiles) | ||||
|  | ||||
|     oldfiles = get_oldfiles('filter file_ oldfiles') | ||||
|     eq({file1, file2}, oldfiles) | ||||
|     eq({ file1, file2 }, oldfiles) | ||||
|  | ||||
|     oldfiles = get_oldfiles('filter /another/ oldfiles') | ||||
|     eq({another}, oldfiles) | ||||
|     eq({ another }, oldfiles) | ||||
|  | ||||
|     oldfiles = get_oldfiles('filter! file_ oldfiles') | ||||
|     eq({another}, oldfiles) | ||||
|     eq({ another }, oldfiles) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local clear, eq, command, funcs = | ||||
|   helpers.clear, helpers.eq, helpers.command, helpers.funcs | ||||
| local clear, eq, command, funcs = helpers.clear, helpers.eq, helpers.command, helpers.funcs | ||||
|  | ||||
| describe(':z^', function() | ||||
|   before_each(clear) | ||||
|   | ||||
| @@ -15,20 +15,24 @@ local file_base = 'Xtest-functional-ex_cmds-quickfix_commands' | ||||
|  | ||||
| before_each(clear) | ||||
|  | ||||
| for _, c in ipairs({'l', 'c'}) do | ||||
| for _, c in ipairs({ 'l', 'c' }) do | ||||
|   local file = ('%s.%s'):format(file_base, c) | ||||
|   local filecmd = c .. 'file' | ||||
|   local getfcmd = c .. 'getfile' | ||||
|   local addfcmd = c .. 'addfile' | ||||
|   local getlist = (c == 'c') and funcs.getqflist or ( | ||||
|       function() return funcs.getloclist(0) end) | ||||
|   local getlist = (c == 'c') and funcs.getqflist or function() | ||||
|     return funcs.getloclist(0) | ||||
|   end | ||||
|  | ||||
|   describe((':%s*file commands'):format(c), function() | ||||
|     before_each(function() | ||||
|       write_file(file, ([[ | ||||
|       write_file( | ||||
|         file, | ||||
|         ([[ | ||||
|         %s-1.res:700:10:Line 700 | ||||
|         %s-2.res:800:15:Line 800 | ||||
|       ]]):format(file, file)) | ||||
|       ]]):format(file, file) | ||||
|       ) | ||||
|     end) | ||||
|     after_each(function() | ||||
|       os.remove(file) | ||||
| @@ -39,10 +43,34 @@ for _, c in ipairs({'l', 'c'}) do | ||||
|       -- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual | ||||
|       -- results. First line (i.e. `{lnum=…`) was obtained from legacy test. | ||||
|       local list = { | ||||
|         {lnum=700, end_lnum=0, col=10, end_col=0, text='Line 700', module='', | ||||
|          nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''}, | ||||
|         {lnum=800, end_lnum=0, col=15, end_col=0, text='Line 800', module='', | ||||
|          nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, | ||||
|         { | ||||
|           lnum = 700, | ||||
|           end_lnum = 0, | ||||
|           col = 10, | ||||
|           end_col = 0, | ||||
|           text = 'Line 700', | ||||
|           module = '', | ||||
|           nr = -1, | ||||
|           bufnr = 2, | ||||
|           valid = 1, | ||||
|           pattern = '', | ||||
|           vcol = 0, | ||||
|           ['type'] = '', | ||||
|         }, | ||||
|         { | ||||
|           lnum = 800, | ||||
|           end_lnum = 0, | ||||
|           col = 15, | ||||
|           end_col = 0, | ||||
|           text = 'Line 800', | ||||
|           module = '', | ||||
|           nr = -1, | ||||
|           bufnr = 3, | ||||
|           valid = 1, | ||||
|           pattern = '', | ||||
|           vcol = 0, | ||||
|           ['type'] = '', | ||||
|         }, | ||||
|       } | ||||
|       eq(list, getlist()) | ||||
|       eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) | ||||
| @@ -51,33 +79,74 @@ for _, c in ipairs({'l', 'c'}) do | ||||
|       -- Run cfile/lfile from a modified buffer | ||||
|       command('set nohidden') | ||||
|       command('enew!') | ||||
|       curbufmeths.set_lines(1, 1, true, {'Quickfix'}) | ||||
|       eq(('Vim(%s):E37: No write since last change (add ! to override)'):format( | ||||
|           filecmd), | ||||
|          exc_exec(('%s %s'):format(filecmd, file))) | ||||
|       curbufmeths.set_lines(1, 1, true, { 'Quickfix' }) | ||||
|       eq( | ||||
|         ('Vim(%s):E37: No write since last change (add ! to override)'):format(filecmd), | ||||
|         exc_exec(('%s %s'):format(filecmd, file)) | ||||
|       ) | ||||
|  | ||||
|       write_file(file, ([[ | ||||
|       write_file( | ||||
|         file, | ||||
|         ([[ | ||||
|         %s-3.res:900:30:Line 900 | ||||
|       ]]):format(file)) | ||||
|       ]]):format(file) | ||||
|       ) | ||||
|       command(('%s %s'):format(addfcmd, file)) | ||||
|       list[#list + 1] = { | ||||
|         lnum=900, end_lnum=0, col=30, end_col=0, text='Line 900', module='', | ||||
|         nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='', | ||||
|         lnum = 900, | ||||
|         end_lnum = 0, | ||||
|         col = 30, | ||||
|         end_col = 0, | ||||
|         text = 'Line 900', | ||||
|         module = '', | ||||
|         nr = -1, | ||||
|         bufnr = 5, | ||||
|         valid = 1, | ||||
|         pattern = '', | ||||
|         vcol = 0, | ||||
|         ['type'] = '', | ||||
|       } | ||||
|       eq(list, getlist()) | ||||
|       eq(('%s-3.res'):format(file), funcs.bufname(list[3].bufnr)) | ||||
|  | ||||
|       write_file(file, ([[ | ||||
|       write_file( | ||||
|         file, | ||||
|         ([[ | ||||
|         %s-1.res:222:77:Line 222 | ||||
|         %s-2.res:333:88:Line 333 | ||||
|       ]]):format(file, file)) | ||||
|       ]]):format(file, file) | ||||
|       ) | ||||
|       command('enew!') | ||||
|       command(('%s %s'):format(getfcmd, file)) | ||||
|       list = { | ||||
|         {lnum=222, end_lnum=0, col=77, end_col=0, text='Line 222', module='', | ||||
|          nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''}, | ||||
|         {lnum=333, end_lnum=0, col=88, end_col=0, text='Line 333', module='', | ||||
|          nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, | ||||
|         { | ||||
|           lnum = 222, | ||||
|           end_lnum = 0, | ||||
|           col = 77, | ||||
|           end_col = 0, | ||||
|           text = 'Line 222', | ||||
|           module = '', | ||||
|           nr = -1, | ||||
|           bufnr = 2, | ||||
|           valid = 1, | ||||
|           pattern = '', | ||||
|           vcol = 0, | ||||
|           ['type'] = '', | ||||
|         }, | ||||
|         { | ||||
|           lnum = 333, | ||||
|           end_lnum = 0, | ||||
|           col = 88, | ||||
|           end_col = 0, | ||||
|           text = 'Line 333', | ||||
|           module = '', | ||||
|           nr = -1, | ||||
|           bufnr = 3, | ||||
|           valid = 1, | ||||
|           pattern = '', | ||||
|           vcol = 0, | ||||
|           ['type'] = '', | ||||
|         }, | ||||
|       } | ||||
|       eq(list, getlist()) | ||||
|       eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) | ||||
| @@ -109,7 +178,7 @@ describe('quickfix', function() | ||||
|         call append(0, ['New line 1', 'New line 2', 'New line 3']) | ||||
|         silent ll | ||||
|     ]]) | ||||
|     eq({0, 6, 1, 0, 1}, funcs.getcurpos()) | ||||
|     eq({ 0, 6, 1, 0, 1 }, funcs.getcurpos()) | ||||
|   end) | ||||
|  | ||||
|   it('BufAdd does not cause E16 when reusing quickfix buffer #18135', function() | ||||
| @@ -127,11 +196,14 @@ describe('quickfix', function() | ||||
| end) | ||||
|  | ||||
| it(':vimgrep can specify Unicode pattern without delimiters', function() | ||||
|   eq('Vim(vimgrep):E480: No match: →', exc_exec('vimgrep → test/functional/fixtures/tty-test.c')) | ||||
|   eq( | ||||
|     'Vim(vimgrep):E480: No match: →', | ||||
|     exc_exec('vimgrep → test/functional/fixtures/tty-test.c') | ||||
|   ) | ||||
|   local screen = Screen.new(40, 6) | ||||
|   screen:set_default_attr_ids({ | ||||
|     [0] = {bold = true, foreground = Screen.colors.Blue},  -- NonText | ||||
|     [1] = {reverse = true},  -- IncSearch | ||||
|     [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|     [1] = { reverse = true }, -- IncSearch | ||||
|   }) | ||||
|   screen:attach() | ||||
|   feed('i→<Esc>:vimgrep →') | ||||
|   | ||||
| @@ -11,4 +11,3 @@ describe(':qa', function() | ||||
|     -- errors | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,7 @@ before_each(clear) | ||||
|  | ||||
| local function source(code) | ||||
|   write_file(tmpfile, code) | ||||
|   command('source '..tmpfile) | ||||
|   command('source ' .. tmpfile) | ||||
| end | ||||
|  | ||||
| describe('script_get-based command', function() | ||||
| @@ -30,29 +30,48 @@ describe('script_get-based command', function() | ||||
|   local function test_garbage_exec(cmd, check_neq) | ||||
|     describe(cmd, function() | ||||
|       it('works correctly when skipping oneline variant', function() | ||||
|         eq(true, pcall(source, (dedent([[ | ||||
|         eq( | ||||
|           true, | ||||
|           pcall( | ||||
|             source, | ||||
|             (dedent([[ | ||||
|           if 0 | ||||
|             %s %s | ||||
|           endif | ||||
|         ]])):format(cmd, garbage))) | ||||
|         ]])):format(cmd, garbage) | ||||
|           ) | ||||
|         ) | ||||
|         eq('', exec_capture('messages')) | ||||
|         if check_neq then | ||||
|           neq(0, exc_exec(dedent([[ | ||||
|           neq( | ||||
|             0, | ||||
|             exc_exec(dedent([[ | ||||
|             %s %s | ||||
|           ]])):format(cmd, garbage)) | ||||
|           ]])):format(cmd, garbage) | ||||
|           ) | ||||
|         end | ||||
|       end) | ||||
|       it('works correctly when skipping HEREdoc variant', function() | ||||
|         eq(true, pcall(source, (dedent([[ | ||||
|         eq( | ||||
|           true, | ||||
|           pcall( | ||||
|             source, | ||||
|             (dedent([[ | ||||
|           if 0 | ||||
|           %s << EOF | ||||
|           %s | ||||
|           EOF | ||||
|           endif | ||||
|         ]])):format(cmd, garbage))) | ||||
|         ]])):format(cmd, garbage) | ||||
|           ) | ||||
|         ) | ||||
|         eq('', exec_capture('messages')) | ||||
|         if check_neq then | ||||
|           eq(true, pcall(source, (dedent([[ | ||||
|           eq( | ||||
|             true, | ||||
|             pcall( | ||||
|               source, | ||||
|               (dedent([[ | ||||
|             let g:exc = 0 | ||||
|             try | ||||
|             %s << EOF | ||||
| @@ -61,7 +80,9 @@ describe('script_get-based command', function() | ||||
|             catch | ||||
|             let g:exc = v:exception | ||||
|             endtry | ||||
|           ]])):format(cmd, garbage))) | ||||
|           ]])):format(cmd, garbage) | ||||
|             ) | ||||
|           ) | ||||
|           neq(0, meths.get_var('exc')) | ||||
|         end | ||||
|       end) | ||||
|   | ||||
| @@ -9,21 +9,21 @@ describe('sign', function() | ||||
|         -- place a sign with id 34 to first buffer | ||||
|         nvim('command', 'sign define Foo text=+ texthl=Delimiter linehl=Comment numhl=Number') | ||||
|         local buf1 = nvim('eval', 'bufnr("%")') | ||||
|         nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf1) | ||||
|         nvim('command', 'sign place 34 line=3 name=Foo buffer=' .. buf1) | ||||
|         -- create a second buffer and place the sign on it as well | ||||
|         nvim('command', 'new') | ||||
|         local buf2 = nvim('eval', 'bufnr("%")') | ||||
|         nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf2) | ||||
|         nvim('command', 'sign place 34 line=3 name=Foo buffer=' .. buf2) | ||||
|         -- now unplace without specifying a buffer | ||||
|         nvim('command', 'sign unplace 34') | ||||
|         eq("--- Signs ---\n", nvim('exec', 'sign place buffer='..buf1, true)) | ||||
|         eq("--- Signs ---\n", nvim('exec', 'sign place buffer='..buf2, true)) | ||||
|         eq('--- Signs ---\n', nvim('exec', 'sign place buffer=' .. buf1, true)) | ||||
|         eq('--- Signs ---\n', nvim('exec', 'sign place buffer=' .. buf2, true)) | ||||
|       end) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   describe('define {id}', function() | ||||
|     it ('does not leak memory when specifying multiple times the same argument', function() | ||||
|     it('does not leak memory when specifying multiple times the same argument', function() | ||||
|       nvim('command', 'sign define Foo culhl=Normal culhl=Normal') | ||||
|       assert_alive() | ||||
|     end) | ||||
|   | ||||
| @@ -52,13 +52,16 @@ describe(':source', function() | ||||
|     meths.set_option_value('shellslash', false, {}) | ||||
|     mkdir('Xshellslash') | ||||
|  | ||||
|     write_file([[Xshellslash/Xstack.vim]], [[ | ||||
|     write_file( | ||||
|       [[Xshellslash/Xstack.vim]], | ||||
|       [[ | ||||
|       let g:stack1 = expand('<stack>') | ||||
|       set shellslash | ||||
|       let g:stack2 = expand('<stack>') | ||||
|       set noshellslash | ||||
|       let g:stack3 = expand('<stack>') | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     for _ = 1, 2 do | ||||
|       command([[source Xshellslash/Xstack.vim]]) | ||||
| @@ -67,13 +70,16 @@ describe(':source', function() | ||||
|       matches([[Xshellslash\Xstack%.vim]], meths.get_var('stack3')) | ||||
|     end | ||||
|  | ||||
|     write_file([[Xshellslash/Xstack.lua]], [[ | ||||
|     write_file( | ||||
|       [[Xshellslash/Xstack.lua]], | ||||
|       [[ | ||||
|       vim.g.stack1 = vim.fn.expand('<stack>') | ||||
|       vim.o.shellslash = true | ||||
|       vim.g.stack2 = vim.fn.expand('<stack>') | ||||
|       vim.o.shellslash = false | ||||
|       vim.g.stack3 = vim.fn.expand('<stack>') | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     for _ = 1, 2 do | ||||
|       command([[source Xshellslash/Xstack.lua]]) | ||||
| @@ -101,11 +107,11 @@ describe(':source', function() | ||||
|     eq("{'k': 'v'}", exec_capture('echo b')) | ||||
|  | ||||
|     -- Script items are created only on script var access | ||||
|     eq("1", exec_capture('echo c')) | ||||
|     eq("0zBEEFCAFE", exec_capture('echo d')) | ||||
|     eq('1', exec_capture('echo c')) | ||||
|     eq('0zBEEFCAFE', exec_capture('echo d')) | ||||
|  | ||||
|     exec('set cpoptions+=C') | ||||
|     eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec('source')) | ||||
|     eq("Vim(let):E723: Missing end of Dictionary '}': ", exc_exec('source')) | ||||
|   end) | ||||
|  | ||||
|   it('selection in current buffer', function() | ||||
| @@ -132,14 +138,14 @@ describe(':source', function() | ||||
|     feed_command(':source') | ||||
|     eq('4', exec_capture('echo a')) | ||||
|     eq("{'K': 'V'}", exec_capture('echo b')) | ||||
|     eq("<SNR>1_C()", exec_capture('echo D()')) | ||||
|     eq('<SNR>1_C()', exec_capture('echo D()')) | ||||
|  | ||||
|     -- Source last line only | ||||
|     feed_command(':$source') | ||||
|     eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()')) | ||||
|  | ||||
|     exec('set cpoptions+=C') | ||||
|     eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec("'<,'>source")) | ||||
|     eq("Vim(let):E723: Missing end of Dictionary '}': ", exc_exec("'<,'>source")) | ||||
|   end) | ||||
|  | ||||
|   it('does not break if current buffer is modified while sourced', function() | ||||
| @@ -163,12 +169,15 @@ describe(':source', function() | ||||
|  | ||||
|   it('can source lua files', function() | ||||
|     local test_file = 'test.lua' | ||||
|     write_file(test_file, [[ | ||||
|     write_file( | ||||
|       test_file, | ||||
|       [[ | ||||
|       vim.g.sourced_lua = 1 | ||||
|       vim.g.sfile_value = vim.fn.expand('<sfile>') | ||||
|       vim.g.stack_value = vim.fn.expand('<stack>') | ||||
|       vim.g.script_value = vim.fn.expand('<script>') | ||||
|     ]]) | ||||
|     ]] | ||||
|     ) | ||||
|  | ||||
|     command('set shellslash') | ||||
|     command('source ' .. test_file) | ||||
| @@ -245,22 +254,22 @@ describe(':source', function() | ||||
|     local test_file = 'test.lua' | ||||
|  | ||||
|     -- Does throw E484 for unreadable files | ||||
|     local ok, result = pcall(exec_capture, ":source "..test_file ..'noexisting') | ||||
|     local ok, result = pcall(exec_capture, ':source ' .. test_file .. 'noexisting') | ||||
|     eq(false, ok) | ||||
|     neq(nil, result:find("E484")) | ||||
|     neq(nil, result:find('E484')) | ||||
|  | ||||
|     -- Doesn't throw for parsing error | ||||
|     write_file (test_file, "vim.g.c = ") | ||||
|     ok, result = pcall(exec_capture, ":source "..test_file) | ||||
|     write_file(test_file, 'vim.g.c = ') | ||||
|     ok, result = pcall(exec_capture, ':source ' .. test_file) | ||||
|     eq(false, ok) | ||||
|     eq(nil, result:find("E484")) | ||||
|     eq(nil, result:find('E484')) | ||||
|     os.remove(test_file) | ||||
|  | ||||
|     -- Doesn't throw for runtime error | ||||
|     write_file (test_file, "error('Cause error anyway :D')") | ||||
|     ok, result = pcall(exec_capture, ":source "..test_file) | ||||
|     write_file(test_file, "error('Cause error anyway :D')") | ||||
|     ok, result = pcall(exec_capture, ':source ' .. test_file) | ||||
|     eq(false, ok) | ||||
|     eq(nil, result:find("E484")) | ||||
|     eq(nil, result:find('E484')) | ||||
|     os.remove(test_file) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| local Screen = require('test.functional.ui.screen') | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local luv = require('luv') | ||||
| local eq, eval, expect, exec = | ||||
|   helpers.eq, helpers.eval, helpers.expect, helpers.exec | ||||
| local eq, eval, expect, exec = helpers.eq, helpers.eval, helpers.expect, helpers.exec | ||||
| local assert_alive = helpers.assert_alive | ||||
| local clear = helpers.clear | ||||
| local command = helpers.command | ||||
| @@ -32,24 +31,24 @@ describe(':recover', function() | ||||
|   it('fails if given a non-existent swapfile', function() | ||||
|     local swapname = 'bogus_swapfile' | ||||
|     local swapname2 = 'bogus_swapfile.swp' | ||||
|     eq('Vim(recover):E305: No swap file found for '..swapname, | ||||
|       pcall_err(command, 'recover '..swapname))  -- Should not segfault. #2117 | ||||
|     eq( | ||||
|       'Vim(recover):E305: No swap file found for ' .. swapname, | ||||
|       pcall_err(command, 'recover ' .. swapname) | ||||
|     ) -- Should not segfault. #2117 | ||||
|     -- Also check filename ending with ".swp". #9504 | ||||
|     eq('Vim(recover):E306: Cannot open '..swapname2, | ||||
|       pcall_err(command, 'recover '..swapname2))  -- Should not segfault. #2117 | ||||
|     eq('Vim(recover):E306: Cannot open ' .. swapname2, pcall_err(command, 'recover ' .. swapname2)) -- Should not segfault. #2117 | ||||
|     assert_alive() | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|  | ||||
| describe("preserve and (R)ecover with custom 'directory'", function() | ||||
|   local swapdir = luv.cwd()..'/Xtest_recover_dir' | ||||
|   local swapdir = luv.cwd() .. '/Xtest_recover_dir' | ||||
|   local testfile = 'Xtest_recover_file1' | ||||
|   -- Put swapdir at the start of the 'directory' list. #1836 | ||||
|   -- Note: `set swapfile` *must* go after `set directory`: otherwise it may | ||||
|   -- attempt to create a swapfile in different directory. | ||||
|   local init = [[ | ||||
|     set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[// | ||||
|     set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[// | ||||
|     set swapfile fileformat=unix undolevels=-1 | ||||
|   ]] | ||||
|  | ||||
| @@ -67,7 +66,7 @@ describe("preserve and (R)ecover with custom 'directory'", function() | ||||
|  | ||||
|   local function setup_swapname() | ||||
|     exec(init) | ||||
|     command('edit! '..testfile) | ||||
|     command('edit! ' .. testfile) | ||||
|     feed('isometext<esc>') | ||||
|     exec('redir => g:swapname | silent swapname | redir END') | ||||
|     return eval('g:swapname') | ||||
| @@ -75,23 +74,23 @@ describe("preserve and (R)ecover with custom 'directory'", function() | ||||
|  | ||||
|   local function test_recover(swappath1) | ||||
|     -- Start another Nvim instance. | ||||
|     local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true) | ||||
|     local nvim2 = spawn({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed' }, true) | ||||
|     set_session(nvim2) | ||||
|  | ||||
|     exec(init) | ||||
|  | ||||
|     -- Use the "SwapExists" event to choose the (R)ecover choice at the dialog. | ||||
|     command('autocmd SwapExists * let v:swapchoice = "r"') | ||||
|     command('silent edit! '..testfile) | ||||
|     command('silent edit! ' .. testfile) | ||||
|     exec('redir => g:swapname | silent swapname | redir END') | ||||
|  | ||||
|     local swappath2 = eval('g:swapname') | ||||
|  | ||||
|     expect('sometext') | ||||
|     -- swapfile from session 1 should end in .swp | ||||
|     eq(testfile..'.swp', string.match(swappath1, '[^%%]+$')) | ||||
|     eq(testfile .. '.swp', string.match(swappath1, '[^%%]+$')) | ||||
|     -- swapfile from session 2 should end in .swo | ||||
|     eq(testfile..'.swo', string.match(swappath2, '[^%%]+$')) | ||||
|     eq(testfile .. '.swo', string.match(swappath2, '[^%%]+$')) | ||||
|     -- Verify that :swapname was not truncated (:help 'shortmess'). | ||||
|     ok(nil == string.find(swappath1, '%.%.%.')) | ||||
|     ok(nil == string.find(swappath2, '%.%.%.')) | ||||
| @@ -116,28 +115,27 @@ describe("preserve and (R)ecover with custom 'directory'", function() | ||||
|     screen0:attach() | ||||
|     local child_server = new_pipename() | ||||
|     funcs.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server }, { | ||||
|       env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } | ||||
|       env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, | ||||
|     }) | ||||
|     screen0:expect({any = pesc('[No Name]')})  -- Wait for the child process to start. | ||||
|     screen0:expect({ any = pesc('[No Name]') }) -- Wait for the child process to start. | ||||
|     local child_session = helpers.connect(child_server) | ||||
|     set_session(child_session) | ||||
|     local swappath1 = setup_swapname() | ||||
|     set_session(nvim0) | ||||
|     command('call chanclose(&channel)') -- Kill the child process. | ||||
|     screen0:expect({any = pesc('[Process exited 1]')})  -- Wait for the child process to stop. | ||||
|     screen0:expect({ any = pesc('[Process exited 1]') }) -- Wait for the child process to stop. | ||||
|     test_recover(swappath1) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|  | ||||
| describe('swapfile detection', function() | ||||
|   local swapdir = luv.cwd()..'/Xtest_swapdialog_dir' | ||||
|   local swapdir = luv.cwd() .. '/Xtest_swapdialog_dir' | ||||
|   local nvim0 | ||||
|   -- Put swapdir at the start of the 'directory' list. #1836 | ||||
|   -- Note: `set swapfile` *must* go after `set directory`: otherwise it may | ||||
|   -- attempt to create a swapfile in different directory. | ||||
|   local init = [[ | ||||
|     set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[// | ||||
|     set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[// | ||||
|     set swapfile fileformat=unix nomodified undolevels=-1 nohidden | ||||
|   ]] | ||||
|   before_each(function() | ||||
| @@ -155,20 +153,20 @@ describe('swapfile detection', function() | ||||
|   it('always show swapfile dialog #8840 #9027', function() | ||||
|     local testfile = 'Xtest_swapdialog_file1' | ||||
|  | ||||
|     local expected_no_dialog = '^'..(' '):rep(256)..'|\n' | ||||
|     for _=1,37 do | ||||
|       expected_no_dialog = expected_no_dialog..'~'..(' '):rep(255)..'|\n' | ||||
|     local expected_no_dialog = '^' .. (' '):rep(256) .. '|\n' | ||||
|     for _ = 1, 37 do | ||||
|       expected_no_dialog = expected_no_dialog .. '~' .. (' '):rep(255) .. '|\n' | ||||
|     end | ||||
|     expected_no_dialog = expected_no_dialog..testfile..(' '):rep(216)..'0,0-1          All|\n' | ||||
|     expected_no_dialog = expected_no_dialog..(' '):rep(256)..'|\n' | ||||
|     expected_no_dialog = expected_no_dialog .. testfile .. (' '):rep(216) .. '0,0-1          All|\n' | ||||
|     expected_no_dialog = expected_no_dialog .. (' '):rep(256) .. '|\n' | ||||
|  | ||||
|     exec(init) | ||||
|     command('edit! '..testfile) | ||||
|     command('edit! ' .. testfile) | ||||
|     feed('isometext<esc>') | ||||
|     command('preserve') | ||||
|  | ||||
|     -- Start another Nvim instance. | ||||
|     local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true, nil, true) | ||||
|     local nvim2 = spawn({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed' }, true, nil, true) | ||||
|     set_session(nvim2) | ||||
|     local screen2 = Screen.new(256, 40) | ||||
|     screen2:attach() | ||||
| @@ -177,45 +175,66 @@ describe('swapfile detection', function() | ||||
|  | ||||
|     -- With shortmess+=F | ||||
|     command('set shortmess+=F') | ||||
|     feed(':edit '..testfile..'<CR>') | ||||
|     screen2:expect{any=[[E325: ATTENTION.*]]..'\n'..[[Found a swap file by the name ".*]] | ||||
|                        ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} | ||||
|     feed(':edit ' .. testfile .. '<CR>') | ||||
|     screen2:expect { | ||||
|       any = [[E325: ATTENTION.*]] | ||||
|         .. '\n' | ||||
|         .. [[Found a swap file by the name ".*]] | ||||
|         .. [[Xtest_swapdialog_dir[/\].*]] | ||||
|         .. testfile | ||||
|         .. [[%.swp"]], | ||||
|     } | ||||
|     feed('e') -- Chose "Edit" at the swap dialog. | ||||
|     screen2:expect(expected_no_dialog) | ||||
|  | ||||
|     -- With :silent and shortmess+=F | ||||
|     feed(':silent edit %<CR>') | ||||
|     screen2:expect{any=[[Found a swap file by the name ".*]] | ||||
|                        ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} | ||||
|     screen2:expect { | ||||
|       any = [[Found a swap file by the name ".*]] | ||||
|         .. [[Xtest_swapdialog_dir[/\].*]] | ||||
|         .. testfile | ||||
|         .. [[%.swp"]], | ||||
|     } | ||||
|     feed('e') -- Chose "Edit" at the swap dialog. | ||||
|     screen2:expect(expected_no_dialog) | ||||
|  | ||||
|     -- With :silent! and shortmess+=F | ||||
|     feed(':silent! edit %<CR>') | ||||
|     screen2:expect{any=[[Found a swap file by the name ".*]] | ||||
|                        ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} | ||||
|     screen2:expect { | ||||
|       any = [[Found a swap file by the name ".*]] | ||||
|         .. [[Xtest_swapdialog_dir[/\].*]] | ||||
|         .. testfile | ||||
|         .. [[%.swp"]], | ||||
|     } | ||||
|     feed('e') -- Chose "Edit" at the swap dialog. | ||||
|     screen2:expect(expected_no_dialog) | ||||
|  | ||||
|     -- With API (via eval/Vimscript) call and shortmess+=F | ||||
|     feed(':call nvim_command("edit %")<CR>') | ||||
|     screen2:expect{any=[[Found a swap file by the name ".*]] | ||||
|                        ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} | ||||
|     screen2:expect { | ||||
|       any = [[Found a swap file by the name ".*]] | ||||
|         .. [[Xtest_swapdialog_dir[/\].*]] | ||||
|         .. testfile | ||||
|         .. [[%.swp"]], | ||||
|     } | ||||
|     feed('e') -- Chose "Edit" at the swap dialog. | ||||
|     feed('<c-c>') | ||||
|     screen2:expect(expected_no_dialog) | ||||
|  | ||||
|     -- With API call and shortmess+=F | ||||
|     async_meths.command('edit %') | ||||
|     screen2:expect{any=[[Found a swap file by the name ".*]] | ||||
|                        ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} | ||||
|     screen2:expect { | ||||
|       any = [[Found a swap file by the name ".*]] | ||||
|         .. [[Xtest_swapdialog_dir[/\].*]] | ||||
|         .. testfile | ||||
|         .. [[%.swp"]], | ||||
|     } | ||||
|     feed('e') -- Chose "Edit" at the swap dialog. | ||||
|     expect_msg_seq({ | ||||
|       ignore={'redraw'}, | ||||
|       seqs={ | ||||
|         { {'notification', 'nvim_error_event', {0, 'Vim(edit):E325: ATTENTION'}}, | ||||
|         } | ||||
|       } | ||||
|       ignore = { 'redraw' }, | ||||
|       seqs = { | ||||
|         { { 'notification', 'nvim_error_event', { 0, 'Vim(edit):E325: ATTENTION' } } }, | ||||
|       }, | ||||
|     }) | ||||
|     feed('<cr>') | ||||
|  | ||||
| @@ -248,8 +267,8 @@ describe('swapfile detection', function() | ||||
|  | ||||
|     local screen = Screen.new(75, 18) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {bold = true, foreground = Screen.colors.Blue},  -- NonText | ||||
|       [1] = {bold = true, foreground = Screen.colors.SeaGreen},  -- MoreMsg | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|       [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg | ||||
|     }) | ||||
|  | ||||
|     local nvim1 = spawn(new_argv(), true, nil, true) | ||||
| @@ -260,7 +279,7 @@ describe('swapfile detection', function() | ||||
|     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: }^') | ||||
|       any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'), | ||||
|     }) | ||||
|     feed('q') | ||||
|     feed(':<CR>') | ||||
| @@ -279,10 +298,10 @@ describe('swapfile detection', function() | ||||
|     command('set more') | ||||
|     command('au bufadd * let foo_w = wincol()') | ||||
|     feed(':e Xfile1<CR>') | ||||
|     screen:expect({any = pesc('{1:-- More --}^')}) | ||||
|     screen:expect({ any = pesc('{1:-- More --}^') }) | ||||
|     feed('<Space>') | ||||
|     screen:expect({ | ||||
|       any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^') | ||||
|       any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'), | ||||
|     }) | ||||
|     feed('q') | ||||
|     command([[echo 'hello']]) | ||||
| @@ -299,9 +318,9 @@ describe('swapfile detection', function() | ||||
|   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 | ||||
|       [1] = {bold = true, foreground = Screen.colors.SeaGreen},  -- MoreMsg | ||||
|       [2] = {background = Screen.colors.Red, foreground = Screen.colors.White},  -- ErrorMsg | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText | ||||
|       [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg | ||||
|       [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg | ||||
|     }) | ||||
|     screen:attach() | ||||
|  | ||||
| @@ -361,10 +380,12 @@ describe('swapfile detection', function() | ||||
|     luv.fs_utime(swname, atime, atime) | ||||
|  | ||||
|     feed(':edit Xswaptest<CR>') | ||||
|     screen:expect({any = table.concat({ | ||||
|     screen:expect({ | ||||
|       any = table.concat({ | ||||
|         pesc('{2:E325: ATTENTION}'), | ||||
|         pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: }^'), | ||||
|     }, '.*')}) | ||||
|       }, '.*'), | ||||
|     }) | ||||
|  | ||||
|     feed('e') | ||||
|   end | ||||
| @@ -372,12 +393,14 @@ describe('swapfile detection', function() | ||||
|   -- 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({ | ||||
|       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) | ||||
|  | ||||
| @@ -386,30 +409,32 @@ describe('swapfile detection', function() | ||||
|       screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' }) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
| end) | ||||
|  | ||||
| describe('quitting swapfile dialog on startup stops TUI properly', function() | ||||
|   local swapdir = luv.cwd()..'/Xtest_swapquit_dir' | ||||
|   local swapdir = luv.cwd() .. '/Xtest_swapquit_dir' | ||||
|   local testfile = 'Xtest_swapquit_file1' | ||||
|   local otherfile = 'Xtest_swapquit_file2' | ||||
|   -- Put swapdir at the start of the 'directory' list. #1836 | ||||
|   -- Note: `set swapfile` *must* go after `set directory`: otherwise it may | ||||
|   -- attempt to create a swapfile in different directory. | ||||
|   local init_dir = [[set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//]] | ||||
|   local init_dir = [[set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[//]] | ||||
|   local init_set = [[set swapfile fileformat=unix nomodified undolevels=-1 nohidden]] | ||||
|  | ||||
|   before_each(function() | ||||
|     clear({args = {'--cmd', init_dir, '--cmd', init_set}}) | ||||
|     clear({ args = { '--cmd', init_dir, '--cmd', init_set } }) | ||||
|     rmdir(swapdir) | ||||
|     mkdir(swapdir) | ||||
|     write_file(testfile, [[ | ||||
|     write_file( | ||||
|       testfile, | ||||
|       [[ | ||||
|       first | ||||
|       second | ||||
|       third | ||||
|  | ||||
|     ]]) | ||||
|     command('edit! '..testfile) | ||||
|     ]] | ||||
|     ) | ||||
|     command('edit! ' .. testfile) | ||||
|     feed('Gisometext<esc>') | ||||
|     poke_eventloop() | ||||
|     clear() -- Leaves a swap file behind | ||||
| @@ -422,63 +447,100 @@ describe('quitting swapfile dialog on startup stops TUI properly', function() | ||||
|   end) | ||||
|  | ||||
|   it('(Q)uit at first file argument', function() | ||||
|     local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', | ||||
|                                  '--cmd', init_dir, '--cmd', init_set, | ||||
|                                  testfile}, { | ||||
|                                    env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } | ||||
|                                  }) | ||||
|     local chan = funcs.termopen( | ||||
|       { nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', init_dir, '--cmd', init_set, testfile }, | ||||
|       { | ||||
|         env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, | ||||
|       } | ||||
|     ) | ||||
|     retry(nil, nil, function() | ||||
|       eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|          eval("getline('$')->trim(' ', 2)")) | ||||
|       eq( | ||||
|         '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|         eval("getline('$')->trim(' ', 2)") | ||||
|       ) | ||||
|     end) | ||||
|     meths.chan_send(chan, 'q') | ||||
|     retry(nil, nil, function() | ||||
|       eq({'', '[Process exited 1]', ''}, | ||||
|          eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) | ||||
|       eq( | ||||
|         { '', '[Process exited 1]', '' }, | ||||
|         eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})") | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('(A)bort at second file argument with -p', function() | ||||
|     local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', | ||||
|                                  '--cmd', init_dir, '--cmd', init_set, | ||||
|                                  '-p', otherfile, testfile}, { | ||||
|                                    env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } | ||||
|     local chan = funcs.termopen({ | ||||
|       nvim_prog, | ||||
|       '-u', | ||||
|       'NONE', | ||||
|       '-i', | ||||
|       'NONE', | ||||
|       '--cmd', | ||||
|       init_dir, | ||||
|       '--cmd', | ||||
|       init_set, | ||||
|       '-p', | ||||
|       otherfile, | ||||
|       testfile, | ||||
|     }, { | ||||
|       env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, | ||||
|     }) | ||||
|     retry(nil, nil, function() | ||||
|       eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|          eval("getline('$')->trim(' ', 2)")) | ||||
|       eq( | ||||
|         '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|         eval("getline('$')->trim(' ', 2)") | ||||
|       ) | ||||
|     end) | ||||
|     meths.chan_send(chan, 'a') | ||||
|     retry(nil, nil, function() | ||||
|       eq({'', '[Process exited 1]', ''}, | ||||
|          eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) | ||||
|       eq( | ||||
|         { '', '[Process exited 1]', '' }, | ||||
|         eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})") | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   it('(Q)uit at file opened by -t', function() | ||||
|     write_file(otherfile, ([[ | ||||
|     write_file( | ||||
|       otherfile, | ||||
|       ([[ | ||||
|       !_TAG_FILE_ENCODING	utf-8	// | ||||
|       first	%s	/^  \zsfirst$/ | ||||
|       second	%s	/^  \zssecond$/ | ||||
|       third	%s	/^  \zsthird$/]]):format(testfile, testfile, testfile)) | ||||
|     local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', | ||||
|                                  '--cmd', init_dir, '--cmd', init_set, | ||||
|                                  '--cmd', 'set tags='..otherfile, '-tsecond'}, { | ||||
|                                    env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } | ||||
|       third	%s	/^  \zsthird$/]]):format(testfile, testfile, testfile) | ||||
|     ) | ||||
|     local chan = funcs.termopen({ | ||||
|       nvim_prog, | ||||
|       '-u', | ||||
|       'NONE', | ||||
|       '-i', | ||||
|       'NONE', | ||||
|       '--cmd', | ||||
|       init_dir, | ||||
|       '--cmd', | ||||
|       init_set, | ||||
|       '--cmd', | ||||
|       'set tags=' .. otherfile, | ||||
|       '-tsecond', | ||||
|     }, { | ||||
|       env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, | ||||
|     }) | ||||
|     retry(nil, nil, function() | ||||
|       eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|          eval("getline('$')->trim(' ', 2)")) | ||||
|       eq( | ||||
|         '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', | ||||
|         eval("getline('$')->trim(' ', 2)") | ||||
|       ) | ||||
|     end) | ||||
|     meths.chan_send(chan, 'q') | ||||
|     retry(nil, nil, function() | ||||
|       eq('Press ENTER or type command to continue', | ||||
|          eval("getline('$')->trim(' ', 2)")) | ||||
|       eq('Press ENTER or type command to continue', eval("getline('$')->trim(' ', 2)")) | ||||
|     end) | ||||
|     meths.chan_send(chan, '\r') | ||||
|     retry(nil, nil, function() | ||||
|       eq({'', '[Process exited 1]', ''}, | ||||
|          eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) | ||||
|       eq( | ||||
|         { '', '[Process exited 1]', '' }, | ||||
|         eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})") | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -8,10 +8,11 @@ describe(':syntax', function() | ||||
|   before_each(clear) | ||||
|  | ||||
|   describe('keyword', function() | ||||
|     it('does not crash when group name contains unprintable characters', | ||||
|     function() | ||||
|       eq('Vim(syntax):E669: Unprintable character in group name', | ||||
|          exc_exec('syntax keyword \024 foo bar')) | ||||
|     it('does not crash when group name contains unprintable characters', function() | ||||
|       eq( | ||||
|         'Vim(syntax):E669: Unprintable character in group name', | ||||
|         exc_exec('syntax keyword \024 foo bar') | ||||
|       ) | ||||
|     end) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -22,7 +22,7 @@ describe(':trust', function() | ||||
|  | ||||
|   before_each(function() | ||||
|     helpers.write_file('test_file', 'test') | ||||
|     clear{env={XDG_STATE_HOME=xstate}} | ||||
|     clear { env = { XDG_STATE_HOME = xstate } } | ||||
|   end) | ||||
|  | ||||
|   after_each(function() | ||||
| @@ -72,7 +72,10 @@ describe(':trust', function() | ||||
|     local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust') | ||||
|     eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) | ||||
|  | ||||
|     matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove test_file')) | ||||
|     matches( | ||||
|       '^Removed ".*test_file" from trust database%.$', | ||||
|       exec_capture('trust ++remove test_file') | ||||
|     ) | ||||
|     trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust') | ||||
|     eq(string.format(''), vim.trim(trust)) | ||||
|   end) | ||||
|   | ||||
| @@ -11,13 +11,15 @@ local function last_set_tests(cmd) | ||||
|   local script_location, script_file | ||||
|   -- All test cases below use the same nvim instance. | ||||
|   setup(function() | ||||
|     clear{args={'-V1'}} | ||||
|     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} | ||||
|     current_dir = call_viml_function('fnamemodify', { current_dir, ':~' }) | ||||
|     script_location = table.concat { current_dir, helpers.get_pathsep(), script_file } | ||||
|  | ||||
|     write_file(script_file, [[ | ||||
|     write_file( | ||||
|       script_file, | ||||
|       [[ | ||||
| vim.api.nvim_set_option_value('hlsearch', false, {}) | ||||
| vim.bo.expandtab = true | ||||
| vim.opt.number = true | ||||
| @@ -45,7 +47,8 @@ function! s:return80()\ | ||||
| endfunction\ | ||||
| let &tw = s:return80()\ | ||||
| ", true) | ||||
| ]]) | ||||
| ]] | ||||
|     ) | ||||
|     exec(cmd .. ' ' .. script_file) | ||||
|   end) | ||||
|  | ||||
| @@ -55,54 +58,84 @@ let &tw = s:return80()\ | ||||
|  | ||||
|   it('"Last set" for option set by Lua', function() | ||||
|     local result = exec_capture(':verbose set hlsearch?') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
| nohlsearch | ||||
| 	Last set from %s line 1]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for option set by vim.o', function() | ||||
|     local result = exec_capture(':verbose set expandtab?') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|   expandtab | ||||
| 	Last set from %s line 2]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for option set by vim.opt', function() | ||||
|     local result = exec_capture(':verbose set number?') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|   number | ||||
| 	Last set from %s line 3]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for mapping set by Lua', function() | ||||
|     local result = exec_capture(':verbose map <leader>key1') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|  | ||||
| n  \key1       * :echo "test"<CR> | ||||
| 	Last set from %s line 4]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for mapping set by vim.keymap', function() | ||||
|     local result = exec_capture(':verbose map <leader>key2') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|  | ||||
| n  \key2       * :echo "test"<CR> | ||||
| 	Last set from %s line 5]], | ||||
|        script_location), result) | ||||
|         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([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
| --- Autocommands --- | ||||
| test_group  FileType | ||||
|     c         setl cindent | ||||
| 	Last set from %s line 7]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for command defined by nvim_command', function() | ||||
| @@ -110,38 +143,58 @@ test_group  FileType | ||||
|       pending('nvim_command does not set the script context') | ||||
|     end | ||||
|     local result = exec_capture(':verbose command Bdelete') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|     Name              Args Address Complete    Definition | ||||
|     Bdelete           0                        :bd | ||||
| 	Last set from %s line 13]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for command defined by nvim_create_user_command', function() | ||||
|     local result = exec_capture(':verbose command TestCommand') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|     Name              Args Address Complete    Definition | ||||
|     TestCommand       0                        :echo 'Hello' | ||||
| 	Last set from %s line 14]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" for function', function() | ||||
|     local result = exec_capture(':verbose function Close_Window') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|    function Close_Window() abort | ||||
| 	Last set from %s line 16 | ||||
| 1    wincmd - | ||||
|    endfunction]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('"Last set" works with anonymous sid', function() | ||||
|     local result = exec_capture(':verbose set tw?') | ||||
|     eq(string.format([[ | ||||
|     eq( | ||||
|       string.format( | ||||
|         [[ | ||||
|   textwidth=80 | ||||
| 	Last set from %s line 22]], | ||||
|        script_location), result) | ||||
|         script_location | ||||
|       ), | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
| end | ||||
|  | ||||
| @@ -159,10 +212,13 @@ describe('lua verbose:', function() | ||||
|   setup(function() | ||||
|     clear() | ||||
|     script_file = 'test_luafile.lua' | ||||
|     write_file(script_file, [[ | ||||
|     write_file( | ||||
|       script_file, | ||||
|       [[ | ||||
|     vim.api.nvim_set_option_value('hlsearch', false, {}) | ||||
|     ]]) | ||||
|     exec(':source '..script_file) | ||||
|     ]] | ||||
|     ) | ||||
|     exec(':source ' .. script_file) | ||||
|   end) | ||||
|  | ||||
|   teardown(function() | ||||
| @@ -171,9 +227,11 @@ describe('lua verbose:', function() | ||||
|  | ||||
|   it('is disabled when verbose = 0', function() | ||||
|     local result = exec_capture(':verbose set hlsearch?') | ||||
|     eq([[ | ||||
|     eq( | ||||
|       [[ | ||||
| nohlsearch | ||||
| 	Last set from Lua]], result) | ||||
| 	Last set from Lua]], | ||||
|       result | ||||
|     ) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| local helpers = require("test.functional.helpers")(after_each) | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local clear = helpers.clear | ||||
| local eq = helpers.eq | ||||
| local funcs = helpers.funcs | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local luv = require('luv') | ||||
| local eq, eval, clear, write_file, source, insert = | ||||
|   helpers.eq, helpers.eval, helpers.clear, helpers.write_file, | ||||
|   helpers.source, helpers.insert | ||||
|   helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.source, helpers.insert | ||||
| local pcall_err = helpers.pcall_err | ||||
| local command = helpers.command | ||||
| local feed_command = helpers.feed_command | ||||
| @@ -40,9 +39,9 @@ describe(':write', function() | ||||
|     command('set backupcopy=auto') | ||||
|     write_file('test_bkc_file.txt', 'content0') | ||||
|     if is_os('win') then | ||||
|       command("silent !mklink test_bkc_link.txt test_bkc_file.txt") | ||||
|       command('silent !mklink test_bkc_link.txt test_bkc_file.txt') | ||||
|     else | ||||
|       command("silent !ln -s test_bkc_file.txt test_bkc_link.txt") | ||||
|       command('silent !ln -s test_bkc_file.txt test_bkc_link.txt') | ||||
|     end | ||||
|     if eval('v:shell_error') ~= 0 then | ||||
|       pending('Cannot create symlink') | ||||
| @@ -61,9 +60,9 @@ describe(':write', function() | ||||
|     command('set backupcopy=no') | ||||
|     write_file('test_bkc_file.txt', 'content0') | ||||
|     if is_os('win') then | ||||
|       command("silent !mklink test_bkc_link.txt test_bkc_file.txt") | ||||
|       command('silent !mklink test_bkc_link.txt test_bkc_file.txt') | ||||
|     else | ||||
|       command("silent !ln -s test_bkc_file.txt test_bkc_link.txt") | ||||
|       command('silent !ln -s test_bkc_file.txt test_bkc_link.txt') | ||||
|     end | ||||
|     if eval('v:shell_error') ~= 0 then | ||||
|       pending('Cannot create symlink') | ||||
| @@ -77,46 +76,50 @@ describe(':write', function() | ||||
|     eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')")) | ||||
|   end) | ||||
|  | ||||
|   it("appends FIFO file", function() | ||||
|   it('appends FIFO file', function() | ||||
|     -- mkfifo creates read-only .lnk files on Windows | ||||
|     if is_os('win') or eval("executable('mkfifo')") == 0 then | ||||
|       pending('missing "mkfifo" command') | ||||
|     end | ||||
|  | ||||
|     local text = "some fifo text from write_spec" | ||||
|     assert(os.execute("mkfifo test_fifo")) | ||||
|     local text = 'some fifo text from write_spec' | ||||
|     assert(os.execute('mkfifo test_fifo')) | ||||
|     insert(text) | ||||
|  | ||||
|     -- Blocks until a consumer reads the FIFO. | ||||
|     feed_command("write >> test_fifo") | ||||
|     feed_command('write >> test_fifo') | ||||
|  | ||||
|     -- Read the FIFO, this will unblock the :write above. | ||||
|     local fifo = assert(io.open("test_fifo")) | ||||
|     eq(text.."\n", fifo:read("*all")) | ||||
|     local fifo = assert(io.open('test_fifo')) | ||||
|     eq(text .. '\n', fifo:read('*all')) | ||||
|     fifo:close() | ||||
|   end) | ||||
|  | ||||
|   it("++p creates missing parent directories", function() | ||||
|   it('++p creates missing parent directories', function() | ||||
|     eq(0, eval("filereadable('p_opt.txt')")) | ||||
|     command("write ++p p_opt.txt") | ||||
|     command('write ++p p_opt.txt') | ||||
|     eq(1, eval("filereadable('p_opt.txt')")) | ||||
|     os.remove("p_opt.txt") | ||||
|     os.remove('p_opt.txt') | ||||
|  | ||||
|     eq(0, eval("filereadable('p_opt.txt')")) | ||||
|     command("write ++p ./p_opt.txt") | ||||
|     command('write ++p ./p_opt.txt') | ||||
|     eq(1, eval("filereadable('p_opt.txt')")) | ||||
|     os.remove("p_opt.txt") | ||||
|     os.remove('p_opt.txt') | ||||
|  | ||||
|     eq(0, eval("filereadable('test/write/p_opt.txt')")) | ||||
|     command("write ++p test/write/p_opt.txt") | ||||
|     command('write ++p test/write/p_opt.txt') | ||||
|     eq(1, eval("filereadable('test/write/p_opt.txt')")) | ||||
|  | ||||
|     eq(('Vim(write):E32: No file name'), pcall_err(command, 'write ++p test_write/')) | ||||
|     eq('Vim(write):E32: No file name', pcall_err(command, 'write ++p test_write/')) | ||||
|     if not is_os('win') then | ||||
|       eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), | ||||
|         pcall_err(command, 'write ++p .')) | ||||
|       eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), | ||||
|         pcall_err(command, 'write ++p ./')) | ||||
|       eq( | ||||
|         ('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'), | ||||
|         pcall_err(command, 'write ++p .') | ||||
|       ) | ||||
|       eq( | ||||
|         ('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'), | ||||
|         pcall_err(command, 'write ++p ./') | ||||
|       ) | ||||
|     end | ||||
|   end) | ||||
|  | ||||
| @@ -126,24 +129,27 @@ describe(':write', function() | ||||
|     eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~')) | ||||
|     -- Message from check_overwrite | ||||
|     if not is_os('win') then | ||||
|       eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), | ||||
|         pcall_err(command, 'write .')) | ||||
|       eq( | ||||
|         ('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'), | ||||
|         pcall_err(command, 'write .') | ||||
|       ) | ||||
|     end | ||||
|     meths.set_option_value('writeany', true, {}) | ||||
|     -- Message from buf_write | ||||
|     eq(('Vim(write):E502: "." is a directory'), pcall_err(command, 'write .')) | ||||
|     eq('Vim(write):E502: "." is a directory', pcall_err(command, 'write .')) | ||||
|     funcs.mkdir(fname_bak) | ||||
|     meths.set_option_value('backupdir', '.', {}) | ||||
|     meths.set_option_value('backup', true, {}) | ||||
|     write_file(fname, 'content0') | ||||
|     command('edit ' .. fname) | ||||
|     funcs.setline(1, 'TTY') | ||||
|     eq('Vim(write):E510: Can\'t make backup file (add ! to override)', | ||||
|        pcall_err(command, 'write')) | ||||
|     eq("Vim(write):E510: Can't make backup file (add ! to override)", pcall_err(command, 'write')) | ||||
|     meths.set_option_value('backup', false, {}) | ||||
|     funcs.setfperm(fname, 'r--------') | ||||
|     eq('Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)', | ||||
|        pcall_err(command, 'write')) | ||||
|     eq( | ||||
|       'Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)', | ||||
|       pcall_err(command, 'write') | ||||
|     ) | ||||
|     if is_os('win') then | ||||
|       eq(0, os.execute('del /q/f ' .. fname)) | ||||
|       eq(0, os.execute('rd /q/s ' .. fname_bak)) | ||||
| @@ -154,7 +160,6 @@ describe(':write', function() | ||||
|     write_file(fname_bak, 'TTYX') | ||||
|     skip(is_os('win'), [[FIXME: exc_exec('write!') outputs 0 in Windows]]) | ||||
|     luv.fs_symlink(fname_bak .. ('/xxxxx'):rep(20), fname) | ||||
|     eq('Vim(write):E166: Can\'t open linked file for writing', | ||||
|        pcall_err(command, 'write!')) | ||||
|     eq("Vim(write):E166: Can't open linked file for writing", pcall_err(command, 'write!')) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -2,9 +2,12 @@ | ||||
|  | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local command, clear, eval, spawn, nvim_prog, set_session = | ||||
|   helpers.command, helpers.clear, helpers.eval, helpers.spawn, | ||||
|   helpers.nvim_prog, helpers.set_session | ||||
|  | ||||
|   helpers.command, | ||||
|   helpers.clear, | ||||
|   helpers.eval, | ||||
|   helpers.spawn, | ||||
|   helpers.nvim_prog, | ||||
|   helpers.set_session | ||||
|  | ||||
| describe(':wundo', function() | ||||
|   before_each(clear) | ||||
| @@ -21,8 +24,16 @@ end) | ||||
|  | ||||
| describe('u_* functions', function() | ||||
|   it('safely fail on new, non-empty buffer', function() | ||||
|     local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', | ||||
|                            '-c', 'set undodir=. undofile'}) | ||||
|     local session = spawn({ | ||||
|       nvim_prog, | ||||
|       '-u', | ||||
|       'NONE', | ||||
|       '-i', | ||||
|       'NONE', | ||||
|       '--embed', | ||||
|       '-c', | ||||
|       'set undodir=. undofile', | ||||
|     }) | ||||
|     set_session(session) | ||||
|     command('echo "True"') -- Should not error out due to crashed Neovim | ||||
|     session:close() | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| local helpers = require('test.functional.helpers')(after_each) | ||||
| local luv = require('luv') | ||||
| local clear = helpers.clear | ||||
| local command, eq, neq, write_file = | ||||
|   helpers.command, helpers.eq, helpers.neq, helpers.write_file | ||||
| local command, eq, neq, write_file = helpers.command, helpers.eq, helpers.neq, helpers.write_file | ||||
| local read_file = helpers.read_file | ||||
| local is_os = helpers.is_os | ||||
|  | ||||
| @@ -10,19 +9,25 @@ describe(':wshada', function() | ||||
|   local shada_file = 'wshada_test' | ||||
|  | ||||
|   before_each(function() | ||||
|     clear{args={'-i', is_os('win') and 'nul' or '/dev/null', | ||||
|     clear { | ||||
|       args = { | ||||
|         '-i', | ||||
|         is_os('win') and 'nul' or '/dev/null', | ||||
|         -- Need 'swapfile' for these tests. | ||||
|                 '--cmd', 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}, | ||||
|           args_rm={'-n', '-i', '--cmd'}} | ||||
|         '--cmd', | ||||
|         'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler', | ||||
|       }, | ||||
|       args_rm = { '-n', '-i', '--cmd' }, | ||||
|     } | ||||
|   end) | ||||
|   after_each(function () | ||||
|   after_each(function() | ||||
|     os.remove(shada_file) | ||||
|   end) | ||||
|  | ||||
|   it('creates a shada file', function() | ||||
|     -- file should _not_ exist | ||||
|     eq(nil, luv.fs_stat(shada_file)) | ||||
|     command('wsh! '..shada_file) | ||||
|     command('wsh! ' .. shada_file) | ||||
|     -- file _should_ exist | ||||
|     neq(nil, luv.fs_stat(shada_file)) | ||||
|   end) | ||||
| @@ -37,14 +42,13 @@ describe(':wshada', function() | ||||
|     eq(text, read_file(shada_file)) | ||||
|     neq(nil, luv.fs_stat(shada_file)) | ||||
|  | ||||
|     command('wsh! '..shada_file) | ||||
|     command('wsh! ' .. shada_file) | ||||
|  | ||||
|     -- File should have been overwritten with a shada file. | ||||
|     local fp = io.open(shada_file, 'r') | ||||
|     local char1 = fp:read(1) | ||||
|     fp:close() | ||||
|     -- ShaDa file starts with a “header” entry | ||||
|     assert(char1:byte() == 0x01, | ||||
|       shada_file..' should be a shada file') | ||||
|     assert(char1:byte() == 0x01, shada_file .. ' should be a shada file') | ||||
|   end) | ||||
| end) | ||||
|   | ||||
| @@ -12,12 +12,12 @@ describe('example', function() | ||||
|   local screen | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     screen = Screen.new(20,5) | ||||
|     screen = Screen.new(20, 5) | ||||
|     screen:attach() | ||||
|     screen:set_default_attr_ids( { | ||||
|       [0] = {bold=true, foreground=Screen.colors.Blue}, | ||||
|       [1] = {bold=true, foreground=Screen.colors.Brown} | ||||
|     } ) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = { bold = true, foreground = Screen.colors.Blue }, | ||||
|       [1] = { bold = true, foreground = Screen.colors.Brown }, | ||||
|     }) | ||||
|   end) | ||||
|  | ||||
|   it('screen test', function() | ||||
| @@ -47,7 +47,7 @@ describe('example', function() | ||||
|     -- For this example, we enable `ext_tabline`: | ||||
|     screen:detach() | ||||
|     screen = Screen.new(25, 5) | ||||
|     screen:attach({rgb=true, ext_tabline=true}) | ||||
|     screen:attach({ rgb = true, ext_tabline = true }) | ||||
|  | ||||
|     -- From ":help ui" we find that `tabline_update` receives `curtab` and | ||||
|     -- `tabs` objects. So we declare the UI handler like this: | ||||
| @@ -60,13 +60,14 @@ describe('example', function() | ||||
|     command('tabedit foo') | ||||
|  | ||||
|     -- Use screen:expect{condition=…} to check the result. | ||||
|     screen:expect{condition=function() | ||||
|     screen:expect { | ||||
|       condition = function() | ||||
|         eq({ id = 2 }, event_curtab) | ||||
|         eq({ | ||||
|           {tab = { id = 1 }, name = '[No Name]'}, | ||||
|           {tab = { id = 2 }, name = 'foo'}, | ||||
|         }, | ||||
|         event_tabs) | ||||
|     end} | ||||
|           { tab = { id = 1 }, name = '[No Name]' }, | ||||
|           { tab = { id = 2 }, name = 'foo' }, | ||||
|         }, event_tabs) | ||||
|       end, | ||||
|     } | ||||
|   end) | ||||
| end) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1 +1 @@ | ||||
| table.insert(_G.test_loadorder, "mittel") | ||||
| table.insert(_G.test_loadorder, 'mittel') | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| table.insert(_G.test_loadorder, "ordinary after") | ||||
| table.insert(_G.test_loadorder, 'ordinary after') | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| table.insert(_G.test_loadorder, "ordinary") | ||||
| table.insert(_G.test_loadorder, 'ordinary') | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes