Merge #26398 lintlua for test/ dir

This commit is contained in:
Justin M. Keyes
2024-01-03 03:05:22 -08:00
committed by GitHub
369 changed files with 32907 additions and 22641 deletions

View File

@@ -1,9 +1,12 @@
/build
/build/
/.deps/
/runtime/lua/coxpcall.lua
/runtime/lua/vim/_meta
/runtime/lua/vim/re.lua
/test/functional
test/functional/ui/decorations_spec.lua
test/functional/ui/float_spec.lua
test/functional/ui/multigrid_spec.lua
/test/functional/fixtures/lua/syntax_error.lua
/test/functional/legacy/030_fileformats_spec.lua
/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua

View File

@@ -227,7 +227,7 @@ endif()
find_program(SHELLCHECK_PRG shellcheck ${LINT_REQUIRED})
find_program(STYLUA_PRG stylua ${LINT_REQUIRED})
set(STYLUA_DIRS runtime scripts src test/unit)
set(STYLUA_DIRS runtime scripts src test)
add_glob_target(
TARGET lintlua-luacheck
@@ -235,7 +235,7 @@ add_glob_target(
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
GLOB_DIRS runtime scripts src test
GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE)
TOUCH_STRATEGY PER_DIR)
add_dependencies(lintlua-luacheck lua-dev-deps)
add_glob_target(
@@ -244,7 +244,7 @@ add_glob_target(
FLAGS --color=always --check --respect-ignores
GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE)
TOUCH_STRATEGY PER_DIR)
add_custom_target(lintlua)
add_dependencies(lintlua lintlua-luacheck lintlua-stylua)
@@ -255,7 +255,7 @@ add_glob_target(
FLAGS -x -a
GLOB_DIRS scripts
GLOB_PAT *.sh
TOUCH_STRATEGY SINGLE)
TOUCH_STRATEGY PER_DIR)
add_custom_target(lintcommit
COMMAND $<TARGET_FILE:nvim> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
@@ -270,7 +270,8 @@ add_glob_target(
COMMAND ${STYLUA_PRG}
FLAGS --respect-ignores
GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua)
GLOB_PAT *.lua
TOUCH_STRATEGY PER_DIR)
add_custom_target(format)
add_dependencies(format formatc formatlua)

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,6 @@ describe('api/buf', function()
return request('buffer_' .. method, 0, ...)
end
describe('nvim_buf_set_lines, nvim_buf_line_count', function()
it('deprecated forms', function()
eq(1, curbuf_depr('line_count'))
@@ -52,54 +51,54 @@ describe('api/buf', function()
it('cursor position is maintained after lines are inserted #9961', function()
-- replace the buffer contents with these three lines.
request('nvim_buf_set_lines', 0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
request('nvim_buf_set_lines', 0, 0, -1, 1, { 'line1', 'line2', 'line3', 'line4' })
-- Set the current cursor to {3, 2}.
curwin('set_cursor', { 3, 2 })
-- add 2 lines and delete 1 line above the current cursor position.
request('nvim_buf_set_lines', 0, 1, 2, 1, {"line5", "line6"})
request('nvim_buf_set_lines', 0, 1, 2, 1, { 'line5', 'line6' })
-- check the current set of lines in the buffer.
eq({"line1", "line5", "line6", "line3", "line4"}, buffer('get_lines', 0, 0, -1, 1))
eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, buffer('get_lines', 0, 0, -1, 1))
-- cursor should be moved below by 1 line.
eq({ 4, 2 }, curwin('get_cursor'))
-- add a line after the current cursor position.
request('nvim_buf_set_lines', 0, 5, 5, 1, {"line7"})
request('nvim_buf_set_lines', 0, 5, 5, 1, { 'line7' })
-- check the current set of lines in the buffer.
eq({"line1", "line5", "line6", "line3", "line4", "line7"}, buffer('get_lines', 0, 0, -1, 1))
eq({ 'line1', 'line5', 'line6', 'line3', 'line4', 'line7' }, buffer('get_lines', 0, 0, -1, 1))
-- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor'))
-- overwrite current cursor line.
request('nvim_buf_set_lines', 0, 3, 5, 1, {"line8", "line9"})
request('nvim_buf_set_lines', 0, 3, 5, 1, { 'line8', 'line9' })
-- check the current set of lines in the buffer.
eq({"line1", "line5", "line6", "line8", "line9", "line7"}, buffer('get_lines', 0, 0, -1, 1))
eq({ 'line1', 'line5', 'line6', 'line8', 'line9', 'line7' }, buffer('get_lines', 0, 0, -1, 1))
-- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor'))
-- delete current cursor line.
request('nvim_buf_set_lines', 0, 3, 5, 1, {})
-- check the current set of lines in the buffer.
eq({"line1", "line5", "line6", "line7"}, buffer('get_lines', 0, 0, -1, 1))
eq({ 'line1', 'line5', 'line6', 'line7' }, buffer('get_lines', 0, 0, -1, 1))
-- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor'))
end)
it('cursor position is maintained in non-current window', function()
meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
meths.buf_set_lines(0, 0, -1, 1, { 'line1', 'line2', 'line3', 'line4' })
meths.win_set_cursor(0, { 3, 2 })
local win = meths.get_current_win()
local buf = meths.get_current_buf()
command('new')
meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"})
eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true))
meths.buf_set_lines(buf, 1, 2, 1, { 'line5', 'line6' })
eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, meths.buf_get_lines(buf, 0, -1, true))
eq({ 4, 2 }, meths.win_get_cursor(win))
end)
it('cursor position is maintained in TWO non-current windows', function()
meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
meths.buf_set_lines(0, 0, -1, 1, { 'line1', 'line2', 'line3', 'line4' })
meths.win_set_cursor(0, { 3, 2 })
local win = meths.get_current_win()
local buf = meths.get_current_buf()
@@ -109,10 +108,10 @@ describe('api/buf', function()
local win2 = meths.get_current_win()
-- set current window to third one with another buffer
command("new")
command('new')
meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"})
eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true))
meths.buf_set_lines(buf, 1, 2, 1, { 'line5', 'line6' })
eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, meths.buf_get_lines(buf, 0, -1, true))
eq({ 4, 2 }, meths.win_get_cursor(win))
eq({ 5, 2 }, meths.win_get_cursor(win2))
end)
@@ -121,7 +120,7 @@ describe('api/buf', function()
-- we'll need to know our bufnr for when it gets unloaded
local bufnr = curbuf('get_number')
-- replace the buffer contents with these three lines
request('nvim_buf_set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
request('nvim_buf_set_lines', bufnr, 0, -1, 1, { 'line1', 'line2', 'line3', 'line4' })
-- check the line count is correct
eq(4, request('nvim_buf_line_count', bufnr))
-- force unload the buffer (this will discard changes)
@@ -135,9 +134,9 @@ describe('api/buf', function()
-- we'll need to know our bufnr for when it gets unloaded
local bufnr = curbuf('get_number')
-- replace the buffer contents with these three lines
buffer('set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
buffer('set_lines', bufnr, 0, -1, 1, { 'line1', 'line2', 'line3', 'line4' })
-- confirm that getting lines works
eq({"line2", "line3"}, buffer('get_lines', bufnr, 1, 3, 1))
eq({ 'line2', 'line3' }, buffer('get_lines', bufnr, 1, 3, 1))
-- force unload the buffer (this will discard changes)
command('new')
command('bunload! ' .. bufnr)
@@ -152,12 +151,12 @@ describe('api/buf', function()
before_each(function()
screen = Screen.new(20, 12)
screen:set_default_attr_ids {
[1] = {bold = true, foreground = Screen.colors.Blue1};
[2] = {reverse = true, bold = true};
[3] = {reverse = true};
[1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = { reverse = true, bold = true },
[3] = { reverse = true },
}
screen:attach()
meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"})
meths.buf_set_lines(0, 0, -1, 1, { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' })
meths.set_option_value('modified', false, {})
end)
@@ -168,7 +167,8 @@ describe('api/buf', function()
command('new | wincmd w')
meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -178,10 +178,12 @@ describe('api/buf', function()
^zzz |
{2:[No Name] }|
|
]]}
]],
}
meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -191,11 +193,13 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
]]}
]],
}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -205,11 +209,13 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
]]}
]],
}
-- inserting just before topline does not scroll up if cursor would be moved
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -219,10 +225,13 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
]], unchanged=true}
]],
unchanged = true,
}
meths.win_set_cursor(0, { 7, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -232,10 +241,12 @@ describe('api/buf', function()
zzz |
{2:[No Name] [+] }|
|
]]}
]],
}
meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 4, 4, true, { 'mmmeeeee' })
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -245,7 +256,8 @@ describe('api/buf', function()
^yyy |
{2:[No Name] [+] }|
|
]]}
]],
}
end)
it('of non-current window', function()
@@ -255,7 +267,8 @@ describe('api/buf', function()
command('new')
meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -265,10 +278,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
]]}
]],
}
meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -278,11 +293,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -292,11 +309,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
-- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -306,7 +325,8 @@ describe('api/buf', function()
yyy |
{3:[No Name] [+] }|
|
]]}
]],
}
end)
it('of split windows with same buffer', function()
@@ -317,7 +337,8 @@ describe('api/buf', function()
meths.win_set_cursor(win, { 8, 0 })
meths.win_set_cursor(0, { 1, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^aaa |
bbb |
ccc |
@@ -330,10 +351,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
]]}
meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
]],
}
meths.buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
screen:expect{grid=[[
screen:expect {
grid = [[
^aaabbb |
ccc |
ddd |
@@ -346,11 +369,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect {
grid = [[
^aaabbb |
ccc |
ddd |
@@ -363,11 +388,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
-- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect {
grid = [[
^aaabbb |
ccc |
ddd |
@@ -380,19 +407,20 @@ describe('api/buf', function()
yyy |
{3:[No Name] [+] }|
|
]]}
]],
}
end)
end)
it('handles clearing out non-current buffer #24911', function()
local buf = meths.get_current_buf()
meths.buf_set_lines(buf, 0, -1, true, {"aaa", "bbb", "ccc"})
command("new")
meths.buf_set_lines(buf, 0, -1, true, { 'aaa', 'bbb', 'ccc' })
command('new')
meths.buf_set_lines(0, 0, -1, true, {"xxx", "yyy", "zzz"})
meths.buf_set_lines(0, 0, -1, true, { 'xxx', 'yyy', 'zzz' })
meths.buf_set_lines(buf, 0, -1, true, {})
eq({"xxx", "yyy", "zzz"}, meths.buf_get_lines(0, 0, -1, true))
eq({ 'xxx', 'yyy', 'zzz' }, meths.buf_get_lines(0, 0, -1, true))
eq({ '' }, meths.buf_get_lines(buf, 0, -1, true))
end)
end)
@@ -467,8 +495,7 @@ describe('api/buf', function()
curbuf_depr('set_line_slice', 1, 2, true, false, { 'a', 'b', 'c' })
eq({ 'a', 'a', 'b', 'c', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', -1, -1, true, true, { 'a', 'b', 'c' })
eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
curbuf_depr('get_line_slice', 0, -1, true, true))
eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', 0, -3, true, false, {})
eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', 0, -1, true, true, {})
@@ -483,14 +510,18 @@ describe('api/buf', function()
it('fails correctly when input is not valid', function()
eq(1, api.curbufmeths.get_number())
eq([['replacement string' item contains newlines]],
pcall_err(bufmeths.set_lines, 1, 1, 2, false, {'b\na'}))
eq(
[['replacement string' item contains newlines]],
pcall_err(bufmeths.set_lines, 1, 1, 2, false, { 'b\na' })
)
end)
it("fails if 'nomodifiable'", function()
command('set nomodifiable')
eq([[Buffer is not 'modifiable']],
pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, {'a','b'}))
eq(
[[Buffer is not 'modifiable']],
pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, { 'a', 'b' })
)
end)
it('has correct line_count when inserting and deleting', function()
@@ -571,8 +602,7 @@ describe('api/buf', function()
set_lines(1, 2, mode, { 'a', 'b', 'c' })
eq({ 'a', 'a', 'b', 'c', 'c' }, get_lines(0, -1, mode))
set_lines(-2, -1, mode, { 'a', 'b', 'c' })
eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
get_lines(0, -1, mode))
eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, get_lines(0, -1, mode))
set_lines(0, -4, mode, {})
eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode))
set_lines(0, -1, mode, {})
@@ -617,7 +647,7 @@ describe('api/buf', function()
eq({ 'e', 'a', 'b', 'c', 'd' }, get_lines(0, -1, true))
end)
it("set_lines on alternate buffer does not access invalid line (E315)", function()
it('set_lines on alternate buffer does not access invalid line (E315)', function()
feed_command('set hidden')
insert('Initial file')
command('enew')
@@ -678,8 +708,7 @@ describe('api/buf', function()
eq(3, funcs.winnr())
feed('<c-w>h')
eq(2, funcs.winnr())
api.meths.buf_set_lines(hiddenbuf, 0, -1, true,
{'hidden buffer line 1', 'line 2'})
api.meths.buf_set_lines(hiddenbuf, 0, -1, true, { 'hidden buffer line 1', 'line 2' })
feed('<c-w>p')
eq(3, funcs.winnr())
end)
@@ -711,7 +740,6 @@ describe('api/buf', function()
eq({ 'hello foo!' }, get_lines(0, 1, true))
-- can replace a single word
set_text(0, 6, 0, 9, { 'world' })
eq({ 'hello world!', 'text' }, get_lines(0, 2, true))
@@ -799,7 +827,7 @@ describe('api/buf', function()
local win = meths.get_current_win()
local buf = meths.get_current_buf()
command("new")
command('new')
-- replace 'world' with 'foo'
meths.buf_set_text(buf, 0, 6, 0, 11, { 'foo' })
@@ -817,12 +845,12 @@ describe('api/buf', function()
local win = meths.get_current_win()
local buf = meths.get_current_buf()
command("split")
command('split')
local win2 = meths.get_current_win()
-- position the cursor on `w`
meths.win_set_cursor(0, { 1, 6 })
command("new")
command('new')
-- replace 'hello' with 'foo'
meths.buf_set_text(buf, 0, 0, 0, 5, { 'foo' })
@@ -886,7 +914,7 @@ describe('api/buf', function()
eq({ 1, 1 }, curwin('get_cursor'))
end)
it('leaves cursor at the same position in INSERT mode in current and non-current window', function()
it('maintains INSERT-mode cursor position current/non-current window', function()
insert([[
abcd]])
@@ -912,7 +940,7 @@ describe('api/buf', function()
end)
describe('when cursor is inside replaced row range', function()
it('keeps cursor at the same position if cursor is at start_row, but before start_col', function()
it('maintains cursor position if at start_row, but before start_col', function()
insert([[
This should be first
then there is a line we do not want
@@ -934,7 +962,7 @@ describe('api/buf', function()
eq({ 1, 14 }, curwin('get_cursor'))
end)
it('keeps cursor at the same position if cursor is at start_row and column is still valid', function()
it('maintains cursor position if at start_row and column is still valid', function()
insert([[
This should be first
then there is a line we do not want
@@ -977,7 +1005,7 @@ describe('api/buf', function()
eq({ 1, 18 }, cursor)
end)
it('adjusts cursor column to keep it valid if start_row got smaller in INSERT mode', function()
it('adjusts cursor column to keep it valid if start_row decreased in INSERT mode', function()
insert([[
This should be first
then there is a line we do not want
@@ -1000,7 +1028,7 @@ describe('api/buf', function()
eq({ 1, 19 }, cursor)
end)
it('adjusts cursor column to keep it valid in a row after start_row if it got smaller', function()
it('adjusts cursor to valid column in row after start_row if it got smaller', function()
insert([[
This should be first
then there is a line we do not want
@@ -1029,7 +1057,9 @@ describe('api/buf', function()
eq({ 2, 5 }, cursor)
end)
it('adjusts cursor column to keep it valid in a row after start_row if it got smaller in INSERT mode', function()
it(
'adjusts cursor to valid column in row after start_row if it got smaller in INSERT mode',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1058,7 +1088,8 @@ describe('api/buf', function()
eq({ 2, 6 }, curwin('get_cursor'))
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 6 }, cursor)
end)
end
)
it('adjusts cursor line and column to keep it inside replacement range', function()
insert([[
@@ -1149,7 +1180,9 @@ describe('api/buf', function()
eq({ 3, 7 }, curwin('get_cursor'))
end)
it('adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode', function()
it(
'adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1168,7 +1201,8 @@ describe('api/buf', function()
}, get_lines(0, -1, true))
-- cursor should end up after 'n' in 'then'
eq({ 3, 8 }, curwin('get_cursor'))
end)
end
)
it('adjusts cursor column if replacement is inside of a single line', function()
insert([[
@@ -1228,7 +1262,7 @@ describe('api/buf', function()
end)
describe('with virtualedit', function()
it('adjusts cursor line and column to keep it inside replacement range if cursor is not after eol', function()
it('adjusts cursor line/col to keep inside replacement range if not after eol', function()
insert([[
This should be first
then there is a line we do not want
@@ -1257,12 +1291,15 @@ describe('api/buf', function()
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 12 }, cursor)
-- coladd should be 0
eq(0, exec_lua([[
eq(
0,
exec_lua([[
return vim.fn.winsaveview().coladd
]]))
]])
)
end)
it('does not change cursor screen column when cursor is after eol and row got shorter', function()
it('does not change cursor screen column when cursor >EOL and row got shorter', function()
insert([[
This should be first
then there is a line we do not want
@@ -1294,12 +1331,17 @@ describe('api/buf', function()
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 26 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column
eq(13, exec_lua([[
eq(
13,
exec_lua([[
return vim.fn.winsaveview().coladd
]]))
]])
)
end)
it('does not change cursor screen column when cursor is after eol and row got longer', function()
it(
'does not change cursor screen column when cursor is after eol and row got longer',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1331,12 +1373,18 @@ describe('api/buf', function()
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 1, 38 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column
eq(2, exec_lua([[
eq(
2,
exec_lua([[
return vim.fn.winsaveview().coladd
]]))
end)
]])
)
end
)
it('does not change cursor screen column when cursor is after eol and row extended past cursor column', function()
it(
'does not change cursor screen column when cursor is after eol and row extended past cursor column',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1368,12 +1416,18 @@ describe('api/buf', function()
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 1, 22 }, cursor)
-- coladd should become 0
eq(0, exec_lua([[
eq(
0,
exec_lua([[
return vim.fn.winsaveview().coladd
]]))
end)
]])
)
end
)
it('does not change cursor screen column when cursor is after eol and row range decreased', function()
it(
'does not change cursor screen column when cursor is after eol and row range decreased',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1406,10 +1460,14 @@ describe('api/buf', function()
-- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 26 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column
eq(13, exec_lua([[
eq(
13,
exec_lua([[
return vim.fn.winsaveview().coladd
]]))
end)
]])
)
end
)
end)
end)
@@ -1434,7 +1492,9 @@ describe('api/buf', function()
eq({ 3, 2 }, curwin('get_cursor'))
end)
it('adjusts cursor column if the range is not bound to either start or end of a line', function()
it(
'adjusts cursor column if the range is not bound to either start or end of a line',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1459,9 +1519,12 @@ describe('api/buf', function()
}, get_lines(0, -1, true))
-- cursor should return back to the original position
eq({ 3, 13 }, curwin('get_cursor'))
end)
end
)
it('adjusts cursor column if replacing lines in range, not just deleting and adding', function()
it(
'adjusts cursor column if replacing lines in range, not just deleting and adding',
function()
insert([[
This should be first
then there is a line we do not want
@@ -1494,7 +1557,8 @@ describe('api/buf', function()
}, get_lines(0, -1, true))
-- cursor should return back to the original position
eq({ 3, 18 }, curwin('get_cursor'))
end)
end
)
it('does not move cursor column after end of a line', function()
insert([[
@@ -1543,7 +1607,7 @@ describe('api/buf', function()
end)
it('adjusts extmarks', function()
local ns = request('nvim_create_namespace', "my-fancy-plugin")
local ns = request('nvim_create_namespace', 'my-fancy-plugin')
insert([[
foo bar
baz
@@ -1551,7 +1615,7 @@ describe('api/buf', function()
local id1 = curbufmeths.set_extmark(ns, 0, 1, {})
local id2 = curbufmeths.set_extmark(ns, 0, 7, {})
local id3 = curbufmeths.set_extmark(ns, 1, 1, {})
set_text(0, 4, 0, 7, {"q"})
set_text(0, 4, 0, 7, { 'q' })
eq({ 'foo q', 'baz' }, get_lines(0, 2, true))
-- mark before replacement point is unaffected
@@ -1562,7 +1626,7 @@ describe('api/buf', function()
eq({ 1, 1 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
-- replacing the text spanning two lines will adjust the mark on the next line
set_text(0, 3, 1, 3, {"qux"})
set_text(0, 3, 1, 3, { 'qux' })
eq({ 'fooqux', '' }, get_lines(0, 2, true))
eq({ 0, 6 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
-- but mark before replacement point is still unaffected
@@ -1585,7 +1649,7 @@ describe('api/buf', function()
eq({ 0, 8 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
end)
it("correctly marks changed region for redraw #13890", function()
it('correctly marks changed region for redraw #13890', function()
local screen = Screen.new(20, 5)
screen:attach()
@@ -1642,12 +1706,12 @@ describe('api/buf', function()
before_each(function()
screen = Screen.new(20, 12)
screen:set_default_attr_ids {
[1] = {bold = true, foreground = Screen.colors.Blue1};
[2] = {reverse = true, bold = true};
[3] = {reverse = true};
[1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = { reverse = true, bold = true },
[3] = { reverse = true },
}
screen:attach()
meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"})
meths.buf_set_lines(0, 0, -1, 1, { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' })
meths.set_option_value('modified', false, {})
end)
@@ -1658,7 +1722,8 @@ describe('api/buf', function()
command('new | wincmd w')
meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -1668,10 +1733,12 @@ describe('api/buf', function()
^zzz |
{2:[No Name] }|
|
]]}
meths.buf_set_text(buf, 0,3, 1,0, {"X"})
]],
}
meths.buf_set_text(buf, 0, 3, 1, 0, { 'X' })
screen:expect{grid=[[
screen:expect {
grid = [[
|
{1:~ }|*4
{3:[No Name] }|
@@ -1681,7 +1748,8 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
]]}
]],
}
end)
it('of non-current window', function()
@@ -1691,7 +1759,8 @@ describe('api/buf', function()
command('new')
meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -1701,10 +1770,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
]]}
]],
}
meths.buf_set_text(buf, 0,3, 1,0, {"X"})
screen:expect{grid=[[
meths.buf_set_text(buf, 0, 3, 1, 0, { 'X' })
screen:expect {
grid = [[
^ |
{1:~ }|*4
{2:[No Name] }|
@@ -1714,7 +1785,8 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
end)
it('of split windows with same buffer', function()
@@ -1725,7 +1797,8 @@ describe('api/buf', function()
meths.win_set_cursor(win, { 8, 0 })
meths.win_set_cursor(0, { 1, 1 })
screen:expect{grid=[[
screen:expect {
grid = [[
a^aa |
bbb |
ccc |
@@ -1738,10 +1811,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
]]}
meths.buf_set_text(buf, 0,3, 1,0, {"X"})
]],
}
meths.buf_set_text(buf, 0, 3, 1, 0, { 'X' })
screen:expect{grid=[[
screen:expect {
grid = [[
a^aaXbbb |
ccc |
ddd |
@@ -1754,7 +1829,8 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
]]}
]],
}
end)
end)
end)
@@ -1823,10 +1899,10 @@ describe('api/buf', function()
meths.set_option_value('eol', true, {})
eq(29, get_offset(5))
command("set hidden")
command("enew")
command('set hidden')
command('enew')
eq(6, bufmeths.get_offset(1, 1))
command("bunload! 1")
command('bunload! 1')
eq(-1, bufmeths.get_offset(1, 1))
eq(-1, bufmeths.get_offset(1, 0))
end)
@@ -1857,10 +1933,8 @@ describe('api/buf', function()
command('lockvar b:lua')
eq('Key is locked: lua', pcall_err(curbufmeths.del_var, 'lua'))
eq('Key is locked: lua', pcall_err(curbufmeths.set_var, 'lua', 1))
eq('Key is read-only: changedtick',
pcall_err(curbufmeths.del_var, 'changedtick'))
eq('Key is read-only: changedtick',
pcall_err(curbufmeths.set_var, 'changedtick', 1))
eq('Key is read-only: changedtick', pcall_err(curbufmeths.del_var, 'changedtick'))
eq('Key is read-only: changedtick', pcall_err(curbufmeths.set_var, 'changedtick', 1))
end)
end)
@@ -1897,7 +1971,7 @@ describe('api/buf', function()
nvim('set_option_value', 'define', 'test', { buf = 0 })
eq('test', nvim('get_option_value', 'define', { buf = 0 }))
-- Doesn't change the global value
eq("", nvim('get_option_value', 'define', {scope='global'}))
eq('', nvim('get_option_value', 'define', { scope = 'global' }))
end)
it('returns values for unset local options', function()

View File

@@ -2,19 +2,21 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq, ok = helpers.eq, helpers.ok
local funcs = helpers.funcs
local buffer, command, eval, nvim, next_msg = helpers.buffer,
helpers.command, helpers.eval, helpers.nvim, helpers.next_msg
local buffer, command, eval, nvim, next_msg =
helpers.buffer, helpers.command, helpers.eval, helpers.nvim, helpers.next_msg
local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err
local sleep = helpers.sleep
local write_file = helpers.write_file
local origlines = {"original line 1",
"original line 2",
"original line 3",
"original line 4",
"original line 5",
"original line 6"}
local origlines = {
'original line 1',
'original line 2',
'original line 3',
'original line 4',
'original line 5',
'original line 6',
}
local function expectn(name, args)
-- expect the next message to be the specified notification event
@@ -27,12 +29,13 @@ local function sendkeys(keys)
-- more key presses - otherwise they all pile up in the queue and get
-- processed at once
local ntime = os.clock() + 0.1
repeat until os.clock() > ntime
repeat
until os.clock() > ntime
end
local function open(activate, lines)
local filename = helpers.tmpname()
write_file(filename, table.concat(lines, "\n").."\n", true)
write_file(filename, table.concat(lines, '\n') .. '\n', true)
command('edit ' .. filename)
local b = nvim('get_current_buf')
-- what is the value of b:changedtick?
@@ -81,18 +84,36 @@ local function reopenwithfolds(b)
-- add a fold
command('2,4fold')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2/*{{{*/',
expectn('nvim_buf_lines_event', {
b,
tick,
1,
4,
{
'original line 2/*{{{*/',
'original line 3',
'original line 4/*}}}*/'}, false})
'original line 4/*}}}*/',
},
false,
})
-- make a new fold that wraps lines 1-6
command('1,6fold')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 6, {'original line 1/*{{{*/',
expectn('nvim_buf_lines_event', {
b,
tick,
0,
6,
{
'original line 1/*{{{*/',
'original line 2/*{{{*/',
'original line 3',
'original line 4/*}}}*/',
'original line 5',
'original line 6/*}}}*/'}, false})
'original line 6/*}}}*/',
},
false,
})
return tick
end
@@ -110,9 +131,10 @@ describe('API: buffer events:', function()
-- add multiple lines at the start of the file
command('normal! GkkyGggP')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 4',
'original line 5',
'original line 6'}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 0, 0, { 'original line 4', 'original line 5', 'original line 6' }, false }
)
-- add one line to the middle of the file, several times
command('normal! ggYjjp')
@@ -128,10 +150,19 @@ describe('API: buffer events:', function()
-- add multiple lines to the middle of the file
command('normal! gg4Yjjp')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 3, 3, {'original line 4',
expectn('nvim_buf_lines_event', {
b,
tick,
3,
3,
{
'original line 4',
'original line 5',
'original line 6',
'original line 4'}, false})
'original line 4',
},
false,
})
-- add one line to the end of the file
command('normal! ggYGp')
@@ -151,10 +182,7 @@ describe('API: buffer events:', function()
command('normal! gg4YGp')
command('normal! Gp')
command('normal! Gp')
local firstfour = {'original line 4',
'original line 5',
'original line 6',
'original line 4'}
local firstfour = { 'original line 4', 'original line 5', 'original line 6', 'original line 4' }
tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 21, 21, firstfour, false })
tick = tick + 1
@@ -171,7 +199,7 @@ describe('API: buffer events:', function()
tick = eval('b:changedtick')
local b2 = nvim('get_current_buf')
ok(buffer('attach', b2, true, {}))
expectn('nvim_buf_lines_event', {b2, tick, 0, -1, {""}, false})
expectn('nvim_buf_lines_event', { b2, tick, 0, -1, { '' }, false })
eval('append(0, ["new line 1"])')
tick = tick + 1
expectn('nvim_buf_lines_event', { b2, tick, 0, 0, { 'new line 1' }, false })
@@ -185,17 +213,18 @@ describe('API: buffer events:', function()
local b3 = nvim('get_current_buf')
ok(buffer('attach', b3, true, {}))
tick = eval('b:changedtick')
expectn('nvim_buf_lines_event', {b3, tick, 0, -1, {""}, false})
expectn('nvim_buf_lines_event', { b3, tick, 0, -1, { '' }, false })
eval('append(0, ["new line 1", "new line 2", "new line 3"])')
tick = tick + 1
expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {'new line 1',
'new line 2',
'new line 3'}, false})
expectn(
'nvim_buf_lines_event',
{ b3, tick, 0, 0, { 'new line 1', 'new line 2', 'new line 3' }, false }
)
-- use the API itself to add a line to the start of the buffer
buffer('set_lines', b3, 0, 0, true, { 'New First Line' })
tick = tick + 1
expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {"New First Line"}, false})
expectn('nvim_buf_lines_event', { b3, tick, 0, 0, { 'New First Line' }, false })
end)
it('when lines are removed', function()
@@ -253,8 +282,10 @@ describe('API: buffer events:', function()
command('normal! jjw')
sendkeys('<C-v>jjllx')
tick = tick + 1
expectn('nvim_buf_lines_event',
{b, tick, 2, 5, {'original e 3', 'original e 4', 'original e 5'}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 2, 5, { 'original e 3', 'original e 4', 'original e 5' }, false }
)
-- replace part of a line line using :s
tick = reopen(b, origlines)
@@ -266,9 +297,10 @@ describe('API: buffer events:', function()
tick = reopen(b, origlines)
command('%s/line [35]/foo/')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 2, 5, {'original foo',
'original line 4',
'original foo'}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 2, 5, { 'original foo', 'original line 4', 'original foo' }, false }
)
-- type text into the first line of a blank file, one character at a time
command('bdelete!')
@@ -319,14 +351,14 @@ describe('API: buffer events:', function()
it('when lines are filtered', function()
-- Test filtering lines with !cat
local b, tick = editoriginal(true, {"A", "C", "E", "B", "D", "F"})
local b, tick = editoriginal(true, { 'A', 'C', 'E', 'B', 'D', 'F' })
command('silent 2,5!cat')
-- the change comes through as two changes:
-- 1) addition of the new lines after the filtered lines
-- 2) removal of the original lines
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 5, 5, {"C", "E", "B", "D"}, false})
expectn('nvim_buf_lines_event', { b, tick, 5, 5, { 'C', 'E', 'B', 'D' }, false })
tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 1, 5, {}, false })
end)
@@ -338,7 +370,7 @@ describe('API: buffer events:', function()
-- use 'o' to start a new line from a line with no indent
command('normal! o')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 1, {""}, false})
expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '' }, false })
-- undo the change, indent line 1 a bit, and try again
command('undo')
@@ -349,12 +381,12 @@ describe('API: buffer events:', function()
command('set autoindent')
command('normal! >>')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tAAA"}, false})
expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tAAA' }, false })
command('normal! ommm')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 1, {"\t"}, false})
expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '\t' }, false })
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 2, {"\tmmm"}, false})
expectn('nvim_buf_lines_event', { b, tick, 1, 2, { '\tmmm' }, false })
-- undo the change, and try again with 'O'
command('undo')
@@ -366,14 +398,14 @@ describe('API: buffer events:', function()
expectn('nvim_buf_changedtick_event', { b, tick })
command('normal! ggOmmm')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 0, {"\t"}, false})
expectn('nvim_buf_lines_event', { b, tick, 0, 0, { '\t' }, false })
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tmmm"}, false})
expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tmmm' }, false })
end)
it('deactivates if the buffer is changed externally', function()
-- Test changing file from outside vim and reloading using :edit
local lines = {"Line 1", "Line 2"};
local lines = { 'Line 1', 'Line 2' }
local b, tick, filename = editoriginal(true, lines)
command('normal! x')
@@ -386,7 +418,7 @@ describe('API: buffer events:', function()
expectn('nvim_buf_changedtick_event', { b, tick })
-- change the file directly
write_file(filename, "another line\n", true, true)
write_file(filename, 'another line\n', true, true)
-- reopen the file and watch buffer events shut down
command('edit')
@@ -540,24 +572,24 @@ describe('API: buffer events:', function()
end)
it('works with :diffput and :diffget', function()
local b1, tick1 = editoriginal(true, {"AAA", "BBB"})
local b1, tick1 = editoriginal(true, { 'AAA', 'BBB' })
local channel = nvim('get_api_info')[1]
command('diffthis')
command('rightbelow vsplit')
local b2, tick2 = open(true, {"BBB", "CCC"})
local b2, tick2 = open(true, { 'BBB', 'CCC' })
command('diffthis')
-- go back to first buffer, and push the 'AAA' line to the second buffer
command('1wincmd w')
command('normal! gg')
command('diffput')
tick2 = tick2 + 1
expectn('nvim_buf_lines_event', {b2, tick2, 0, 0, {"AAA"}, false})
expectn('nvim_buf_lines_event', { b2, tick2, 0, 0, { 'AAA' }, false })
-- use :diffget to grab the other change from buffer 2
command('normal! G')
command('diffget')
tick1 = tick1 + 1
expectn('nvim_buf_lines_event', {b1, tick1, 2, 2, {"CCC"}, false})
expectn('nvim_buf_lines_event', { b1, tick1, 2, 2, { 'CCC' }, false })
eval('rpcnotify(' .. channel .. ', "Goodbye")')
expectn('Goodbye', {})
@@ -565,29 +597,25 @@ describe('API: buffer events:', function()
it('works with :sort', function()
-- test for :sort
local b, tick = editoriginal(true, {"B", "D", "C", "A", "E"})
local b, tick = editoriginal(true, { 'B', 'D', 'C', 'A', 'E' })
command('%sort')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 5, {"A", "B", "C", "D", "E"}, false})
expectn('nvim_buf_lines_event', { b, tick, 0, 5, { 'A', 'B', 'C', 'D', 'E' }, false })
end)
it('works with :left', function()
local b, tick = editoriginal(true, {" A", " B", "B", "\tB", "\t\tC"})
local b, tick = editoriginal(true, { ' A', ' B', 'B', '\tB', '\t\tC' })
command('2,4left')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 4, {"B", "B", "B"}, false})
expectn('nvim_buf_lines_event', { b, tick, 1, 4, { 'B', 'B', 'B' }, false })
end)
it('works with :right', function()
local b, tick = editoriginal(true, {" A",
"\t B",
"\t \tBB",
" \tB",
"\t\tC"})
local b, tick = editoriginal(true, { ' A', '\t B', '\t \tBB', ' \tB', '\t\tC' })
command('set ts=2 et')
command('2,4retab')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 4, {" B", " BB", " B"}, false})
expectn('nvim_buf_lines_event', { b, tick, 1, 4, { ' B', ' BB', ' B' }, false })
end)
it('works with :move', function()
@@ -595,8 +623,10 @@ describe('API: buffer events:', function()
-- move text down towards the end of the file
command('2,3move 4')
tick = tick + 2
expectn('nvim_buf_lines_event', {b, tick, 4, 4, {"original line 2",
"original line 3"}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 4, 4, { 'original line 2', 'original line 3' }, false }
)
tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 1, 3, {}, false })
@@ -604,8 +634,10 @@ describe('API: buffer events:', function()
tick = reopen(b, origlines)
command('4,5move 2')
tick = tick + 2
expectn('nvim_buf_lines_event', {b, tick, 2, 2, {"original line 4",
"original line 5"}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 2, 2, { 'original line 4', 'original line 5' }, false }
)
tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 5, 7, {}, false })
end)
@@ -617,9 +649,10 @@ describe('API: buffer events:', function()
-- delete the inner fold
command('normal! zR3Gzd')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2',
'original line 3',
'original line 4'}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 1, 4, { 'original line 2', 'original line 3', 'original line 4' }, false }
)
-- delete the outer fold
command('normal! zd')
tick = tick + 1
@@ -649,9 +682,10 @@ describe('API: buffer events:', function()
-- delete the fold which only has one marker
command('normal! Gzd')
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 3, 6, {'original line 4',
'original line 5',
'original line 6'}, false})
expectn(
'nvim_buf_lines_event',
{ b, tick, 3, 6, { 'original line 4', 'original line 5', 'original line 6' }, false }
)
end)
it('detaches if the buffer is closed', function()
@@ -763,7 +797,7 @@ describe('API: buffer events:', function()
it('returns a proper error on nonempty options dict', function()
clear()
local b = editoriginal(false)
eq("Invalid key: 'builtin'", pcall_err(buffer, 'attach', b, false, {builtin="asfd"}))
eq("Invalid key: 'builtin'", pcall_err(buffer, 'attach', b, false, { builtin = 'asfd' }))
end)
it('nvim_buf_attach returns response after delay #8634', function()
@@ -777,7 +811,9 @@ describe('API: buffer events:', function()
[2] = 'nvim_buf_changedtick_event',
[3] = {
[1] = { id = 1 },
[2] = 2 }, }, next_msg())
[2] = 2,
},
}, next_msg())
end)
end)
@@ -803,7 +839,7 @@ describe('API: buffer events:', function()
local function assert_match_somewhere(expected_lines, buffer_lines)
local msg = next_msg()
while(msg ~= nil) do
while msg ~= nil do
local event = msg[2]
if event == 'nvim_buf_lines_event' then
local args = msg[3]
@@ -834,7 +870,7 @@ describe('API: buffer events:', function()
local buffer_lines = {}
local expected_lines = {}
funcs.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '-n', '-c', 'set shortmess+=A' }, {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
})
local b = nvim('get_current_buf')
@@ -844,15 +880,13 @@ describe('API: buffer events:', function()
table.insert(expected_lines, '~')
end
expected_lines[1] = ''
expected_lines[22] = ('tmp_terminal_nvim'..(' '):rep(45)
..'0,0-1 All')
expected_lines[22] = ('tmp_terminal_nvim' .. (' '):rep(45) .. '0,0-1 All')
sendkeys('i:e tmp_terminal_nvim<Enter>')
assert_match_somewhere(expected_lines, buffer_lines)
expected_lines[1] = 'Blarg'
expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41)
..'1,6 All')
expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '1,6 All')
sendkeys('iBlarg')
assert_match_somewhere(expected_lines, buffer_lines)
@@ -860,12 +894,10 @@ describe('API: buffer events:', function()
for i = 1, 21 do
expected_lines[i] = 'xyz'
end
expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41)
..'31,4 Bot')
expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '31,4 Bot')
local s = string.rep('\nxyz', 30)
sendkeys(s)
assert_match_somewhere(expected_lines, buffer_lines)
end)
end)

View File

@@ -16,8 +16,38 @@ 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()
@@ -25,10 +55,8 @@ describe('nvim_get_commands', function()
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()
@@ -36,7 +64,7 @@ describe('nvim_get_commands', function()
command('command -nargs=1 Hello echo "Hello World"')
eq({ Hello = cmd_dict }, meths.get_commands({ builtin = false }))
-- Define another command.
command('command -nargs=? Pwd pwd');
command('command -nargs=? Pwd pwd')
eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, meths.get_commands({ builtin = false }))
-- Delete a command.
command('delcommand Pwd')
@@ -59,11 +87,86 @@ describe('nvim_get_commands', function()
end)
it('gets various command attributes', function()
local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', 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>
@@ -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)
@@ -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]] },
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
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,21 +678,51 @@ 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()
@@ -566,7 +731,7 @@ describe('nvim_create_user_command', function()
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 [[
@@ -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)

View File

@@ -46,10 +46,10 @@ end
local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
local rv = get_extmark_by_id(ns, mark)
eq({ er, ec }, rv)
feed("u")
feed('u')
rv = get_extmark_by_id(ns, mark)
eq({ sr, sc }, rv)
feed("<c-r>")
feed('<c-r>')
rv = get_extmark_by_id(ns, mark)
eq({ er, ec }, rv)
end
@@ -75,9 +75,9 @@ end
local function batch_check_undo_redo(ns_id, ids, before, after)
batch_check(ns_id, ids, after)
feed("u")
feed('u')
batch_check(ns_id, ids, before)
feed("<c-r>")
feed('<c-r>')
batch_check(ns_id, ids, after)
end
@@ -89,48 +89,77 @@ describe('API/extmarks', function()
before_each(function()
-- Initialize some namespaces and insert 12345 into a buffer
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
positions = {{0, 0,}, {0, 2}, {0, 3}}
positions = { { 0, 0 }, { 0, 2 }, { 0, 3 } }
init_text = "12345"
init_text = '12345'
row = 0
col = 2
clear()
insert(init_text)
ns = request('nvim_create_namespace', "my-fancy-plugin")
ns2 = request('nvim_create_namespace', "my-fancy-plugin2")
ns = request('nvim_create_namespace', 'my-fancy-plugin')
ns2 = request('nvim_create_namespace', 'my-fancy-plugin2')
end)
it('validation', function()
eq("Invalid 'end_col': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 }))
eq("Invalid 'end_row': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} }))
eq("Invalid 'virt_text_pos': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 }))
eq("Invalid 'virt_text_pos': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' }))
eq("Invalid 'hl_mode': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 }))
eq(
"Invalid 'end_col': expected Integer, got Array",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 })
)
eq(
"Invalid 'end_row': expected Integer, got Array",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} })
)
eq(
"Invalid 'virt_text_pos': expected String, got Integer",
pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 })
)
eq(
"Invalid 'virt_text_pos': 'foo'",
pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' })
)
eq(
"Invalid 'hl_mode': expected String, got Integer",
pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 })
)
eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' }))
eq("Invalid 'id': expected Integer, got Array", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }))
eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1}))
eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1}))
eq(
"Invalid 'id': expected Integer, got Array",
pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 })
)
eq(
'Invalid mark position: expected 2 Integer items',
pcall_err(get_extmarks, ns, {}, { -1, -1 })
)
eq(
'Invalid mark position: expected mark id Integer or 2-item Array',
pcall_err(get_extmarks, ns, true, { -1, -1 })
)
-- No memory leak with virt_text, virt_lines, sign_text
eq("right_gravity is not a boolean", pcall_err(set_extmark, ns, marks[2], 0, 0, {
eq(
'right_gravity is not a boolean',
pcall_err(set_extmark, ns, marks[2], 0, 0, {
virt_text = { { 'foo', 'Normal' } },
virt_lines = { { { 'bar', 'Normal' } } },
sign_text = 'a',
right_gravity = 'baz',
}))
})
)
end)
it("can end extranges past final newline using end_col = 0", function()
it('can end extranges past final newline using end_col = 0', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 0,
end_row = 1
end_row = 1,
})
eq("Invalid 'end_col': out of range",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
eq(
"Invalid 'end_col': out of range",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })
)
end)
it("can end extranges past final newline when strict mode is false", function()
it('can end extranges past final newline when strict mode is false', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 1,
end_row = 1,
@@ -138,7 +167,7 @@ describe('API/extmarks', function()
})
end)
it("can end extranges past final column when strict mode is false", function()
it('can end extranges past final column when strict mode is false', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 6,
end_row = 0,
@@ -324,9 +353,11 @@ describe('API/extmarks', function()
eq(2, #rv)
-- prevrange with positional when mark exists at position
rv = get_extmarks(ns, positions[3], positions[1])
eq({{marks[3], positions[3][1], positions[3][2]},
eq({
{ marks[3], positions[3][1], positions[3][2] },
{ marks[2], positions[2][1], positions[2][2] },
{marks[1], positions[1][1], positions[1][2]}}, rv)
{ marks[1], positions[1][1], positions[1][2] },
}, rv)
rv = get_extmarks(ns, positions[2], positions[1])
eq(2, #rv)
-- prevrange with positional index (no mark at position)
@@ -378,10 +409,10 @@ describe('API/extmarks', function()
set_extmark(ns, marks[1], 0, 4) -- check col > our upper bound
set_extmark(ns, marks[2], 1, 1) -- check col < lower bound
set_extmark(ns, marks[3], 2, 0) -- check is inclusive
eq({{marks[1], 0, 4},
{marks[2], 1, 1},
{marks[3], 2, 0}},
get_extmarks(ns, {0, 3}, {2, 0}))
eq(
{ { marks[1], 0, 4 }, { marks[2], 1, 1 }, { marks[3], 2, 0 } },
get_extmarks(ns, { 0, 3 }, { 2, 0 })
)
end)
it('get_marks works in reverse when mark col < lower col', function()
@@ -393,10 +424,7 @@ describe('API/extmarks', function()
set_extmark(ns, marks[2], 1, 4) -- check col > upper bound
set_extmark(ns, marks[3], 0, 2) -- check is inclusive
local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 })
eq({{marks[1], 2, 1},
{marks[2], 1, 4},
{marks[3], 0, 2}},
rv)
eq({ { marks[1], 2, 1 }, { marks[2], 1, 4 }, { marks[3], 0, 2 } }, rv)
end)
it('get_marks limit=0 returns nothing', function()
@@ -405,15 +433,14 @@ describe('API/extmarks', function()
eq({}, rv)
end)
it('marks move with line insertations', function()
set_extmark(ns, marks[1], 0, 0)
feed("yyP")
feed('yyP')
check_undo_redo(ns, marks[1], 0, 0, 1, 0)
end)
it('marks move with multiline insertations', function()
feed("a<cr>22<cr>33<esc>")
feed('a<cr>22<cr>33<esc>')
set_extmark(ns, marks[1], 1, 1)
feed('ggVGyP')
check_undo_redo(ns, marks[1], 1, 1, 4, 1)
@@ -421,7 +448,7 @@ describe('API/extmarks', function()
it('marks move with line join', function()
-- do_join in ops.c
feed("a<cr>222<esc>")
feed('a<cr>222<esc>')
set_extmark(ns, marks[1], 1, 0)
feed('ggJ')
check_undo_redo(ns, marks[1], 1, 0, 0, 6)
@@ -430,7 +457,7 @@ describe('API/extmarks', function()
it('join works when no marks are present', function()
screen = Screen.new(15, 10)
screen:attach()
feed("a<cr>1<esc>")
feed('a<cr>1<esc>')
feed('kJ')
-- This shouldn't seg fault
screen:expect([[
@@ -442,21 +469,21 @@ describe('API/extmarks', function()
it('marks move with multiline join', function()
-- do_join in ops.c
feed("a<cr>222<cr>333<cr>444<esc>")
feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 3, 0)
feed('2GVGJ')
check_undo_redo(ns, marks[1], 3, 0, 1, 8)
end)
it('marks move with line deletes', function()
feed("a<cr>222<cr>333<cr>444<esc>")
feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 2, 1)
feed('ggjdd')
check_undo_redo(ns, marks[1], 2, 1, 1, 1)
end)
it('marks move with multiline deletes', function()
feed("a<cr>222<cr>333<cr>444<esc>")
feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 3, 0)
feed('gg2dd')
check_undo_redo(ns, marks[1], 3, 0, 1, 0)
@@ -468,7 +495,7 @@ describe('API/extmarks', function()
it('marks move with open line', function()
-- open_line in change.c
-- testing marks below are also moved
feed("yyP")
feed('yyP')
set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4)
feed('1G<s-o><esc>')
@@ -501,12 +528,12 @@ describe('API/extmarks', function()
-- insertchar in edit.c (the ins_str branch)
set_extmark(ns, marks[1], 0, 2)
feed('03l')
insert("X")
insert('X')
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
-- check multibyte chars
feed('03l<esc>')
insert("")
insert('')
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
end)
@@ -530,7 +557,7 @@ describe('API/extmarks', function()
it('marks move with line splits (using enter)', function()
-- open_line in change.c
-- testing marks below are also moved
feed("yyP")
feed('yyP')
set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4)
feed('1Gla<cr><esc>')
@@ -547,16 +574,16 @@ describe('API/extmarks', function()
it('yet again marks move with line splits', function()
-- the first test above wasn't catching all errors..
feed("A67890<esc>")
feed('A67890<esc>')
set_extmark(ns, marks[1], 0, 4)
feed("04li<cr><esc>")
feed('04li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 4, 1, 0)
end)
it('and one last time line splits...', function()
set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 2)
feed("02li<cr><esc>")
feed('02li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 1, 0, 1)
check_undo_redo(ns, marks[2], 0, 2, 1, 0)
end)
@@ -564,7 +591,7 @@ describe('API/extmarks', function()
it('multiple marks move with mark splits', function()
set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 3)
feed("0li<cr><esc>")
feed('0li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 1, 1, 0)
check_undo_redo(ns, marks[2], 0, 3, 1, 2)
end)
@@ -656,11 +683,11 @@ describe('API/extmarks', function()
feed('0vx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
feed("u")
feed('u')
feed('0vlx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
feed("u")
feed('u')
feed('0v2lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
@@ -675,16 +702,16 @@ describe('API/extmarks', function()
feed('0x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
feed("u")
feed('u')
feed('02x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
feed("u")
feed('u')
feed('0v3lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
-- from the other side (nothing should happen)
feed("u")
feed('u')
feed('$vx')
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
end)
@@ -742,17 +769,31 @@ describe('API/extmarks', function()
it('delete', function()
local pos1 = {
{2, 4}, {2, 12}, {2, 13}, {2, 14}, {2, 25},
{4, 8}, {4, 10}, {4, 20},
{5, 3}, {6, 10}
{ 2, 4 },
{ 2, 12 },
{ 2, 13 },
{ 2, 14 },
{ 2, 25 },
{ 4, 8 },
{ 4, 10 },
{ 4, 20 },
{ 5, 3 },
{ 6, 10 },
}
local ids = batch_set(ns, pos1)
batch_check(ns, ids, pos1)
feed('3Gfiv2+ftd')
batch_check_undo_redo(ns, ids, pos1, {
{2, 4}, {2, 12}, {2, 13}, {2, 13}, {2, 13},
{2, 13}, {2, 15}, {2, 25},
{3, 3}, {4, 10}
{ 2, 4 },
{ 2, 12 },
{ 2, 13 },
{ 2, 13 },
{ 2, 13 },
{ 2, 13 },
{ 2, 15 },
{ 2, 25 },
{ 3, 3 },
{ 4, 10 },
})
end)
@@ -762,7 +803,10 @@ describe('API/extmarks', function()
set_extmark(ns, 3, 0, 5, { end_row = 2, end_col = 10 })
set_extmark(ns, 4, 0, 0, { end_row = 1, end_col = 0 })
eq({ { 2, 2, 5 } }, get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = false }))
eq({{ 1, 0, 0 }, { 3, 0, 5}, {2, 2, 5}}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=true }))
eq(
{ { 1, 0, 0 }, { 3, 0, 5 }, { 2, 2, 5 } },
get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = true })
)
end)
end)
@@ -862,11 +906,11 @@ describe('API/extmarks', function()
set_extmark(ns, marks[2], 0, -1)
set_extmark(ns, marks[3], 0, -1)
feed("u")
feed('u')
local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv)
feed("<c-r>")
feed('<c-r>')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv)
@@ -875,19 +919,26 @@ describe('API/extmarks', function()
set_extmark(ns, marks[1], positions[1][1], positions[1][2])
rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 })
eq(1, #rv)
feed("u")
feed("<c-r>")
feed('u')
feed('<c-r>')
-- old value is NOT kept in history
check_undo_redo(ns, marks[1], positions[1][1], positions[1][2], positions[1][1], positions[1][2])
check_undo_redo(
ns,
marks[1],
positions[1][1],
positions[1][2],
positions[1][1],
positions[1][2]
)
-- Test unset
feed('o<esc>')
curbufmeths.del_extmark(ns, marks[3])
feed("u")
feed('u')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
-- undo does NOT restore deleted marks
eq(2, #rv)
feed("<c-r>")
feed('<c-r>')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(2, #rv)
end)
@@ -966,12 +1017,12 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
feed("0iint <esc>A {1M1<esc>b<esc>")
feed('0iint <esc>A {1M1<esc>b<esc>')
-- Set the mark on the M, should move..
set_extmark(ns, marks[1], 0, 12)
-- Set the mark before the cursor, should stay there
set_extmark(ns, marks[2], 0, 10)
feed("i<cr><esc>")
feed('i<cr><esc>')
local rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv)
rv = get_extmark_by_id(ns, marks[2])
@@ -984,14 +1035,14 @@ describe('API/extmarks', function()
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
-- <c-f> will force an indent of 2
feed("0iint <esc>A {<cr><esc>0i1M1<esc>")
feed('0iint <esc>A {<cr><esc>0i1M1<esc>')
set_extmark(ns, marks[1], 1, 1)
feed("0i<c-f><esc>")
feed('0i<c-f><esc>')
local rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv)
check_undo_redo(ns, marks[1], 1, 1, 1, 3)
-- now check when cursor at eol
feed("uA<c-f><esc>")
feed('uA<c-f><esc>')
rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv)
end)
@@ -1000,14 +1051,14 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
feed("0i<tab><esc>")
feed('0i<tab><esc>')
set_extmark(ns, marks[1], 0, 3)
feed("bi<c-d><esc>")
feed('bi<c-d><esc>')
local rv = get_extmark_by_id(ns, marks[1])
eq({ 0, 1 }, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
-- check when cursor at eol
feed("uA<c-d><esc>")
feed('uA<c-d><esc>')
rv = get_extmark_by_id(ns, marks[1])
eq({ 0, 1 }, rv)
end)
@@ -1016,7 +1067,7 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
feed("0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>")
feed('0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>')
set_extmark(ns, marks[1], 1, 1)
set_extmark(ns, marks[2], 2, 1)
feed('=gg')
@@ -1374,7 +1425,10 @@ describe('API/extmarks', function()
it('throws consistent error codes', function()
local ns_invalid = ns2 + 1
eq("Invalid 'ns_id': 3", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
eq(
"Invalid 'ns_id': 3",
pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])
)
eq("Invalid 'ns_id': 3", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
eq("Invalid 'ns_id': 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
@@ -1398,7 +1452,10 @@ describe('API/extmarks', function()
it('fails when line > line_count', function()
local invalid_col = init_text:len() + 1
local invalid_lnum = 3
eq("Invalid 'line': out of range", pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
eq(
"Invalid 'line': out of range",
pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col)
)
eq({}, get_extmark_by_id(ns, marks[1]))
end)
@@ -1414,7 +1471,7 @@ describe('API/extmarks', function()
end)
it('in read-only buffer', function()
command("view! runtime/doc/help.txt")
command('view! runtime/doc/help.txt')
eq(true, meths.get_option_value('ro', {}))
local id = set_extmark(ns, 0, 0, 2)
eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
@@ -1422,7 +1479,7 @@ describe('API/extmarks', function()
it('can set a mark to other buffer', function()
local buf = request('nvim_create_buf', 0, 1)
request('nvim_buf_set_lines', buf, 0, -1, 1, {"", ""})
request('nvim_buf_set_lines', buf, 0, -1, 1, { '', '' })
local id = bufmeths.set_extmark(buf, ns, 1, 0, {})
eq({ { id, 1, 0 } }, bufmeths.get_extmarks(buf, ns, 0, -1, {}))
end)
@@ -1444,45 +1501,47 @@ describe('API/extmarks', function()
curbufmeths.set_extmark(ns, 0, 5, { right_gravity = true })
feed([[Aasdfasdf]])
eq({ {1, 0, 5}, {2, 0, 13} },
curbufmeths.get_extmarks(ns, 0, -1, {}))
eq({ { 1, 0, 5 }, { 2, 0, 13 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
-- but both move when text is inserted before
feed([[<esc>Iasdf<esc>]])
-- eq({}, curbufmeths.get_lines(0, -1, true))
eq({ {1, 0, 9}, {2, 0, 17} },
curbufmeths.get_extmarks(ns, 0, -1, {}))
eq({ { 1, 0, 9 }, { 2, 0, 17 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
-- clear text
curbufmeths.set_text(0, 0, 0, 17, {})
-- handles set_text correctly as well
eq({ {1, 0, 0}, {2, 0, 0} },
meths.buf_get_extmarks(0, ns, 0, -1, {}))
eq({ { 1, 0, 0 }, { 2, 0, 0 } }, meths.buf_get_extmarks(0, ns, 0, -1, {}))
curbufmeths.set_text(0, 0, 0, 0, { 'asdfasdf' })
eq({ {1, 0, 0}, {2, 0, 8} },
curbufmeths.get_extmarks(ns, 0, -1, {}))
eq({ { 1, 0, 0 }, { 2, 0, 8 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
feed('u')
-- handles pasting
exec([[let @a='asdfasdf']])
feed([["ap]])
eq({ {1, 0, 0}, {2, 0, 8} },
meths.buf_get_extmarks(0, ns, 0, -1, {}))
eq({ { 1, 0, 0 }, { 2, 0, 8 } }, meths.buf_get_extmarks(0, ns, 0, -1, {}))
end)
it('can accept "end_row" or "end_line" #16548', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 0,
end_line = 1
end_line = 1,
})
eq({ {1, 0, 0, {
eq({
{
1,
0,
0,
{
ns_id = 1,
end_col = 0,
end_row = 1,
right_gravity = true,
end_right_gravity = false,
}} }, get_extmarks(ns, 0, -1, {details=true}))
},
},
}, get_extmarks(ns, 0, -1, { details = true }))
end)
it('in prompt buffer', function()
@@ -1495,86 +1554,103 @@ describe('API/extmarks', function()
it('can get details', function()
set_extmark(ns, marks[1], 0, 0, {
conceal = "c",
cursorline_hl_group = "Statement",
conceal = 'c',
cursorline_hl_group = 'Statement',
end_col = 0,
end_right_gravity = true,
end_row = 1,
hl_eol = true,
hl_group = "String",
hl_mode = "blend",
line_hl_group = "Statement",
number_hl_group = "Statement",
hl_group = 'String',
hl_mode = 'blend',
line_hl_group = 'Statement',
number_hl_group = 'Statement',
priority = 0,
right_gravity = false,
sign_hl_group = "Statement",
sign_text = ">>",
sign_hl_group = 'Statement',
sign_text = '>>',
spell = true,
virt_lines = {
{ { "lines", "Macro" }, { "???" } },
{ { "stack", { "Type", "Search" } }, { "!!!" } },
{ { 'lines', 'Macro' }, { '???' } },
{ { 'stack', { 'Type', 'Search' } }, { '!!!' } },
},
virt_lines_above = true,
virt_lines_leftcol = true,
virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
virt_text_hide = true,
virt_text_pos = "right_align",
virt_text_pos = 'right_align',
})
set_extmark(ns, marks[2], 0, 0, {
priority = 0,
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
virt_text_win_col = 1,
})
eq({0, 0, {
conceal = "c",
cursorline_hl_group = "Statement",
eq({
0,
0,
{
conceal = 'c',
cursorline_hl_group = 'Statement',
end_col = 0,
end_right_gravity = true,
end_row = 1,
hl_eol = true,
hl_group = "String",
hl_mode = "blend",
line_hl_group = "Statement",
hl_group = 'String',
hl_mode = 'blend',
line_hl_group = 'Statement',
ns_id = 1,
number_hl_group = "Statement",
number_hl_group = 'Statement',
priority = 0,
right_gravity = false,
sign_hl_group = "Statement",
sign_text = ">>",
sign_hl_group = 'Statement',
sign_text = '>>',
spell = true,
virt_lines = {
{ { "lines", "Macro" }, { "???" } },
{ { "stack", { "Type", "Search" } }, { "!!!" } },
{ { 'lines', 'Macro' }, { '???' } },
{ { 'stack', { 'Type', 'Search' } }, { '!!!' } },
},
virt_lines_above = true,
virt_lines_leftcol = true,
virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
virt_text_repeat_linebreak = false,
virt_text_hide = true,
virt_text_pos = "right_align",
} }, get_extmark_by_id(ns, marks[1], { details = true }))
eq({0, 0, {
virt_text_pos = 'right_align',
},
}, get_extmark_by_id(ns, marks[1], { details = true }))
eq({
0,
0,
{
ns_id = 1,
right_gravity = true,
priority = 0,
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
virt_text_repeat_linebreak = false,
virt_text_hide = false,
virt_text_pos = "win_col",
virt_text_pos = 'win_col',
virt_text_win_col = 1,
} }, get_extmark_by_id(ns, marks[2], { details = true }))
set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = "Statement" })
eq({0, 0, {
},
}, get_extmark_by_id(ns, marks[2], { details = true }))
set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = 'Statement' })
eq({
0,
0,
{
ns_id = 1,
cursorline_hl_group = "Statement",
cursorline_hl_group = 'Statement',
priority = 4096,
right_gravity = true,
} }, get_extmark_by_id(ns, marks[3], { details = true }))
},
}, get_extmark_by_id(ns, marks[3], { details = true }))
curbufmeths.clear_namespace(ns, 0, -1)
-- legacy sign mark includes sign name
command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine')
command('sign place 1 name=sign1 line=1')
eq({ {1, 0, 0, {
eq({
{
1,
0,
0,
{
cursorline_hl_group = 'CursorLine',
invalidate = true,
line_hl_group = 'LineNr',
@@ -1585,18 +1661,21 @@ describe('API/extmarks', function()
sign_hl_group = 'Title',
sign_name = 'sign1',
sign_text = 's1',
undo_restore = false
} } }, get_extmarks(-1, 0, -1, { details = true }))
undo_restore = false,
},
},
}, get_extmarks(-1, 0, -1, { details = true }))
end)
it('can get marks from anonymous namespaces', function()
ns = request('nvim_create_namespace', "")
ns2 = request('nvim_create_namespace', "")
ns = request('nvim_create_namespace', '')
ns2 = request('nvim_create_namespace', '')
set_extmark(ns, 1, 0, 0, {})
set_extmark(ns2, 2, 1, 0, {})
eq({{ 1, 0, 0, { ns_id = ns, right_gravity = true }},
{ 2, 1, 0, { ns_id = ns2, right_gravity = true }}},
get_extmarks(-1, 0, -1, { details = true }))
eq({
{ 1, 0, 0, { ns_id = ns, right_gravity = true } },
{ 2, 1, 0, { ns_id = ns2, right_gravity = true } },
}, get_extmarks(-1, 0, -1, { details = true }))
end)
it('can filter by extmark properties', function()
@@ -1612,7 +1691,7 @@ describe('API/extmarks', function()
eq({ { 5, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_lines' }))
end)
it("invalidated marks are deleted", function()
it('invalidated marks are deleted', function()
screen = Screen.new(40, 6)
screen:attach()
feed('dd6iaaa bbb ccc<CR><ESC>gg')
@@ -1641,8 +1720,13 @@ describe('API/extmarks', function()
command('1d 2')
eq(0, #get_extmarks(-1, 0, -1, {}))
-- mark is not removed when deleting bytes before the range
set_extmark(ns, 3, 0, 4, { invalidate = true, undo_restore = false,
hl_group = 'Error', end_col = 7 })
set_extmark(
ns,
3,
0,
4,
{ invalidate = true, undo_restore = false, hl_group = 'Error', end_col = 7 }
)
feed('dw')
eq(3, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
-- mark is not removed when deleting bytes at the start of the range
@@ -1658,8 +1742,13 @@ describe('API/extmarks', function()
feed('hx')
eq({}, get_extmark_by_id(ns, 3, {}))
-- multiline mark is not removed when start of its range is deleted
set_extmark(ns, 4, 1, 4, { undo_restore = false, invalidate = true,
hl_group = 'Error', end_col = 7, end_row = 3 })
set_extmark(
ns,
4,
1,
4,
{ undo_restore = false, invalidate = true, hl_group = 'Error', end_col = 7, end_row = 3 }
)
feed('ddDdd')
eq({ 0, 0 }, get_extmark_by_id(ns, 4, {}))
-- multiline mark is removed when entirety of its range is deleted
@@ -1674,12 +1763,12 @@ describe('Extmarks buffer api with many marks', function()
local ns_marks = {}
before_each(function()
clear()
ns1 = request('nvim_create_namespace', "ns1")
ns2 = request('nvim_create_namespace', "ns2")
ns1 = request('nvim_create_namespace', 'ns1')
ns2 = request('nvim_create_namespace', 'ns2')
ns_marks = { [ns1] = {}, [ns2] = {} }
local lines = {}
for i = 1, 30 do
lines[#lines+1] = string.rep("x ",i)
lines[#lines + 1] = string.rep('x ', i)
end
curbufmeths.set_lines(0, -1, true, lines)
local ns = ns1
@@ -1696,7 +1785,6 @@ describe('Extmarks buffer api with many marks', function()
end
eq(233, #ns_marks[ns1])
eq(232, #ns_marks[ns2])
end)
local function get_marks(ns)
@@ -1704,18 +1792,18 @@ describe('Extmarks buffer api with many marks', function()
local marks = {}
for _, mark in ipairs(mark_list) do
local id, row, col = unpack(mark)
eq(nil, marks[id], "duplicate mark")
eq(nil, marks[id], 'duplicate mark')
marks[id] = { row, col }
end
return marks
end
it("can get marks", function()
it('can get marks', function()
eq(ns_marks[ns1], get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2))
end)
it("can clear all marks in ns", function()
it('can clear all marks in ns', function()
curbufmeths.clear_namespace(ns1, 0, -1)
eq({}, get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2))
@@ -1724,7 +1812,7 @@ describe('Extmarks buffer api with many marks', function()
eq({}, get_marks(ns2))
end)
it("can clear line range", function()
it('can clear line range', function()
curbufmeths.clear_namespace(ns1, 10, 20)
for id, mark in pairs(ns_marks[ns1]) do
if 10 <= mark[1] and mark[1] < 20 then
@@ -1735,7 +1823,7 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
it("can delete line", function()
it('can delete line', function()
feed('10Gdd')
for _, marks in pairs(ns_marks) do
for id, mark in pairs(marks) do
@@ -1750,7 +1838,7 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
it("can delete lines", function()
it('can delete lines', function()
feed('10G10dd')
for _, marks in pairs(ns_marks) do
for id, mark in pairs(marks) do
@@ -1765,7 +1853,7 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
it("can wipe buffer", function()
it('can wipe buffer', function()
command('bwipe!')
eq({}, get_marks(ns1))
eq({}, get_marks(ns2))
@@ -1781,15 +1869,15 @@ describe('API/win_extmark', function()
-- Initialize some namespaces and insert text into a buffer
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
line1 = "non ui-watched line"
line2 = "ui-watched line"
line1 = 'non ui-watched line'
line2 = 'ui-watched line'
clear()
insert(line1)
feed("o<esc>")
feed('o<esc>')
insert(line2)
ns = request('nvim_create_namespace', "extmark-ui")
ns = request('nvim_create_namespace', 'extmark-ui')
end)
it('sends and only sends ui-watched marks to ui', function()
@@ -1810,7 +1898,7 @@ describe('API/win_extmark', function()
[2] = {
-- positioned at the end of the 2nd line
{ { id = 1000 }, ns, marks[1], 1, 16 },
}
},
},
})
end)
@@ -1820,10 +1908,10 @@ describe('API/win_extmark', function()
screen:attach()
feed('15A!<Esc>')
-- should send all of these
set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = "overlay" })
set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = "overlay" })
set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = "overlay" })
set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = "overlay" })
set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[5], 1, 8, { ui_watched = true })
screen:expect({
grid = [[
@@ -1856,7 +1944,7 @@ describe('API/win_extmark', function()
{ { id = 1000 }, ns, marks[4], 1, 6 },
-- eol
{ { id = 1000 }, ns, marks[5], 2, 11 },
}
},
},
})
end)
@@ -1869,7 +1957,7 @@ describe('API/win_extmark', function()
-- should not send this
set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
-- make some changes
insert(" update")
insert(' update')
screen:expect({
grid = [[
non ui-watched line |
@@ -1883,10 +1971,10 @@ describe('API/win_extmark', function()
{ { id = 1000 }, ns, marks[1], 1, 16 },
-- updated and wrapped to 3rd line
{ { id = 1000 }, ns, marks[1], 2, 2 },
}
}
},
},
})
feed("<c-e>")
feed('<c-e>')
screen:expect({
grid = [[
ui-watched linupdat^e|
@@ -1901,8 +1989,8 @@ describe('API/win_extmark', function()
-- updated and wrapped to 3rd line
{ { id = 1000 }, ns, marks[1], 2, 2 },
-- scrolled up one line, should be handled by grid scroll
}
}
},
},
})
end)
@@ -1942,11 +2030,11 @@ describe('API/win_extmark', function()
[4] = {
-- only after split
{ { id = 1001 }, ns, marks[1], 1, 16 },
}
}
},
},
})
-- make some changes
insert(" update")
insert(' update')
screen:expect({
grid = [[
## grid 1
@@ -1976,8 +2064,8 @@ describe('API/win_extmark', function()
{ { id = 1001 }, ns, marks[1], 1, 16 },
-- updated
{ { id = 1001 }, ns, marks[1], 2, 2 },
}
}
},
},
})
end)
end)

View File

@@ -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 })
-- 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,76 +307,72 @@ 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'))
eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
end)
it("can modify a highlight in the global namespace", function()
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'))
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'))
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'))
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'))
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'))
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'))
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))
eq({ foreground = 131, background = 243 }, nvim('get_hl_by_name', 'Normal', true))
end)
it('does not segfault on invalid group name #20009', function()
@@ -380,13 +391,15 @@ describe('API: get highlight', function()
local highlight1 = {
bg = highlight_color.bg,
fg = highlight_color.fg,
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,
underline = true,
reverse = true,
cterm = { underline = true, reverse = true },
}
local highlight3_config = {
@@ -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,13 +458,12 @@ 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 })
eq(1, funcs.hlexists('Bar'))
@@ -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,14 +574,28 @@ 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 },
}, meths.get_hl(0, { id = hl_id }))
@@ -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,28 +628,28 @@ 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)
@@ -613,17 +657,17 @@ describe('API: get highlight', function()
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,
'FooBarA',
{ default = true, fg = '#ffffff', cterm = { bold = true, italic = true } }
)
eq('Foo xxx cleared',
exec_capture('highlight Foo'))
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('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()

View File

@@ -67,9 +67,7 @@ describe('nvim_get_keymap', function()
-- and the dictionary you would get from maparg
-- since this is a global map, and not script local
eq({ foo_bar_map_table }, meths.get_keymap('n'))
eq({funcs.maparg('foo', 'n', false, true)},
meths.get_keymap('n')
)
eq({ funcs.maparg('foo', 'n', false, true) }, meths.get_keymap('n'))
-- Add another mapping
command('nnoremap foo_longer bar_longer')
@@ -78,15 +76,11 @@ describe('nvim_get_keymap', function()
foolong_bar_map_table['lhsraw'] = 'foo_longer'
foolong_bar_map_table['rhs'] = 'bar_longer'
eq({foolong_bar_map_table, foo_bar_map_table},
meths.get_keymap('n')
)
eq({ foolong_bar_map_table, foo_bar_map_table }, meths.get_keymap('n'))
-- Remove a mapping
command('unmap foo_longer')
eq({foo_bar_map_table},
meths.get_keymap('n')
)
eq({ foo_bar_map_table }, meths.get_keymap('n'))
end)
it('works for other modes', function()
@@ -162,15 +156,16 @@ describe('nvim_get_keymap', function()
-- Test toggle switches for basic options
-- @param option The key represented in the `maparg()` result dict
local function global_and_buffer_test(map,
local function global_and_buffer_test(
map,
option,
option_token,
global_on_result,
buffer_on_result,
global_off_result,
buffer_off_result,
new_windows)
new_windows
)
local function make_new_windows(number_of_windows)
if new_windows == nil then
return nil
@@ -184,41 +179,77 @@ describe('nvim_get_keymap', function()
local mode = string.sub(map, 1, 1)
-- Don't run this for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then
it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)',
global_on_result, option, option_token, map, mode), function()
it(
string.format(
'returns %d for the key "%s" when %s is used globally with %s (%s)',
global_on_result,
option,
option_token,
map,
mode
),
function()
make_new_windows(new_windows)
command(map .. ' ' .. option_token .. ' foo bar')
local result = meths.get_keymap(mode)[1][option]
eq(global_on_result, result)
end)
end
)
end
it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)',
buffer_on_result, option, option_token, map, mode), function()
it(
string.format(
'returns %d for the key "%s" when %s is used for buffers with %s (%s)',
buffer_on_result,
option,
option_token,
map,
mode
),
function()
make_new_windows(new_windows)
command(map .. ' <buffer> ' .. option_token .. ' foo bar')
local result = curbufmeths.get_keymap(mode)[1][option]
eq(buffer_on_result, result)
end)
end
)
-- Don't run these for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then
it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)',
global_off_result, option, option_token, map, mode), function()
it(
string.format(
'returns %d for the key "%s" when %s is not used globally with %s (%s)',
global_off_result,
option,
option_token,
map,
mode
),
function()
make_new_windows(new_windows)
command(map .. ' baz bat')
local result = meths.get_keymap(mode)[1][option]
eq(global_off_result, result)
end)
end
)
it(string.format('returns %d for the key "%s" when %s is not used for buffers with %s (%s)',
buffer_off_result, option, option_token, map, mode), function()
it(
string.format(
'returns %d for the key "%s" when %s is not used for buffers with %s (%s)',
buffer_off_result,
option,
option_token,
map,
mode
),
function()
make_new_windows(new_windows)
command(map .. ' <buffer> foo bar')
local result = curbufmeths.get_keymap(mode)[1][option]
eq(buffer_off_result, result)
end)
end
)
end
end
@@ -323,18 +354,22 @@ describe('nvim_get_keymap', function()
'set cpo+=B',
}) do
command(cmd)
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')},
get_keymap_noraw('n'))
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')},
get_keymap_noraw('x'))
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')},
get_keymap_noraw('s'))
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')},
get_keymap_noraw('o'))
eq({
cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n'),
}, get_keymap_noraw('n'))
eq({
cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x'),
}, get_keymap_noraw('x'))
eq({
cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's'),
}, get_keymap_noraw('s'))
eq({
cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o'),
}, get_keymap_noraw('o'))
end
end)
@@ -361,19 +396,25 @@ describe('nvim_get_keymap', function()
end)
it('can handle lua mappings', function()
eq(0, exec_lua([[
eq(
0,
exec_lua([[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]]))
]])
)
feed('asdf\n')
eq(1, exec_lua([[return GlobalCount]]))
eq(2, exec_lua([[
eq(
2,
exec_lua([[
vim.api.nvim_get_keymap('n')[1].callback()
return GlobalCount
]]))
]])
)
exec([[
call nvim_get_keymap('n')[0].callback()
@@ -401,7 +442,7 @@ describe('nvim_get_keymap', function()
end)
it('can handle map descriptions', function()
meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
meths.set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
eq({
lhs = 'lhs',
lhsraw = 'lhs',
@@ -418,7 +459,7 @@ describe('nvim_get_keymap', function()
abbr = 0,
noremap = 0,
lnum = 0,
desc='map description'
desc = 'map description',
}, meths.get_keymap('n')[1])
end)
end)
@@ -503,10 +544,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
-- 51 chars should produce an error
lhs = lhs .. '1'
eq('LHS exceeds maximum map length: '..lhs,
pcall_err(meths.set_keymap, '', lhs, 'rhs', {}))
eq('LHS exceeds maximum map length: '..lhs,
pcall_err(meths.del_keymap, '', lhs))
eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(meths.set_keymap, '', lhs, 'rhs', {}))
eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(meths.del_keymap, '', lhs))
end)
it('does not throw errors when rhs is longer than MAXMAPLEN', function()
@@ -517,8 +556,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end
rhs = rhs .. '1'
meths.set_keymap('', 'lhs', rhs, {})
eq(generate_mapargs('', 'lhs', rhs),
get_mapargs('', 'lhs'))
eq(generate_mapargs('', 'lhs', rhs), get_mapargs('', 'lhs'))
end)
it('error on invalid mode shortname', function()
@@ -534,7 +572,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq('Invalid mode shortname: "!!"', pcall_err(meths.set_keymap, '!!', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "vmap"', pcall_err(meths.set_keymap, 'vmap', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {}))
eq(
'Invalid mode shortname: "xnoremap"',
pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {})
)
eq('Invalid mode shortname: " "', pcall_err(meths.del_keymap, ' ', 'lhs'))
eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs'))
eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs'))
@@ -551,22 +592,20 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('error on invalid optnames', function()
eq("Invalid key: 'silentt'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true}))
eq("Invalid key: 'sidd'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {sidd = false}))
eq("Invalid key: 'nowaiT'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {nowaiT = false}))
eq("Invalid key: 'silentt'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { silentt = true }))
eq("Invalid key: 'sidd'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { sidd = false }))
eq("Invalid key: 'nowaiT'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { nowaiT = false }))
end)
it('error on <buffer> option key', function()
eq("Invalid key: 'buffer'",
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true}))
eq("Invalid key: 'buffer'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { buffer = true }))
end)
it('error when "replace_keycodes" is used without "expr"', function()
eq('"replace_keycodes" requires "expr"',
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {replace_keycodes = true}))
eq(
'"replace_keycodes" requires "expr"',
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { replace_keycodes = true })
)
end)
local optnames = { 'nowait', 'silent', 'script', 'expr', 'unique' }
@@ -575,8 +614,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('throws an error when given non-boolean value for ' .. opt, function()
local opts = {}
opts[opt] = 'fooo'
eq(opt..' is not a boolean',
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
eq(opt .. ' is not a boolean', pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
end)
end
@@ -591,26 +629,21 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('does not throw when LHS or RHS have leading/trailing whitespace', function()
meths.set_keymap('n', ' lhs', 'rhs', {})
eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'),
get_mapargs('n', ' lhs'))
eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), get_mapargs('n', ' lhs'))
meths.set_keymap('n', 'lhs ', 'rhs', {})
eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'),
get_mapargs('n', 'lhs '))
eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), get_mapargs('n', 'lhs '))
meths.set_keymap('v', ' lhs ', '\trhs\t\f', {})
eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'),
get_mapargs('v', ' lhs '))
eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), get_mapargs('v', ' lhs '))
end)
it('can set noremap mappings', function()
meths.set_keymap('x', 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs('x', 'lhs', 'rhs', {noremap = true}),
get_mapargs('x', 'lhs'))
eq(generate_mapargs('x', 'lhs', 'rhs', { noremap = true }), get_mapargs('x', 'lhs'))
meths.set_keymap('t', 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs('t', 'lhs', 'rhs', {noremap = true}),
get_mapargs('t', 'lhs'))
eq(generate_mapargs('t', 'lhs', 'rhs', { noremap = true }), get_mapargs('t', 'lhs'))
end)
it('can unmap mappings', function()
@@ -637,8 +670,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
for _, lhs in ipairs(special_chars) do
for _, rhs in ipairs(special_chars) do
local mapmode = '!'
it('can set mappings with special characters, lhs: '..lhs..', rhs: '..rhs,
function()
it('can set mappings with special characters, lhs: ' .. lhs .. ', rhs: ' .. rhs, function()
meths.set_keymap(mapmode, lhs, rhs, {})
eq(generate_mapargs(mapmode, lhs, rhs), get_mapargs(mapmode, lhs))
end)
@@ -655,8 +687,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
meths.set_keymap('i', 'lhs', '<Nop>', {})
command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing
eq(generate_mapargs('i', 'lhs', '<Nop>', {}),
get_mapargs('i', 'lhs'))
eq(generate_mapargs('i', 'lhs', '<Nop>', {}), get_mapargs('i', 'lhs'))
-- also test for case insensitivity
meths.set_keymap('i', 'lhs', '<nOp>', {})
@@ -664,29 +695,25 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq({ '' }, curbufmeths.get_lines(0, -1, 0))
-- note: RHS in returned mapargs() dict reflects the original RHS
-- provided by the user
eq(generate_mapargs('i', 'lhs', '<nOp>', {}),
get_mapargs('i', 'lhs'))
eq(generate_mapargs('i', 'lhs', '<nOp>', {}), get_mapargs('i', 'lhs'))
meths.set_keymap('i', 'lhs', '<NOP>', {})
command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '<NOP>', {}),
get_mapargs('i', 'lhs'))
eq(generate_mapargs('i', 'lhs', '<NOP>', {}), get_mapargs('i', 'lhs'))
-- a single ^V in RHS is also <Nop> (see :h map-empty-rhs)
meths.set_keymap('i', 'lhs', '\022', {})
command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '\022', {}),
get_mapargs('i', 'lhs'))
eq(generate_mapargs('i', 'lhs', '\022', {}), get_mapargs('i', 'lhs'))
end)
it('treats an empty RHS in a mapping like a <Nop>', function()
meths.set_keymap('i', 'lhs', '', {})
command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '', {}),
get_mapargs('i', 'lhs'))
eq(generate_mapargs('i', 'lhs', '', {}), get_mapargs('i', 'lhs'))
end)
it('can set and unset <M-">', function()
@@ -698,19 +725,22 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq({}, get_mapargs('i', '<M-">'))
end)
it('interprets control sequences in expr-quotes correctly when called '
..'inside vim', function()
it(
'interprets control sequences in expr-quotes correctly when called ' .. 'inside vim',
function()
command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
eq(generate_mapargs('i', '<Space>', '\t', {sid=0}),
get_mapargs('i', '<Space>'))
eq(generate_mapargs('i', '<Space>', '\t', { sid = 0 }), get_mapargs('i', '<Space>'))
feed('i ')
eq({ '\t' }, curbufmeths.get_lines(0, -1, 0))
end)
end
)
it('throws appropriate error messages when setting <unique> maps', function()
meths.set_keymap('l', 'lhs', 'rhs', {})
eq('E227: mapping already exists for lhs',
pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', {unique = true}))
eq(
'E227: mapping already exists for lhs',
pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', { unique = true })
)
-- different mapmode, no error should be thrown
meths.set_keymap('t', 'lhs', 'rhs', { unique = true })
end)
@@ -764,7 +794,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq({ 'mhs' }, curbufmeths.get_lines(0, -1, 0))
end)
it("can set nowait mappings that fire without waiting", function()
it('can set nowait mappings that fire without waiting', function()
meths.set_keymap('i', '123456', 'longer', {})
meths.set_keymap('i', '123', 'shorter', { nowait = true })
@@ -783,8 +813,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
for _, mapmode in ipairs(mapmodes) do
it('can set/unset normal mappings in mapmode ' .. mapmode, function()
meths.set_keymap(mapmode, 'lhs', 'rhs', {})
eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
get_mapargs(mapmode, 'lhs'))
eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
-- some mapmodes (like 'o') will prevent other mapmodes (like '!') from
-- taking effect, so unmap after each mapping
@@ -796,8 +825,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
for _, mapmode in ipairs(mapmodes) do
it('can set/unset noremap mappings using mapmode ' .. mapmode, function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs(mapmode, 'lhs', 'rhs', {noremap = true}),
get_mapargs(mapmode, 'lhs'))
eq(generate_mapargs(mapmode, 'lhs', 'rhs', { noremap = true }), get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
@@ -810,45 +838,62 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
for _, mapmode in ipairs(mapmodes) do
-- Test with single mappings
for _, maparg in ipairs(optnames) do
it('can set/unset '..mapmode..'-mappings with maparg: '..maparg,
function()
it('can set/unset ' .. mapmode .. '-mappings with maparg: ' .. maparg, function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = true })
eq(generate_mapargs(mapmode, 'lhs', 'rhs', {[maparg] = true}),
get_mapargs(mapmode, 'lhs'))
eq(
generate_mapargs(mapmode, 'lhs', 'rhs', { [maparg] = true }),
get_mapargs(mapmode, 'lhs')
)
meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
it ('can set/unset '..mapmode..'-mode mappings with maparg '..
maparg..', whose value is false', function()
it(
'can set/unset '
.. mapmode
.. '-mode mappings with maparg '
.. maparg
.. ', whose value is false',
function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = false })
eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
get_mapargs(mapmode, 'lhs'))
eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
end
)
end
-- Test with triplets of mappings, one of which is false
for i = 1, (#optnames - 2) do
local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2]
it('can set/unset '..mapmode..'-mode mappings with mapargs '..
opt1..', '..opt2..', '..opt3, function()
it(
'can set/unset '
.. mapmode
.. '-mode mappings with mapargs '
.. opt1
.. ', '
.. opt2
.. ', '
.. opt3,
function()
local opts = { [opt1] = true, [opt2] = false, [opt3] = true }
meths.set_keymap(mapmode, 'lhs', 'rhs', opts)
eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts),
get_mapargs(mapmode, 'lhs'))
eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
end
)
end
end
it('can make lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -862,7 +907,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
assert.truthy(
string.match(
exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]],
"^\nn asdf <Lua %d+>"
'^\nn asdf <Lua %d+>'
)
)
end)
@@ -871,18 +916,20 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
exec_lua [[
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(string.match(funcs.mapcheck('asdf', 'n'),
"^<Lua %d+>"))
assert.truthy(string.match(funcs.mapcheck('asdf', 'n'), '^<Lua %d+>'))
end)
it('maparg() returns lua mapping correctly', function()
eq(0, exec_lua([[
eq(
0,
exec_lua([[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]]))
]])
)
assert.truthy(string.match(funcs.maparg('asdf', 'n'), "^<Lua %d+>"))
assert.truthy(string.match(funcs.maparg('asdf', 'n'), '^<Lua %d+>'))
local mapargs = funcs.maparg('asdf', 'n', false, true)
mapargs.callback = nil
@@ -890,10 +937,13 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
mapargs.lhsrawalt = nil
eq(generate_mapargs('n', 'asdf', nil, { sid = sid_lua }), mapargs)
eq(1, exec_lua([[
eq(
1,
exec_lua([[
vim.fn.maparg('asdf', 'n', false, true).callback()
return GlobalCount
]]))
]])
)
exec([[
call maparg('asdf', 'n', v:false, v:true).callback()
@@ -932,21 +982,27 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('does not reset pum in lua mapping', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
VisibleCount = 0
vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
return VisibleCount
]])
]]
)
feed('i<C-X><C-V><F2><F2><esc>')
eq(2, exec_lua [[return VisibleCount]])
end)
it('redo of lua mappings in op-pending mode work', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
OpCount = 0
vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end})
return OpCount
]])
]]
)
feed('d<F2>')
eq(1, exec_lua [[return OpCount]])
feed('.')
@@ -954,11 +1010,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -974,11 +1033,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('can unmap lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -995,11 +1057,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('no double-free when unmapping simplifiable lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('<C-I>\n')
@@ -1016,10 +1081,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it('can set descriptions on mappings', function()
meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
eq(generate_mapargs('n', 'lhs', 'rhs', {desc="map description"}), get_mapargs('n', 'lhs'))
eq("\nn lhs rhs\n map description",
helpers.exec_capture("nmap lhs"))
meths.set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
eq(generate_mapargs('n', 'lhs', 'rhs', { desc = 'map description' }), get_mapargs('n', 'lhs'))
eq('\nn lhs rhs\n map description', helpers.exec_capture('nmap lhs'))
end)
it('can define !-mode abbreviations with lua callbacks', function()
@@ -1103,8 +1167,10 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end
it('rejects negative bufnr values', function()
eq('Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer',
pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {}))
eq(
'Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer',
pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {})
)
end)
it('can set mappings active in the current buffer but not others', function()
@@ -1153,8 +1219,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it("can't disable mappings given wrong buffer handle", function()
local first, second = make_two_buffers(false)
bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
eq('E31: No such mapping',
pcall_err(bufmeths.del_keymap, second, '', 'lhs'))
eq('E31: No such mapping', pcall_err(bufmeths.del_keymap, second, '', 'lhs'))
-- should still work
switch_to_buf(first)
@@ -1162,17 +1227,20 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
eq({ 'rhs' }, bufmeths.get_lines(0, 0, 1, 1))
end)
it("does not crash when setting mapping in a non-existing buffer #13541", function()
it('does not crash when setting mapping in a non-existing buffer #13541', function()
pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
helpers.assert_alive()
end)
it('can make lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -1199,13 +1267,15 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
eq({ '<space>' }, meths.buf_get_lines(0, 0, -1, false))
end)
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -1221,11 +1291,14 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end)
it('can unmap lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('asdf\n')
@@ -1242,11 +1315,14 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end)
it('no double-free when unmapping simplifiable lua mappings', function()
eq(0, exec_lua [[
eq(
0,
exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
]]
)
feed('<C-I>\n')

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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
@@ -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)

View File

@@ -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")
if method == 'doit' then
funcs.rpcnotify(cid, 'headsup')
eq(true, received)
return "retval"
return 'retval'
end
end
local function on_notification(method)
if method == "headsup" then
if method == 'headsup' then
received = true
end
end
@@ -152,10 +152,10 @@ describe('server -> client', function()
end
local function on_request(method)
if method == "notify" then
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
@@ -167,9 +167,9 @@ describe('server -> client', function()
end
local function on_notification(method)
if method == "notification" then
if method == 'notification' then
eq('done!', eval('rpcrequest(' .. cid .. ', "nested")'))
elseif method == "nested_done" then
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')")
@@ -208,15 +214,17 @@ describe('server -> client', function()
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,11 +269,11 @@ describe('server -> client', function()
error(string.format('missing nvim Lua module? (%s)', rv))
end
eq('ok', rv)
funcs.rpcnotify(jobid, "ping")
funcs.rpcnotify(jobid, 'ping')
eq({ 'notification', 'pong', {} }, next_msg())
eq("done!",funcs.rpcrequest(jobid, "write_stderr", "fluff\n"))
eq('done!', funcs.rpcrequest(jobid, 'write_stderr', 'fluff\n'))
eq({ 'notification', 'stderr', { 0, { 'fluff', '' } } }, next_msg())
pcall(funcs.rpcrequest, jobid, "exit")
pcall(funcs.rpcrequest, jobid, 'exit')
eq({ 'notification', 'stderr', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
@@ -311,7 +322,7 @@ 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
@@ -333,7 +344,7 @@ describe('server -> client', function()
it('via hostname', function()
local server = spawn(nvim_argv)
set_session(server)
local address = funcs.serverstart("localhost:")
local address = funcs.serverstart('localhost:')
eq('localhost:', string.sub(address, 1, 10))
connect_test(server, 'tcp', address)
end)
@@ -365,7 +376,7 @@ describe('server -> client', function()
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)

View File

@@ -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

View File

@@ -23,37 +23,51 @@ 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 }))
eq(
'UI already attached to channel: 1',
pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false })
)
end)
end)
@@ -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

View File

@@ -19,36 +19,35 @@ 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)
@@ -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
@@ -106,14 +105,16 @@ describe("api metadata", function()
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,19 +125,23 @@ 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
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)
@@ -146,12 +151,21 @@ describe("api metadata", function()
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
@@ -160,18 +174,21 @@ describe("api metadata", function()
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 = {}
@@ -190,28 +207,40 @@ describe("api metadata", function()
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

View File

@@ -1,9 +1,18 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf,
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval,
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq, ok, feed, insert, eval, tabpage =
helpers.clear,
helpers.nvim,
helpers.curbuf,
helpers.curbuf_contents,
helpers.window,
helpers.curwin,
helpers.eq,
helpers.neq,
helpers.ok,
helpers.feed,
helpers.insert,
helpers.eval,
helpers.tabpage
local poke_eventloop = helpers.poke_eventloop
local curwinmeths = helpers.curwinmeths
@@ -25,8 +34,7 @@ describe('API/win', function()
nvim('command', 'new')
nvim('set_current_win', nvim('list_wins')[2])
eq(curbuf(), window('get_buf', nvim('list_wins')[2]))
neq(window('get_buf', nvim('list_wins')[1]),
window('get_buf', nvim('list_wins')[2]))
neq(window('get_buf', nvim('list_wins')[1]), window('get_buf', nvim('list_wins')[2]))
end)
end)
@@ -48,15 +56,25 @@ describe('API/win', function()
local new_buf = meths.create_buf(true, true)
local old_win = meths.get_current_win()
local new_win = meths.open_win(new_buf, false, {
relative='editor', row=10, col=10, width=50, height=10,
relative = 'editor',
row = 10,
col = 10,
width = 50,
height = 10,
})
feed('q:')
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, 0, new_buf))
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, old_win, new_buf))
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, new_win, 0))
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, 0, new_buf)
)
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, old_win, new_buf)
)
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_set_buf, new_win, 0)
)
local next_buf = meths.create_buf(true, true)
meths.win_set_buf(new_win, next_buf)
@@ -76,53 +94,60 @@ describe('API/win', function()
end)
it('does not leak memory when using invalid window ID with invalid pos', function()
eq('Invalid window id: 1', pcall_err(meths.win_set_cursor, 1, {"b\na"}))
eq('Invalid window id: 1', pcall_err(meths.win_set_cursor, 1, { 'b\na' }))
end)
it('updates the screen, and also when the window is unfocused', function()
local screen = Screen.new(30, 9)
screen:set_default_attr_ids({
[1] = { bold = true, foreground = Screen.colors.Blue },
[2] = {bold = true, reverse = true};
[3] = {reverse = true};
[2] = { bold = true, reverse = true },
[3] = { reverse = true },
})
screen:attach()
insert("prologue")
insert('prologue')
feed('100o<esc>')
insert("epilogue")
insert('epilogue')
local win = curwin()
feed('gg')
screen:expect{grid=[[
screen:expect {
grid = [[
^prologue |
|*8
]]}
]],
}
-- cursor position is at beginning
eq({ 1, 0 }, window('get_cursor', win))
-- move cursor to end
window('set_cursor', win, { 101, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
|*7
^epilogue |
|
]]}
]],
}
-- move cursor to the beginning again
window('set_cursor', win, { 1, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^prologue |
|*8
]]}
]],
}
-- move focus to new window
nvim('command',"new")
nvim('command', 'new')
neq(win, curwin())
-- sanity check, cursor position is kept
eq({ 1, 0 }, window('get_cursor', win))
screen:expect{grid=[[
screen:expect {
grid = [[
^ |
{1:~ }|*2
{2:[No Name] }|
@@ -130,11 +155,13 @@ describe('API/win', function()
|*2
{3:[No Name] [+] }|
|
]]}
]],
}
-- move cursor to end
window('set_cursor', win, { 101, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^ |
{1:~ }|*2
{2:[No Name] }|
@@ -142,11 +169,13 @@ describe('API/win', function()
epilogue |
{3:[No Name] [+] }|
|
]]}
]],
}
-- move cursor to the beginning again
window('set_cursor', win, { 1, 0 })
screen:expect{grid=[[
screen:expect {
grid = [[
^ |
{1:~ }|*2
{2:[No Name] }|
@@ -154,16 +183,17 @@ describe('API/win', function()
|*2
{3:[No Name] [+] }|
|
]]}
]],
}
-- curwin didn't change back
neq(win, curwin())
end)
it('remembers what column it wants to be in', function()
insert("first line")
insert('first line')
feed('o<esc>')
insert("second line")
insert('second line')
feed('gg')
poke_eventloop() -- let nvim process the 'gg' command
@@ -264,12 +294,13 @@ describe('API/win', function()
describe('{get,set}_height', function()
it('works', function()
nvim('command', 'vsplit')
eq(window('get_height', nvim('list_wins')[2]),
window('get_height', nvim('list_wins')[1]))
eq(window('get_height', nvim('list_wins')[2]), window('get_height', nvim('list_wins')[1]))
nvim('set_current_win', nvim('list_wins')[2])
nvim('command', 'split')
eq(window('get_height', nvim('list_wins')[2]),
math.floor(window('get_height', nvim('list_wins')[1]) / 2))
eq(
window('get_height', nvim('list_wins')[2]),
math.floor(window('get_height', nvim('list_wins')[1]) / 2)
)
window('set_height', nvim('list_wins')[2], 2)
eq(2, window('get_height', nvim('list_wins')[2]))
end)
@@ -310,12 +341,13 @@ describe('API/win', function()
describe('{get,set}_width', function()
it('works', function()
nvim('command', 'split')
eq(window('get_width', nvim('list_wins')[2]),
window('get_width', nvim('list_wins')[1]))
eq(window('get_width', nvim('list_wins')[2]), window('get_width', nvim('list_wins')[1]))
nvim('set_current_win', nvim('list_wins')[2])
nvim('command', 'vsplit')
eq(window('get_width', nvim('list_wins')[2]),
math.floor(window('get_width', nvim('list_wins')[1]) / 2))
eq(
window('get_width', nvim('list_wins')[2]),
math.floor(window('get_width', nvim('list_wins')[1]) / 2)
)
window('set_width', nvim('list_wins')[2], 2)
eq(2, window('get_width', nvim('list_wins')[2]))
end)
@@ -372,16 +404,16 @@ describe('API/win', function()
it('works', function()
nvim('set_option_value', 'colorcolumn', '4,3', {})
eq('4,3', nvim('get_option_value', 'colorcolumn', {}))
command("set modified hidden")
command("enew") -- edit new buffer, window option is preserved
command('set modified hidden')
command('enew') -- edit new buffer, window option is preserved
eq('4,3', nvim('get_option_value', 'colorcolumn', {}))
-- global-local option
nvim('set_option_value', 'statusline', 'window-status', { win = 0 })
eq('window-status', nvim('get_option_value', 'statusline', { win = 0 }))
eq('', nvim('get_option_value', 'statusline', { scope = 'global' }))
command("set modified")
command("enew") -- global-local: not preserved in new buffer
command('set modified')
command('enew') -- global-local: not preserved in new buffer
-- confirm local value was not copied
eq('', nvim('get_option_value', 'statusline', { win = 0 }))
eq('', eval('&l:statusline'))
@@ -413,10 +445,8 @@ describe('API/win', function()
eq({ 0, 0 }, window('get_position', nvim('list_wins')[1]))
local vsplit_pos = math.floor(width / 2)
local split_pos = math.floor(height / 2)
local win2row, win2col =
unpack(window('get_position', nvim('list_wins')[2]))
local win3row, win3col =
unpack(window('get_position', nvim('list_wins')[3]))
local win2row, win2col = unpack(window('get_position', nvim('list_wins')[2]))
local win3row, win3col = unpack(window('get_position', nvim('list_wins')[3]))
eq(0, win2row)
eq(0, win3col)
ok(vsplit_pos - 1 <= win2col and win2col <= vsplit_pos + 1)
@@ -428,12 +458,9 @@ describe('API/win', function()
it('works', function()
nvim('command', 'tabnew')
nvim('command', 'vsplit')
eq(window('get_tabpage',
nvim('list_wins')[1]), nvim('list_tabpages')[1])
eq(window('get_tabpage',
nvim('list_wins')[2]), nvim('list_tabpages')[2])
eq(window('get_tabpage',
nvim('list_wins')[3]), nvim('list_tabpages')[2])
eq(window('get_tabpage', nvim('list_wins')[1]), nvim('list_tabpages')[1])
eq(window('get_tabpage', nvim('list_wins')[2]), nvim('list_tabpages')[2])
eq(window('get_tabpage', nvim('list_wins')[3]), nvim('list_tabpages')[2])
end)
end)
@@ -495,8 +522,10 @@ describe('API/win', function()
insert('text')
command('new')
local newwin = meths.get_current_win()
eq("Vim:E37: No write since last change (add ! to override)",
pcall_err(meths.win_close, oldwin,false))
eq(
'Vim:E37: No write since last change (add ! to override)',
pcall_err(meths.win_close, oldwin, false)
)
eq({ newwin, oldwin }, meths.list_wins())
end)
@@ -514,15 +543,21 @@ describe('API/win', function()
eq(2, #meths.list_wins())
local oldwin = meths.get_current_win()
local otherwin = meths.open_win(0, false, {
relative='editor', row=10, col=10, width=10, height=10,
relative = 'editor',
row = 10,
col = 10,
width = 10,
height = 10,
})
-- Open cmdline-window.
feed('q:')
eq(4, #meths.list_wins())
eq(':', funcs.getcmdwintype())
-- Not allowed to close previous window from cmdline-window.
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_close, oldwin, true))
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_close, oldwin, true)
)
-- Closing other windows is fine.
meths.win_close(otherwin, true)
eq(false, meths.win_is_valid(otherwin))
@@ -538,7 +573,11 @@ describe('API/win', function()
local prevwin = curwin().id
eq(2, eval('tabpagenr()'))
local win = meths.open_win(0, true, {
relative='editor', row=10, col=10, width=50, height=10
relative = 'editor',
row = 10,
col = 10,
width = 50,
height = 10,
})
local tab = eval('tabpagenr()')
command('tabprevious')
@@ -570,7 +609,11 @@ describe('API/win', function()
local oldbuf = meths.get_current_buf()
local buf = meths.create_buf(true, false)
local newwin = meths.open_win(buf, true, {
relative='win', row=3, col=3, width=12, height=3
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
})
meths.win_hide(newwin)
eq({ oldwin }, meths.list_wins())
@@ -581,7 +624,11 @@ describe('API/win', function()
local oldbuf = meths.get_current_buf()
local buf = meths.create_buf(true, false).id
local newwin = meths.open_win(buf, true, {
relative='win', row=3, col=3, width=12, height=3
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
})
meths.set_option_value('bufhidden', 'wipe', { buf = buf })
meths.win_hide(newwin)
@@ -596,12 +643,18 @@ describe('API/win', function()
local old_win = meths.get_current_win()
local other_win = meths.open_win(0, false, {
relative='win', row=3, col=3, width=12, height=3
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
})
feed('q:')
-- Cannot close the previous window.
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_hide, old_win))
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.win_hide, old_win)
)
-- Can close other windows.
meths.win_hide(other_win)
eq(false, meths.win_is_valid(other_win))
@@ -617,48 +670,66 @@ describe('API/win', function()
ccc
ddd
eee]])
eq("Invalid window id: 23",
pcall_err(meths.win_text_height, 23, {}))
eq("Line index out of bounds",
pcall_err(curwinmeths.text_height, { start_row = 5 }))
eq("Line index out of bounds",
pcall_err(curwinmeths.text_height, { start_row = -6 }))
eq("Line index out of bounds",
pcall_err(curwinmeths.text_height, { end_row = 5 }))
eq("Line index out of bounds",
pcall_err(curwinmeths.text_height, { end_row = -6 }))
eq("'start_row' is higher than 'end_row'",
pcall_err(curwinmeths.text_height, { start_row = 3, end_row = 1 }))
eq("'start_vcol' specified without 'start_row'",
pcall_err(curwinmeths.text_height, { end_row = 2, start_vcol = 0 }))
eq("'end_vcol' specified without 'end_row'",
pcall_err(curwinmeths.text_height, { start_row = 2, end_vcol = 0 }))
eq("Invalid 'start_vcol': out of range",
pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = -1 }))
eq("Invalid 'start_vcol': out of range",
pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = X + 1 }))
eq("Invalid 'end_vcol': out of range",
pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = -1 }))
eq("Invalid 'end_vcol': out of range",
pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = X + 1 }))
eq("'start_vcol' is higher than 'end_vcol'",
pcall_err(curwinmeths.text_height, { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 }))
eq('Invalid window id: 23', pcall_err(meths.win_text_height, 23, {}))
eq('Line index out of bounds', pcall_err(curwinmeths.text_height, { start_row = 5 }))
eq('Line index out of bounds', pcall_err(curwinmeths.text_height, { start_row = -6 }))
eq('Line index out of bounds', pcall_err(curwinmeths.text_height, { end_row = 5 }))
eq('Line index out of bounds', pcall_err(curwinmeths.text_height, { end_row = -6 }))
eq(
"'start_row' is higher than 'end_row'",
pcall_err(curwinmeths.text_height, { start_row = 3, end_row = 1 })
)
eq(
"'start_vcol' specified without 'start_row'",
pcall_err(curwinmeths.text_height, { end_row = 2, start_vcol = 0 })
)
eq(
"'end_vcol' specified without 'end_row'",
pcall_err(curwinmeths.text_height, { start_row = 2, end_vcol = 0 })
)
eq(
"Invalid 'start_vcol': out of range",
pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = -1 })
)
eq(
"Invalid 'start_vcol': out of range",
pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = X + 1 })
)
eq(
"Invalid 'end_vcol': out of range",
pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = -1 })
)
eq(
"Invalid 'end_vcol': out of range",
pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = X + 1 })
)
eq(
"'start_vcol' is higher than 'end_vcol'",
pcall_err(
curwinmeths.text_height,
{ start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 }
)
)
end)
it('with two diff windows', function()
local X = meths.get_vvar('maxcol')
local screen = Screen.new(45, 22)
screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Blue1, bold = true};
[1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey};
[2] = {foreground = Screen.colors.Brown};
[3] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true};
[4] = {background = Screen.colors.LightBlue};
[5] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey};
[6] = {background = Screen.colors.Plum1};
[7] = {background = Screen.colors.Red, bold = true};
[8] = {reverse = true};
[9] = {bold = true, reverse = true};
[0] = { foreground = Screen.colors.Blue1, bold = true },
[1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Grey },
[2] = { foreground = Screen.colors.Brown },
[3] = {
foreground = Screen.colors.Blue1,
background = Screen.colors.LightCyan1,
bold = true,
},
[4] = { background = Screen.colors.LightBlue },
[5] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey },
[6] = { background = Screen.colors.Plum1 },
[7] = { background = Screen.colors.Red, bold = true },
[8] = { reverse = true },
[9] = { bold = true, reverse = true },
})
screen:attach()
exec([[
@@ -670,7 +741,8 @@ describe('API/win', function()
windo diffthis
]])
feed('24gg')
screen:expect{grid=[[
screen:expect {
grid = [[
{1: }{2: }{3:----------------}│{1: }{2: 1 }{4:00000001! }|
{1: }{2: }{3:----------------}│{1: }{2: 2 }{4:00000002!! }|
{1: }{2: 1 }00000003!!! │{1: }{2: 3 }00000003!!! |
@@ -693,13 +765,16 @@ describe('API/win', function()
{1: }{2: 41 }{4:00000050!!!!!!!!}│{1: }{2: }{3:----------------}|
{8:[No Name] [+] }{9:[No Name] [+] }|
|
]]}
]],
}
screen:try_resize(45, 3)
screen:expect{grid=[[
screen:expect {
grid = [[
{1: }{2: 19 }00000028!!!!!!!!│{1: }{2: 24 }^00000028!!!!!!!!|
{8:[No Name] [+] }{9:[No Name] [+] }|
|
]]}
]],
}
eq({ all = 20, fill = 5 }, meths.win_text_height(1000, {}))
eq({ all = 20, fill = 5 }, meths.win_text_height(1001, {}))
eq({ all = 20, fill = 5 }, meths.win_text_height(1000, { start_row = 0 }))
@@ -724,27 +799,51 @@ describe('API/win', function()
eq({ all = 7, fill = 3 }, meths.win_text_height(1001, { start_row = 16, end_row = 19 }))
eq({ all = 6, fill = 5 }, meths.win_text_height(1000, { start_row = -1 }))
eq({ all = 5, fill = 5 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X }))
eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 }))
eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X }))
eq({ all = 1, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X }))
eq(
{ all = 0, fill = 0 },
meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 })
)
eq(
{ all = 0, fill = 0 },
meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(1000, { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X })
)
eq({ all = 3, fill = 2 }, meths.win_text_height(1001, { end_row = 0 }))
eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { end_row = 0, end_vcol = 0 }))
eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 }))
eq({ all = 0, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 }))
eq({ all = 1, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X }))
eq(
{ all = 2, fill = 2 },
meths.win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 })
)
eq(
{ all = 0, fill = 0 },
meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X })
)
eq({ all = 11, fill = 5 }, meths.win_text_height(1001, { end_row = 18 }))
eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 }))
eq(
{ all = 9, fill = 3 },
meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 })
)
eq({ all = 10, fill = 5 }, meths.win_text_height(1001, { end_row = 18, end_vcol = 0 }))
eq({ all = 8, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 }))
eq(
{ all = 8, fill = 3 },
meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 })
)
end)
it('with wrapped lines', function()
local X = meths.get_vvar('maxcol')
local screen = Screen.new(45, 22)
screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Blue1, bold = true};
[1] = {foreground = Screen.colors.Brown};
[2] = {background = Screen.colors.Yellow};
[0] = { foreground = Screen.colors.Blue1, bold = true },
[1] = { foreground = Screen.colors.Brown },
[2] = { background = Screen.colors.Yellow },
})
screen:attach()
exec([[
@@ -752,9 +851,22 @@ describe('API/win', function()
call setline(1, repeat([repeat('foobar-', 36)], 3))
]])
local ns = meths.create_namespace('')
meths.buf_set_extmark(0, ns, 1, 100, { virt_text = {{('?'):rep(15), 'Search'}}, virt_text_pos = 'inline' })
meths.buf_set_extmark(0, ns, 2, 200, { virt_text = {{('!'):rep(75), 'Search'}}, virt_text_pos = 'inline' })
screen:expect{grid=[[
meths.buf_set_extmark(
0,
ns,
1,
100,
{ virt_text = { { ('?'):rep(15), 'Search' } }, virt_text_pos = 'inline' }
)
meths.buf_set_extmark(
0,
ns,
2,
200,
{ virt_text = { { ('!'):rep(75), 'Search' } }, virt_text_pos = 'inline' }
)
screen:expect {
grid = [[
{1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar|
-foobar-foobar-foobar-foobar-foobar-foobar-fo|
obar-foobar-foobar-foobar-foobar-foobar-fooba|
@@ -777,48 +889,123 @@ describe('API/win', function()
{2:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba|
r-foobar-foobar- |
|
]]}
]],
}
screen:try_resize(45, 2)
screen:expect{grid=[[
screen:expect {
grid = [[
{1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar|
|
]]}
]],
}
eq({ all = 21, fill = 0 }, meths.win_text_height(0, {}))
eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 0, end_row = 0 }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, end_row = 1 }))
eq({ all = 8, fill = 0 }, meths.win_text_height(0, { start_row = 2, end_row = 2 }))
eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 }))
eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 }))
eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 }))
eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 }))
eq({ all = 3, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 }))
eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X }))
eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X }))
eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X }))
eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X }))
eq({ all = 5, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X }))
eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X }))
eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X }))
eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X }))
eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X }))
eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 }))
eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 }))
eq(
{ all = 0, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 })
)
eq(
{ all = 2, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 })
)
eq(
{ all = 2, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 })
)
eq(
{ all = 3, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 })
)
eq(
{ all = 6, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 })
)
eq(
{ all = 7, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 })
)
eq(
{ all = 7, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 })
)
eq(
{ all = 7, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 })
)
eq(
{ all = 7, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X })
)
eq(
{ all = 7, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X })
)
eq(
{ all = 6, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X })
)
eq(
{ all = 6, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X })
)
eq(
{ all = 5, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X })
)
eq(
{ all = 2, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X })
)
eq(
{ all = 0, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 })
)
eq(
{ all = 1, fill = 0 },
meths.win_text_height(0, { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 })
)
eq({ all = 18, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131 }))
eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130 }))
eq({ all = 20, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 311 }))
eq({ all = 21, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 312 }))
eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 }))
eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 }))
eq(
{ all = 17, fill = 0 },
meths.win_text_height(0, { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 })
)
eq(
{ all = 19, fill = 0 },
meths.win_text_height(0, { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 })
)
eq({ all = 16, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221 }))
eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220 }))
eq({ all = 14, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 41 }))
eq({ all = 15, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 42 }))
eq({ all = 9, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 }))
eq({ all = 11, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 }))
eq(
{ all = 9, fill = 0 },
meths.win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 })
)
eq(
{ all = 11, fill = 0 },
meths.win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 })
)
end)
end)
@@ -826,11 +1013,20 @@ describe('API/win', function()
it('noautocmd option works', function()
command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1')
meths.open_win(meths.create_buf(true, true), true, {
relative='win', row=3, col=3, width=12, height=3, noautocmd=true
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
noautocmd = true,
})
eq(0, funcs.exists('g:fired'))
meths.open_win(meths.create_buf(true, true), true, {
relative='win', row=3, col=3, width=12, height=3
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
})
eq(1, funcs.exists('g:fired'))
end)
@@ -838,25 +1034,51 @@ describe('API/win', function()
it('disallowed in cmdwin if enter=true or buf=curbuf', function()
local new_buf = meths.create_buf(true, true)
feed('q:')
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.open_win, new_buf, true, {
relative='editor', row=5, col=5, width=5, height=5,
}))
eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
relative = 'editor',
row = 5,
col = 5,
width = 5,
height = 5,
})
)
eq(
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
pcall_err(meths.open_win, 0, false, {
relative='editor', row=5, col=5, width=5, height=5,
}))
relative = 'editor',
row = 5,
col = 5,
width = 5,
height = 5,
})
)
eq(new_buf, meths.win_get_buf(meths.open_win(new_buf, false, {
relative='editor', row=5, col=5, width=5, height=5,
})))
eq(
new_buf,
meths.win_get_buf(meths.open_win(new_buf, false, {
relative = 'editor',
row = 5,
col = 5,
width = 5,
height = 5,
}))
)
end)
it('aborts if buffer is invalid', function()
local wins_before = meths.list_wins()
eq('Invalid buffer id: 1337', pcall_err(meths.open_win, 1337, false, {
relative='editor', row=5, col=5, width=5, height=5,
}))
eq(
'Invalid buffer id: 1337',
pcall_err(meths.open_win, 1337, false, {
relative = 'editor',
row = 5,
col = 5,
width = 5,
height = 5,
})
)
eq(wins_before, meths.list_wins())
end)
end)
@@ -865,7 +1087,11 @@ describe('API/win', function()
it('includes border', function()
local b = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }
local win = meths.open_win(0, true, {
relative='win', row=3, col=3, width=12, height=3,
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
border = b,
})
@@ -885,7 +1111,11 @@ describe('API/win', function()
{ 'h', 'PreProc' },
}
local win = meths.open_win(0, true, {
relative='win', row=3, col=3, width=12, height=3,
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
border = b,
})
@@ -897,8 +1127,14 @@ describe('API/win', function()
local title = { { 'A', { 'StatusLine', 'TabLine' } }, { 'B' }, { 'C', 'WinBar' } }
local footer = { { 'A', 'WinBar' }, { 'B' }, { 'C', { 'StatusLine', 'TabLine' } } }
local win = meths.open_win(0, true, {
relative='win', row=3, col=3, width=12, height=3,
border = 'single', title = title, footer = footer,
relative = 'win',
row = 3,
col = 3,
width = 12,
height = 3,
border = 'single',
title = title,
footer = footer,
})
local cfg = meths.win_get_config(win)
@@ -912,15 +1148,17 @@ describe('API/win', function()
local win = meths.open_win(0, true, {
width = 10,
height = 10,
relative = "editor",
relative = 'editor',
row = 10,
col = 10,
title = { { "test" } },
border = "single",
title = { { 'test' } },
border = 'single',
})
eq("title/footer cannot be an empty array",
pcall_err(meths.win_set_config, win, {title = {}}))
command("redraw!")
eq(
'title/footer cannot be an empty array',
pcall_err(meths.win_set_config, win, { title = {} })
)
command('redraw!')
assert_alive()
end)
@@ -928,15 +1166,17 @@ describe('API/win', function()
local win = meths.open_win(0, true, {
width = 10,
height = 10,
relative = "editor",
relative = 'editor',
row = 10,
col = 10,
footer = { { "test" } },
border = "single",
footer = { { 'test' } },
border = 'single',
})
eq("title/footer cannot be an empty array",
pcall_err(meths.win_set_config, win, {footer = {}}))
command("redraw!")
eq(
'title/footer cannot be an empty array',
pcall_err(meths.win_set_config, win, { footer = {} })
)
command('redraw!')
assert_alive()
end)
end)

View File

@@ -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 ]]
@@ -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)

View File

@@ -106,9 +106,12 @@ 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)
@@ -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()
@@ -252,7 +262,11 @@ describe('autocmd', function()
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},
[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,11 +334,13 @@ 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 {
@@ -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'))
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,32 +429,56 @@ 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()
@@ -440,18 +489,22 @@ describe('autocmd', function()
})
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()
@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)")
@@ -26,8 +26,10 @@ describe('cmdline autocommands', function()
feed(':')
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())
@@ -35,12 +37,14 @@ describe('cmdline autocommands', function()
-- 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
@@ -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: }|
: |
@@ -169,11 +173,17 @@ describe('cmdline autocommands', function()
feed(':')
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())
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()
@@ -181,42 +191,71 @@ describe('cmdline autocommands', function()
feed(':')
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())")
command(
"autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())"
)
feed(':')
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())
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)

View File

@@ -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()

View File

@@ -47,7 +47,7 @@ describe('CursorMoved', function()
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

View File

@@ -21,17 +21,31 @@ 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)
@@ -91,7 +105,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status1, err1 = pcall(function()
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'))
@@ -100,7 +117,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status2, err2 = pcall(function()
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'))
@@ -109,7 +129,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status3, err3 = pcall(function()
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,9 +142,9 @@ 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()
@@ -238,7 +261,7 @@ describe('autocmd DirChanged and DirChangedPre', function()
end
end)
it("are triggered by switching to win/tab with different CWD #6054", function()
it('are triggered by switching to win/tab with different CWD #6054', function()
command('lcd ' .. dirs[3]) -- window 3
command('split ' .. dirs[2] .. '/foo') -- window 2
command('lcd ' .. dirs[2])

View File

@@ -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)

View File

@@ -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=[[
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)

View File

@@ -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'))

View File

@@ -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()

View File

@@ -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' })
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,7 +36,8 @@ 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()
@@ -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)

View File

@@ -8,7 +8,9 @@ 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')

View File

@@ -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('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('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('tabclosed:2:2:1', nvim('exec', 'close', true))
eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
end)
end)
end)
end)

View File

@@ -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]

View File

@@ -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')
@@ -172,7 +203,9 @@ 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()

View File

@@ -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,7 +66,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '',
regtype = 'V',
visual = false
visual = false,
}, eval('g:event'))
command('set debug=msg')
@@ -97,7 +97,7 @@ 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))
@@ -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)

View File

@@ -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)

View File

@@ -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,9 +52,8 @@ 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)
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())
@@ -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())
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)

View File

@@ -59,7 +59,12 @@ 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

View File

@@ -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,7 +50,7 @@ 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 {}
@@ -61,15 +60,15 @@ describe('fileio', function()
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):
@@ -102,12 +101,17 @@ describe('fileio', function()
-- 4. Exit caused by deadly signal (+ 'swapfile').
local j = funcs.jobstart(vim.tbl_flatten({ args, '--embed' }), { rpc = true })
funcs.rpcrequest(j, 'nvim_exec2', [[
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.
@@ -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 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 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)
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}
[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={
clear({
env = {
NVIM_APPNAME = 'a/b',
NVIM_LOG_FILE = testlog,
TMPDIR = os_tmpdir,
} })
},
})
matches([=[.*[/\\]a%%b%.[^/\\]+]=], funcs.tempname())
end)
end)

View File

@@ -1,11 +1,22 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim,
testprg, ok, source, write_file, mkdir, rmdir = helpers.clear,
helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed,
helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
helpers.testprg, helpers.ok, helpers.source,
helpers.write_file, helpers.mkdir, helpers.rmdir
local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim, testprg, ok, source, write_file, mkdir, rmdir =
helpers.clear,
helpers.eq,
helpers.eval,
helpers.exc_exec,
helpers.feed_command,
helpers.feed,
helpers.insert,
helpers.neq,
helpers.next_msg,
helpers.nvim,
helpers.testprg,
helpers.ok,
helpers.source,
helpers.write_file,
helpers.mkdir,
helpers.rmdir
local assert_alive = helpers.assert_alive
local command = helpers.command
local funcs = helpers.funcs
@@ -55,7 +66,7 @@ describe('jobs', function()
end)
it('must specify env option as a dict', function()
command("let g:job_opts.env = v:true")
command('let g:job_opts.env = v:true')
local _, err = pcall(function()
if is_os('win') then
nvim('command', "let j = jobstart('set', g:job_opts)")
@@ -63,7 +74,7 @@ describe('jobs', function()
nvim('command', "let j = jobstart('env', g:job_opts)")
end
end)
ok(string.find(err, "E475: Invalid argument: env") ~= nil)
ok(string.find(err, 'E475: Invalid argument: env') ~= nil)
end)
it('append environment #env', function()
@@ -76,45 +87,39 @@ describe('jobs', function()
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
expect_msg_seq(
{
expect_msg_seq({
{ 'notification', 'stdout', { 0, { 'hello world abc' } } },
{ 'notification', 'stdout', { 0, { '', '' } } },
},
{
}, {
{ 'notification', 'stdout', { 0, { 'hello world abc', '' } } },
{'notification', 'stdout', {0, {''}}}
}
)
{ 'notification', 'stdout', { 0, { '' } } },
})
end)
it('append environment with pty #env', function()
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.pty = v:true")
nvim('command', 'let g:job_opts.pty = v:true')
nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
if is_os('win') then
nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
else
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
expect_msg_seq(
{
expect_msg_seq({
{ 'notification', 'stdout', { 0, { 'hello world abc' } } },
{ 'notification', 'stdout', { 0, { '', '' } } },
},
{
}, {
{ 'notification', 'stdout', { 0, { 'hello world abc', '' } } },
{'notification', 'stdout', {0, {''}}}
}
)
{ 'notification', 'stdout', { 0, { '' } } },
})
end)
it('replace environment #env', function()
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
nvim('command', "let g:job_opts.clear_env = 1")
nvim('command', 'let g:job_opts.clear_env = 1')
-- libuv ensures that certain "required" environment variables are
-- preserved if the user doesn't provide them in a custom environment
@@ -126,13 +131,13 @@ describe('jobs', function()
if is_os('win') then
nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
expect_msg_seq({
{'notification', 'stdout', {0, {'hello world %VAR%', ''}}}
{ 'notification', 'stdout', { 0, { 'hello world %VAR%', '' } } },
})
else
nvim('command', "set shell=/bin/sh")
nvim('command', 'set shell=/bin/sh')
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
expect_msg_seq({
{'notification', 'stdout', {0, {'hello world', ''}}}
{ 'notification', 'stdout', { 0, { 'hello world', '' } } },
})
end
end)
@@ -147,8 +152,8 @@ describe('jobs', function()
else
nvim('command', [[let j = jobstart('env | grep -i toto=', g:job_opts)]])
end
nvim('command', "call jobwait([j])")
nvim('command', "let g:output = Normalize(g:job_opts.stdout)")
nvim('command', 'call jobwait([j])')
nvim('command', 'let g:output = Normalize(g:job_opts.stdout)')
local actual = eval('g:output')
local expected
if is_os('win') then
@@ -182,14 +187,13 @@ describe('jobs', function()
else
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
eq({'notification', 'stdout',
{0, {pathroot(), ''}}}, next_msg())
eq({ 'notification', 'stdout', { 0, { pathroot(), '' } } }, next_msg())
eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
it('changes to given `cwd` directory', function()
local dir = eval("resolve(tempname())"):gsub("/", get_pathsep())
local dir = eval('resolve(tempname())'):gsub('/', get_pathsep())
mkdir(dir)
nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
if is_os('win') then
@@ -198,15 +202,17 @@ describe('jobs', function()
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
expect_msg_seq(
{ {'notification', 'stdout', {0, {dir, ''} } },
{
{ 'notification', 'stdout', { 0, { dir, '' } } },
{ 'notification', 'stdout', { 0, { '' } } },
{'notification', 'exit', {0, 0} }
{ 'notification', 'exit', { 0, 0 } },
},
-- Alternative sequence:
{ {'notification', 'stdout', {0, {dir} } },
{
{ 'notification', 'stdout', { 0, { dir } } },
{ 'notification', 'stdout', { 0, { '', '' } } },
{ 'notification', 'stdout', { 0, { '' } } },
{'notification', 'exit', {0, 0} }
{ 'notification', 'exit', { 0, 0 } },
}
)
rmdir(dir)
@@ -222,7 +228,7 @@ describe('jobs', function()
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
end)
ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil)
ok(string.find(err, 'E475: Invalid argument: expected valid directory$') ~= nil)
end)
it('error on non-executable `cwd`', function()
@@ -231,16 +237,18 @@ describe('jobs', function()
local dir = 'Xtest_not_executable_dir'
mkdir(dir)
funcs.setfperm(dir, 'rw-------')
matches('^Vim%(call%):E903: Process failed to start: permission denied: .*',
pcall_err(nvim, 'command', "call jobstart(['pwd'], {'cwd': '"..dir.."'})"))
matches(
'^Vim%(call%):E903: Process failed to start: permission denied: .*',
pcall_err(nvim, 'command', "call jobstart(['pwd'], {'cwd': '" .. dir .. "'})")
)
rmdir(dir)
end)
it('returns 0 when it fails to start', function()
eq("", eval("v:errmsg"))
feed_command("let g:test_jobid = jobstart([])")
eq(0, eval("g:test_jobid"))
eq("E474:", string.match(eval("v:errmsg"), "E%d*:"))
eq('', eval('v:errmsg'))
feed_command('let g:test_jobid = jobstart([])')
eq(0, eval('g:test_jobid'))
eq('E474:', string.match(eval('v:errmsg'), 'E%d*:'))
end)
it('returns -1 when target is not executable #5465', function()
@@ -249,10 +257,13 @@ describe('jobs', function()
end
local executable_jobid = new_job()
local exe = is_os('win') and './test/functional/fixtures' or './test/functional/fixtures/non_executable.txt'
eq("Vim:E475: Invalid value for argument cmd: '"..exe.."' is not executable",
pcall_err(eval, "jobstart(['"..exe.."'])"))
eq("", eval("v:errmsg"))
local exe = is_os('win') and './test/functional/fixtures'
or './test/functional/fixtures/non_executable.txt'
eq(
"Vim:E475: Invalid value for argument cmd: '" .. exe .. "' is not executable",
pcall_err(eval, "jobstart(['" .. exe .. "'])")
)
eq('', eval('v:errmsg'))
-- Non-executable job should not increment the job ids. #5465
eq(executable_jobid + 1, new_job())
end)
@@ -260,9 +271,10 @@ describe('jobs', function()
it('invokes callbacks when the job writes and exits', function()
nvim('command', "let g:job_opts.on_stderr = function('OnEvent')")
nvim('command', [[call jobstart(has('win32') ? 'echo:' : 'echo', g:job_opts)]])
expect_twostreams({{'notification', 'stdout', {0, {'', ''}}},
{'notification', 'stdout', {0, {''}}}},
{{'notification', 'stderr', {0, {''}}}})
expect_twostreams({
{ 'notification', 'stdout', { 0, { '', '' } } },
{ 'notification', 'stdout', { 0, { '' } } },
}, { { 'notification', 'stderr', { 0, { '' } } } })
eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
@@ -273,23 +285,23 @@ describe('jobs', function()
eq({ 'notification', 'stdout', { 0, { 'abc', '' } } }, next_msg())
nvim('command', 'call jobsend(j, "123\\nxyz\\n")')
expect_msg_seq(
{ {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
},
{ { 'notification', 'stdout', { 0, { '123', 'xyz', '' } } } },
-- Alternative sequence:
{ {'notification', 'stdout', {0, {'123', ''}}},
{'notification', 'stdout', {0, {'xyz', ''}}}
{
{ 'notification', 'stdout', { 0, { '123', '' } } },
{ 'notification', 'stdout', { 0, { 'xyz', '' } } },
}
)
nvim('command', 'call jobsend(j, [123, "xyz", ""])')
expect_msg_seq(
{ {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
},
{ { 'notification', 'stdout', { 0, { '123', 'xyz', '' } } } },
-- Alternative sequence:
{ {'notification', 'stdout', {0, {'123', ''}}},
{'notification', 'stdout', {0, {'xyz', ''}}}
{
{ 'notification', 'stdout', { 0, { '123', '' } } },
{ 'notification', 'stdout', { 0, { 'xyz', '' } } },
}
)
nvim('command', "call jobstop(j)")
nvim('command', 'call jobstop(j)')
eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
@@ -297,7 +309,7 @@ describe('jobs', function()
it('preserves NULs', function()
-- Make a file with NULs in it.
local filename = helpers.tmpname()
write_file(filename, "abc\0def\n")
write_file(filename, 'abc\0def\n')
nvim('command', "let j = jobstart(['cat', '" .. filename .. "'], g:job_opts)")
eq({ 'notification', 'stdout', { 0, { 'abc\ndef', '' } } }, next_msg())
@@ -309,14 +321,14 @@ describe('jobs', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', [[call jobsend(j, ["123\n456",""])]])
eq({ 'notification', 'stdout', { 0, { '123\n456', '' } } }, next_msg())
nvim('command', "call jobstop(j)")
nvim('command', 'call jobstop(j)')
end)
it("emits partial lines (does NOT buffer data lacking newlines)", function()
it('emits partial lines (does NOT buffer data lacking newlines)', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "abc\\nxyz")')
eq({ 'notification', 'stdout', { 0, { 'abc', 'xyz' } } }, next_msg())
nvim('command', "call jobstop(j)")
nvim('command', 'call jobstop(j)')
eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
@@ -324,16 +336,14 @@ describe('jobs', function()
it('preserves newlines', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")')
eq({'notification', 'stdout',
{0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg())
eq({ 'notification', 'stdout', { 0, { 'a', '', 'c', '', '', '', 'b', '', '' } } }, next_msg())
end)
it('preserves NULs', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])')
eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}},
next_msg())
nvim('command', "call jobstop(j)")
eq({ 'notification', 'stdout', { 0, { '\n123\n', 'abc\nxyz\n', '' } } }, next_msg())
nvim('command', 'call jobstop(j)')
eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
@@ -341,9 +351,8 @@ describe('jobs', function()
it('avoids sending final newline', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["some data", "without\nfinal nl"])')
eq({'notification', 'stdout', {0, {'some data', 'without\nfinal nl'}}},
next_msg())
nvim('command', "call jobstop(j)")
eq({ 'notification', 'stdout', { 0, { 'some data', 'without\nfinal nl' } } }, next_msg())
nvim('command', 'call jobstop(j)')
eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
@@ -355,18 +364,24 @@ describe('jobs', function()
eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
it("disallows jobsend on a job that closed stdin", function()
it('disallows jobsend on a job that closed stdin', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobclose(j, "stdin")')
eq(false, pcall(function()
eq(
false,
pcall(function()
nvim('command', 'call jobsend(j, ["some data"])')
end))
end)
)
command("let g:job_opts.stdin = 'null'")
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
eq(false, pcall(function()
eq(
false,
pcall(function()
nvim('command', 'call jobsend(j, ["some data"])')
end))
end)
)
end)
it('disallows jobsend on a non-existent job', function()
@@ -377,8 +392,8 @@ describe('jobs', function()
it('jobstop twice on the stopped or exited job return 0', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
neq(0, eval('j'))
eq(1, eval("jobstop(j)"))
eq(0, eval("jobstop(j)"))
eq(1, eval('jobstop(j)'))
eq(0, eval('jobstop(j)'))
end)
it('will not leak memory if we leave a job running', function()
@@ -395,9 +410,12 @@ describe('jobs', function()
eq(NIL, meths.get_proc(pid))
end)
it("disposed on Nvim exit", function()
it('disposed on Nvim exit', function()
-- use sleep, which doesn't die on stdin close
nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
nvim(
'command',
"let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)"
)
local pid = eval('jobpid(g:j)')
neq(NIL, meths.get_proc(pid))
clear()
@@ -406,7 +424,10 @@ describe('jobs', function()
it('can survive the exit of nvim with "detach"', function()
nvim('command', 'let g:job_opts.detach = 1')
nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
nvim(
'command',
"let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)"
)
local pid = eval('jobpid(g:j)')
neq(NIL, meths.get_proc(pid))
clear()
@@ -420,11 +441,13 @@ describe('jobs', function()
nvim('command', [[call jobstart('echo foo', g:job_opts)]])
local data = { n = 5, s = 'str', l = { 1 } }
expect_msg_seq(
{ {'notification', 'stdout', {data, {'foo', ''}}},
{
{ 'notification', 'stdout', { data, { 'foo', '' } } },
{ 'notification', 'stdout', { data, { '' } } },
},
-- Alternative sequence:
{ {'notification', 'stdout', {data, {'foo'}}},
{
{ 'notification', 'stdout', { data, { 'foo' } } },
{ 'notification', 'stdout', { data, { '', '' } } },
{ 'notification', 'stdout', { data, { '' } } },
}
@@ -444,11 +467,13 @@ describe('jobs', function()
nvim('command', 'let g:job_opts.user = 5')
nvim('command', [[call jobstart('echo foo', g:job_opts)]])
expect_msg_seq(
{ {'notification', 'stdout', {5, {'foo', ''} } },
{
{ 'notification', 'stdout', { 5, { 'foo', '' } } },
{ 'notification', 'stdout', { 5, { '' } } },
},
-- Alternative sequence:
{ {'notification', 'stdout', {5, {'foo'} } },
{
{ 'notification', 'stdout', { 5, { 'foo' } } },
{ 'notification', 'stdout', { 5, { '', '' } } },
{ 'notification', 'stdout', { 5, { '' } } },
}
@@ -496,7 +521,7 @@ describe('jobs', function()
endfunction
]])
eq("", eval("v:errmsg"))
eq('', eval('v:errmsg'))
end)
it('requires funcrefs for script-local (s:) functions', function()
@@ -505,7 +530,7 @@ describe('jobs', function()
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}
[3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
-- Pass job callback names _without_ `function(...)`.
@@ -520,7 +545,7 @@ describe('jobs', function()
\ })
]])
screen:expect{any="{2:E120: Using <SID> not in a script context: s:OnEvent}"}
screen:expect { any = '{2:E120: Using <SID> not in a script context: s:OnEvent}' }
end)
it('does not repeat output with slow output handlers', function()
@@ -619,10 +644,10 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
},
{ { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
{ {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
{
{ 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
{ 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
@@ -639,10 +664,10 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
},
{ { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
{ {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
{
{ 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
{ 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
@@ -654,10 +679,10 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
},
{ { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
{ {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
{
{ 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
{ 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
@@ -665,7 +690,8 @@ describe('jobs', function()
it('jobstart() environment: $NVIM, $NVIM_LISTEN_ADDRESS #11009', function()
local function get_env_in_child_job(envname, env)
return exec_lua([[
return exec_lua(
[[
local envname, env = ...
local join = function(s) return vim.fn.join(s, '') end
local stdout = {}
@@ -682,7 +708,8 @@ describe('jobs', function()
return join({ join(stdout), join(stderr) })
]],
envname,
env)
env
)
end
local addr = eval('v:servername')
@@ -693,11 +720,15 @@ describe('jobs', function()
eq('NVIM=' .. addr, get_env_in_child_job('NVIM'))
-- $NVIM_LISTEN_ADDRESS is unset by server_init in the child.
eq('NVIM_LISTEN_ADDRESS=v:null', get_env_in_child_job('NVIM_LISTEN_ADDRESS'))
eq('NVIM_LISTEN_ADDRESS=v:null', get_env_in_child_job('NVIM_LISTEN_ADDRESS',
{ NVIM_LISTEN_ADDRESS='Xtest_jobstart_env' }))
eq(
'NVIM_LISTEN_ADDRESS=v:null',
get_env_in_child_job('NVIM_LISTEN_ADDRESS', { NVIM_LISTEN_ADDRESS = 'Xtest_jobstart_env' })
)
-- User can explicitly set $NVIM_LOG_FILE, $VIM, $VIMRUNTIME.
eq('NVIM_LOG_FILE=Xtest_jobstart_env',
get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE='Xtest_jobstart_env' }))
eq(
'NVIM_LOG_FILE=Xtest_jobstart_env',
get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE = 'Xtest_jobstart_env' })
)
os.remove('Xtest_jobstart_env')
end)
@@ -752,8 +783,7 @@ describe('jobs', function()
\ ])
call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits))
]])
eq({'notification', 'wait',
{{3,4,5,6}, {3,4,5,6}}}, next_msg())
eq({ 'notification', 'wait', { { 3, 4, 5, 6 }, { 3, 4, 5, 6 } } }, next_msg())
end)
it('will return status codes in the order of passed ids', function()
@@ -784,22 +814,26 @@ describe('jobs', function()
end)
it('will return -2 when interrupted without timeout', function()
feed_command('call rpcnotify(g:channel, "ready") | '..
'call rpcnotify(g:channel, "wait", '..
'jobwait([jobstart("'..
(is_os('win') and 'Start-Sleep 10' or 'sleep 10')..
'; exit 55")]))')
feed_command(
'call rpcnotify(g:channel, "ready") | '
.. 'call rpcnotify(g:channel, "wait", '
.. 'jobwait([jobstart("'
.. (is_os('win') and 'Start-Sleep 10' or 'sleep 10')
.. '; exit 55")]))'
)
eq({ 'notification', 'ready', {} }, next_msg())
feed('<c-c>')
eq({ 'notification', 'wait', { { -2 } } }, next_msg())
end)
it('will return -2 when interrupted with timeout', function()
feed_command('call rpcnotify(g:channel, "ready") | '..
'call rpcnotify(g:channel, "wait", '..
'jobwait([jobstart("'..
(is_os('win') and 'Start-Sleep 10' or 'sleep 10')..
'; exit 55")], 10000))')
feed_command(
'call rpcnotify(g:channel, "ready") | '
.. 'call rpcnotify(g:channel, "wait", '
.. 'jobwait([jobstart("'
.. (is_os('win') and 'Start-Sleep 10' or 'sleep 10')
.. '; exit 55")], 10000))'
)
eq({ 'notification', 'ready', {} }, next_msg())
feed('<c-c>')
eq({ 'notification', 'wait', { { -2 } } }, next_msg())
@@ -879,9 +913,9 @@ describe('jobs', function()
it('hides cursor and flushes messages before blocking', function()
local screen = Screen.new(50, 6)
screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Blue, bold = true}; -- NonText
[1] = {bold = true, reverse = true}; -- MsgSeparator
[2] = {bold = true, foreground = Screen.colors.SeaGreen}; -- MoreMsg
[0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
[1] = { bold = true, reverse = true }, -- MsgSeparator
[2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
command([[let g:id = jobstart([v:progpath, '--clean', '--headless'])]])
@@ -893,21 +927,26 @@ describe('jobs', function()
endfunc
]])
feed_command('call PrintAndWait()')
screen:expect{grid=[[
screen:expect {
grid = [[
|
{0:~ }|*2
{1: }|
aaa |
bbb |
]], timeout=100}
screen:expect{grid=[[
]],
timeout = 100,
}
screen:expect {
grid = [[
|
{1: }|
aaa |
bbb |
ccc |
{2:Press ENTER or type command to continue}^ |
]]}
]],
}
feed('<CR>')
funcs.jobstop(meths.get_var('id'))
end)
@@ -919,17 +958,20 @@ describe('jobs', function()
nvim('eval', 'jobsend(j, "abcdef")')
nvim('eval', 'jobstop(j)')
expect_msg_seq(
{ {'notification', 'stdout', {0, {'abcdef'}}},
{
{ 'notification', 'stdout', { 0, { 'abcdef' } } },
{ 'notification', 'stdout', { 0, { '' } } },
{ 'notification', 'stderr', { 0, { '' } } },
},
-- Alternative sequence:
{ {'notification', 'stderr', {0, {''}}},
{
{ 'notification', 'stderr', { 0, { '' } } },
{ 'notification', 'stdout', { 0, { 'abcdef' } } },
{ 'notification', 'stdout', { 0, { '' } } },
},
-- Alternative sequence:
{ {'notification', 'stdout', {0, {'abcdef'}}},
{
{ 'notification', 'stdout', { 0, { 'abcdef' } } },
{ 'notification', 'stderr', { 0, { '' } } },
{ 'notification', 'stdout', { 0, { '' } } },
}
@@ -938,10 +980,13 @@ describe('jobs', function()
end)
it('cannot have both rpc and pty options', function()
command("let g:job_opts.pty = v:true")
command("let g:job_opts.rpc = v:true")
command('let g:job_opts.pty = v:true')
command('let g:job_opts.rpc = v:true')
local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)")
ok(string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set") ~= nil)
ok(
string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set")
~= nil
)
end)
it('does not crash when repeatedly failing to start shell', function()
@@ -954,7 +999,7 @@ describe('jobs', function()
]])
-- The crash only triggered if both jobs are cleaned up on the same event
-- loop tick. This is also prevented by try-block, so feed must be used.
feed_command("call DoIt()")
feed_command('call DoIt()')
feed('<cr>') -- press RETURN
assert_alive()
end)
@@ -1015,9 +1060,7 @@ describe('jobs', function()
endfunction
]])
end
local sleep_cmd = (is_os('win')
and 'ping -n 31 127.0.0.1'
or 'sleep 30')
local sleep_cmd = (is_os('win') and 'ping -n 31 127.0.0.1' or 'sleep 30')
local j = eval("jobstart('" .. sleep_cmd .. ' | ' .. sleep_cmd .. ' | ' .. sleep_cmd .. "')")
local ppid = funcs.jobpid(j)
local children
@@ -1063,7 +1106,9 @@ describe('jobs', function()
end)
describe('running tty-test program', function()
if skip(is_os('win')) then return end
if skip(is_os('win')) then
return
end
local function next_chunk()
local rv
while true do
@@ -1097,7 +1142,7 @@ describe('jobs', function()
insert(testprg('tty-test'))
nvim('command', 'let g:job_opts.pty = 1')
nvim('command', 'let exec = [expand("<cfile>:p")]')
nvim('command', "let j = jobstart(exec, g:job_opts)")
nvim('command', 'let j = jobstart(exec, g:job_opts)')
j = eval 'j'
eq('tty ready', next_chunk())
end)
@@ -1144,19 +1189,25 @@ describe('jobs', function()
it('does not close the same handle twice on exit #25086', function()
local filename = string.format('%s.lua', helpers.tmpname())
write_file(filename, [[
write_file(
filename,
[[
vim.api.nvim_create_autocmd('VimLeavePre', {
callback = function()
local id = vim.fn.jobstart('sleep 0')
vim.fn.jobwait({id})
end,
})
]])
]]
)
local screen = thelpers.setup_child_nvim({
'--cmd', 'set notermguicolors',
'-i', 'NONE',
'-u', filename,
'--cmd',
'set notermguicolors',
'-i',
'NONE',
'-u',
filename,
})
-- Wait for startup to complete, so that all terminal responses are received.
screen:expect([[
@@ -1177,7 +1228,7 @@ describe('jobs', function()
end)
end)
describe("pty process teardown", function()
describe('pty process teardown', function()
local screen
before_each(function()
clear()
@@ -1190,14 +1241,22 @@ describe("pty process teardown", function()
]])
end)
it("does not prevent/delay exit. #4798 #4900", function()
it('does not prevent/delay exit. #4798 #4900', function()
skip(is_os('win'))
-- Use a nested nvim (in :term) to test without --headless.
funcs.termopen({
helpers.nvim_prog, '-u', 'NONE', '-i', "NONE", '--cmd', nvim_set,
helpers.nvim_prog,
'-u',
'NONE',
'-i',
'NONE',
'--cmd',
nvim_set,
-- Use :term again in the _nested_ nvim to get a PTY process.
-- Use `sleep` to simulate a long-running child of the PTY.
'+terminal', '+!(sleep 300 &)', '+qa',
'+terminal',
'+!(sleep 300 &)',
'+qa',
}, { env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } })
-- Exiting should terminate all descendants (PTY, its children, ...).

View File

@@ -32,11 +32,13 @@ 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={
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)

View File

@@ -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([[
|
@@ -102,11 +128,21 @@ 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}))
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)
@@ -115,11 +151,24 @@ describe('command-line option', function()
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}))
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)

View File

@@ -67,10 +67,10 @@ 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)
@@ -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'

View File

@@ -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)

View File

@@ -25,6 +25,7 @@ describe('spellfile', function()
local spellheader = 'VIMspell\050'
it('errors out when prefcond section is truncated', function()
meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -35,11 +36,11 @@ describe('spellfile', function()
-- │ │ ┌ Condition regex (missing!)
.. '\000\001\001')
meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E758: Truncated spell file',
exc_exec('set spell'))
eq('Vim(set):E758: Truncated spell file', exc_exec('set spell'))
end)
it('errors out when prefcond regexp contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -55,11 +56,11 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
end)
it('errors out when region contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_REGION)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -72,11 +73,11 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
end)
it('errors out when SAL section contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_SAL)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -96,15 +97,12 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
end)
it('errors out when spell header contains NUL bytes', function()
meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
spellheader:sub(1, -3) .. '\000\000')
write_file(testdir .. '/spell/en.ascii.spl', spellheader:sub(1, -3) .. '\000\000')
meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E757: This does not look like a spell file',
exc_exec('set spell'))
eq('Vim(set):E757: This does not look like a spell file', exc_exec('set spell'))
end)
end)

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,9 @@ describe('K', function()
-- 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)
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)
@@ -64,5 +66,4 @@ describe('K', function()
feed('K')
eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
end)
end)

View File

@@ -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)
@@ -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
@@ -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 |
@@ -729,7 +735,7 @@ describe('completion', function()
end)
it('disables folding during completion', function()
feed_command("set foldmethod=indent")
feed_command('set foldmethod=indent')
feed('i<Tab>foo<CR><Tab>bar<Esc>gg')
screen:expect([[
^foo |
@@ -748,7 +754,7 @@ describe('completion', function()
end)
it('popupmenu is not interrupted by events', function()
feed_command("set complete=.")
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,23 +796,28 @@ 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()
@@ -870,7 +884,8 @@ describe('completion', function()
endfunction
]])
meths.set_option_value('completeopt', 'menuone,noselect', {})
meths.set_var('_complist', {{
meths.set_var('_complist', {
{
word = 0,
abbr = 1,
menu = 2,
@@ -879,7 +894,8 @@ describe('completion', function()
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,7 +923,8 @@ 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()
@@ -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 |
@@ -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()

View File

@@ -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,10 +37,10 @@ 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.
@@ -48,7 +48,9 @@ describe("CTRL-C (mapped)", function()
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

View File

@@ -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
@@ -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')
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')
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$')
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')
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')
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')
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')
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')
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
@@ -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

View File

@@ -60,7 +60,8 @@ describe('jumplist', function()
feed('35gg')
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"
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 |

View File

@@ -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

View File

@@ -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()
@@ -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)

View File

@@ -11,7 +11,6 @@ local meths = helpers.meths
local insert = helpers.insert
local curbufmeths = helpers.curbufmeths
describe('macros', function()
before_each(function()
clear({ args_rm = { '--cmd' } })
@@ -74,7 +73,6 @@ hello]]
end)
it('can be replayed with @q and @w', function()
insert [[hello
hello
hello]]

View File

@@ -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")
feed('mA')
command('next')
feed("'A")
eq(1, meths.get_current_buf().id)
eq({ 2, 0 }, cursor())
end)
it("can move to them using `", function()
command("args " .. file1 .. " " .. file2)
feed("jll")
feed("ma")
feed("G`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")
feed('mA')
command('next')
feed('`A')
eq(1, meths.get_current_buf().id)
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")
feed('mA')
command('next')
feed("g'A")
eq(1, meths.get_current_buf().id)
eq({ 2, 0 }, cursor())
end)
it("can move to them using g`", function()
command("args " .. file1 .. " " .. file2)
feed("jll")
feed("ma")
feed("Gg`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")
feed('mA')
command('next')
feed('g`A')
eq(1, meths.get_current_buf().id)
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")
feed('mA')
command('next')
command("'A")
eq(1, meths.get_current_buf().id)
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,124 +180,124 @@ 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)
@@ -328,15 +330,15 @@ describe('named marks view', function()
local function content()
local c = {}
for i = 1, 30 do
c[i] = i .. " line"
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 |
@@ -360,7 +362,7 @@ describe('named marks view', function()
|
]]
screen:expect({ grid = expected })
feed("G`a")
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([[
|

View File

@@ -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)

View File

@@ -54,19 +54,23 @@ describe('cmdline', function()
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()

View File

@@ -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)

View File

@@ -51,7 +51,9 @@ 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)
@@ -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],
@@ -300,14 +308,15 @@ describe('put command', function()
}
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,12 +650,12 @@ 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
@@ -682,9 +700,7 @@ describe('put command', 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')
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()
@@ -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()
@@ -812,50 +827,33 @@ describe('put command', function()
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,
' '
)
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,
' '
)
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)
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)

View File

@@ -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)

View File

@@ -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,7 +68,8 @@ describe('tabpage', function()
new
autocmd WinClosed * tabprev | bwipe!
close
]])
]]
)
assert_alive()
end)
@@ -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')

View File

@@ -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')

View File

@@ -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)

View File

@@ -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)

View File

@@ -21,14 +21,26 @@ 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
@@ -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('cd ' .. directories.global)
command("call delete('../" .. directories.global .. "', 'd')")
eq("", helpers.eval("getcwd()"))
eq('', helpers.eval('getcwd()'))
end)
it("works with 'autochdir' after local directory was set (#9892)", function()

View File

@@ -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()
@@ -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>')
@@ -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 |
@@ -468,7 +470,6 @@ describe('mappings with <Cmd>', function()
eq('i', eval('mode(1)'))
end)
it('works in operator-pending mode', function()
feed('d<F4>')
expect([[
@@ -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
@@ -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)
feed('<f2>')
eq('', eval('v:errmsg'))
eq(10, eval('g:x'))
end)
end)

View File

@@ -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
@@ -247,14 +246,14 @@ describe('Vimscript dictionary notifications', function()
{ '= 3', { new = 3 } },
{ '= 6', { old = 3, new = 6 } },
{ '+= 3', { old = 6, new = 9 } },
{'', {old = 9}}
{ '', { old = 9 } },
})
test_updates({
{ '= "str"', { new = 'str' } },
{ '= "str2"', { old = 'str', new = 'str2' } },
{ '.= "2str"', { old = 'str2', new = 'str22str' } },
{'', {old = 'str22str'}}
{ '', { old = 'str22str' } },
})
test_updates({
@@ -262,7 +261,7 @@ describe('Vimscript dictionary notifications', function()
{ '= [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}}}
{ '', { old = { 1, 2, 3, 4, 5 } } },
})
test_updates({
@@ -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)
--[[
@@ -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)

View File

@@ -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()
@@ -16,11 +16,11 @@ describe(":drop", function()
[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)

View File

@@ -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)
@@ -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()
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}))'))
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('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()
@@ -308,8 +326,8 @@ 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()
@@ -325,10 +343,8 @@ describe(':echo :echon :echomsg :echoerr', function()
it('dumps recursive dictionaries without the error', function()
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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -19,7 +19,7 @@ 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'
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
@@ -30,7 +30,6 @@ describe(':file', function()
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'), '[^%%]+$'))
eq(testfile_renamed .. '.swp', string.match(funcs.execute('swapname'), '[^%%]+$'))
end)
end)

View File

@@ -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()

View File

@@ -44,6 +44,4 @@ describe(':ls', function()
eq('\n 3 %aF ', string.match(ls_output, '^\n *3 ... '))
end)
end)
end)

View File

@@ -14,7 +14,7 @@ describe(':make', function()
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()
@@ -25,7 +25,10 @@ describe(':make', 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()
@@ -36,7 +39,5 @@ describe(':make', function()
matches('LastExitCode%s+ready [$]%s+[(]', out)
matches('\n.*%: ready [$]', out)
end)
end)
end)

View File

@@ -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([[
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')

View File

@@ -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)

View File

@@ -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'

View File

@@ -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)

View File

@@ -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()

View File

@@ -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)

View File

@@ -20,15 +20,19 @@ for _, c in ipairs({'l', 'c'}) do
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))
@@ -52,32 +80,73 @@ for _, c in ipairs({'l', 'c'}) do
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)))
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))
@@ -127,7 +196,10 @@ 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

View File

@@ -11,4 +11,3 @@ describe(':qa', function()
-- errors
end)
end)

View File

@@ -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)

View File

@@ -16,8 +16,8 @@ describe('sign', function()
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)

View File

@@ -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)
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)

View File

@@ -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,14 +31,14 @@ 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()
@@ -116,7 +115,7 @@ 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.
local child_session = helpers.connect(child_server)
@@ -127,7 +126,6 @@ describe("preserve and (R)ecover with custom 'directory'", function()
screen0:expect({ any = pesc('[Process exited 1]') }) -- Wait for the child process to stop.
test_recover(swappath1)
end)
end)
describe('swapfile detection', function()
@@ -178,44 +176,65 @@ 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"]]}
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'}},
}
}
{ { 'notification', 'nvim_error_event', { 0, 'Vim(edit):E325: ATTENTION' } } },
},
})
feed('<cr>')
@@ -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>')
@@ -282,7 +301,7 @@ describe('swapfile detection', function()
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']])
@@ -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,7 +409,6 @@ 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()
@@ -403,12 +425,15 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
clear({ args = { '--cmd', init_dir, '--cmd', init_set } })
rmdir(swapdir)
mkdir(swapdir)
write_file(testfile, [[
write_file(
testfile,
[[
first
second
third
]])
]]
)
command('edit! ' .. testfile)
feed('Gisometext<esc>')
poke_eventloop()
@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -17,7 +17,9 @@ local function last_set_tests(cmd)
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,9 +212,12 @@ 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)
end)
@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -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,10 +9,16 @@ 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()
os.remove(shada_file)
@@ -44,7 +49,6 @@ describe(':wshada', function()
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)

View File

@@ -16,7 +16,7 @@ describe('example', function()
screen:attach()
screen:set_default_attr_ids({
[0] = { bold = true, foreground = Screen.colors.Blue },
[1] = {bold=true, foreground=Screen.colors.Brown}
[1] = { bold = true, foreground = Screen.colors.Brown },
})
end)
@@ -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}
}, event_tabs)
end,
}
end)
end)

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
table.insert(_G.test_loadorder, "mittel")
table.insert(_G.test_loadorder, 'mittel')

Some files were not shown because too many files have changed in this diff Show More