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/coxpcall.lua
/runtime/lua/vim/_meta /runtime/lua/vim/_meta
/runtime/lua/vim/re.lua /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/fixtures/lua/syntax_error.lua
/test/functional/legacy/030_fileformats_spec.lua /test/functional/legacy/030_fileformats_spec.lua
/test/functional/legacy/044_099_regexp_multibyte_magic_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(SHELLCHECK_PRG shellcheck ${LINT_REQUIRED})
find_program(STYLUA_PRG stylua ${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( add_glob_target(
TARGET lintlua-luacheck 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 FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
GLOB_DIRS runtime scripts src test GLOB_DIRS runtime scripts src test
GLOB_PAT *.lua GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE) TOUCH_STRATEGY PER_DIR)
add_dependencies(lintlua-luacheck lua-dev-deps) add_dependencies(lintlua-luacheck lua-dev-deps)
add_glob_target( add_glob_target(
@@ -244,7 +244,7 @@ add_glob_target(
FLAGS --color=always --check --respect-ignores FLAGS --color=always --check --respect-ignores
GLOB_DIRS ${STYLUA_DIRS} GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE) TOUCH_STRATEGY PER_DIR)
add_custom_target(lintlua) add_custom_target(lintlua)
add_dependencies(lintlua lintlua-luacheck lintlua-stylua) add_dependencies(lintlua lintlua-luacheck lintlua-stylua)
@@ -255,7 +255,7 @@ add_glob_target(
FLAGS -x -a FLAGS -x -a
GLOB_DIRS scripts GLOB_DIRS scripts
GLOB_PAT *.sh GLOB_PAT *.sh
TOUCH_STRATEGY SINGLE) TOUCH_STRATEGY PER_DIR)
add_custom_target(lintcommit add_custom_target(lintcommit
COMMAND $<TARGET_FILE:nvim> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main) COMMAND $<TARGET_FILE:nvim> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
@@ -270,7 +270,8 @@ add_glob_target(
COMMAND ${STYLUA_PRG} COMMAND ${STYLUA_PRG}
FLAGS --respect-ignores FLAGS --respect-ignores
GLOB_DIRS ${STYLUA_DIRS} GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua) GLOB_PAT *.lua
TOUCH_STRATEGY PER_DIR)
add_custom_target(format) add_custom_target(format)
add_dependencies(format formatc formatlua) 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, ...) return request('buffer_' .. method, 0, ...)
end end
describe('nvim_buf_set_lines, nvim_buf_line_count', function() describe('nvim_buf_set_lines, nvim_buf_line_count', function()
it('deprecated forms', function() it('deprecated forms', function()
eq(1, curbuf_depr('line_count')) 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() it('cursor position is maintained after lines are inserted #9961', function()
-- replace the buffer contents with these three lines. -- 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}. -- Set the current cursor to {3, 2}.
curwin('set_cursor', { 3, 2 }) curwin('set_cursor', { 3, 2 })
-- add 2 lines and delete 1 line above the current cursor position. -- 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. -- 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. -- cursor should be moved below by 1 line.
eq({ 4, 2 }, curwin('get_cursor')) eq({ 4, 2 }, curwin('get_cursor'))
-- add a line after the current cursor position. -- 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. -- 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. -- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor')) eq({ 4, 2 }, curwin('get_cursor'))
-- overwrite current cursor line. -- 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. -- 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. -- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor')) eq({ 4, 2 }, curwin('get_cursor'))
-- delete current cursor line. -- delete current cursor line.
request('nvim_buf_set_lines', 0, 3, 5, 1, {}) request('nvim_buf_set_lines', 0, 3, 5, 1, {})
-- check the current set of lines in the buffer. -- 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. -- cursor position is unchanged.
eq({ 4, 2 }, curwin('get_cursor')) eq({ 4, 2 }, curwin('get_cursor'))
end) end)
it('cursor position is maintained in non-current window', function() 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 }) meths.win_set_cursor(0, { 3, 2 })
local win = meths.get_current_win() local win = meths.get_current_win()
local buf = meths.get_current_buf() local buf = meths.get_current_buf()
command('new') command('new')
meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"}) 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({ 'line1', 'line5', 'line6', 'line3', 'line4' }, meths.buf_get_lines(buf, 0, -1, true))
eq({ 4, 2 }, meths.win_get_cursor(win)) eq({ 4, 2 }, meths.win_get_cursor(win))
end) end)
it('cursor position is maintained in TWO non-current windows', function() 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 }) meths.win_set_cursor(0, { 3, 2 })
local win = meths.get_current_win() local win = meths.get_current_win()
local buf = meths.get_current_buf() local buf = meths.get_current_buf()
@@ -109,10 +108,10 @@ describe('api/buf', function()
local win2 = meths.get_current_win() local win2 = meths.get_current_win()
-- set current window to third one with another buffer -- set current window to third one with another buffer
command("new") command('new')
meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"}) 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({ 'line1', 'line5', 'line6', 'line3', 'line4' }, meths.buf_get_lines(buf, 0, -1, true))
eq({ 4, 2 }, meths.win_get_cursor(win)) eq({ 4, 2 }, meths.win_get_cursor(win))
eq({ 5, 2 }, meths.win_get_cursor(win2)) eq({ 5, 2 }, meths.win_get_cursor(win2))
end) end)
@@ -121,7 +120,7 @@ describe('api/buf', function()
-- we'll need to know our bufnr for when it gets unloaded -- we'll need to know our bufnr for when it gets unloaded
local bufnr = curbuf('get_number') local bufnr = curbuf('get_number')
-- replace the buffer contents with these three lines -- 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 -- check the line count is correct
eq(4, request('nvim_buf_line_count', bufnr)) eq(4, request('nvim_buf_line_count', bufnr))
-- force unload the buffer (this will discard changes) -- 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 -- we'll need to know our bufnr for when it gets unloaded
local bufnr = curbuf('get_number') local bufnr = curbuf('get_number')
-- replace the buffer contents with these three lines -- 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 -- 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) -- force unload the buffer (this will discard changes)
command('new') command('new')
command('bunload! ' .. bufnr) command('bunload! ' .. bufnr)
@@ -152,12 +151,12 @@ describe('api/buf', function()
before_each(function() before_each(function()
screen = Screen.new(20, 12) screen = Screen.new(20, 12)
screen:set_default_attr_ids { screen:set_default_attr_ids {
[1] = {bold = true, foreground = Screen.colors.Blue1}; [1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = {reverse = true, bold = true}; [2] = { reverse = true, bold = true },
[3] = {reverse = true}; [3] = { reverse = true },
} }
screen:attach() 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, {}) meths.set_option_value('modified', false, {})
end) end)
@@ -168,7 +167,8 @@ describe('api/buf', function()
command('new | wincmd w') command('new | wincmd w')
meths.win_set_cursor(win, { 8, 0 }) meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -178,10 +178,12 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] }| {2:[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 = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -191,11 +193,13 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]]} ]],
}
-- replacing topline keeps it the topline -- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -205,11 +209,13 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]]} ]],
}
-- inserting just before topline does not scroll up if cursor would be moved -- inserting just before topline does not scroll up if cursor would be moved
meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -219,10 +225,13 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]], unchanged=true} ]],
unchanged = true,
}
meths.win_set_cursor(0, { 7, 0 }) meths.win_set_cursor(0, { 7, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -232,10 +241,12 @@ describe('api/buf', function()
zzz | zzz |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]]} ]],
}
meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"}) meths.buf_set_lines(buf, 4, 4, true, { 'mmmeeeee' })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -245,7 +256,8 @@ describe('api/buf', function()
^yyy | ^yyy |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]]} ]],
}
end) end)
it('of non-current window', function() it('of non-current window', function()
@@ -255,7 +267,8 @@ describe('api/buf', function()
command('new') command('new')
meths.win_set_cursor(win, { 8, 0 }) meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -265,10 +278,12 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] }| {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 = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -278,11 +293,13 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
-- replacing topline keeps it the topline -- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -292,11 +309,13 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
-- inserting just before topline scrolls up -- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -306,7 +325,8 @@ describe('api/buf', function()
yyy | yyy |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
end) end)
it('of split windows with same buffer', function() 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(win, { 8, 0 })
meths.win_set_cursor(0, { 1, 0 }) meths.win_set_cursor(0, { 1, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
^aaa | ^aaa |
bbb | bbb |
ccc | ccc |
@@ -330,10 +351,12 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] }| {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 | ^aaabbb |
ccc | ccc |
ddd | ddd |
@@ -346,11 +369,13 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
-- replacing topline keeps it the topline -- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) meths.buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
screen:expect{grid=[[ screen:expect {
grid = [[
^aaabbb | ^aaabbb |
ccc | ccc |
ddd | ddd |
@@ -363,11 +388,13 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
-- inserting just before topline scrolls up -- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) meths.buf_set_lines(buf, 3, 3, true, { 'mmm' })
screen:expect{grid=[[ screen:expect {
grid = [[
^aaabbb | ^aaabbb |
ccc | ccc |
ddd | ddd |
@@ -380,19 +407,20 @@ describe('api/buf', function()
yyy | yyy |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
end) end)
end) end)
it('handles clearing out non-current buffer #24911', function() it('handles clearing out non-current buffer #24911', function()
local buf = meths.get_current_buf() local buf = meths.get_current_buf()
meths.buf_set_lines(buf, 0, -1, true, {"aaa", "bbb", "ccc"}) meths.buf_set_lines(buf, 0, -1, true, { 'aaa', 'bbb', 'ccc' })
command("new") 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, {}) 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)) eq({ '' }, meths.buf_get_lines(buf, 0, -1, true))
end) end)
end) end)
@@ -467,8 +495,7 @@ describe('api/buf', function()
curbuf_depr('set_line_slice', 1, 2, true, false, { 'a', 'b', 'c' }) 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)) 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' }) curbuf_depr('set_line_slice', -1, -1, true, true, { 'a', 'b', 'c' })
eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'}, eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', 0, -3, true, false, {}) curbuf_depr('set_line_slice', 0, -3, true, false, {})
eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true)) eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_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() it('fails correctly when input is not valid', function()
eq(1, api.curbufmeths.get_number()) eq(1, api.curbufmeths.get_number())
eq([['replacement string' item contains newlines]], eq(
pcall_err(bufmeths.set_lines, 1, 1, 2, false, {'b\na'})) [['replacement string' item contains newlines]],
pcall_err(bufmeths.set_lines, 1, 1, 2, false, { 'b\na' })
)
end) end)
it("fails if 'nomodifiable'", function() it("fails if 'nomodifiable'", function()
command('set nomodifiable') command('set nomodifiable')
eq([[Buffer is not 'modifiable']], eq(
pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, {'a','b'})) [[Buffer is not 'modifiable']],
pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, { 'a', 'b' })
)
end) end)
it('has correct line_count when inserting and deleting', function() 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' }) set_lines(1, 2, mode, { 'a', 'b', 'c' })
eq({ 'a', 'a', 'b', 'c', 'c' }, get_lines(0, -1, mode)) eq({ 'a', 'a', 'b', 'c', 'c' }, get_lines(0, -1, mode))
set_lines(-2, -1, mode, { 'a', 'b', 'c' }) set_lines(-2, -1, mode, { 'a', 'b', 'c' })
eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'}, eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, get_lines(0, -1, mode))
get_lines(0, -1, mode))
set_lines(0, -4, mode, {}) set_lines(0, -4, mode, {})
eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode)) eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode))
set_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)) eq({ 'e', 'a', 'b', 'c', 'd' }, get_lines(0, -1, true))
end) 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') feed_command('set hidden')
insert('Initial file') insert('Initial file')
command('enew') command('enew')
@@ -678,8 +708,7 @@ describe('api/buf', function()
eq(3, funcs.winnr()) eq(3, funcs.winnr())
feed('<c-w>h') feed('<c-w>h')
eq(2, funcs.winnr()) eq(2, funcs.winnr())
api.meths.buf_set_lines(hiddenbuf, 0, -1, true, api.meths.buf_set_lines(hiddenbuf, 0, -1, true, { 'hidden buffer line 1', 'line 2' })
{'hidden buffer line 1', 'line 2'})
feed('<c-w>p') feed('<c-w>p')
eq(3, funcs.winnr()) eq(3, funcs.winnr())
end) end)
@@ -711,7 +740,6 @@ describe('api/buf', function()
eq({ 'hello foo!' }, get_lines(0, 1, true)) eq({ 'hello foo!' }, get_lines(0, 1, true))
-- can replace a single word -- can replace a single word
set_text(0, 6, 0, 9, { 'world' }) set_text(0, 6, 0, 9, { 'world' })
eq({ 'hello world!', 'text' }, get_lines(0, 2, true)) eq({ 'hello world!', 'text' }, get_lines(0, 2, true))
@@ -799,7 +827,7 @@ describe('api/buf', function()
local win = meths.get_current_win() local win = meths.get_current_win()
local buf = meths.get_current_buf() local buf = meths.get_current_buf()
command("new") command('new')
-- replace 'world' with 'foo' -- replace 'world' with 'foo'
meths.buf_set_text(buf, 0, 6, 0, 11, { '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 win = meths.get_current_win()
local buf = meths.get_current_buf() local buf = meths.get_current_buf()
command("split") command('split')
local win2 = meths.get_current_win() local win2 = meths.get_current_win()
-- position the cursor on `w` -- position the cursor on `w`
meths.win_set_cursor(0, { 1, 6 }) meths.win_set_cursor(0, { 1, 6 })
command("new") command('new')
-- replace 'hello' with 'foo' -- replace 'hello' with 'foo'
meths.buf_set_text(buf, 0, 0, 0, 5, { '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')) eq({ 1, 1 }, curwin('get_cursor'))
end) 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([[ insert([[
abcd]]) abcd]])
@@ -912,7 +940,7 @@ describe('api/buf', function()
end) end)
describe('when cursor is inside replaced row range', function() 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -934,7 +962,7 @@ describe('api/buf', function()
eq({ 1, 14 }, curwin('get_cursor')) eq({ 1, 14 }, curwin('get_cursor'))
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -977,7 +1005,7 @@ describe('api/buf', function()
eq({ 1, 18 }, cursor) eq({ 1, 18 }, cursor)
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1000,7 +1028,7 @@ describe('api/buf', function()
eq({ 1, 19 }, cursor) eq({ 1, 19 }, cursor)
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1029,7 +1057,9 @@ describe('api/buf', function()
eq({ 2, 5 }, cursor) eq({ 2, 5 }, cursor)
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1058,7 +1088,8 @@ describe('api/buf', function()
eq({ 2, 6 }, curwin('get_cursor')) eq({ 2, 6 }, curwin('get_cursor'))
-- immediate call to nvim_win_get_cursor should have returned the same position -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 6 }, cursor) eq({ 2, 6 }, cursor)
end) end
)
it('adjusts cursor line and column to keep it inside replacement range', function() it('adjusts cursor line and column to keep it inside replacement range', function()
insert([[ insert([[
@@ -1149,7 +1180,9 @@ describe('api/buf', function()
eq({ 3, 7 }, curwin('get_cursor')) eq({ 3, 7 }, curwin('get_cursor'))
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1168,7 +1201,8 @@ describe('api/buf', function()
}, get_lines(0, -1, true)) }, get_lines(0, -1, true))
-- cursor should end up after 'n' in 'then' -- cursor should end up after 'n' in 'then'
eq({ 3, 8 }, curwin('get_cursor')) eq({ 3, 8 }, curwin('get_cursor'))
end) end
)
it('adjusts cursor column if replacement is inside of a single line', function() it('adjusts cursor column if replacement is inside of a single line', function()
insert([[ insert([[
@@ -1228,7 +1262,7 @@ describe('api/buf', function()
end) end)
describe('with virtualedit', function() 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([[ insert([[
This should be first This should be first
then there is a line we do not want 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 -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 12 }, cursor) eq({ 2, 12 }, cursor)
-- coladd should be 0 -- coladd should be 0
eq(0, exec_lua([[ eq(
0,
exec_lua([[
return vim.fn.winsaveview().coladd return vim.fn.winsaveview().coladd
]])) ]])
)
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want 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 -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 26 }, cursor) eq({ 2, 26 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column -- 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 return vim.fn.winsaveview().coladd
]])) ]])
)
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want 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 -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 1, 38 }, cursor) eq({ 1, 38 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column -- 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 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([[ insert([[
This should be first This should be first
then there is a line we do not want 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 -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 1, 22 }, cursor) eq({ 1, 22 }, cursor)
-- coladd should become 0 -- coladd should become 0
eq(0, exec_lua([[ eq(
0,
exec_lua([[
return vim.fn.winsaveview().coladd 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([[ insert([[
This should be first This should be first
then there is a line we do not want 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 -- immediate call to nvim_win_get_cursor should have returned the same position
eq({ 2, 26 }, cursor) eq({ 2, 26 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column -- 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 return vim.fn.winsaveview().coladd
]])) ]])
end) )
end
)
end) end)
end) end)
@@ -1434,7 +1492,9 @@ describe('api/buf', function()
eq({ 3, 2 }, curwin('get_cursor')) eq({ 3, 2 }, curwin('get_cursor'))
end) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1459,9 +1519,12 @@ describe('api/buf', function()
}, get_lines(0, -1, true)) }, get_lines(0, -1, true))
-- cursor should return back to the original position -- cursor should return back to the original position
eq({ 3, 13 }, curwin('get_cursor')) 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([[ insert([[
This should be first This should be first
then there is a line we do not want then there is a line we do not want
@@ -1494,7 +1557,8 @@ describe('api/buf', function()
}, get_lines(0, -1, true)) }, get_lines(0, -1, true))
-- cursor should return back to the original position -- cursor should return back to the original position
eq({ 3, 18 }, curwin('get_cursor')) eq({ 3, 18 }, curwin('get_cursor'))
end) end
)
it('does not move cursor column after end of a line', function() it('does not move cursor column after end of a line', function()
insert([[ insert([[
@@ -1543,7 +1607,7 @@ describe('api/buf', function()
end) end)
it('adjusts extmarks', function() it('adjusts extmarks', function()
local ns = request('nvim_create_namespace', "my-fancy-plugin") local ns = request('nvim_create_namespace', 'my-fancy-plugin')
insert([[ insert([[
foo bar foo bar
baz baz
@@ -1551,7 +1615,7 @@ describe('api/buf', function()
local id1 = curbufmeths.set_extmark(ns, 0, 1, {}) local id1 = curbufmeths.set_extmark(ns, 0, 1, {})
local id2 = curbufmeths.set_extmark(ns, 0, 7, {}) local id2 = curbufmeths.set_extmark(ns, 0, 7, {})
local id3 = curbufmeths.set_extmark(ns, 1, 1, {}) 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)) eq({ 'foo q', 'baz' }, get_lines(0, 2, true))
-- mark before replacement point is unaffected -- mark before replacement point is unaffected
@@ -1562,7 +1626,7 @@ describe('api/buf', function()
eq({ 1, 1 }, curbufmeths.get_extmark_by_id(ns, id3, {})) eq({ 1, 1 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
-- replacing the text spanning two lines will adjust the mark on the next line -- 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({ 'fooqux', '' }, get_lines(0, 2, true))
eq({ 0, 6 }, curbufmeths.get_extmark_by_id(ns, id3, {})) eq({ 0, 6 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
-- but mark before replacement point is still unaffected -- 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, {})) eq({ 0, 8 }, curbufmeths.get_extmark_by_id(ns, id3, {}))
end) 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) local screen = Screen.new(20, 5)
screen:attach() screen:attach()
@@ -1642,12 +1706,12 @@ describe('api/buf', function()
before_each(function() before_each(function()
screen = Screen.new(20, 12) screen = Screen.new(20, 12)
screen:set_default_attr_ids { screen:set_default_attr_ids {
[1] = {bold = true, foreground = Screen.colors.Blue1}; [1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = {reverse = true, bold = true}; [2] = { reverse = true, bold = true },
[3] = {reverse = true}; [3] = { reverse = true },
} }
screen:attach() 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, {}) meths.set_option_value('modified', false, {})
end) end)
@@ -1658,7 +1722,8 @@ describe('api/buf', function()
command('new | wincmd w') command('new | wincmd w')
meths.win_set_cursor(win, { 8, 0 }) meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{1:~ }|*4 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -1668,10 +1733,12 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] }| {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 {1:~ }|*4
{3:[No Name] }| {3:[No Name] }|
@@ -1681,7 +1748,8 @@ describe('api/buf', function()
^zzz | ^zzz |
{2:[No Name] [+] }| {2:[No Name] [+] }|
| |
]]} ]],
}
end) end)
it('of non-current window', function() it('of non-current window', function()
@@ -1691,7 +1759,8 @@ describe('api/buf', function()
command('new') command('new')
meths.win_set_cursor(win, { 8, 0 }) meths.win_set_cursor(win, { 8, 0 })
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -1701,10 +1770,12 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] }| {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 = [[
^ | ^ |
{1:~ }|*4 {1:~ }|*4
{2:[No Name] }| {2:[No Name] }|
@@ -1714,7 +1785,8 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
end) end)
it('of split windows with same buffer', function() 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(win, { 8, 0 })
meths.win_set_cursor(0, { 1, 1 }) meths.win_set_cursor(0, { 1, 1 })
screen:expect{grid=[[ screen:expect {
grid = [[
a^aa | a^aa |
bbb | bbb |
ccc | ccc |
@@ -1738,10 +1811,12 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] }| {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 | a^aaXbbb |
ccc | ccc |
ddd | ddd |
@@ -1754,7 +1829,8 @@ describe('api/buf', function()
zzz | zzz |
{3:[No Name] [+] }| {3:[No Name] [+] }|
| |
]]} ]],
}
end) end)
end) end)
end) end)
@@ -1823,10 +1899,10 @@ describe('api/buf', function()
meths.set_option_value('eol', true, {}) meths.set_option_value('eol', true, {})
eq(29, get_offset(5)) eq(29, get_offset(5))
command("set hidden") command('set hidden')
command("enew") command('enew')
eq(6, bufmeths.get_offset(1, 1)) 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, 1))
eq(-1, bufmeths.get_offset(1, 0)) eq(-1, bufmeths.get_offset(1, 0))
end) end)
@@ -1857,10 +1933,8 @@ describe('api/buf', function()
command('lockvar b:lua') command('lockvar b:lua')
eq('Key is locked: lua', pcall_err(curbufmeths.del_var, '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 locked: lua', pcall_err(curbufmeths.set_var, 'lua', 1))
eq('Key is read-only: changedtick', eq('Key is read-only: changedtick', pcall_err(curbufmeths.del_var, '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.set_var, 'changedtick', 1))
end) end)
end) end)
@@ -1897,7 +1971,7 @@ describe('api/buf', function()
nvim('set_option_value', 'define', 'test', { buf = 0 }) nvim('set_option_value', 'define', 'test', { buf = 0 })
eq('test', nvim('get_option_value', 'define', { buf = 0 })) eq('test', nvim('get_option_value', 'define', { buf = 0 }))
-- Doesn't change the global value -- Doesn't change the global value
eq("", nvim('get_option_value', 'define', {scope='global'})) eq('', nvim('get_option_value', 'define', { scope = 'global' }))
end) end)
it('returns values for unset local options', function() 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 clear = helpers.clear
local eq, ok = helpers.eq, helpers.ok local eq, ok = helpers.eq, helpers.ok
local funcs = helpers.funcs local funcs = helpers.funcs
local buffer, command, eval, nvim, next_msg = helpers.buffer, local buffer, command, eval, nvim, next_msg =
helpers.command, helpers.eval, helpers.nvim, helpers.next_msg helpers.buffer, helpers.command, helpers.eval, helpers.nvim, helpers.next_msg
local nvim_prog = helpers.nvim_prog local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err local pcall_err = helpers.pcall_err
local sleep = helpers.sleep local sleep = helpers.sleep
local write_file = helpers.write_file local write_file = helpers.write_file
local origlines = {"original line 1", local origlines = {
"original line 2", 'original line 1',
"original line 3", 'original line 2',
"original line 4", 'original line 3',
"original line 5", 'original line 4',
"original line 6"} 'original line 5',
'original line 6',
}
local function expectn(name, args) local function expectn(name, args)
-- expect the next message to be the specified notification event -- 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 -- more key presses - otherwise they all pile up in the queue and get
-- processed at once -- processed at once
local ntime = os.clock() + 0.1 local ntime = os.clock() + 0.1
repeat until os.clock() > ntime repeat
until os.clock() > ntime
end end
local function open(activate, lines) local function open(activate, lines)
local filename = helpers.tmpname() 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) command('edit ' .. filename)
local b = nvim('get_current_buf') local b = nvim('get_current_buf')
-- what is the value of b:changedtick? -- what is the value of b:changedtick?
@@ -81,18 +84,36 @@ local function reopenwithfolds(b)
-- add a fold -- add a fold
command('2,4fold') command('2,4fold')
tick = tick + 1 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 3',
'original line 4/*}}}*/'}, false}) 'original line 4/*}}}*/',
},
false,
})
-- make a new fold that wraps lines 1-6 -- make a new fold that wraps lines 1-6
command('1,6fold') command('1,6fold')
tick = tick + 1 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 2/*{{{*/',
'original line 3', 'original line 3',
'original line 4/*}}}*/', 'original line 4/*}}}*/',
'original line 5', 'original line 5',
'original line 6/*}}}*/'}, false}) 'original line 6/*}}}*/',
},
false,
})
return tick return tick
end end
@@ -110,9 +131,10 @@ describe('API: buffer events:', function()
-- add multiple lines at the start of the file -- add multiple lines at the start of the file
command('normal! GkkyGggP') command('normal! GkkyGggP')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 4', expectn(
'original line 5', 'nvim_buf_lines_event',
'original line 6'}, false}) { 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 -- add one line to the middle of the file, several times
command('normal! ggYjjp') command('normal! ggYjjp')
@@ -128,10 +150,19 @@ describe('API: buffer events:', function()
-- add multiple lines to the middle of the file -- add multiple lines to the middle of the file
command('normal! gg4Yjjp') command('normal! gg4Yjjp')
tick = tick + 1 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 5',
'original line 6', 'original line 6',
'original line 4'}, false}) 'original line 4',
},
false,
})
-- add one line to the end of the file -- add one line to the end of the file
command('normal! ggYGp') command('normal! ggYGp')
@@ -151,10 +182,7 @@ describe('API: buffer events:', function()
command('normal! gg4YGp') command('normal! gg4YGp')
command('normal! Gp') command('normal! Gp')
command('normal! Gp') command('normal! Gp')
local firstfour = {'original line 4', local firstfour = { 'original line 4', 'original line 5', 'original line 6', 'original line 4' }
'original line 5',
'original line 6',
'original line 4'}
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 21, 21, firstfour, false }) expectn('nvim_buf_lines_event', { b, tick, 21, 21, firstfour, false })
tick = tick + 1 tick = tick + 1
@@ -171,7 +199,7 @@ describe('API: buffer events:', function()
tick = eval('b:changedtick') tick = eval('b:changedtick')
local b2 = nvim('get_current_buf') local b2 = nvim('get_current_buf')
ok(buffer('attach', b2, true, {})) 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"])') eval('append(0, ["new line 1"])')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', { b2, tick, 0, 0, { 'new line 1' }, false }) 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') local b3 = nvim('get_current_buf')
ok(buffer('attach', b3, true, {})) ok(buffer('attach', b3, true, {}))
tick = eval('b:changedtick') 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"])') eval('append(0, ["new line 1", "new line 2", "new line 3"])')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {'new line 1', expectn(
'new line 2', 'nvim_buf_lines_event',
'new line 3'}, false}) { 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 -- use the API itself to add a line to the start of the buffer
buffer('set_lines', b3, 0, 0, true, { 'New First Line' }) buffer('set_lines', b3, 0, 0, true, { 'New First Line' })
tick = tick + 1 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) end)
it('when lines are removed', function() it('when lines are removed', function()
@@ -253,8 +282,10 @@ describe('API: buffer events:', function()
command('normal! jjw') command('normal! jjw')
sendkeys('<C-v>jjllx') sendkeys('<C-v>jjllx')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', expectn(
{b, tick, 2, 5, {'original e 3', 'original e 4', 'original e 5'}, false}) '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 -- replace part of a line line using :s
tick = reopen(b, origlines) tick = reopen(b, origlines)
@@ -266,9 +297,10 @@ describe('API: buffer events:', function()
tick = reopen(b, origlines) tick = reopen(b, origlines)
command('%s/line [35]/foo/') command('%s/line [35]/foo/')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 2, 5, {'original foo', expectn(
'original line 4', 'nvim_buf_lines_event',
'original foo'}, false}) { 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 -- type text into the first line of a blank file, one character at a time
command('bdelete!') command('bdelete!')
@@ -319,14 +351,14 @@ describe('API: buffer events:', function()
it('when lines are filtered', function() it('when lines are filtered', function()
-- Test filtering lines with !cat -- 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') command('silent 2,5!cat')
-- the change comes through as two changes: -- the change comes through as two changes:
-- 1) addition of the new lines after the filtered lines -- 1) addition of the new lines after the filtered lines
-- 2) removal of the original lines -- 2) removal of the original lines
tick = tick + 1 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 tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 1, 5, {}, false }) expectn('nvim_buf_lines_event', { b, tick, 1, 5, {}, false })
end) end)
@@ -338,7 +370,7 @@ describe('API: buffer events:', function()
-- use 'o' to start a new line from a line with no indent -- use 'o' to start a new line from a line with no indent
command('normal! o') command('normal! o')
tick = tick + 1 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 -- undo the change, indent line 1 a bit, and try again
command('undo') command('undo')
@@ -349,12 +381,12 @@ describe('API: buffer events:', function()
command('set autoindent') command('set autoindent')
command('normal! >>') command('normal! >>')
tick = tick + 1 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') command('normal! ommm')
tick = tick + 1 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 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' -- undo the change, and try again with 'O'
command('undo') command('undo')
@@ -366,14 +398,14 @@ describe('API: buffer events:', function()
expectn('nvim_buf_changedtick_event', { b, tick }) expectn('nvim_buf_changedtick_event', { b, tick })
command('normal! ggOmmm') command('normal! ggOmmm')
tick = tick + 1 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 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) end)
it('deactivates if the buffer is changed externally', function() it('deactivates if the buffer is changed externally', function()
-- Test changing file from outside vim and reloading using :edit -- 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) local b, tick, filename = editoriginal(true, lines)
command('normal! x') command('normal! x')
@@ -386,7 +418,7 @@ describe('API: buffer events:', function()
expectn('nvim_buf_changedtick_event', { b, tick }) expectn('nvim_buf_changedtick_event', { b, tick })
-- change the file directly -- 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 -- reopen the file and watch buffer events shut down
command('edit') command('edit')
@@ -540,24 +572,24 @@ describe('API: buffer events:', function()
end) end)
it('works with :diffput and :diffget', function() 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] local channel = nvim('get_api_info')[1]
command('diffthis') command('diffthis')
command('rightbelow vsplit') command('rightbelow vsplit')
local b2, tick2 = open(true, {"BBB", "CCC"}) local b2, tick2 = open(true, { 'BBB', 'CCC' })
command('diffthis') command('diffthis')
-- go back to first buffer, and push the 'AAA' line to the second buffer -- go back to first buffer, and push the 'AAA' line to the second buffer
command('1wincmd w') command('1wincmd w')
command('normal! gg') command('normal! gg')
command('diffput') command('diffput')
tick2 = tick2 + 1 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 -- use :diffget to grab the other change from buffer 2
command('normal! G') command('normal! G')
command('diffget') command('diffget')
tick1 = tick1 + 1 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")') eval('rpcnotify(' .. channel .. ', "Goodbye")')
expectn('Goodbye', {}) expectn('Goodbye', {})
@@ -565,29 +597,25 @@ describe('API: buffer events:', function()
it('works with :sort', function() it('works with :sort', function()
-- test for :sort -- 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') command('%sort')
tick = tick + 1 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) end)
it('works with :left', function() 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') command('2,4left')
tick = tick + 1 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) end)
it('works with :right', function() it('works with :right', function()
local b, tick = editoriginal(true, {" A", local b, tick = editoriginal(true, { ' A', '\t B', '\t \tBB', ' \tB', '\t\tC' })
"\t B",
"\t \tBB",
" \tB",
"\t\tC"})
command('set ts=2 et') command('set ts=2 et')
command('2,4retab') command('2,4retab')
tick = tick + 1 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) end)
it('works with :move', function() it('works with :move', function()
@@ -595,8 +623,10 @@ describe('API: buffer events:', function()
-- move text down towards the end of the file -- move text down towards the end of the file
command('2,3move 4') command('2,3move 4')
tick = tick + 2 tick = tick + 2
expectn('nvim_buf_lines_event', {b, tick, 4, 4, {"original line 2", expectn(
"original line 3"}, false}) 'nvim_buf_lines_event',
{ b, tick, 4, 4, { 'original line 2', 'original line 3' }, false }
)
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 1, 3, {}, false }) expectn('nvim_buf_lines_event', { b, tick, 1, 3, {}, false })
@@ -604,8 +634,10 @@ describe('API: buffer events:', function()
tick = reopen(b, origlines) tick = reopen(b, origlines)
command('4,5move 2') command('4,5move 2')
tick = tick + 2 tick = tick + 2
expectn('nvim_buf_lines_event', {b, tick, 2, 2, {"original line 4", expectn(
"original line 5"}, false}) 'nvim_buf_lines_event',
{ b, tick, 2, 2, { 'original line 4', 'original line 5' }, false }
)
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', { b, tick, 5, 7, {}, false }) expectn('nvim_buf_lines_event', { b, tick, 5, 7, {}, false })
end) end)
@@ -617,9 +649,10 @@ describe('API: buffer events:', function()
-- delete the inner fold -- delete the inner fold
command('normal! zR3Gzd') command('normal! zR3Gzd')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2', expectn(
'original line 3', 'nvim_buf_lines_event',
'original line 4'}, false}) { b, tick, 1, 4, { 'original line 2', 'original line 3', 'original line 4' }, false }
)
-- delete the outer fold -- delete the outer fold
command('normal! zd') command('normal! zd')
tick = tick + 1 tick = tick + 1
@@ -649,9 +682,10 @@ describe('API: buffer events:', function()
-- delete the fold which only has one marker -- delete the fold which only has one marker
command('normal! Gzd') command('normal! Gzd')
tick = tick + 1 tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 3, 6, {'original line 4', expectn(
'original line 5', 'nvim_buf_lines_event',
'original line 6'}, false}) { b, tick, 3, 6, { 'original line 4', 'original line 5', 'original line 6' }, false }
)
end) end)
it('detaches if the buffer is closed', function() 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() it('returns a proper error on nonempty options dict', function()
clear() clear()
local b = editoriginal(false) 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) end)
it('nvim_buf_attach returns response after delay #8634', function() it('nvim_buf_attach returns response after delay #8634', function()
@@ -777,7 +811,9 @@ describe('API: buffer events:', function()
[2] = 'nvim_buf_changedtick_event', [2] = 'nvim_buf_changedtick_event',
[3] = { [3] = {
[1] = { id = 1 }, [1] = { id = 1 },
[2] = 2 }, }, next_msg()) [2] = 2,
},
}, next_msg())
end) end)
end) end)
@@ -803,7 +839,7 @@ describe('API: buffer events:', function()
local function assert_match_somewhere(expected_lines, buffer_lines) local function assert_match_somewhere(expected_lines, buffer_lines)
local msg = next_msg() local msg = next_msg()
while(msg ~= nil) do while msg ~= nil do
local event = msg[2] local event = msg[2]
if event == 'nvim_buf_lines_event' then if event == 'nvim_buf_lines_event' then
local args = msg[3] local args = msg[3]
@@ -834,7 +870,7 @@ describe('API: buffer events:', function()
local buffer_lines = {} local buffer_lines = {}
local expected_lines = {} local expected_lines = {}
funcs.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '-n', '-c', 'set shortmess+=A' }, { 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') local b = nvim('get_current_buf')
@@ -844,15 +880,13 @@ describe('API: buffer events:', function()
table.insert(expected_lines, '~') table.insert(expected_lines, '~')
end end
expected_lines[1] = '' expected_lines[1] = ''
expected_lines[22] = ('tmp_terminal_nvim'..(' '):rep(45) expected_lines[22] = ('tmp_terminal_nvim' .. (' '):rep(45) .. '0,0-1 All')
..'0,0-1 All')
sendkeys('i:e tmp_terminal_nvim<Enter>') sendkeys('i:e tmp_terminal_nvim<Enter>')
assert_match_somewhere(expected_lines, buffer_lines) assert_match_somewhere(expected_lines, buffer_lines)
expected_lines[1] = 'Blarg' expected_lines[1] = 'Blarg'
expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41) expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '1,6 All')
..'1,6 All')
sendkeys('iBlarg') sendkeys('iBlarg')
assert_match_somewhere(expected_lines, buffer_lines) assert_match_somewhere(expected_lines, buffer_lines)
@@ -860,12 +894,10 @@ describe('API: buffer events:', function()
for i = 1, 21 do for i = 1, 21 do
expected_lines[i] = 'xyz' expected_lines[i] = 'xyz'
end end
expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41) expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '31,4 Bot')
..'31,4 Bot')
local s = string.rep('\nxyz', 30) local s = string.rep('\nxyz', 30)
sendkeys(s) sendkeys(s)
assert_match_somewhere(expected_lines, buffer_lines) assert_match_somewhere(expected_lines, buffer_lines)
end) end)
end) end)

View File

@@ -16,8 +16,38 @@ local feed = helpers.feed
local funcs = helpers.funcs local funcs = helpers.funcs
describe('nvim_get_commands', function() 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_dict = {
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, } 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) before_each(clear)
it('gets empty list if no commands were defined', function() it('gets empty list if no commands were defined', function()
@@ -25,10 +55,8 @@ describe('nvim_get_commands', function()
end) end)
it('validation', function() it('validation', function()
eq('builtin=true not implemented', pcall_err(meths.get_commands, eq('builtin=true not implemented', pcall_err(meths.get_commands, { builtin = true }))
{builtin=true})) eq("Invalid key: 'foo'", pcall_err(meths.get_commands, { foo = 'blah' }))
eq("Invalid key: 'foo'", pcall_err(meths.get_commands,
{foo='blah'}))
end) end)
it('gets global user-defined commands', function() it('gets global user-defined commands', function()
@@ -36,7 +64,7 @@ describe('nvim_get_commands', function()
command('command -nargs=1 Hello echo "Hello World"') command('command -nargs=1 Hello echo "Hello World"')
eq({ Hello = cmd_dict }, meths.get_commands({ builtin = false })) eq({ Hello = cmd_dict }, meths.get_commands({ builtin = false }))
-- Define another command. -- 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 })) eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, meths.get_commands({ builtin = false }))
-- Delete a command. -- Delete a command.
command('delcommand Pwd') command('delcommand Pwd')
@@ -59,11 +87,86 @@ describe('nvim_get_commands', function()
end) end)
it('gets various command attributes', function() 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 cmd0 = {
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, } addr = 'arguments',
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, } bang = false,
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, } bar = false,
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, } 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([[ source([[
let s:foo = 1 let s:foo = 1
command -complete=custom,ListUsers -nargs=+ Finger !finger <args> command -complete=custom,ListUsers -nargs=+ Finger !finger <args>
@@ -88,7 +191,10 @@ describe('nvim_get_commands', function()
command -register Cmd4 call <SID>just_great() command -register Cmd4 call <SID>just_great()
]]) ]])
-- TODO(justinmk): Order is stable but undefined. Sort before return? -- 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)
end) end)
@@ -113,14 +219,15 @@ describe('nvim_create_user_command', function()
}) })
]] ]]
eq({ eq(
name = "CommandWithLuaCallback", {
name = 'CommandWithLuaCallback',
args = [[this\ is a\ test]], args = [[this\ is a\ test]],
fargs = {"this ", "is", "a test"}, fargs = { 'this ', 'is', 'a test' },
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -136,7 +243,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -144,20 +251,23 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [=[ },
exec_lua [=[
vim.api.nvim_command([[CommandWithLuaCallback this\ is a\ test]]) vim.api.nvim_command([[CommandWithLuaCallback this\ is a\ test]])
return result return result
]=]) ]=]
)
eq({ eq(
name = "CommandWithLuaCallback", {
name = 'CommandWithLuaCallback',
args = [[this includes\ a backslash: \\]], args = [[this includes\ a backslash: \\]],
fargs = {"this", "includes a", "backslash:", "\\"}, fargs = { 'this', 'includes a', 'backslash:', '\\' },
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -173,7 +283,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -181,20 +291,23 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [=[ },
exec_lua [=[
vim.api.nvim_command([[CommandWithLuaCallback this includes\ a backslash: \\]]) vim.api.nvim_command([[CommandWithLuaCallback this includes\ a backslash: \\]])
return result return result
]=]) ]=]
)
eq({ eq(
name = "CommandWithLuaCallback", {
args = "a\\b", name = 'CommandWithLuaCallback',
fargs = {"a\\b"}, args = 'a\\b',
fargs = { 'a\\b' },
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -210,7 +323,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -218,20 +331,23 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [=[ },
exec_lua [=[
vim.api.nvim_command('CommandWithLuaCallback a\\b') vim.api.nvim_command('CommandWithLuaCallback a\\b')
return result return result
]=]) ]=]
)
eq({ eq(
name = "CommandWithLuaCallback", {
name = 'CommandWithLuaCallback',
args = 'h\tey ', args = 'h\tey ',
fargs = { [[h]], [[ey]] }, fargs = { [[h]], [[ey]] },
bang = true, bang = true,
line1 = 10, line1 = 10,
line2 = 10, line2 = 10,
mods = "confirm unsilent botright horizontal", mods = 'confirm unsilent botright horizontal',
smods = { smods = {
browse = false, browse = false,
confirm = true, confirm = true,
@@ -247,7 +363,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "botright", split = 'botright',
tab = -1, tab = -1,
unsilent = true, unsilent = true,
verbose = -1, verbose = -1,
@@ -255,20 +371,23 @@ describe('nvim_create_user_command', function()
}, },
range = 1, range = 1,
count = 10, count = 10,
reg = "", reg = '',
}, exec_lua [=[ },
exec_lua [=[
vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ') vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ')
return result return result
]=]) ]=]
)
eq({ eq(
name = "CommandWithLuaCallback", {
args = "h", name = 'CommandWithLuaCallback',
fargs = {"h"}, args = 'h',
fargs = { 'h' },
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 42, line2 = 42,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -284,7 +403,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -292,20 +411,23 @@ describe('nvim_create_user_command', function()
}, },
range = 1, range = 1,
count = 42, count = 42,
reg = "", reg = '',
}, exec_lua [[ },
exec_lua [[
vim.api.nvim_command('CommandWithLuaCallback 42 h') vim.api.nvim_command('CommandWithLuaCallback 42 h')
return result return result
]]) ]]
)
eq({ eq(
name = "CommandWithLuaCallback", {
args = "", name = 'CommandWithLuaCallback',
args = '',
fargs = {}, -- fargs works without args fargs = {}, -- fargs works without args
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -321,7 +443,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -329,11 +451,13 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [[ },
exec_lua [[
vim.api.nvim_command('CommandWithLuaCallback') vim.api.nvim_command('CommandWithLuaCallback')
return result return result
]]) ]]
)
-- f-args doesn't split when command nargs is 1 or "?" -- f-args doesn't split when command nargs is 1 or "?"
exec_lua [[ exec_lua [[
@@ -347,14 +471,15 @@ describe('nvim_create_user_command', function()
}) })
]] ]]
eq({ eq(
name = "CommandWithOneOrNoArg", {
name = 'CommandWithOneOrNoArg',
args = "hello I'm one argument", args = "hello I'm one argument",
fargs = { "hello I'm one argument" }, -- Doesn't split args fargs = { "hello I'm one argument" }, -- Doesn't split args
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -370,7 +495,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -378,21 +503,24 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [[ },
exec_lua [[
vim.api.nvim_command('CommandWithOneOrNoArg hello I\'m one argument') vim.api.nvim_command('CommandWithOneOrNoArg hello I\'m one argument')
return result return result
]]) ]]
)
-- f-args is an empty table if no args were passed -- f-args is an empty table if no args were passed
eq({ eq(
name = "CommandWithOneOrNoArg", {
args = "", name = 'CommandWithOneOrNoArg',
args = '',
fargs = {}, fargs = {},
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -408,7 +536,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -416,11 +544,13 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [[ },
exec_lua [[
vim.api.nvim_command('CommandWithOneOrNoArg') vim.api.nvim_command('CommandWithOneOrNoArg')
return result return result
]]) ]]
)
-- f-args is an empty table when the command nargs=0 -- f-args is an empty table when the command nargs=0
exec_lua [[ exec_lua [[
@@ -434,14 +564,15 @@ describe('nvim_create_user_command', function()
register = true, register = true,
}) })
]] ]]
eq({ eq(
name = "CommandWithNoArgs", {
args = "", name = 'CommandWithNoArgs',
args = '',
fargs = {}, fargs = {},
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -457,7 +588,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -465,20 +596,23 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "", reg = '',
}, exec_lua [[ },
exec_lua [[
vim.cmd('CommandWithNoArgs') vim.cmd('CommandWithNoArgs')
return result return result
]]) ]]
)
-- register can be specified -- register can be specified
eq({ eq(
name = "CommandWithNoArgs", {
args = "", name = 'CommandWithNoArgs',
args = '',
fargs = {}, fargs = {},
bang = false, bang = false,
line1 = 1, line1 = 1,
line2 = 1, line2 = 1,
mods = "", mods = '',
smods = { smods = {
browse = false, browse = false,
confirm = false, confirm = false,
@@ -494,7 +628,7 @@ describe('nvim_create_user_command', function()
noswapfile = false, noswapfile = false,
sandbox = false, sandbox = false,
silent = false, silent = false,
split = "", split = '',
tab = -1, tab = -1,
unsilent = false, unsilent = false,
verbose = -1, verbose = -1,
@@ -502,20 +636,21 @@ describe('nvim_create_user_command', function()
}, },
range = 0, range = 0,
count = 2, count = 2,
reg = "+", reg = '+',
}, exec_lua [[ },
exec_lua [[
vim.cmd('CommandWithNoArgs +') vim.cmd('CommandWithNoArgs +')
return result return result
]]) ]]
)
end) end)
it('can define buffer-local commands', function() it('can define buffer-local commands', function()
local bufnr = meths.create_buf(false, false) local bufnr = meths.create_buf(false, false)
bufmeths.create_user_command(bufnr, "Hello", "", {}) bufmeths.create_user_command(bufnr, 'Hello', '', {})
matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) matches('Not an editor command: Hello', pcall_err(meths.command, 'Hello'))
meths.set_current_buf(bufnr) meths.set_current_buf(bufnr)
meths.command("Hello") meths.command('Hello')
assert_alive() assert_alive()
end) end)
@@ -543,21 +678,51 @@ describe('nvim_create_user_command', function()
end) end)
it('does not allow invalid command names', function() 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"', {}) 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"', {}) 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"', {}) 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"', {}) 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"', {}) vim.api.nvim_create_user_command('💩', 'echo "hi"', {})
]])) ]]
)
)
end) end)
it('smods can be used with nvim_cmd', function() 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 }, {}) vim.api.nvim_cmd({ cmd = 'echo', args = { '&verbose' }, mods = opts.smods }, {})
end, {}) 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()) eq(1, #meths.list_tabpages())
exec_lua [[ exec_lua [[
@@ -599,13 +764,13 @@ describe('nvim_del_user_command', function()
meths.create_user_command('Hello', 'echo "Hi"', {}) meths.create_user_command('Hello', 'echo "Hi"', {})
meths.command('Hello') meths.command('Hello')
meths.del_user_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) end)
it('can delete buffer-local commands', function() it('can delete buffer-local commands', function()
bufmeths.create_user_command(0, 'Hello', 'echo "Hi"', {}) bufmeths.create_user_command(0, 'Hello', 'echo "Hi"', {})
meths.command('Hello') meths.command('Hello')
bufmeths.del_user_command(0, '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)
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 function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
local rv = get_extmark_by_id(ns, mark) local rv = get_extmark_by_id(ns, mark)
eq({ er, ec }, rv) eq({ er, ec }, rv)
feed("u") feed('u')
rv = get_extmark_by_id(ns, mark) rv = get_extmark_by_id(ns, mark)
eq({ sr, sc }, rv) eq({ sr, sc }, rv)
feed("<c-r>") feed('<c-r>')
rv = get_extmark_by_id(ns, mark) rv = get_extmark_by_id(ns, mark)
eq({ er, ec }, rv) eq({ er, ec }, rv)
end end
@@ -75,9 +75,9 @@ end
local function batch_check_undo_redo(ns_id, ids, before, after) local function batch_check_undo_redo(ns_id, ids, before, after)
batch_check(ns_id, ids, after) batch_check(ns_id, ids, after)
feed("u") feed('u')
batch_check(ns_id, ids, before) batch_check(ns_id, ids, before)
feed("<c-r>") feed('<c-r>')
batch_check(ns_id, ids, after) batch_check(ns_id, ids, after)
end end
@@ -89,48 +89,77 @@ describe('API/extmarks', function()
before_each(function() before_each(function()
-- Initialize some namespaces and insert 12345 into a buffer -- Initialize some namespaces and insert 12345 into a buffer
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 } 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 row = 0
col = 2 col = 2
clear() clear()
insert(init_text) insert(init_text)
ns = request('nvim_create_namespace', "my-fancy-plugin") ns = request('nvim_create_namespace', 'my-fancy-plugin')
ns2 = request('nvim_create_namespace', "my-fancy-plugin2") ns2 = request('nvim_create_namespace', 'my-fancy-plugin2')
end) end)
it('validation', function() 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(
eq("Invalid 'end_row': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} })) "Invalid 'end_col': expected Integer, got Array",
eq("Invalid 'virt_text_pos': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 })) pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 })
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_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 '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(
eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1})) "Invalid 'id': expected Integer, got Array",
eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1})) 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 -- 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_text = { { 'foo', 'Normal' } },
virt_lines = { { { 'bar', 'Normal' } } }, virt_lines = { { { 'bar', 'Normal' } } },
sign_text = 'a', sign_text = 'a',
right_gravity = 'baz', right_gravity = 'baz',
})) })
)
end) 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, { set_extmark(ns, marks[1], 0, 0, {
end_col = 0, end_col = 0,
end_row = 1 end_row = 1,
}) })
eq("Invalid 'end_col': out of range", eq(
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })) "Invalid 'end_col': out of range",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })
)
end) 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, { set_extmark(ns, marks[1], 0, 0, {
end_col = 1, end_col = 1,
end_row = 1, end_row = 1,
@@ -138,7 +167,7 @@ describe('API/extmarks', function()
}) })
end) 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, { set_extmark(ns, marks[1], 0, 0, {
end_col = 6, end_col = 6,
end_row = 0, end_row = 0,
@@ -324,9 +353,11 @@ describe('API/extmarks', function()
eq(2, #rv) eq(2, #rv)
-- prevrange with positional when mark exists at position -- prevrange with positional when mark exists at position
rv = get_extmarks(ns, positions[3], positions[1]) 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[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]) rv = get_extmarks(ns, positions[2], positions[1])
eq(2, #rv) eq(2, #rv)
-- prevrange with positional index (no mark at position) -- 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[1], 0, 4) -- check col > our upper bound
set_extmark(ns, marks[2], 1, 1) -- check col < lower bound set_extmark(ns, marks[2], 1, 1) -- check col < lower bound
set_extmark(ns, marks[3], 2, 0) -- check is inclusive set_extmark(ns, marks[3], 2, 0) -- check is inclusive
eq({{marks[1], 0, 4}, eq(
{marks[2], 1, 1}, { { marks[1], 0, 4 }, { marks[2], 1, 1 }, { marks[3], 2, 0 } },
{marks[3], 2, 0}}, get_extmarks(ns, { 0, 3 }, { 2, 0 })
get_extmarks(ns, {0, 3}, {2, 0})) )
end) end)
it('get_marks works in reverse when mark col < lower col', function() 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[2], 1, 4) -- check col > upper bound
set_extmark(ns, marks[3], 0, 2) -- check is inclusive set_extmark(ns, marks[3], 0, 2) -- check is inclusive
local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 }) local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 })
eq({{marks[1], 2, 1}, eq({ { marks[1], 2, 1 }, { marks[2], 1, 4 }, { marks[3], 0, 2 } }, rv)
{marks[2], 1, 4},
{marks[3], 0, 2}},
rv)
end) end)
it('get_marks limit=0 returns nothing', function() it('get_marks limit=0 returns nothing', function()
@@ -405,15 +433,14 @@ describe('API/extmarks', function()
eq({}, rv) eq({}, rv)
end) end)
it('marks move with line insertations', function() it('marks move with line insertations', function()
set_extmark(ns, marks[1], 0, 0) set_extmark(ns, marks[1], 0, 0)
feed("yyP") feed('yyP')
check_undo_redo(ns, marks[1], 0, 0, 1, 0) check_undo_redo(ns, marks[1], 0, 0, 1, 0)
end) end)
it('marks move with multiline insertations', function() 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) set_extmark(ns, marks[1], 1, 1)
feed('ggVGyP') feed('ggVGyP')
check_undo_redo(ns, marks[1], 1, 1, 4, 1) 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() it('marks move with line join', function()
-- do_join in ops.c -- do_join in ops.c
feed("a<cr>222<esc>") feed('a<cr>222<esc>')
set_extmark(ns, marks[1], 1, 0) set_extmark(ns, marks[1], 1, 0)
feed('ggJ') feed('ggJ')
check_undo_redo(ns, marks[1], 1, 0, 0, 6) 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() it('join works when no marks are present', function()
screen = Screen.new(15, 10) screen = Screen.new(15, 10)
screen:attach() screen:attach()
feed("a<cr>1<esc>") feed('a<cr>1<esc>')
feed('kJ') feed('kJ')
-- This shouldn't seg fault -- This shouldn't seg fault
screen:expect([[ screen:expect([[
@@ -442,21 +469,21 @@ describe('API/extmarks', function()
it('marks move with multiline join', function() it('marks move with multiline join', function()
-- do_join in ops.c -- 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) set_extmark(ns, marks[1], 3, 0)
feed('2GVGJ') feed('2GVGJ')
check_undo_redo(ns, marks[1], 3, 0, 1, 8) check_undo_redo(ns, marks[1], 3, 0, 1, 8)
end) end)
it('marks move with line deletes', function() 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) set_extmark(ns, marks[1], 2, 1)
feed('ggjdd') feed('ggjdd')
check_undo_redo(ns, marks[1], 2, 1, 1, 1) check_undo_redo(ns, marks[1], 2, 1, 1, 1)
end) end)
it('marks move with multiline deletes', function() 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) set_extmark(ns, marks[1], 3, 0)
feed('gg2dd') feed('gg2dd')
check_undo_redo(ns, marks[1], 3, 0, 1, 0) 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() it('marks move with open line', function()
-- open_line in change.c -- open_line in change.c
-- testing marks below are also moved -- testing marks below are also moved
feed("yyP") feed('yyP')
set_extmark(ns, marks[1], 0, 4) set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4) set_extmark(ns, marks[2], 1, 4)
feed('1G<s-o><esc>') feed('1G<s-o><esc>')
@@ -501,12 +528,12 @@ describe('API/extmarks', function()
-- insertchar in edit.c (the ins_str branch) -- insertchar in edit.c (the ins_str branch)
set_extmark(ns, marks[1], 0, 2) set_extmark(ns, marks[1], 0, 2)
feed('03l') feed('03l')
insert("X") insert('X')
check_undo_redo(ns, marks[1], 0, 2, 0, 2) check_undo_redo(ns, marks[1], 0, 2, 0, 2)
-- check multibyte chars -- check multibyte chars
feed('03l<esc>') feed('03l<esc>')
insert("") insert('')
check_undo_redo(ns, marks[1], 0, 2, 0, 2) check_undo_redo(ns, marks[1], 0, 2, 0, 2)
end) end)
@@ -530,7 +557,7 @@ describe('API/extmarks', function()
it('marks move with line splits (using enter)', function() it('marks move with line splits (using enter)', function()
-- open_line in change.c -- open_line in change.c
-- testing marks below are also moved -- testing marks below are also moved
feed("yyP") feed('yyP')
set_extmark(ns, marks[1], 0, 4) set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4) set_extmark(ns, marks[2], 1, 4)
feed('1Gla<cr><esc>') feed('1Gla<cr><esc>')
@@ -547,16 +574,16 @@ describe('API/extmarks', function()
it('yet again marks move with line splits', function() it('yet again marks move with line splits', function()
-- the first test above wasn't catching all errors.. -- the first test above wasn't catching all errors..
feed("A67890<esc>") feed('A67890<esc>')
set_extmark(ns, marks[1], 0, 4) 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) check_undo_redo(ns, marks[1], 0, 4, 1, 0)
end) end)
it('and one last time line splits...', function() it('and one last time line splits...', function()
set_extmark(ns, marks[1], 0, 1) set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 2) 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[1], 0, 1, 0, 1)
check_undo_redo(ns, marks[2], 0, 2, 1, 0) check_undo_redo(ns, marks[2], 0, 2, 1, 0)
end) end)
@@ -564,7 +591,7 @@ describe('API/extmarks', function()
it('multiple marks move with mark splits', function() it('multiple marks move with mark splits', function()
set_extmark(ns, marks[1], 0, 1) set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 3) 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[1], 0, 1, 1, 0)
check_undo_redo(ns, marks[2], 0, 3, 1, 2) check_undo_redo(ns, marks[2], 0, 3, 1, 2)
end) end)
@@ -656,11 +683,11 @@ describe('API/extmarks', function()
feed('0vx<esc>') feed('0vx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2) check_undo_redo(ns, marks[1], 0, 3, 0, 2)
feed("u") feed('u')
feed('0vlx<esc>') feed('0vlx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1) check_undo_redo(ns, marks[1], 0, 3, 0, 1)
feed("u") feed('u')
feed('0v2lx<esc>') feed('0v2lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0) check_undo_redo(ns, marks[1], 0, 3, 0, 0)
@@ -675,16 +702,16 @@ describe('API/extmarks', function()
feed('0x<esc>') feed('0x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2) check_undo_redo(ns, marks[1], 0, 3, 0, 2)
feed("u") feed('u')
feed('02x<esc>') feed('02x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1) check_undo_redo(ns, marks[1], 0, 3, 0, 1)
feed("u") feed('u')
feed('0v3lx<esc>') feed('0v3lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0) check_undo_redo(ns, marks[1], 0, 3, 0, 0)
-- from the other side (nothing should happen) -- from the other side (nothing should happen)
feed("u") feed('u')
feed('$vx') feed('$vx')
check_undo_redo(ns, marks[1], 0, 3, 0, 3) check_undo_redo(ns, marks[1], 0, 3, 0, 3)
end) end)
@@ -742,17 +769,31 @@ describe('API/extmarks', function()
it('delete', function() it('delete', function()
local pos1 = { local pos1 = {
{2, 4}, {2, 12}, {2, 13}, {2, 14}, {2, 25}, { 2, 4 },
{4, 8}, {4, 10}, {4, 20}, { 2, 12 },
{5, 3}, {6, 10} { 2, 13 },
{ 2, 14 },
{ 2, 25 },
{ 4, 8 },
{ 4, 10 },
{ 4, 20 },
{ 5, 3 },
{ 6, 10 },
} }
local ids = batch_set(ns, pos1) local ids = batch_set(ns, pos1)
batch_check(ns, ids, pos1) batch_check(ns, ids, pos1)
feed('3Gfiv2+ftd') feed('3Gfiv2+ftd')
batch_check_undo_redo(ns, ids, pos1, { batch_check_undo_redo(ns, ids, pos1, {
{2, 4}, {2, 12}, {2, 13}, {2, 13}, {2, 13}, { 2, 4 },
{2, 13}, {2, 15}, {2, 25}, { 2, 12 },
{3, 3}, {4, 10} { 2, 13 },
{ 2, 13 },
{ 2, 13 },
{ 2, 13 },
{ 2, 15 },
{ 2, 25 },
{ 3, 3 },
{ 4, 10 },
}) })
end) end)
@@ -762,7 +803,10 @@ describe('API/extmarks', function()
set_extmark(ns, 3, 0, 5, { end_row = 2, end_col = 10 }) set_extmark(ns, 3, 0, 5, { end_row = 2, end_col = 10 })
set_extmark(ns, 4, 0, 0, { end_row = 1, end_col = 0 }) 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({ { 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)
end) end)
@@ -862,11 +906,11 @@ describe('API/extmarks', function()
set_extmark(ns, marks[2], 0, -1) set_extmark(ns, marks[2], 0, -1)
set_extmark(ns, marks[3], 0, -1) set_extmark(ns, marks[3], 0, -1)
feed("u") feed('u')
local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv) eq(3, #rv)
feed("<c-r>") feed('<c-r>')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv) eq(3, #rv)
@@ -875,19 +919,26 @@ describe('API/extmarks', function()
set_extmark(ns, marks[1], positions[1][1], positions[1][2]) set_extmark(ns, marks[1], positions[1][1], positions[1][2])
rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 }) rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 })
eq(1, #rv) eq(1, #rv)
feed("u") feed('u')
feed("<c-r>") feed('<c-r>')
-- old value is NOT kept in history -- 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 -- Test unset
feed('o<esc>') feed('o<esc>')
curbufmeths.del_extmark(ns, marks[3]) curbufmeths.del_extmark(ns, marks[3])
feed("u") feed('u')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
-- undo does NOT restore deleted marks -- undo does NOT restore deleted marks
eq(2, #rv) eq(2, #rv)
feed("<c-r>") feed('<c-r>')
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(2, #rv) eq(2, #rv)
end) end)
@@ -966,12 +1017,12 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>') feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>') feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<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 the mark on the M, should move..
set_extmark(ns, marks[1], 0, 12) set_extmark(ns, marks[1], 0, 12)
-- Set the mark before the cursor, should stay there -- Set the mark before the cursor, should stay there
set_extmark(ns, marks[2], 0, 10) set_extmark(ns, marks[2], 0, 10)
feed("i<cr><esc>") feed('i<cr><esc>')
local rv = get_extmark_by_id(ns, marks[1]) local rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv) eq({ 1, 3 }, rv)
rv = get_extmark_by_id(ns, marks[2]) rv = get_extmark_by_id(ns, marks[2])
@@ -984,14 +1035,14 @@ describe('API/extmarks', function()
feed(':set autoindent<cr><esc>') feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>') feed(':set shiftwidth=2<cr><esc>')
-- <c-f> will force an indent of 2 -- <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) 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]) local rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv) eq({ 1, 3 }, rv)
check_undo_redo(ns, marks[1], 1, 1, 1, 3) check_undo_redo(ns, marks[1], 1, 1, 1, 3)
-- now check when cursor at eol -- now check when cursor at eol
feed("uA<c-f><esc>") feed('uA<c-f><esc>')
rv = get_extmark_by_id(ns, marks[1]) rv = get_extmark_by_id(ns, marks[1])
eq({ 1, 3 }, rv) eq({ 1, 3 }, rv)
end) end)
@@ -1000,14 +1051,14 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>') feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>') feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>') feed(':set shiftwidth=2<cr><esc>')
feed("0i<tab><esc>") feed('0i<tab><esc>')
set_extmark(ns, marks[1], 0, 3) 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]) local rv = get_extmark_by_id(ns, marks[1])
eq({ 0, 1 }, rv) eq({ 0, 1 }, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 1) check_undo_redo(ns, marks[1], 0, 3, 0, 1)
-- check when cursor at eol -- check when cursor at eol
feed("uA<c-d><esc>") feed('uA<c-d><esc>')
rv = get_extmark_by_id(ns, marks[1]) rv = get_extmark_by_id(ns, marks[1])
eq({ 0, 1 }, rv) eq({ 0, 1 }, rv)
end) end)
@@ -1016,7 +1067,7 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>') feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>') feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<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[1], 1, 1)
set_extmark(ns, marks[2], 2, 1) set_extmark(ns, marks[2], 2, 1)
feed('=gg') feed('=gg')
@@ -1374,7 +1425,10 @@ describe('API/extmarks', function()
it('throws consistent error codes', function() it('throws consistent error codes', function()
local ns_invalid = ns2 + 1 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(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_extmarks, ns_invalid, positions[1], positions[2]))
eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1])) 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() it('fails when line > line_count', function()
local invalid_col = init_text:len() + 1 local invalid_col = init_text:len() + 1
local invalid_lnum = 3 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])) eq({}, get_extmark_by_id(ns, marks[1]))
end) end)
@@ -1414,7 +1471,7 @@ describe('API/extmarks', function()
end) end)
it('in read-only buffer', function() 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', {})) eq(true, meths.get_option_value('ro', {}))
local id = set_extmark(ns, 0, 0, 2) local id = set_extmark(ns, 0, 0, 2)
eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1)) 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() it('can set a mark to other buffer', function()
local buf = request('nvim_create_buf', 0, 1) 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, {}) local id = bufmeths.set_extmark(buf, ns, 1, 0, {})
eq({ { id, 1, 0 } }, bufmeths.get_extmarks(buf, ns, 0, -1, {})) eq({ { id, 1, 0 } }, bufmeths.get_extmarks(buf, ns, 0, -1, {}))
end) end)
@@ -1444,45 +1501,47 @@ describe('API/extmarks', function()
curbufmeths.set_extmark(ns, 0, 5, { right_gravity = true }) curbufmeths.set_extmark(ns, 0, 5, { right_gravity = true })
feed([[Aasdfasdf]]) feed([[Aasdfasdf]])
eq({ {1, 0, 5}, {2, 0, 13} }, eq({ { 1, 0, 5 }, { 2, 0, 13 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
curbufmeths.get_extmarks(ns, 0, -1, {}))
-- but both move when text is inserted before -- but both move when text is inserted before
feed([[<esc>Iasdf<esc>]]) feed([[<esc>Iasdf<esc>]])
-- eq({}, curbufmeths.get_lines(0, -1, true)) -- eq({}, curbufmeths.get_lines(0, -1, true))
eq({ {1, 0, 9}, {2, 0, 17} }, eq({ { 1, 0, 9 }, { 2, 0, 17 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
curbufmeths.get_extmarks(ns, 0, -1, {}))
-- clear text -- clear text
curbufmeths.set_text(0, 0, 0, 17, {}) curbufmeths.set_text(0, 0, 0, 17, {})
-- handles set_text correctly as well -- handles set_text correctly as well
eq({ {1, 0, 0}, {2, 0, 0} }, eq({ { 1, 0, 0 }, { 2, 0, 0 } }, meths.buf_get_extmarks(0, ns, 0, -1, {}))
meths.buf_get_extmarks(0, ns, 0, -1, {}))
curbufmeths.set_text(0, 0, 0, 0, { 'asdfasdf' }) curbufmeths.set_text(0, 0, 0, 0, { 'asdfasdf' })
eq({ {1, 0, 0}, {2, 0, 8} }, eq({ { 1, 0, 0 }, { 2, 0, 8 } }, curbufmeths.get_extmarks(ns, 0, -1, {}))
curbufmeths.get_extmarks(ns, 0, -1, {}))
feed('u') feed('u')
-- handles pasting -- handles pasting
exec([[let @a='asdfasdf']]) exec([[let @a='asdfasdf']])
feed([["ap]]) feed([["ap]])
eq({ {1, 0, 0}, {2, 0, 8} }, eq({ { 1, 0, 0 }, { 2, 0, 8 } }, meths.buf_get_extmarks(0, ns, 0, -1, {}))
meths.buf_get_extmarks(0, ns, 0, -1, {}))
end) end)
it('can accept "end_row" or "end_line" #16548', function() it('can accept "end_row" or "end_line" #16548', function()
set_extmark(ns, marks[1], 0, 0, { set_extmark(ns, marks[1], 0, 0, {
end_col = 0, end_col = 0,
end_line = 1 end_line = 1,
}) })
eq({ {1, 0, 0, { eq({
{
1,
0,
0,
{
ns_id = 1, ns_id = 1,
end_col = 0, end_col = 0,
end_row = 1, end_row = 1,
right_gravity = true, right_gravity = true,
end_right_gravity = false, end_right_gravity = false,
}} }, get_extmarks(ns, 0, -1, {details=true})) },
},
}, get_extmarks(ns, 0, -1, { details = true }))
end) end)
it('in prompt buffer', function() it('in prompt buffer', function()
@@ -1495,86 +1554,103 @@ describe('API/extmarks', function()
it('can get details', function() it('can get details', function()
set_extmark(ns, marks[1], 0, 0, { set_extmark(ns, marks[1], 0, 0, {
conceal = "c", conceal = 'c',
cursorline_hl_group = "Statement", cursorline_hl_group = 'Statement',
end_col = 0, end_col = 0,
end_right_gravity = true, end_right_gravity = true,
end_row = 1, end_row = 1,
hl_eol = true, hl_eol = true,
hl_group = "String", hl_group = 'String',
hl_mode = "blend", hl_mode = 'blend',
line_hl_group = "Statement", line_hl_group = 'Statement',
number_hl_group = "Statement", number_hl_group = 'Statement',
priority = 0, priority = 0,
right_gravity = false, right_gravity = false,
sign_hl_group = "Statement", sign_hl_group = 'Statement',
sign_text = ">>", sign_text = '>>',
spell = true, spell = true,
virt_lines = { virt_lines = {
{ { "lines", "Macro" }, { "???" } }, { { 'lines', 'Macro' }, { '???' } },
{ { "stack", { "Type", "Search" } }, { "!!!" } }, { { 'stack', { 'Type', 'Search' } }, { '!!!' } },
}, },
virt_lines_above = true, virt_lines_above = true,
virt_lines_leftcol = 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_hide = true,
virt_text_pos = "right_align", virt_text_pos = 'right_align',
}) })
set_extmark(ns, marks[2], 0, 0, { set_extmark(ns, marks[2], 0, 0, {
priority = 0, priority = 0,
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } }, virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
virt_text_win_col = 1, virt_text_win_col = 1,
}) })
eq({0, 0, { eq({
conceal = "c", 0,
cursorline_hl_group = "Statement", 0,
{
conceal = 'c',
cursorline_hl_group = 'Statement',
end_col = 0, end_col = 0,
end_right_gravity = true, end_right_gravity = true,
end_row = 1, end_row = 1,
hl_eol = true, hl_eol = true,
hl_group = "String", hl_group = 'String',
hl_mode = "blend", hl_mode = 'blend',
line_hl_group = "Statement", line_hl_group = 'Statement',
ns_id = 1, ns_id = 1,
number_hl_group = "Statement", number_hl_group = 'Statement',
priority = 0, priority = 0,
right_gravity = false, right_gravity = false,
sign_hl_group = "Statement", sign_hl_group = 'Statement',
sign_text = ">>", sign_text = '>>',
spell = true, spell = true,
virt_lines = { virt_lines = {
{ { "lines", "Macro" }, { "???" } }, { { 'lines', 'Macro' }, { '???' } },
{ { "stack", { "Type", "Search" } }, { "!!!" } }, { { 'stack', { 'Type', 'Search' } }, { '!!!' } },
}, },
virt_lines_above = true, virt_lines_above = true,
virt_lines_leftcol = 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_repeat_linebreak = false,
virt_text_hide = true, virt_text_hide = true,
virt_text_pos = "right_align", virt_text_pos = 'right_align',
} }, get_extmark_by_id(ns, marks[1], { details = true })) },
eq({0, 0, { }, get_extmark_by_id(ns, marks[1], { details = true }))
eq({
0,
0,
{
ns_id = 1, ns_id = 1,
right_gravity = true, right_gravity = true,
priority = 0, priority = 0,
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } }, virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
virt_text_repeat_linebreak = false, virt_text_repeat_linebreak = false,
virt_text_hide = false, virt_text_hide = false,
virt_text_pos = "win_col", virt_text_pos = 'win_col',
virt_text_win_col = 1, 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" }) }, get_extmark_by_id(ns, marks[2], { details = true }))
eq({0, 0, { set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = 'Statement' })
eq({
0,
0,
{
ns_id = 1, ns_id = 1,
cursorline_hl_group = "Statement", cursorline_hl_group = 'Statement',
priority = 4096, priority = 4096,
right_gravity = true, 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) curbufmeths.clear_namespace(ns, 0, -1)
-- legacy sign mark includes sign name -- legacy sign mark includes sign name
command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine') command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine')
command('sign place 1 name=sign1 line=1') command('sign place 1 name=sign1 line=1')
eq({ {1, 0, 0, { eq({
{
1,
0,
0,
{
cursorline_hl_group = 'CursorLine', cursorline_hl_group = 'CursorLine',
invalidate = true, invalidate = true,
line_hl_group = 'LineNr', line_hl_group = 'LineNr',
@@ -1585,18 +1661,21 @@ describe('API/extmarks', function()
sign_hl_group = 'Title', sign_hl_group = 'Title',
sign_name = 'sign1', sign_name = 'sign1',
sign_text = 's1', sign_text = 's1',
undo_restore = false undo_restore = false,
} } }, get_extmarks(-1, 0, -1, { details = true })) },
},
}, get_extmarks(-1, 0, -1, { details = true }))
end) end)
it('can get marks from anonymous namespaces', function() it('can get marks from anonymous namespaces', function()
ns = request('nvim_create_namespace', "") ns = request('nvim_create_namespace', '')
ns2 = request('nvim_create_namespace', "") ns2 = request('nvim_create_namespace', '')
set_extmark(ns, 1, 0, 0, {}) set_extmark(ns, 1, 0, 0, {})
set_extmark(ns2, 2, 1, 0, {}) set_extmark(ns2, 2, 1, 0, {})
eq({{ 1, 0, 0, { ns_id = ns, right_gravity = true }}, eq({
{ 2, 1, 0, { ns_id = ns2, right_gravity = true }}}, { 1, 0, 0, { ns_id = ns, right_gravity = true } },
get_extmarks(-1, 0, -1, { details = true })) { 2, 1, 0, { ns_id = ns2, right_gravity = true } },
}, get_extmarks(-1, 0, -1, { details = true }))
end) end)
it('can filter by extmark properties', function() 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' })) eq({ { 5, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_lines' }))
end) end)
it("invalidated marks are deleted", function() it('invalidated marks are deleted', function()
screen = Screen.new(40, 6) screen = Screen.new(40, 6)
screen:attach() screen:attach()
feed('dd6iaaa bbb ccc<CR><ESC>gg') feed('dd6iaaa bbb ccc<CR><ESC>gg')
@@ -1641,8 +1720,13 @@ describe('API/extmarks', function()
command('1d 2') command('1d 2')
eq(0, #get_extmarks(-1, 0, -1, {})) eq(0, #get_extmarks(-1, 0, -1, {}))
-- mark is not removed when deleting bytes before the range -- mark is not removed when deleting bytes before the range
set_extmark(ns, 3, 0, 4, { invalidate = true, undo_restore = false, set_extmark(
hl_group = 'Error', end_col = 7 }) ns,
3,
0,
4,
{ invalidate = true, undo_restore = false, hl_group = 'Error', end_col = 7 }
)
feed('dw') feed('dw')
eq(3, get_extmark_by_id(ns, 3, { details = true })[3].end_col) 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 -- mark is not removed when deleting bytes at the start of the range
@@ -1658,8 +1742,13 @@ describe('API/extmarks', function()
feed('hx') feed('hx')
eq({}, get_extmark_by_id(ns, 3, {})) eq({}, get_extmark_by_id(ns, 3, {}))
-- multiline mark is not removed when start of its range is deleted -- multiline mark is not removed when start of its range is deleted
set_extmark(ns, 4, 1, 4, { undo_restore = false, invalidate = true, set_extmark(
hl_group = 'Error', end_col = 7, end_row = 3 }) ns,
4,
1,
4,
{ undo_restore = false, invalidate = true, hl_group = 'Error', end_col = 7, end_row = 3 }
)
feed('ddDdd') feed('ddDdd')
eq({ 0, 0 }, get_extmark_by_id(ns, 4, {})) eq({ 0, 0 }, get_extmark_by_id(ns, 4, {}))
-- multiline mark is removed when entirety of its range is deleted -- 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 = {} local ns_marks = {}
before_each(function() before_each(function()
clear() clear()
ns1 = request('nvim_create_namespace', "ns1") ns1 = request('nvim_create_namespace', 'ns1')
ns2 = request('nvim_create_namespace', "ns2") ns2 = request('nvim_create_namespace', 'ns2')
ns_marks = { [ns1] = {}, [ns2] = {} } ns_marks = { [ns1] = {}, [ns2] = {} }
local lines = {} local lines = {}
for i = 1, 30 do for i = 1, 30 do
lines[#lines+1] = string.rep("x ",i) lines[#lines + 1] = string.rep('x ', i)
end end
curbufmeths.set_lines(0, -1, true, lines) curbufmeths.set_lines(0, -1, true, lines)
local ns = ns1 local ns = ns1
@@ -1696,7 +1785,6 @@ describe('Extmarks buffer api with many marks', function()
end end
eq(233, #ns_marks[ns1]) eq(233, #ns_marks[ns1])
eq(232, #ns_marks[ns2]) eq(232, #ns_marks[ns2])
end) end)
local function get_marks(ns) local function get_marks(ns)
@@ -1704,18 +1792,18 @@ describe('Extmarks buffer api with many marks', function()
local marks = {} local marks = {}
for _, mark in ipairs(mark_list) do for _, mark in ipairs(mark_list) do
local id, row, col = unpack(mark) local id, row, col = unpack(mark)
eq(nil, marks[id], "duplicate mark") eq(nil, marks[id], 'duplicate mark')
marks[id] = { row, col } marks[id] = { row, col }
end end
return marks return marks
end end
it("can get marks", function() it('can get marks', function()
eq(ns_marks[ns1], get_marks(ns1)) eq(ns_marks[ns1], get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2)) eq(ns_marks[ns2], get_marks(ns2))
end) end)
it("can clear all marks in ns", function() it('can clear all marks in ns', function()
curbufmeths.clear_namespace(ns1, 0, -1) curbufmeths.clear_namespace(ns1, 0, -1)
eq({}, get_marks(ns1)) eq({}, get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2)) eq(ns_marks[ns2], get_marks(ns2))
@@ -1724,7 +1812,7 @@ describe('Extmarks buffer api with many marks', function()
eq({}, get_marks(ns2)) eq({}, get_marks(ns2))
end) end)
it("can clear line range", function() it('can clear line range', function()
curbufmeths.clear_namespace(ns1, 10, 20) curbufmeths.clear_namespace(ns1, 10, 20)
for id, mark in pairs(ns_marks[ns1]) do for id, mark in pairs(ns_marks[ns1]) do
if 10 <= mark[1] and mark[1] < 20 then 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)) eq(ns_marks[ns2], get_marks(ns2))
end) end)
it("can delete line", function() it('can delete line', function()
feed('10Gdd') feed('10Gdd')
for _, marks in pairs(ns_marks) do for _, marks in pairs(ns_marks) do
for id, mark in pairs(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)) eq(ns_marks[ns2], get_marks(ns2))
end) end)
it("can delete lines", function() it('can delete lines', function()
feed('10G10dd') feed('10G10dd')
for _, marks in pairs(ns_marks) do for _, marks in pairs(ns_marks) do
for id, mark in pairs(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)) eq(ns_marks[ns2], get_marks(ns2))
end) end)
it("can wipe buffer", function() it('can wipe buffer', function()
command('bwipe!') command('bwipe!')
eq({}, get_marks(ns1)) eq({}, get_marks(ns1))
eq({}, get_marks(ns2)) eq({}, get_marks(ns2))
@@ -1781,15 +1869,15 @@ describe('API/win_extmark', function()
-- Initialize some namespaces and insert text into a buffer -- Initialize some namespaces and insert text into a buffer
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 } marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
line1 = "non ui-watched line" line1 = 'non ui-watched line'
line2 = "ui-watched line" line2 = 'ui-watched line'
clear() clear()
insert(line1) insert(line1)
feed("o<esc>") feed('o<esc>')
insert(line2) insert(line2)
ns = request('nvim_create_namespace', "extmark-ui") ns = request('nvim_create_namespace', 'extmark-ui')
end) end)
it('sends and only sends ui-watched marks to ui', function() it('sends and only sends ui-watched marks to ui', function()
@@ -1810,7 +1898,7 @@ describe('API/win_extmark', function()
[2] = { [2] = {
-- positioned at the end of the 2nd line -- positioned at the end of the 2nd line
{ { id = 1000 }, ns, marks[1], 1, 16 }, { { id = 1000 }, ns, marks[1], 1, 16 },
} },
}, },
}) })
end) end)
@@ -1820,10 +1908,10 @@ describe('API/win_extmark', function()
screen:attach() screen:attach()
feed('15A!<Esc>') feed('15A!<Esc>')
-- should send all of these -- should send all of these
set_extmark(ns, marks[1], 1, 0, { 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[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[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[4], 1, 6, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[5], 1, 8, { ui_watched = true }) set_extmark(ns, marks[5], 1, 8, { ui_watched = true })
screen:expect({ screen:expect({
grid = [[ grid = [[
@@ -1856,7 +1944,7 @@ describe('API/win_extmark', function()
{ { id = 1000 }, ns, marks[4], 1, 6 }, { { id = 1000 }, ns, marks[4], 1, 6 },
-- eol -- eol
{ { id = 1000 }, ns, marks[5], 2, 11 }, { { id = 1000 }, ns, marks[5], 2, 11 },
} },
}, },
}) })
end) end)
@@ -1869,7 +1957,7 @@ describe('API/win_extmark', function()
-- should not send this -- should not send this
set_extmark(ns, marks[2], 0, 0, { ui_watched = false }) set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
-- make some changes -- make some changes
insert(" update") insert(' update')
screen:expect({ screen:expect({
grid = [[ grid = [[
non ui-watched line | non ui-watched line |
@@ -1883,10 +1971,10 @@ describe('API/win_extmark', function()
{ { id = 1000 }, ns, marks[1], 1, 16 }, { { id = 1000 }, ns, marks[1], 1, 16 },
-- updated and wrapped to 3rd line -- updated and wrapped to 3rd line
{ { id = 1000 }, ns, marks[1], 2, 2 }, { { id = 1000 }, ns, marks[1], 2, 2 },
} },
} },
}) })
feed("<c-e>") feed('<c-e>')
screen:expect({ screen:expect({
grid = [[ grid = [[
ui-watched linupdat^e| ui-watched linupdat^e|
@@ -1901,8 +1989,8 @@ describe('API/win_extmark', function()
-- updated and wrapped to 3rd line -- updated and wrapped to 3rd line
{ { id = 1000 }, ns, marks[1], 2, 2 }, { { id = 1000 }, ns, marks[1], 2, 2 },
-- scrolled up one line, should be handled by grid scroll -- scrolled up one line, should be handled by grid scroll
} },
} },
}) })
end) end)
@@ -1942,11 +2030,11 @@ describe('API/win_extmark', function()
[4] = { [4] = {
-- only after split -- only after split
{ { id = 1001 }, ns, marks[1], 1, 16 }, { { id = 1001 }, ns, marks[1], 1, 16 },
} },
} },
}) })
-- make some changes -- make some changes
insert(" update") insert(' update')
screen:expect({ screen:expect({
grid = [[ grid = [[
## grid 1 ## grid 1
@@ -1976,8 +2064,8 @@ describe('API/win_extmark', function()
{ { id = 1001 }, ns, marks[1], 1, 16 }, { { id = 1001 }, ns, marks[1], 1, 16 },
-- updated -- updated
{ { id = 1001 }, ns, marks[1], 2, 2 }, { { id = 1001 }, ns, marks[1], 2, 2 },
} },
} },
}) })
end) end)
end) end)

View File

@@ -45,31 +45,35 @@ describe('API: highlight',function()
before_each(function() before_each(function()
clear() 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) end)
it("nvim_get_hl_by_id", function() it('nvim_get_hl_by_id', function()
local hl_id = eval("hlID('NewHighlight')") 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')") hl_id = eval("hlID('NewHighlight')")
-- Test valid id. -- 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. -- Test invalid id.
eq('Invalid highlight id: 30000', pcall_err(meths.get_hl_by_id, 30000, false)) eq('Invalid highlight id: 30000', pcall_err(meths.get_hl_by_id, 30000, false))
-- Test all highlight properties. -- Test all highlight properties.
command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') 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 -- Test undercurl
command('hi NewHighlight gui=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. -- Test nil argument.
eq('Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer', eq(
pcall_err(meths.get_hl_by_id, { nil }, false)) '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. -- Test 0 argument.
eq('Invalid highlight id: 0', pcall_err(meths.get_hl_by_id, 0, false)) 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 Normal ctermfg=red ctermbg=yellow')
command('hi NewConstant ctermfg=green guifg=white guibg=blue') command('hi NewConstant ctermfg=green guifg=white guibg=blue')
hl_id = eval("hlID('NewConstant')") 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. -- Test highlight group without ctermfg value.
command('hi clear NewConstant') command('hi clear NewConstant')
command('hi NewConstant ctermbg=Magenta guifg=white guibg=blue') 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. -- Test highlight group with ctermfg and ctermbg values.
command('hi clear NewConstant') command('hi clear NewConstant')
command('hi NewConstant ctermfg=green ctermbg=Magenta guifg=white guibg=blue') 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) end)
it("nvim_get_hl_by_name", function() it('nvim_get_hl_by_name', function()
local expected_normal = { background = Screen.colors.Yellow, local expected_normal = { background = Screen.colors.Yellow, foreground = Screen.colors.Red }
foreground = Screen.colors.Red }
-- Test `Normal` default values. -- 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_cterm, nvim('get_hl_by_name', 'NewHighlight', false))
eq(expected_rgb, nvim("get_hl_by_name", 'NewHighlight', true)) eq(expected_rgb, nvim('get_hl_by_name', 'NewHighlight', true))
-- Test `Normal` modified values. -- Test `Normal` modified values.
command('hi Normal guifg=red guibg=yellow') 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. -- Test invalid name.
eq("Invalid highlight name: 'unknown_highlight'", eq(
pcall_err(meths.get_hl_by_name , 'unknown_highlight', false)) "Invalid highlight name: 'unknown_highlight'",
pcall_err(meths.get_hl_by_name, 'unknown_highlight', false)
)
-- Test nil argument. -- Test nil argument.
eq('Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String', eq(
pcall_err(meths.get_hl_by_name , { nil }, false)) '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. -- Test empty string argument.
eq('Invalid highlight name', eq('Invalid highlight name', pcall_err(meths.get_hl_by_name, '', false))
pcall_err(meths.get_hl_by_name , '', false))
-- Test "standout" attribute. #8054 -- Test "standout" attribute. #8054
eq({ underline = true, }, eq({ underline = true }, meths.get_hl_by_name('cursorline', 0))
meths.get_hl_by_name('cursorline', 0));
command('hi CursorLine cterm=standout,underline term=standout,underline gui=standout,underline') command('hi CursorLine cterm=standout,underline term=standout,underline gui=standout,underline')
command('set cursorline') command('set cursorline')
eq({ underline = true, standout = true, }, eq({ underline = true, standout = true }, meths.get_hl_by_name('cursorline', 0))
meths.get_hl_by_name('cursorline', 0));
-- Test cterm & Normal values. #18024 (tail) & #18980 -- Test cterm & Normal values. #18024 (tail) & #18980
-- Ensure Normal, and groups that match Normal return their fg & bg cterm values -- 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, 'Normal', { ctermfg = 17, ctermbg = 213 })
meths.set_hl(0, 'NotNormal', { ctermfg = 17, ctermbg = 213, nocombine = true }) meths.set_hl(0, 'NotNormal', { ctermfg = 17, ctermbg = 213, nocombine = true })
-- Note colors are "cterm" values, not rgb-as-ints -- 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 }, 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, nocombine = true },
nvim('get_hl_by_name', 'NotNormal', false)
)
end) end)
it('nvim_get_hl_id_by_name', function() it('nvim_get_hl_id_by_name', function()
-- precondition: use a hl group that does not yet exist -- 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("Invalid highlight name: 'Shrubbery'", pcall_err(meths.get_hl_by_name, 'Shrubbery', true))
eq(0, funcs.hlID("Shrubbery")) 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) ok(hl_id > 0)
eq(hl_id, funcs.hlID("Shrubbery")) eq(hl_id, funcs.hlID('Shrubbery'))
command('hi Shrubbery guifg=#888888 guibg=#888888') command('hi Shrubbery guifg=#888888 guibg=#888888')
eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, eq(
meths.get_hl_by_id(hl_id, true)) { foreground = tonumber('0x888888'), background = tonumber('0x888888') },
eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, meths.get_hl_by_id(hl_id, true)
meths.get_hl_by_name("Shrubbery", true)) )
eq(
{ foreground = tonumber('0x888888'), background = tonumber('0x888888') },
meths.get_hl_by_name('Shrubbery', true)
)
end) end)
it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function() 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)
end) end)
describe("API: set highlight", function() describe('API: set highlight', function()
local highlight_color = { local highlight_color = {
fg = tonumber('0xff0000'), fg = tonumber('0xff0000'),
bg = tonumber('0x0032aa'), bg = tonumber('0x0032aa'),
@@ -207,7 +218,7 @@ describe("API: set highlight", function()
strikethrough = true, strikethrough = true,
altfont = true, altfont = true,
nocombine = true, nocombine = true,
} },
} }
local highlight3_result_gui = { local highlight3_result_gui = {
background = highlight_color.bg, background = highlight_color.bg,
@@ -238,31 +249,35 @@ describe("API: set highlight", function()
before_each(clear) before_each(clear)
it('validation', function() it('validation', function()
eq("Invalid 'blend': out of range", eq(
pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend=999})) "Invalid 'blend': out of range",
eq("Invalid 'blend': expected Integer, got Array", pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = 999 })
pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend={}})) )
eq(
"Invalid 'blend': expected Integer, got Array",
pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = {} })
)
end) end)
it("can set gui highlight", function() it('can set gui highlight', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight1) meths.set_hl(ns, 'Test_hl', highlight1)
eq(highlight1, meths.get_hl_by_name('Test_hl', true)) eq(highlight1, meths.get_hl_by_name('Test_hl', true))
end) end)
it("can set cterm highlight", function() it('can set cterm highlight', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight2_config) meths.set_hl(ns, 'Test_hl', highlight2_config)
eq(highlight2_result, meths.get_hl_by_name('Test_hl', false)) eq(highlight2_result, meths.get_hl_by_name('Test_hl', false))
end) end)
it("can set empty cterm attr", function() it('can set empty cterm attr', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', { cterm = {} }) meths.set_hl(ns, 'Test_hl', { cterm = {} })
eq({}, meths.get_hl_by_name('Test_hl', false)) eq({}, meths.get_hl_by_name('Test_hl', false))
end) end)
it("cterm attr defaults to gui attr", function() it('cterm attr defaults to gui attr', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight1) meths.set_hl(ns, 'Test_hl', highlight1)
eq({ eq({
@@ -271,14 +286,14 @@ describe("API: set highlight", function()
}, meths.get_hl_by_name('Test_hl', false)) }, meths.get_hl_by_name('Test_hl', false))
end) end)
it("can overwrite attr for cterm", function() it('can overwrite attr for cterm', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', highlight3_config) meths.set_hl(ns, 'Test_hl', highlight3_config)
eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true)) eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true))
eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false)) eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false))
end) end)
it("only allows one underline attribute #22371", function() it('only allows one underline attribute #22371', function()
local ns = get_ns() local ns = get_ns()
meths.set_hl(ns, 'Test_hl', { meths.set_hl(ns, 'Test_hl', {
underdouble = true, underdouble = true,
@@ -292,76 +307,72 @@ describe("API: set highlight", function()
eq({ underdotted = true }, meths.get_hl_by_name('Test_hl', true)) eq({ underdotted = true }, meths.get_hl_by_name('Test_hl', true))
end) 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) meths.set_hl(0, 'Test_hl', highlight2_config)
eq('Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse', eq(
exec_capture('highlight Test_hl')) '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 }) meths.set_hl(0, 'Test_hl', { background = highlight_color.bg })
eq('Test_hl xxx guibg=#0032aa', eq('Test_hl xxx guibg=#0032aa', exec_capture('highlight Test_hl'))
exec_capture('highlight Test_hl'))
meths.set_hl(0, 'Test_hl2', highlight3_config) 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', eq(
exec_capture('highlight Test_hl2')) '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 -- Colors are stored with the name they are defined, but
-- with canonical casing -- with canonical casing
meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' }) meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
eq('Test_hl3 xxx guifg=Blue guibg=Red', eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
end) 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' }) meths.set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue' })
eq('Test_hl3 xxx guifg=Blue guibg=Red', eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
meths.set_hl(0, 'Test_hl3', { bg = 'red' }) meths.set_hl(0, 'Test_hl3', { bg = 'red' })
eq('Test_hl3 xxx guibg=Red', eq('Test_hl3 xxx guibg=Red', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12 }) meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12 })
eq('Test_hl3 xxx ctermfg=12 ctermbg=9', eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
meths.set_hl(0, 'Test_hl3', { ctermbg = 'red', ctermfg = 'blue' }) meths.set_hl(0, 'Test_hl3', { ctermbg = 'red', ctermfg = 'blue' })
eq('Test_hl3 xxx ctermfg=12 ctermbg=9', eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
meths.set_hl(0, 'Test_hl3', { ctermbg = 9 }) meths.set_hl(0, 'Test_hl3', { ctermbg = 9 })
eq('Test_hl3 xxx ctermbg=9', eq('Test_hl3 xxx ctermbg=9', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
eq("Invalid highlight color: 'redd'", eq("Invalid highlight color: 'redd'", pcall_err(meths.set_hl, 0, 'Test_hl3', { fg = 'redd' }))
pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'}))
eq("Invalid highlight color: 'bleu'", eq(
pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'})) "Invalid highlight color: 'bleu'",
pcall_err(meths.set_hl, 0, 'Test_hl3', { ctermfg = 'bleu' })
)
meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF' }) meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF' })
eq('Test_hl3 xxx guifg=#ff00ff', eq('Test_hl3 xxx guifg=#ff00ff', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
eq("Invalid highlight color: '#FF00FF'", eq(
pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'})) "Invalid highlight color: '#FF00FF'",
pcall_err(meths.set_hl, 0, 'Test_hl3', { ctermfg = '#FF00FF' })
)
for _, fg_val in ipairs { nil, 'NONE', 'nOnE', '', -1 } do for _, fg_val in ipairs { nil, 'NONE', 'nOnE', '', -1 } do
meths.set_hl(0, 'Test_hl3', { fg = fg_val }) meths.set_hl(0, 'Test_hl3', { fg = fg_val })
eq('Test_hl3 xxx cleared', eq('Test_hl3 xxx cleared', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
end end
meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 }) meths.set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 })
eq('Test_hl3 xxx guifg=#ff00ff blend=50', eq('Test_hl3 xxx guifg=#ff00ff blend=50', exec_capture('highlight Test_hl3'))
exec_capture('highlight Test_hl3'))
end) end)
it("correctly sets 'Normal' internal properties", function() it("correctly sets 'Normal' internal properties", function()
-- Normal has some special handling internally. #18024 -- Normal has some special handling internally. #18024
meths.set_hl(0, 'Normal', { fg = '#000083', bg = '#0000F3' }) 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) end)
it('does not segfault on invalid group name #20009', function() it('does not segfault on invalid group name #20009', function()
@@ -380,13 +391,15 @@ describe('API: get highlight', function()
local highlight1 = { local highlight1 = {
bg = highlight_color.bg, bg = highlight_color.bg,
fg = highlight_color.fg, fg = highlight_color.fg,
bold = true, italic = true, bold = true,
italic = true,
cterm = { bold = true, italic = true }, cterm = { bold = true, italic = true },
} }
local highlight2 = { local highlight2 = {
ctermbg = highlight_color.ctermbg, ctermbg = highlight_color.ctermbg,
ctermfg = highlight_color.ctermfg, ctermfg = highlight_color.ctermfg,
underline = true, reverse = true, underline = true,
reverse = true,
cterm = { underline = true, reverse = true }, cterm = { underline = true, reverse = true },
} }
local highlight3_config = { local highlight3_config = {
@@ -413,8 +426,19 @@ describe('API: get highlight', function()
fg = highlight_color.fg, fg = highlight_color.fg,
ctermbg = highlight_color.ctermbg, ctermbg = highlight_color.ctermbg,
ctermfg = highlight_color.ctermfg, ctermfg = highlight_color.ctermfg,
bold = true, italic = true, reverse = true, underdashed = true, strikethrough = true, altfont = true, bold = true,
cterm = {italic = true, nocombine = true, reverse = true, strikethrough = true, altfont = 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() local function get_ns()
@@ -434,13 +458,12 @@ describe('API: get highlight', function()
before_each(clear) before_each(clear)
it('validation', function() it('validation', function()
eq("Invalid 'name': expected String, got Integer", eq("Invalid 'name': expected String, got Integer", pcall_err(meths.get_hl, 0, { name = 177 }))
pcall_err(meths.get_hl, 0, { name = 177 }))
eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' })) eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' }))
end) end)
it('nvim_get_hl with create flag', function() 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')) eq(0, funcs.hlexists('Foo'))
meths.get_hl(0, { name = 'Bar', create = true }) meths.get_hl(0, { name = 'Bar', create = true })
eq(1, funcs.hlexists('Bar')) eq(1, funcs.hlexists('Bar'))
@@ -454,11 +477,11 @@ describe('API: get highlight', function()
meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' }) meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' })
eq({ eq({
Test_hl = { Test_hl = {
bg = 11845374 bg = 11845374,
}, },
Test_hl_link = { Test_hl_link = {
link = 'Test_hl' link = 'Test_hl',
} },
}, meths.get_hl(ns, {})) }, meths.get_hl(ns, {}))
end) end)
@@ -502,8 +525,7 @@ describe('API: get highlight', function()
undercurl = true, undercurl = true,
}, },
}) })
eq({ underdotted = true, cterm = { undercurl = true} }, eq({ underdotted = true, cterm = { undercurl = true } }, meths.get_hl(ns, { name = 'Test_hl' }))
meths.get_hl(ns, { name = 'Test_hl' }))
end) end)
it('can get a highlight in the global namespace', function() it('can get a highlight in the global namespace', function()
@@ -533,8 +555,13 @@ describe('API: get highlight', function()
command( command(
'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' 'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold'
) )
eq({ fg = 16711680, bg = 16776960, sp = 255, bold = true, eq({
ctermbg = 10, cterm = { underline = true }, fg = 16711680,
bg = 16776960,
sp = 255,
bold = true,
ctermbg = 10,
cterm = { underline = true },
}, meths.get_hl(0, { id = hl_id })) }, meths.get_hl(0, { id = hl_id }))
-- Test 0 argument -- Test 0 argument
@@ -547,14 +574,28 @@ describe('API: get highlight', function()
-- Test all highlight properties. -- Test all highlight properties.
command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine')
eq({ fg = 16711680, bg = 16776960, sp = 255, eq({
altfont = true, bold = true, italic = true, nocombine = true, reverse = true, strikethrough = true, underline = true, fg = 16711680,
ctermbg = 10, cterm = {underline = true}, 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 })) }, meths.get_hl(0, { id = hl_id }))
-- Test undercurl -- Test undercurl
command('hi NewHighlight gui=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, ctermbg = 10,
cterm = { underline = true }, cterm = { underline = true },
}, meths.get_hl(0, { id = hl_id })) }, meths.get_hl(0, { id = hl_id }))
@@ -573,7 +614,10 @@ describe('API: get highlight', function()
command('hi Bar guifg=red') command('hi Bar guifg=red')
command('hi Foo guifg=#00ff00 gui=bold,underline') command('hi Foo guifg=#00ff00 gui=bold,underline')
command('hi! link Foo Bar') 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) end)
it('can set link as well as other attributes', function() it('can set link as well as other attributes', function()
@@ -584,28 +628,28 @@ describe('API: get highlight', function()
end) end)
it("doesn't contain unset groups", function() 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) ok(id > 0)
local data = meths.get_hl(0, {}) local data = meths.get_hl(0, {})
eq(nil, data["@foobar.hubbabubba"]) eq(nil, data['@foobar.hubbabubba'])
eq(nil, data["@foobar"]) eq(nil, data['@foobar'])
command 'hi @foobar.hubbabubba gui=bold' command 'hi @foobar.hubbabubba gui=bold'
data = meths.get_hl(0, {}) data = meths.get_hl(0, {})
eq({bold = true}, data["@foobar.hubbabubba"]) eq({ bold = true }, data['@foobar.hubbabubba'])
eq(nil, data["@foobar"]) eq(nil, data['@foobar'])
-- @foobar.hubbabubba was explicitly cleared and thus shows up -- @foobar.hubbabubba was explicitly cleared and thus shows up
-- but @foobar was never touched, and thus doesn't -- but @foobar was never touched, and thus doesn't
command 'hi clear @foobar.hubbabubba' command 'hi clear @foobar.hubbabubba'
data = meths.get_hl(0, {}) data = meths.get_hl(0, {})
eq({}, data["@foobar.hubbabubba"]) eq({}, data['@foobar.hubbabubba'])
eq(nil, data["@foobar"]) eq(nil, data['@foobar'])
end) end)
it('should return default flag', function() 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' })) eq({ fg = tonumber('00ff00', 16), default = true }, meths.get_hl(0, { name = 'Tried' }))
end) end)
@@ -613,17 +657,17 @@ describe('API: get highlight', function()
meths.set_hl(0, 'Foo', { default = true }) meths.set_hl(0, 'Foo', { default = true })
meths.set_hl(0, 'Bar', { default = true, fg = '#ffffff' }) meths.set_hl(0, 'Bar', { default = true, fg = '#ffffff' })
meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } }) meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } })
meths.set_hl(0, 'FooBarA', { default = true, fg = '#ffffff', cterm = {bold = true,italic = true}}) meths.set_hl(
0,
'FooBarA',
{ default = true, fg = '#ffffff', cterm = { bold = true, italic = true } }
)
eq('Foo xxx cleared', eq('Foo xxx cleared', exec_capture('highlight Foo'))
exec_capture('highlight Foo'))
eq({ default = true }, meths.get_hl(0, { name = 'Foo' })) eq({ default = true }, meths.get_hl(0, { name = 'Foo' }))
eq('Bar xxx guifg=#ffffff', eq('Bar xxx guifg=#ffffff', exec_capture('highlight Bar'))
exec_capture('highlight Bar')) eq('FooBar xxx cterm=bold guifg=#ffffff', exec_capture('highlight FooBar'))
eq('FooBar xxx cterm=bold guifg=#ffffff', eq('FooBarA xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA'))
exec_capture('highlight FooBar'))
eq('FooBarA xxx cterm=bold,italic guifg=#ffffff',
exec_capture('highlight FooBarA'))
end) end)
it('can override exist highlight group by force #20323', function() 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 -- and the dictionary you would get from maparg
-- since this is a global map, and not script local -- since this is a global map, and not script local
eq({ foo_bar_map_table }, meths.get_keymap('n')) eq({ foo_bar_map_table }, meths.get_keymap('n'))
eq({funcs.maparg('foo', 'n', false, true)}, eq({ funcs.maparg('foo', 'n', false, true) }, meths.get_keymap('n'))
meths.get_keymap('n')
)
-- Add another mapping -- Add another mapping
command('nnoremap foo_longer bar_longer') 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['lhsraw'] = 'foo_longer'
foolong_bar_map_table['rhs'] = 'bar_longer' foolong_bar_map_table['rhs'] = 'bar_longer'
eq({foolong_bar_map_table, foo_bar_map_table}, eq({ foolong_bar_map_table, foo_bar_map_table }, meths.get_keymap('n'))
meths.get_keymap('n')
)
-- Remove a mapping -- Remove a mapping
command('unmap foo_longer') command('unmap foo_longer')
eq({foo_bar_map_table}, eq({ foo_bar_map_table }, meths.get_keymap('n'))
meths.get_keymap('n')
)
end) end)
it('works for other modes', function() it('works for other modes', function()
@@ -162,15 +156,16 @@ describe('nvim_get_keymap', function()
-- Test toggle switches for basic options -- Test toggle switches for basic options
-- @param option The key represented in the `maparg()` result dict -- @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,
option_token, option_token,
global_on_result, global_on_result,
buffer_on_result, buffer_on_result,
global_off_result, global_off_result,
buffer_off_result, buffer_off_result,
new_windows) new_windows
)
local function make_new_windows(number_of_windows) local function make_new_windows(number_of_windows)
if new_windows == nil then if new_windows == nil then
return nil return nil
@@ -184,41 +179,77 @@ describe('nvim_get_keymap', function()
local mode = string.sub(map, 1, 1) local mode = string.sub(map, 1, 1)
-- Don't run this for the <buffer> mapping, since it doesn't make sense -- Don't run this for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then if option_token ~= '<buffer>' then
it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)', it(
global_on_result, option, option_token, map, mode), function() 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) make_new_windows(new_windows)
command(map .. ' ' .. option_token .. ' foo bar') command(map .. ' ' .. option_token .. ' foo bar')
local result = meths.get_keymap(mode)[1][option] local result = meths.get_keymap(mode)[1][option]
eq(global_on_result, result) eq(global_on_result, result)
end) end
)
end end
it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)', it(
buffer_on_result, option, option_token, map, mode), function() 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) make_new_windows(new_windows)
command(map .. ' <buffer> ' .. option_token .. ' foo bar') command(map .. ' <buffer> ' .. option_token .. ' foo bar')
local result = curbufmeths.get_keymap(mode)[1][option] local result = curbufmeths.get_keymap(mode)[1][option]
eq(buffer_on_result, result) eq(buffer_on_result, result)
end) end
)
-- Don't run these for the <buffer> mapping, since it doesn't make sense -- Don't run these for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then if option_token ~= '<buffer>' then
it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)', it(
global_off_result, option, option_token, map, mode), function() 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) make_new_windows(new_windows)
command(map .. ' baz bat') command(map .. ' baz bat')
local result = meths.get_keymap(mode)[1][option] local result = meths.get_keymap(mode)[1][option]
eq(global_off_result, result) 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)', it(
buffer_off_result, option, option_token, map, mode), function() 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) make_new_windows(new_windows)
command(map .. ' <buffer> foo bar') command(map .. ' <buffer> foo bar')
local result = curbufmeths.get_keymap(mode)[1][option] local result = curbufmeths.get_keymap(mode)[1][option]
eq(buffer_off_result, result) eq(buffer_off_result, result)
end) end
)
end end
end end
@@ -323,18 +354,22 @@ describe('nvim_get_keymap', function()
'set cpo+=B', 'set cpo+=B',
}) do }) do
command(cmd) command(cmd)
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), eq({
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')}, cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
get_keymap_noraw('n')) cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n'),
eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), }, get_keymap_noraw('n'))
cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')}, eq({
get_keymap_noraw('x')) cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x'),
cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')}, }, get_keymap_noraw('x'))
get_keymap_noraw('s')) eq({
eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), 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>', 'o')}, cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's'),
get_keymap_noraw('o')) }, 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
end) end)
@@ -361,19 +396,25 @@ describe('nvim_get_keymap', function()
end) end)
it('can handle lua mappings', function() it('can handle lua mappings', function()
eq(0, exec_lua([[ eq(
0,
exec_lua([[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]])) ]])
)
feed('asdf\n') feed('asdf\n')
eq(1, exec_lua([[return GlobalCount]])) eq(1, exec_lua([[return GlobalCount]]))
eq(2, exec_lua([[ eq(
2,
exec_lua([[
vim.api.nvim_get_keymap('n')[1].callback() vim.api.nvim_get_keymap('n')[1].callback()
return GlobalCount return GlobalCount
]])) ]])
)
exec([[ exec([[
call nvim_get_keymap('n')[0].callback() call nvim_get_keymap('n')[0].callback()
@@ -401,7 +442,7 @@ describe('nvim_get_keymap', function()
end) end)
it('can handle map descriptions', function() 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({ eq({
lhs = 'lhs', lhs = 'lhs',
lhsraw = 'lhs', lhsraw = 'lhs',
@@ -418,7 +459,7 @@ describe('nvim_get_keymap', function()
abbr = 0, abbr = 0,
noremap = 0, noremap = 0,
lnum = 0, lnum = 0,
desc='map description' desc = 'map description',
}, meths.get_keymap('n')[1]) }, meths.get_keymap('n')[1])
end) end)
end) end)
@@ -503,10 +544,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
-- 51 chars should produce an error -- 51 chars should produce an error
lhs = lhs .. '1' lhs = lhs .. '1'
eq('LHS exceeds maximum map length: '..lhs, eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(meths.set_keymap, '', lhs, 'rhs', {}))
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.del_keymap, '', lhs))
end) end)
it('does not throw errors when rhs is longer than MAXMAPLEN', function() 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 end
rhs = rhs .. '1' rhs = rhs .. '1'
meths.set_keymap('', 'lhs', rhs, {}) meths.set_keymap('', 'lhs', rhs, {})
eq(generate_mapargs('', 'lhs', rhs), eq(generate_mapargs('', 'lhs', rhs), get_mapargs('', 'lhs'))
get_mapargs('', 'lhs'))
end) end)
it('error on invalid mode shortname', function() 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: "!!"', pcall_err(meths.set_keymap, '!!', 'lhs', 'rhs', {}))
eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', '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: "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: " "', pcall_err(meths.del_keymap, ' ', 'lhs'))
eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs')) eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs'))
eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs')) eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs'))
@@ -551,22 +592,20 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('error on invalid optnames', function() it('error on invalid optnames', function()
eq("Invalid key: 'silentt'", eq("Invalid key: 'silentt'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { silentt = true }))
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: 'sidd'", eq("Invalid key: 'nowaiT'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { nowaiT = false }))
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) end)
it('error on <buffer> option key', function() it('error on <buffer> option key', function()
eq("Invalid key: 'buffer'", eq("Invalid key: 'buffer'", pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { buffer = true }))
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true}))
end) end)
it('error when "replace_keycodes" is used without "expr"', function() it('error when "replace_keycodes" is used without "expr"', function()
eq('"replace_keycodes" requires "expr"', eq(
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {replace_keycodes = true})) '"replace_keycodes" requires "expr"',
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', { replace_keycodes = true })
)
end) end)
local optnames = { 'nowait', 'silent', 'script', 'expr', 'unique' } 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() it('throws an error when given non-boolean value for ' .. opt, function()
local opts = {} local opts = {}
opts[opt] = 'fooo' opts[opt] = 'fooo'
eq(opt..' is not a boolean', eq(opt .. ' is not a boolean', pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
end) end)
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() it('does not throw when LHS or RHS have leading/trailing whitespace', function()
meths.set_keymap('n', ' lhs', 'rhs', {}) meths.set_keymap('n', ' lhs', 'rhs', {})
eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), get_mapargs('n', ' lhs'))
get_mapargs('n', ' lhs'))
meths.set_keymap('n', 'lhs ', 'rhs', {}) meths.set_keymap('n', 'lhs ', 'rhs', {})
eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), get_mapargs('n', 'lhs '))
get_mapargs('n', 'lhs '))
meths.set_keymap('v', ' lhs ', '\trhs\t\f', {}) meths.set_keymap('v', ' lhs ', '\trhs\t\f', {})
eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), get_mapargs('v', ' lhs '))
get_mapargs('v', ' lhs '))
end) end)
it('can set noremap mappings', function() it('can set noremap mappings', function()
meths.set_keymap('x', 'lhs', 'rhs', { noremap = true }) meths.set_keymap('x', 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs('x', 'lhs', 'rhs', {noremap = true}), eq(generate_mapargs('x', 'lhs', 'rhs', { noremap = true }), get_mapargs('x', 'lhs'))
get_mapargs('x', 'lhs'))
meths.set_keymap('t', 'lhs', 'rhs', { noremap = true }) meths.set_keymap('t', 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs('t', 'lhs', 'rhs', {noremap = true}), eq(generate_mapargs('t', 'lhs', 'rhs', { noremap = true }), get_mapargs('t', 'lhs'))
get_mapargs('t', 'lhs'))
end) end)
it('can unmap mappings', function() 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 _, lhs in ipairs(special_chars) do
for _, rhs in ipairs(special_chars) do for _, rhs in ipairs(special_chars) do
local mapmode = '!' local mapmode = '!'
it('can set mappings with special characters, lhs: '..lhs..', rhs: '..rhs, it('can set mappings with special characters, lhs: ' .. lhs .. ', rhs: ' .. rhs, function()
function()
meths.set_keymap(mapmode, lhs, rhs, {}) 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))
end) end)
@@ -655,8 +687,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
meths.set_keymap('i', 'lhs', '<Nop>', {}) meths.set_keymap('i', 'lhs', '<Nop>', {})
command('normal ilhs') command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing eq({ '' }, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing
eq(generate_mapargs('i', 'lhs', '<Nop>', {}), eq(generate_mapargs('i', 'lhs', '<Nop>', {}), get_mapargs('i', 'lhs'))
get_mapargs('i', 'lhs'))
-- also test for case insensitivity -- also test for case insensitivity
meths.set_keymap('i', 'lhs', '<nOp>', {}) 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)) eq({ '' }, curbufmeths.get_lines(0, -1, 0))
-- note: RHS in returned mapargs() dict reflects the original RHS -- note: RHS in returned mapargs() dict reflects the original RHS
-- provided by the user -- provided by the user
eq(generate_mapargs('i', 'lhs', '<nOp>', {}), eq(generate_mapargs('i', 'lhs', '<nOp>', {}), get_mapargs('i', 'lhs'))
get_mapargs('i', 'lhs'))
meths.set_keymap('i', 'lhs', '<NOP>', {}) meths.set_keymap('i', 'lhs', '<NOP>', {})
command('normal ilhs') command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0)) eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '<NOP>', {}), eq(generate_mapargs('i', 'lhs', '<NOP>', {}), get_mapargs('i', 'lhs'))
get_mapargs('i', 'lhs'))
-- a single ^V in RHS is also <Nop> (see :h map-empty-rhs) -- a single ^V in RHS is also <Nop> (see :h map-empty-rhs)
meths.set_keymap('i', 'lhs', '\022', {}) meths.set_keymap('i', 'lhs', '\022', {})
command('normal ilhs') command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0)) eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '\022', {}), eq(generate_mapargs('i', 'lhs', '\022', {}), get_mapargs('i', 'lhs'))
get_mapargs('i', 'lhs'))
end) end)
it('treats an empty RHS in a mapping like a <Nop>', function() it('treats an empty RHS in a mapping like a <Nop>', function()
meths.set_keymap('i', 'lhs', '', {}) meths.set_keymap('i', 'lhs', '', {})
command('normal ilhs') command('normal ilhs')
eq({ '' }, curbufmeths.get_lines(0, -1, 0)) eq({ '' }, curbufmeths.get_lines(0, -1, 0))
eq(generate_mapargs('i', 'lhs', '', {}), eq(generate_mapargs('i', 'lhs', '', {}), get_mapargs('i', 'lhs'))
get_mapargs('i', 'lhs'))
end) end)
it('can set and unset <M-">', function() it('can set and unset <M-">', function()
@@ -698,19 +725,22 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq({}, get_mapargs('i', '<M-">')) eq({}, get_mapargs('i', '<M-">'))
end) end)
it('interprets control sequences in expr-quotes correctly when called ' it(
..'inside vim', function() 'interprets control sequences in expr-quotes correctly when called ' .. 'inside vim',
function()
command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]]) command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
eq(generate_mapargs('i', '<Space>', '\t', {sid=0}), eq(generate_mapargs('i', '<Space>', '\t', { sid = 0 }), get_mapargs('i', '<Space>'))
get_mapargs('i', '<Space>'))
feed('i ') feed('i ')
eq({ '\t' }, curbufmeths.get_lines(0, -1, 0)) eq({ '\t' }, curbufmeths.get_lines(0, -1, 0))
end) end
)
it('throws appropriate error messages when setting <unique> maps', function() it('throws appropriate error messages when setting <unique> maps', function()
meths.set_keymap('l', 'lhs', 'rhs', {}) meths.set_keymap('l', 'lhs', 'rhs', {})
eq('E227: mapping already exists for lhs', eq(
pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', {unique = true})) 'E227: mapping already exists for lhs',
pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', { unique = true })
)
-- different mapmode, no error should be thrown -- different mapmode, no error should be thrown
meths.set_keymap('t', 'lhs', 'rhs', { unique = true }) meths.set_keymap('t', 'lhs', 'rhs', { unique = true })
end) end)
@@ -764,7 +794,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq({ 'mhs' }, curbufmeths.get_lines(0, -1, 0)) eq({ 'mhs' }, curbufmeths.get_lines(0, -1, 0))
end) 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', '123456', 'longer', {})
meths.set_keymap('i', '123', 'shorter', { nowait = true }) 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 for _, mapmode in ipairs(mapmodes) do
it('can set/unset normal mappings in mapmode ' .. mapmode, function() it('can set/unset normal mappings in mapmode ' .. mapmode, function()
meths.set_keymap(mapmode, 'lhs', 'rhs', {}) meths.set_keymap(mapmode, 'lhs', 'rhs', {})
eq(generate_mapargs(mapmode, 'lhs', 'rhs'), eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
get_mapargs(mapmode, 'lhs'))
-- some mapmodes (like 'o') will prevent other mapmodes (like '!') from -- some mapmodes (like 'o') will prevent other mapmodes (like '!') from
-- taking effect, so unmap after each mapping -- 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 for _, mapmode in ipairs(mapmodes) do
it('can set/unset noremap mappings using mapmode ' .. mapmode, function() it('can set/unset noremap mappings using mapmode ' .. mapmode, function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { noremap = true }) meths.set_keymap(mapmode, 'lhs', 'rhs', { noremap = true })
eq(generate_mapargs(mapmode, 'lhs', 'rhs', {noremap = true}), eq(generate_mapargs(mapmode, 'lhs', 'rhs', { noremap = true }), get_mapargs(mapmode, 'lhs'))
get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs') meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(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 for _, mapmode in ipairs(mapmodes) do
-- Test with single mappings -- Test with single mappings
for _, maparg in ipairs(optnames) do for _, maparg in ipairs(optnames) do
it('can set/unset '..mapmode..'-mappings with maparg: '..maparg, it('can set/unset ' .. mapmode .. '-mappings with maparg: ' .. maparg, function()
function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = true }) meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = true })
eq(generate_mapargs(mapmode, 'lhs', 'rhs', {[maparg] = true}), eq(
get_mapargs(mapmode, 'lhs')) generate_mapargs(mapmode, 'lhs', 'rhs', { [maparg] = true }),
get_mapargs(mapmode, 'lhs')
)
meths.del_keymap(mapmode, 'lhs') meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs')) eq({}, get_mapargs(mapmode, 'lhs'))
end) end)
it ('can set/unset '..mapmode..'-mode mappings with maparg '.. it(
maparg..', whose value is false', function() 'can set/unset '
.. mapmode
.. '-mode mappings with maparg '
.. maparg
.. ', whose value is false',
function()
meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = false }) meths.set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = false })
eq(generate_mapargs(mapmode, 'lhs', 'rhs'), eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs') meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs')) eq({}, get_mapargs(mapmode, 'lhs'))
end) end
)
end end
-- Test with triplets of mappings, one of which is false -- Test with triplets of mappings, one of which is false
for i = 1, (#optnames - 2) do for i = 1, (#optnames - 2) do
local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2] local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2]
it('can set/unset '..mapmode..'-mode mappings with mapargs '.. it(
opt1..', '..opt2..', '..opt3, function() 'can set/unset '
.. mapmode
.. '-mode mappings with mapargs '
.. opt1
.. ', '
.. opt2
.. ', '
.. opt3,
function()
local opts = { [opt1] = true, [opt2] = false, [opt3] = true } local opts = { [opt1] = true, [opt2] = false, [opt3] = true }
meths.set_keymap(mapmode, 'lhs', 'rhs', opts) meths.set_keymap(mapmode, 'lhs', 'rhs', opts)
eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), get_mapargs(mapmode, 'lhs'))
get_mapargs(mapmode, 'lhs'))
meths.del_keymap(mapmode, 'lhs') meths.del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs')) eq({}, get_mapargs(mapmode, 'lhs'))
end) end
)
end end
end end
it('can make lua mappings', function() it('can make lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') feed('asdf\n')
@@ -862,7 +907,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
assert.truthy( assert.truthy(
string.match( string.match(
exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]], exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]],
"^\nn asdf <Lua %d+>" '^\nn asdf <Lua %d+>'
) )
) )
end) end)
@@ -871,18 +916,20 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
exec_lua [[ exec_lua [[
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end })
]] ]]
assert.truthy(string.match(funcs.mapcheck('asdf', 'n'), assert.truthy(string.match(funcs.mapcheck('asdf', 'n'), '^<Lua %d+>'))
"^<Lua %d+>"))
end) end)
it('maparg() returns lua mapping correctly', function() it('maparg() returns lua mapping correctly', function()
eq(0, exec_lua([[ eq(
0,
exec_lua([[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount 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) local mapargs = funcs.maparg('asdf', 'n', false, true)
mapargs.callback = nil mapargs.callback = nil
@@ -890,10 +937,13 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
mapargs.lhsrawalt = nil mapargs.lhsrawalt = nil
eq(generate_mapargs('n', 'asdf', nil, { sid = sid_lua }), mapargs) 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() vim.fn.maparg('asdf', 'n', false, true).callback()
return GlobalCount return GlobalCount
]])) ]])
)
exec([[ exec([[
call maparg('asdf', 'n', v:false, v:true).callback() call maparg('asdf', 'n', v:false, v:true).callback()
@@ -932,21 +982,27 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('does not reset pum in lua mapping', function() it('does not reset pum in lua mapping', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
VisibleCount = 0 VisibleCount = 0
vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end}) vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
return VisibleCount return VisibleCount
]]) ]]
)
feed('i<C-X><C-V><F2><F2><esc>') feed('i<C-X><C-V><F2><F2><esc>')
eq(2, exec_lua [[return VisibleCount]]) eq(2, exec_lua [[return VisibleCount]])
end) end)
it('redo of lua mappings in op-pending mode work', function() it('redo of lua mappings in op-pending mode work', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
OpCount = 0 OpCount = 0
vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end}) vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end})
return OpCount return OpCount
]]) ]]
)
feed('d<F2>') feed('d<F2>')
eq(1, exec_lua [[return OpCount]]) eq(1, exec_lua [[return OpCount]])
feed('.') feed('.')
@@ -954,11 +1010,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('can overwrite lua mappings', function() it('can overwrite lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') feed('asdf\n')
@@ -974,11 +1033,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('can unmap lua mappings', function() it('can unmap lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') feed('asdf\n')
@@ -995,11 +1057,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('no double-free when unmapping simplifiable lua mappings', function() it('no double-free when unmapping simplifiable lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('<C-I>\n') feed('<C-I>\n')
@@ -1016,10 +1081,9 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end) end)
it('can set descriptions on mappings', function() it('can set descriptions on mappings', function()
meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"}) meths.set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
eq(generate_mapargs('n', 'lhs', 'rhs', {desc="map description"}), get_mapargs('n', 'lhs')) eq(generate_mapargs('n', 'lhs', 'rhs', { desc = 'map description' }), get_mapargs('n', 'lhs'))
eq("\nn lhs rhs\n map description", eq('\nn lhs rhs\n map description', helpers.exec_capture('nmap lhs'))
helpers.exec_capture("nmap lhs"))
end) end)
it('can define !-mode abbreviations with lua callbacks', function() it('can define !-mode abbreviations with lua callbacks', function()
@@ -1103,8 +1167,10 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end end
it('rejects negative bufnr values', function() it('rejects negative bufnr values', function()
eq('Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer', eq(
pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {})) 'Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer',
pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {})
)
end) end)
it('can set mappings active in the current buffer but not others', function() 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() it("can't disable mappings given wrong buffer handle", function()
local first, second = make_two_buffers(false) local first, second = make_two_buffers(false)
bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
eq('E31: No such mapping', eq('E31: No such mapping', pcall_err(bufmeths.del_keymap, second, '', 'lhs'))
pcall_err(bufmeths.del_keymap, second, '', 'lhs'))
-- should still work -- should still work
switch_to_buf(first) 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)) eq({ 'rhs' }, bufmeths.get_lines(0, 0, 1, 1))
end) 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>', {}) pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
helpers.assert_alive() helpers.assert_alive()
end) end)
it('can make lua mappings', function() it('can make lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') 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)) eq({ '<space>' }, meths.buf_get_lines(0, 0, -1, false))
end) end)
it('can overwrite lua mappings', function() it('can overwrite lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') feed('asdf\n')
@@ -1221,11 +1291,14 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end) end)
it('can unmap lua mappings', function() it('can unmap lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('asdf\n') feed('asdf\n')
@@ -1242,11 +1315,14 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end) end)
it('no double-free when unmapping simplifiable lua mappings', function() it('no double-free when unmapping simplifiable lua mappings', function()
eq(0, exec_lua [[ eq(
0,
exec_lua [[
GlobalCount = 0 GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount return GlobalCount
]]) ]]
)
feed('<C-I>\n') feed('<C-I>\n')

View File

@@ -5,8 +5,7 @@ local clear = helpers.clear
local command = helpers.command local command = helpers.command
local feed = helpers.feed local feed = helpers.feed
describe("update_menu notification", function() describe('update_menu notification', function()
local screen local screen
before_each(function() before_each(function()
@@ -16,7 +15,8 @@ describe("update_menu notification", function()
end) end)
local function expect_sent(expected) local function expect_sent(expected)
screen:expect{condition=function() screen:expect {
condition = function()
if screen.update_menu ~= expected then if screen.update_menu ~= expected then
if expected then if expected then
error('update_menu was expected but not sent') error('update_menu was expected but not sent')
@@ -24,15 +24,17 @@ describe("update_menu notification", function()
error('update_menu was sent unexpectedly') error('update_menu was sent unexpectedly')
end end
end end
end, unchanged=(not expected)} end,
unchanged = not expected,
}
end end
it("should be sent when adding a menu", function() it('should be sent when adding a menu', function()
command('menu Test.Test :') command('menu Test.Test :')
expect_sent(true) expect_sent(true)
end) end)
it("should be sent when deleting a menu", function() it('should be sent when deleting a menu', function()
command('menu Test.Test :') command('menu Test.Test :')
screen.update_menu = false screen.update_menu = false
@@ -40,9 +42,8 @@ describe("update_menu notification", function()
expect_sent(true) expect_sent(true)
end) end)
it("should not be sent unnecessarily", function() it('should not be sent unnecessarily', function()
feed('i12345<ESC>:redraw<CR>') feed('i12345<ESC>:redraw<CR>')
expect_sent(false) expect_sent(false)
end) end)
end) end)

View File

@@ -43,16 +43,16 @@ describe('API', function()
end) end)
it('validation', function() 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(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(false, status)
eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*'))
-- Assume PID 99999 does not exist. -- 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(true, status)
eq({}, rv) eq({}, rv)
end) end)
@@ -69,16 +69,16 @@ describe('API', function()
end) end)
it('validation', function() 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(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(false, status)
eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*'))
-- Assume PID 99999 does not exist. -- 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(true, status)
eq(NIL, rv) eq(NIL, rv)
end) end)

View File

@@ -15,8 +15,8 @@ local function on_request(method, args)
return 'ok' return 'ok'
elseif method == 'write_stderr' then elseif method == 'write_stderr' then
io.stderr:write(args[1]) io.stderr:write(args[1])
return "done!" return 'done!'
elseif method == "exit" then elseif method == 'exit' then
session:stop() session:stop()
return vim.NIL return vim.NIL
end end
@@ -24,7 +24,7 @@ end
local function on_notification(event, args) local function on_notification(event, args)
if event == 'ping' and #args == 0 then 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
end end

View File

@@ -1,8 +1,7 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local assert_log = helpers.assert_log local assert_log = helpers.assert_log
local eq, clear, eval, command, nvim, next_msg = local eq, clear, eval, command, nvim, next_msg =
helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, helpers.next_msg
helpers.next_msg
local meths = helpers.meths local meths = helpers.meths
local exec_lua = helpers.exec_lua local exec_lua = helpers.exec_lua
local retry = helpers.retry local retry = helpers.retry
@@ -90,14 +89,24 @@ describe('notify', function()
it('cancels stale events on channel close', function() it('cancels stale events on channel close', function()
local catchan = eval("jobstart(['cat'], {'rpc': v:true})") local catchan = eval("jobstart(['cat'], {'rpc': v:true})")
local catpath = eval('exepath("cat")') 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_call_function", 'chanclose', {..., 'rpc'})
vim.rpcnotify(..., "nvim_subscribe", "daily_rant") vim.rpcnotify(..., "nvim_subscribe", "daily_rant")
return vim.api.nvim_get_chan_info(...) return vim.api.nvim_get_chan_info(...)
]], catchan)) ]],
catchan
)
)
assert_alive() assert_alive()
eq({false, 'Invalid channel: '..catchan}, eq(
exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan)) { false, 'Invalid channel: ' .. catchan },
retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :( 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)
end) end)

View File

@@ -113,18 +113,18 @@ describe('server -> client', function()
it('does not delay notifications during pending request', function() it('does not delay notifications during pending request', function()
local received = false local received = false
local function on_setup() local function on_setup()
eq("retval", funcs.rpcrequest(cid, "doit")) eq('retval', funcs.rpcrequest(cid, 'doit'))
stop() stop()
end end
local function on_request(method) local function on_request(method)
if method == "doit" then if method == 'doit' then
funcs.rpcnotify(cid, "headsup") funcs.rpcnotify(cid, 'headsup')
eq(true, received) eq(true, received)
return "retval" return 'retval'
end end
end end
local function on_notification(method) local function on_notification(method)
if method == "headsup" then if method == 'headsup' then
received = true received = true
end end
end end
@@ -152,10 +152,10 @@ describe('server -> client', function()
end end
local function on_request(method) local function on_request(method)
if method == "notify" then if method == 'notify' then
eq(1, eval('rpcnotify(' .. cid .. ', "notification")')) eq(1, eval('rpcnotify(' .. cid .. ', "notification")'))
return 'notified!' return 'notified!'
elseif method == "nested" then elseif method == 'nested' then
-- do some busywork, so the first request will return -- do some busywork, so the first request will return
-- before this one -- before this one
for _ = 1, 5 do for _ = 1, 5 do
@@ -167,9 +167,9 @@ describe('server -> client', function()
end end
local function on_notification(method) local function on_notification(method)
if method == "notification" then if method == 'notification' then
eq('done!', eval('rpcrequest(' .. cid .. ', "nested")')) eq('done!', eval('rpcrequest(' .. cid .. ', "nested")'))
elseif method == "nested_done" then elseif method == 'nested_done' then
ok(false, 'never sent', 'sent') ok(false, 'never sent', 'sent')
end end
end end
@@ -182,11 +182,17 @@ describe('server -> client', function()
describe('recursive (child) nvim client', function() describe('recursive (child) nvim client', function()
before_each(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')) neq(0, eval('vim'))
end) 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() it('can send/receive notifications and make requests', function()
nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')") 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')") eval("rpcnotify(vim, 'buffer_set_line', " .. buf .. ", 0, 'SOME TEXT')")
nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait 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) -- 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) end)
it('returns an error if the request failed', function() it('returns an error if the request failed', function()
eq("Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist", eq(
pcall_err(eval, "rpcrequest(vim, 'does-not-exist')")) "Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist",
pcall_err(eval, "rpcrequest(vim, 'does-not-exist')")
)
end) end)
end) end)
@@ -236,13 +244,14 @@ describe('server -> client', function()
\ 'rpc': v:true \ 'rpc': v:true
\ } \ }
]]) ]])
meths.set_var("args", { meths.set_var('args', {
nvim_prog, '-ll', nvim_prog,
'-ll',
'test/functional/api/rpc_fixture.lua', 'test/functional/api/rpc_fixture.lua',
package.path, package.path,
package.cpath, package.cpath,
}) })
jobid = eval("jobstart(g:args, g:job_opts)") jobid = eval('jobstart(g:args, g:job_opts)')
neq(0, jobid) neq(0, jobid)
end) end)
@@ -250,7 +259,9 @@ describe('server -> client', function()
pcall(funcs.jobstop, jobid) pcall(funcs.jobstop, jobid)
end) 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() it('rpc and text stderr can be combined', function()
local status, rv = pcall(funcs.rpcrequest, jobid, 'poll') 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)) error(string.format('missing nvim Lua module? (%s)', rv))
end end
eq('ok', rv) eq('ok', rv)
funcs.rpcnotify(jobid, "ping") funcs.rpcnotify(jobid, 'ping')
eq({ 'notification', 'pong', {} }, next_msg()) 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()) 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', 'stderr', { 0, { '' } } }, next_msg())
eq({ 'notification', 'exit', { 0, 0 } }, next_msg()) eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end) end)
@@ -311,7 +322,7 @@ describe('server -> client', function()
it('via ipv4 address', function() it('via ipv4 address', function()
local server = spawn(nvim_argv) local server = spawn(nvim_argv)
set_session(server) 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 if not status then
pending('no ipv4 stack') pending('no ipv4 stack')
end end
@@ -333,7 +344,7 @@ describe('server -> client', function()
it('via hostname', function() it('via hostname', function()
local server = spawn(nvim_argv) local server = spawn(nvim_argv)
set_session(server) set_session(server)
local address = funcs.serverstart("localhost:") local address = funcs.serverstart('localhost:')
eq('localhost:', string.sub(address, 1, 10)) eq('localhost:', string.sub(address, 1, 10))
connect_test(server, 'tcp', address) connect_test(server, 'tcp', address)
end) end)
@@ -365,7 +376,7 @@ describe('server -> client', function()
funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') funcs.rpcrequest(id, 'nvim_set_current_line', 'hello')
eq('hello', meths.get_current_line()) 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]) eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1])
end) end)

View File

@@ -1,7 +1,6 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, tabpage, curtab, eq, ok = local clear, nvim, tabpage, curtab, eq, ok =
helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, helpers.ok
helpers.ok
local curtabmeths = helpers.curtabmeths local curtabmeths = helpers.curtabmeths
local funcs = helpers.funcs local funcs = helpers.funcs
local request = helpers.request local request = helpers.request

View File

@@ -23,37 +23,51 @@ describe('nvim_ui_attach()', function()
end) end)
it('validation', function() it('validation', function()
eq('No such UI option: foo', eq('No such UI option: foo', pcall_err(meths.ui_attach, 80, 24, { foo = { 'foo' } }))
pcall_err(meths.ui_attach, 80, 24, { foo={'foo'} }))
eq("Invalid 'ext_linegrid': expected Boolean, got Array", eq(
pcall_err(meths.ui_attach, 80, 24, { ext_linegrid={} })) "Invalid 'ext_linegrid': expected Boolean, got Array",
eq("Invalid 'override': expected Boolean, got Array", pcall_err(meths.ui_attach, 80, 24, { ext_linegrid = {} })
pcall_err(meths.ui_attach, 80, 24, { override={} })) )
eq("Invalid 'rgb': expected Boolean, got Array", eq(
pcall_err(meths.ui_attach, 80, 24, { rgb={} })) "Invalid 'override': expected Boolean, got Array",
eq("Invalid 'term_name': expected String, got Boolean", pcall_err(meths.ui_attach, 80, 24, { override = {} })
pcall_err(meths.ui_attach, 80, 24, { term_name=true })) )
eq("Invalid 'term_colors': expected Integer, got Boolean", eq(
pcall_err(meths.ui_attach, 80, 24, { term_colors=true })) "Invalid 'rgb': expected Boolean, got Array",
eq("Invalid 'stdin_fd': expected Integer, got String", pcall_err(meths.ui_attach, 80, 24, { rgb = {} })
pcall_err(meths.ui_attach, 80, 24, { stdin_fd='foo' })) )
eq("Invalid 'stdin_tty': expected Boolean, got String", eq(
pcall_err(meths.ui_attach, 80, 24, { stdin_tty='foo' })) "Invalid 'term_name': expected String, got Boolean",
eq("Invalid 'stdout_tty': expected Boolean, got String", pcall_err(meths.ui_attach, 80, 24, { term_name = true })
pcall_err(meths.ui_attach, 80, 24, { stdout_tty='foo' })) )
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', eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_try_resize', 40, 10))
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', eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_detach'))
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() local screen = Screen.new()
screen:attach({ rgb = false }) screen:attach({ rgb = false })
eq('UI already attached to channel: 1', eq(
pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb=false })) 'UI already attached to channel: 1',
pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false })
)
end) end)
end) end)
@@ -89,21 +103,27 @@ it('autocmds VimSuspend/VimResume #22041', function()
eq(false, screen.suspended) eq(false, screen.suspended)
feed('<C-Z>') feed('<C-Z>')
screen:expect(function() eq(true, screen.suspended) end) screen:expect(function()
eq(true, screen.suspended)
end)
eq({ 's' }, eval('g:ev')) eq({ 's' }, eval('g:ev'))
screen.suspended = false screen.suspended = false
feed('<Ignore>') feed('<Ignore>')
eq({ 's', 'r' }, eval('g:ev')) eq({ 's', 'r' }, eval('g:ev'))
command('suspend') 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')) eq({ 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false screen.suspended = false
meths.input_mouse('move', '', '', 0, 0, 0) meths.input_mouse('move', '', '', 0, 0, 0)
eq({ 's', 'r', 's', 'r' }, eval('g:ev')) eq({ 's', 'r', 's', 'r' }, eval('g:ev'))
feed('<C-Z><C-Z><C-Z>') 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) meths.ui_set_focus(false)
eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev')) eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false screen.suspended = false
@@ -111,7 +131,9 @@ it('autocmds VimSuspend/VimResume #22041', function()
eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev')) eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
command('suspend | suspend | suspend') command('suspend | suspend | suspend')
screen:expect(function() eq(true, screen.suspended) end) screen:expect(function()
eq(true, screen.suspended)
end)
screen:detach() screen:detach()
eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev')) eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false screen.suspended = false

View File

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

View File

@@ -12,7 +12,7 @@ describe('oldtests', function()
before_each(clear) before_each(clear)
local exec_lines = function(str) local exec_lines = function(str)
return funcs.split(funcs.execute(str), "\n") return funcs.split(funcs.execute(str), '\n')
end end
local add_an_autocmd = function() local add_an_autocmd = function()
@@ -38,7 +38,6 @@ describe('oldtests', function()
exec [[ augroup vimBarTest| au!| augroup END ]] exec [[ augroup vimBarTest| au!| augroup END ]]
eq(1, #exec_lines('au vimBarTest')) eq(1, #exec_lines('au vimBarTest'))
-- test that a bar is recognized after the {event} -- test that a bar is recognized after the {event}
add_an_autocmd() add_an_autocmd()
exec [[ augroup vimBarTest| au!BufReadCmd| augroup END ]] exec [[ augroup vimBarTest| au!BufReadCmd| augroup END ]]
@@ -72,7 +71,7 @@ describe('oldtests', function()
q q
]] ]]
funcs.writefile(funcs.split(content, "\n"), fname) funcs.writefile(funcs.split(content, '\n'), fname)
funcs.delete('Xout') funcs.delete('Xout')
funcs.system(string.format('%s --clean -N -S %s', meths.get_vvar('progpath'), fname)) 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) local screen = Screen.new(75, 10)
screen:attach() screen:attach()
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = {background = Screen.colors.Cyan}; [1] = { background = Screen.colors.Cyan },
}) })
exec([[ exec([[
set noshowcmd noruler scrolloff=0 set noshowcmd noruler scrolloff=0
@@ -97,7 +96,8 @@ describe('oldtests', function()
edit test/old/testdir/samples/box.txt edit test/old/testdir/samples/box.txt
]]) ]])
feed('249GV<C-End>d') feed('249GV<C-End>d')
screen:expect{grid=[[ screen:expect {
grid = [[
const auto themeEmoji = _forPeer->themeEmoji(); | const auto themeEmoji = _forPeer->themeEmoji(); |
if (themeEmoji.isEmpty()) { | if (themeEmoji.isEmpty()) { |
return nonCustom; | return nonCustom; |
@@ -108,9 +108,11 @@ describe('oldtests', function()
return nonCustom; | return nonCustom; |
{1:^}} | {1:^}} |
353 fewer lines | 353 fewer lines |
]]} ]],
}
feed('<PageUp>') feed('<PageUp>')
screen:expect{grid=[[ screen:expect {
grid = [[
| |
auto BackgroundBox::Inner::resolveResetCustomPaper() const | auto BackgroundBox::Inner::resolveResetCustomPaper() const |
-> std::optional<Data::WallPaper> { | -> std::optional<Data::WallPaper> { |
@@ -121,6 +123,7 @@ describe('oldtests', function()
const auto themeEmoji = _forPeer->themeEmoji(); | const auto themeEmoji = _forPeer->themeEmoji(); |
^if (themeEmoji.isEmpty()) { | ^if (themeEmoji.isEmpty()) { |
353 fewer lines | 353 fewer lines |
]]} ]],
}
end) end)
end) end)

View File

@@ -106,9 +106,12 @@ describe('autocmd', function()
local buf1 = eval("bufnr('%')") local buf1 = eval("bufnr('%')")
command('new') command('new')
local buf2 = eval("bufnr('%')") 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. -- Attempt recursion.
..' | bdelete '..buf2) .. ' | bdelete '
.. buf2
)
command('tabedit testfile2') command('tabedit testfile2')
command('tabedit testfile3') command('tabedit testfile3')
command('bdelete ' .. buf2) command('bdelete ' .. buf2)
@@ -139,16 +142,15 @@ describe('autocmd', function()
end) end)
describe('BufLeave autocommand', function() describe('BufLeave autocommand', function()
it('can wipe out the buffer created by :edit which triggered autocmd', it('can wipe out the buffer created by :edit which triggered autocmd', function()
function()
meths.set_option_value('hidden', true, {}) meths.set_option_value('hidden', true, {})
curbufmeths.set_lines(0, 1, false, { curbufmeths.set_lines(0, 1, false, {
'start of test file xx', 'start of test file xx',
'end of test file xx'}) 'end of test file xx',
})
command('autocmd BufLeave * bwipeout yy') command('autocmd BufLeave * bwipeout yy')
eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy'))
exc_exec('edit yy'))
expect([[ expect([[
start of test file xx start of test file xx
@@ -177,7 +179,8 @@ describe('autocmd', function()
command('autocmd TabNew * ++once :call add(g:foo, "Once2")') command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
command('autocmd TabNew * :call add(g:foo, "Many2")') command('autocmd TabNew * :call add(g:foo, "Many2")')
command('autocmd TabNew * ++once :call add(g:foo, "Once3")') command('autocmd TabNew * ++once :call add(g:foo, "Once3")')
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
TabNew TabNew
@@ -186,18 +189,21 @@ describe('autocmd', function()
:call add(g:foo, "Once2") :call add(g:foo, "Once2")
:call add(g:foo, "Many2") :call add(g:foo, "Many2")
:call add(g:foo, "Once3")]]), :call add(g:foo, "Once3")]]),
funcs.execute('autocmd Tabnew')) funcs.execute('autocmd Tabnew')
)
command('tabnew') command('tabnew')
command('tabnew') command('tabnew')
command('tabnew') command('tabnew')
eq(expected, eval('g:foo')) eq(expected, eval('g:foo'))
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
TabNew TabNew
* :call add(g:foo, "Many1") * :call add(g:foo, "Many1")
:call add(g:foo, "Many2")]]), :call add(g:foo, "Many2")]]),
funcs.execute('autocmd Tabnew')) funcs.execute('autocmd Tabnew')
)
-- --
-- ":autocmd ... ++once" handlers can be deleted. -- ":autocmd ... ++once" handlers can be deleted.
@@ -218,7 +224,9 @@ describe('autocmd', function()
} }
command('let g:foo = []') command('let g:foo = []')
command('autocmd OptionSet binary ++nested ++once :call add(g:foo, "OptionSet-Once")') 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'") command("put ='foo bar baz'")
feed('0llhlh') feed('0llhlh')
eq(expected, eval('g:foo')) eq(expected, eval('g:foo'))
@@ -236,10 +244,12 @@ describe('autocmd', function()
command('autocmd TabNew * ++once :call add(g:foo, "Once2")') command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
command('tabnew') command('tabnew')
eq(expected, eval('g:foo')) eq(expected, eval('g:foo'))
eq(dedent([[ eq(
dedent([[
--- Autocommands ---]]), --- Autocommands ---]]),
funcs.execute('autocmd Tabnew')) funcs.execute('autocmd Tabnew')
)
end) end)
it('internal `aucmd_win` window', function() it('internal `aucmd_win` window', function()
@@ -252,7 +262,11 @@ describe('autocmd', function()
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = { bold = true, foreground = Screen.colors.Blue1 }, [1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = { background = Screen.colors.LightMagenta }, [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([[ source([[
@@ -276,7 +290,7 @@ describe('autocmd', function()
| |
]]) ]])
feed(":enew | doautoall User<cr>") feed(':enew | doautoall User<cr>')
screen:expect([[ screen:expect([[
{2:bb }| {2:bb }|
{3:~ }|*4 {3:~ }|*4
@@ -293,14 +307,16 @@ describe('autocmd', function()
eq(7, eval('g:test')) eq(7, eval('g:test'))
-- API calls are blocked when aucmd_win is not in scope -- API calls are blocked when aucmd_win is not in scope
eq('Vim(call):E5555: API call: Invalid window id: 1001', eq(
pcall_err(command, "call nvim_set_current_win(g:winid)")) '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 -- second time aucmd_win is needed, a different code path is invoked
-- to reuse the same window, so check again -- to reuse the same window, so check again
command("let g:test = v:null") command('let g:test = v:null')
command("let g:had_value = v:null") command('let g:had_value = v:null')
feed(":doautoall User<cr>") feed(':doautoall User<cr>')
screen:expect([[ screen:expect([[
{2:bb }| {2:bb }|
{3:~ }|*4 {3:~ }|*4
@@ -318,11 +334,13 @@ describe('autocmd', function()
eq(0, eval('g:had_value')) eq(0, eval('g:had_value'))
eq(7, eval('g:test')) eq(7, eval('g:test'))
eq('Vim(call):E5555: API call: Invalid window id: 1001', eq(
pcall_err(command, "call nvim_set_current_win(g:winid)")) 'Vim(call):E5555: API call: Invalid window id: 1001',
pcall_err(command, 'call nvim_set_current_win(g:winid)')
)
end) 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) local screen = Screen.new(50, 10)
screen:attach() screen:attach()
screen:set_default_attr_ids { screen:set_default_attr_ids {
@@ -371,13 +389,16 @@ describe('autocmd', function()
-- After all of our messing around, aucmd_win should still be floating. -- 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). -- 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.cmd "only"
vim.api.nvim_buf_call(_G.buf, function() vim.api.nvim_buf_call(_G.buf, function()
_G.config = vim.api.nvim_win_get_config(0) _G.config = vim.api.nvim_win_get_config(0)
end) end)
return _G.config.relative return _G.config.relative
]]) ]]
)
end) end)
describe('closing last non-floating window in tab from `aucmd_win`', function() describe('closing last non-floating window in tab from `aucmd_win`', function()
@@ -388,14 +409,18 @@ describe('autocmd', function()
end) end)
it('gives E814 when there are no other floating windows', function() 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', eq(
pcall_err(command, 'doautoall BufAdd')) 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
pcall_err(command, 'doautoall BufAdd')
)
end) end)
it('gives E814 when there are other floating windows', function() 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 }) 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', eq(
pcall_err(command, 'doautoall BufAdd')) 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
pcall_err(command, 'doautoall BufAdd')
)
end) end)
end) end)
@@ -404,32 +429,56 @@ describe('autocmd', function()
vim.cmd('tabnew') vim.cmd('tabnew')
_G.buf = vim.api.nvim_create_buf(true, true) _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() vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_close(win, true) vim.api.nvim_win_close(win, true)
end) 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() vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.cmd('tabnext') vim.cmd('tabnext')
vim.api.nvim_win_close(win, true) vim.api.nvim_win_close(win, true)
end) 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() vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_hide(win) vim.api.nvim_win_hide(win)
end) 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() vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.cmd('tabnext') vim.cmd('tabnext')
vim.api.nvim_win_hide(win) vim.api.nvim_win_hide(win)
end) end)
]])) ]]
)
)
end) end)
it(':doautocmd does not warn "No matching autocommands" #10689', function() it(':doautocmd does not warn "No matching autocommands" #10689', function()
@@ -440,18 +489,22 @@ describe('autocmd', function()
}) })
feed(':doautocmd User Foo<cr>') feed(':doautocmd User Foo<cr>')
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }| {1:~ }|
:doautocmd User Foo | :doautocmd User Foo |
]]} ]],
}
feed(':autocmd! SessionLoadPost<cr>') feed(':autocmd! SessionLoadPost<cr>')
feed(':doautocmd SessionLoadPost<cr>') feed(':doautocmd SessionLoadPost<cr>')
screen:expect{grid=[[ screen:expect {
grid = [[
^ | ^ |
{1:~ }| {1:~ }|
:doautocmd SessionLoadPost | :doautocmd SessionLoadPost |
]]} ]],
}
end) end)
describe('v:event is readonly #18063', function() describe('v:event is readonly #18063', function()
@@ -473,15 +526,19 @@ describe('autocmd', function()
it('during RecordingLeave event', function() it('during RecordingLeave event', function()
command([[autocmd RecordingLeave * let v:event.regname = '']]) command([[autocmd RecordingLeave * let v:event.regname = '']])
eq('RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"', eq(
pcall_err(command, 'normal! qqq')) 'RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
pcall_err(command, 'normal! qqq')
)
end) end)
it('during TermClose event', function() it('during TermClose event', function()
command('autocmd TermClose * let v:event.status = 0') command('autocmd TermClose * let v:event.status = 0')
command('terminal') command('terminal')
eq('TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"', eq(
pcall_err(command, 'bdelete!')) 'TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
pcall_err(command, 'bdelete!')
)
end) end)
end) end)
@@ -549,9 +606,12 @@ describe('autocmd', function()
eq(0, funcs.exists('#WinNew')) eq(0, funcs.exists('#WinNew'))
-- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') -- 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 au WinNew * ++once ++once echo bad
]]) ]]
)
eq(false, ok) eq(false, ok)
eq(true, not not string.find(msg, 'E983:')) eq(true, not not string.find(msg, 'E983:'))
@@ -559,7 +619,7 @@ describe('autocmd', function()
it('should have autocmds in filetypedetect group', function() it('should have autocmds in filetypedetect group', function()
source [[filetype on]] source [[filetype on]]
neq({}, meths.get_autocmds { group = "filetypedetect" }) neq({}, meths.get_autocmds { group = 'filetypedetect' })
end) end)
it('should allow comma-separated patterns', function() it('should allow comma-separated patterns', function()
@@ -571,7 +631,7 @@ describe('autocmd', function()
augroup END augroup END
]] ]]
eq(4, #meths.get_autocmds { event = "BufReadCmd", group = "TestingPatterns" }) eq(4, #meths.get_autocmds { event = 'BufReadCmd', group = 'TestingPatterns' })
end) end)
end) end)

View File

@@ -12,7 +12,7 @@ describe('autocmd BufEnter', function()
it("triggered by nvim_command('edit <dir>')", function() it("triggered by nvim_command('edit <dir>')", function()
command("autocmd BufEnter * if isdirectory(expand('<afile>')) | let g:dir_bufenter = 1 | endif") 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(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
end) end)
@@ -27,21 +27,20 @@ describe('autocmd BufEnter', function()
endtry endtry
endfunction endfunction
]]) ]])
command("call Test()") command('call Test()')
eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory. eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
eq(2, eval("bufnr('%')")) -- Switched to the dir buffer. eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
end) end)
it('triggered by ":split normal|:help|:bw"', function() it('triggered by ":split normal|:help|:bw"', function()
helpers.add_builddir_to_rtp() helpers.add_builddir_to_rtp()
command("split normal") command('split normal')
command("wincmd j") command('wincmd j')
command("help") command('help')
command("wincmd L") command('wincmd L')
command("autocmd BufEnter normal let g:bufentered = 1") command('autocmd BufEnter normal let g:bufentered = 1')
command("bw") command('bw')
eq(1, eval('bufnr("%")')) -- The cursor is back to the bottom window eq(1, eval('bufnr("%")')) -- The cursor is back to the bottom window
eq(0, eval("exists('g:bufentered')")) -- The autocmd hasn't been triggered eq(0, eval("exists('g:bufentered')")) -- The autocmd hasn't been triggered
end) end)
end) end)

View File

@@ -14,9 +14,9 @@ describe('BufModified', function()
let g:modified = 0 let g:modified = 0
autocmd BufModifiedSet * let g:modified += 1 autocmd BufModifiedSet * let g:modified += 1
]]) ]])
request("nvim_command", [[normal! aa\<Esc>]]) request('nvim_command', [[normal! aa\<Esc>]])
eq(1, eval('g:modified')) eq(1, eval('g:modified'))
request("nvim_command", [[normal! u]]) request('nvim_command', [[normal! u]])
eq(2, eval('g:modified')) eq(2, eval('g:modified'))
end) end)
end) end)

View File

@@ -15,7 +15,7 @@ describe('cmdline autocommands', function()
before_each(function() before_each(function()
clear() clear()
channel = meths.get_api_info()[1] 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 CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)")
command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)") command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)")
command("autocmd CmdWinEnter * call rpcnotify(g:channel, 'CmdWinEnter', v:event)") command("autocmd CmdWinEnter * call rpcnotify(g:channel, 'CmdWinEnter', v:event)")
@@ -26,8 +26,10 @@ describe('cmdline autocommands', function()
feed(':') feed(':')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('redraw<cr>') feed('redraw<cr>')
eq({'notification', 'CmdlineLeave', eq(
{{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
next_msg()
)
feed(':') feed(':')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) 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' -- note: feed('bork<c-c>') might not consume 'bork'
-- due to out-of-band interrupt handling -- due to out-of-band interrupt handling
feed('bork<esc>') feed('bork<esc>')
eq({'notification', 'CmdlineLeave', eq(
{{cmdtype=':', cmdlevel=1, abort=true}}}, next_msg()) { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = true } } },
next_msg()
)
end) end)
it('can abort cmdline', function() 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>") feed(":put! ='ok'<cr>")
expect([[ expect([[
ok ok
@@ -99,7 +103,7 @@ describe('cmdline autocommands', function()
command("autocmd CmdlineChanged * echoerr 'change erreor'") command("autocmd CmdlineChanged * echoerr 'change erreor'")
-- history recall still works -- history recall still works
feed(":<c-p>") feed(':<c-p>')
screen:expect([[ screen:expect([[
| |
lorem ipsum | lorem ipsum |
@@ -111,7 +115,7 @@ describe('cmdline autocommands', function()
:put ='lorem ipsum'^ | :put ='lorem ipsum'^ |
]]) ]])
feed("<left>") feed('<left>')
screen:expect([[ screen:expect([[
| |
lorem ipsum | lorem ipsum |
@@ -124,7 +128,7 @@ describe('cmdline autocommands', function()
]]) ]])
-- edit still works -- edit still works
feed(".") feed('.')
screen:expect([[ screen:expect([[
{4: }| {4: }|
: | : |
@@ -169,11 +173,17 @@ describe('cmdline autocommands', function()
feed(':') feed(':')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg()) eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg())
feed('<c-c>') 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>') feed('<c-c>')
eq({ 'notification', 'CmdWinLeave', { {} } }, next_msg()) eq({ 'notification', 'CmdWinLeave', { {} } }, next_msg())
feed('1+2<cr>') 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) end)
it('no crash with recursive use of v:event #19484', function() it('no crash with recursive use of v:event #19484', function()
@@ -181,42 +191,71 @@ describe('cmdline autocommands', function()
feed(':') feed(':')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('<CR>') feed('<CR>')
eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) eq(
{ 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
next_msg()
)
end) end)
it('supports CmdlineChanged', function() 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(':') feed(':')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('l') feed('l')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'l' } }, next_msg())
feed('e') feed('e')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'le' } }, next_msg())
feed('t') feed('t')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let' } }, next_msg())
feed('<space>') feed('<space>')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg()) eq(
{ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let ' } },
next_msg()
)
feed('x') feed('x')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg()) eq(
{ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x' } },
next_msg()
)
feed('<space>') feed('<space>')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg()) eq(
{ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x ' } },
next_msg()
)
feed('=') feed('=')
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg()) eq(
{ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x =' } },
next_msg()
)
feed('<space>') 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>=') feed('<c-r>=')
eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg()) eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg())
feed('1') feed('1')
eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1' } }, next_msg())
feed('+') feed('+')
eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+' } }, next_msg())
feed('1') feed('1')
eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg()) eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+1' } }, next_msg())
feed('<cr>') feed('<cr>')
eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg()) eq(
eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg()) { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } },
next_msg()
)
eq(
{ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = 2' } },
next_msg()
)
feed('<cr>') 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')) eq(2, eval('x'))
end) end)
end) end)

View File

@@ -44,10 +44,18 @@ describe('CursorHold', function()
local ignore_key = meths.replace_termcodes('<Ignore>', true, true, true) local ignore_key = meths.replace_termcodes('<Ignore>', true, true, true)
test_cursorhold(function() end, 1) test_cursorhold(function() end, 1)
test_cursorhold(function() feed('') end, 1) test_cursorhold(function()
test_cursorhold(function() meths.feedkeys('', 'n', true) end, 1) feed('')
test_cursorhold(function() feed('<Ignore>') end, 0) end, 1)
test_cursorhold(function() meths.feedkeys(ignore_key, 'n', true) end, 0) 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) end)
it("reducing 'updatetime' while waiting for CursorHold #20241", function() it("reducing 'updatetime' while waiting for CursorHold #20241", function()

View File

@@ -47,7 +47,7 @@ describe('CursorMoved', function()
eq(0, eval('g:cursormoved')) eq(0, eval('g:cursormoved'))
end) 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([[ source([[
let g:cursormoved = 0 let g:cursormoved = 0
autocmd! CursorMoved autocmd! CursorMoved

View File

@@ -21,17 +21,31 @@ describe('autocmd DirChanged and DirChangedPre', function()
curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3', curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3',
} }
setup(function() for _, dir in pairs(dirs) do helpers.mkdir(dir) end end) setup(function()
teardown(function() for _, dir in pairs(dirs) do helpers.rmdir(dir) end end) 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() before_each(function()
clear() clear()
command('autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] ' command(
..'= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]') 'autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] ' .. '= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]'
..'= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 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. -- 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:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]])
command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]]) command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
end) end)
@@ -91,7 +105,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status1, err1 = pcall(function() local status1, err1 = pcall(function()
command('lcd ' .. dirs[1] .. '/doesnotexist') command('lcd ' .. dirs[1] .. '/doesnotexist')
end) 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({}, eval('g:ev'))
eq('window', eval('g:amatchpre')) eq('window', eval('g:amatchpre'))
eq(1, eval('g:cdprecount')) eq(1, eval('g:cdprecount'))
@@ -100,7 +117,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status2, err2 = pcall(function() local status2, err2 = pcall(function()
command('lcd ' .. dirs[2] .. '/doesnotexist') command('lcd ' .. dirs[2] .. '/doesnotexist')
end) 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({}, eval('g:ev'))
eq('window', eval('g:amatchpre')) eq('window', eval('g:amatchpre'))
eq(2, eval('g:cdprecount')) eq(2, eval('g:cdprecount'))
@@ -109,7 +129,10 @@ describe('autocmd DirChanged and DirChangedPre', function()
local status3, err3 = pcall(function() local status3, err3 = pcall(function()
command('lcd ' .. dirs[3] .. '/doesnotexist') command('lcd ' .. dirs[3] .. '/doesnotexist')
end) 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({}, eval('g:ev'))
eq('window', eval('g:amatchpre')) eq('window', eval('g:amatchpre'))
eq(3, eval('g:cdprecount')) eq(3, eval('g:cdprecount'))
@@ -119,9 +142,9 @@ describe('autocmd DirChanged and DirChangedPre', function()
eq(false, status2) eq(false, status2)
eq(false, status3) eq(false, status3)
eq('E344:', string.match(err1, "E%d*:")) eq('E344:', string.match(err1, 'E%d*:'))
eq('E344:', string.match(err2, "E%d*:")) eq('E344:', string.match(err2, 'E%d*:'))
eq('E344:', string.match(err3, "E%d*:")) eq('E344:', string.match(err3, 'E%d*:'))
end) end)
it("are triggered by 'autochdir'", function() it("are triggered by 'autochdir'", function()
@@ -238,7 +261,7 @@ describe('autocmd DirChanged and DirChangedPre', function()
end end
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('lcd ' .. dirs[3]) -- window 3
command('split ' .. dirs[2] .. '/foo') -- window 2 command('split ' .. dirs[2] .. '/foo') -- window 2
command('lcd ' .. dirs[2]) command('lcd ' .. dirs[2])

View File

@@ -7,11 +7,11 @@ local command = helpers.command
describe('autocmd FileType', function() describe('autocmd FileType', function()
before_each(clear) before_each(clear)
it("is triggered by :help only once", function() it('is triggered by :help only once', function()
helpers.add_builddir_to_rtp() helpers.add_builddir_to_rtp()
command("let g:foo = 0") command('let g:foo = 0')
command("autocmd FileType help let g:foo = g:foo + 1") command('autocmd FileType help let g:foo = g:foo + 1')
command("help help") command('help help')
assert.same(1, eval('g:foo')) assert.same(1, eval('g:foo'))
end) end)
end) end)

View File

@@ -5,7 +5,9 @@ local clear = helpers.clear
local feed_command = helpers.feed_command local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data 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() describe('autoread TUI FocusGained/FocusLost', function()
local f1 = 'xtest-foo' local f1 = 'xtest-foo'
@@ -14,10 +16,14 @@ describe('autoread TUI FocusGained/FocusLost', function()
before_each(function() before_each(function()
clear() clear()
screen = thelpers.setup_child_nvim({ screen = thelpers.setup_child_nvim({
'-u', 'NONE', '-u',
'-i', 'NONE', 'NONE',
'--cmd', 'colorscheme vim', '-i',
'--cmd', 'set noswapfile noshowcmd noruler notermguicolors', 'NONE',
'--cmd',
'colorscheme vim',
'--cmd',
'set noswapfile noshowcmd noruler notermguicolors',
}) })
end) end)
@@ -38,36 +44,44 @@ describe('autoread TUI FocusGained/FocusLost', function()
local atime = os.time() - 10 local atime = os.time() - 10
luv.fs_utime(path, atime, atime) luv.fs_utime(path, atime, atime)
screen:expect{grid=[[ screen:expect {
grid = [[
{1: } | {1: } |
{4:~ }|*3 {4:~ }|*3
{5:[No Name] }| {5:[No Name] }|
| |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]} ]],
}
feed_command('edit ' .. path) feed_command('edit ' .. path)
screen:expect{grid=[[ screen:expect {
grid = [[
{1: } | {1: } |
{4:~ }|*3 {4:~ }|*3
{5:xtest-foo }| {5:xtest-foo }|
:edit xtest-foo | :edit xtest-foo |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]} ]],
}
feed_data('\027[O') feed_data('\027[O')
feed_data('\027[O') feed_data('\027[O')
screen:expect{grid=[[ screen:expect {
grid = [[
{1: } | {1: } |
{4:~ }|*3 {4:~ }|*3
{5:xtest-foo }| {5:xtest-foo }|
:edit xtest-foo | :edit xtest-foo |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], unchanged=true} ]],
unchanged = true,
}
helpers.write_file(path, expected_addition) helpers.write_file(path, expected_addition)
feed_data('\027[I') feed_data('\027[I')
screen:expect{grid=[[ screen:expect {
grid = [[
{1:l}ine 1 | {1:l}ine 1 |
line 2 | line 2 |
line 3 | line 3 |
@@ -75,6 +89,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
{5:xtest-foo }| {5:xtest-foo }|
"xtest-foo" 4L, 28B | "xtest-foo" 4L, 28B |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]]} ]],
}
end) end)
end) end)

View File

@@ -17,15 +17,15 @@ describe('ModeChanged', function()
feed('i') feed('i')
eq({ eq({
old_mode = 'nt', old_mode = 'nt',
new_mode = 't' new_mode = 't',
}, eval('g:event')) }, eval('g:event'))
feed('<c-\\><c-n>') feed('<c-\\><c-n>')
eq({ eq({
old_mode = 't', old_mode = 't',
new_mode = 'nt' new_mode = 'nt',
}, eval('g:event')) }, eval('g:event'))
eq(3, eval('g:count')) eq(3, eval('g:count'))
command("bd!") command('bd!')
-- v:event is cleared after the autocommand is done -- v:event is cleared after the autocommand is done
eq({}, eval('v:event')) eq({}, eval('v:event'))

View File

@@ -15,7 +15,8 @@ describe('autocmd SearchWrapped', function()
command('autocmd! SearchWrapped * let g:test += 1') command('autocmd! SearchWrapped * let g:test += 1')
curbufmeths.set_lines(0, 1, false, { curbufmeths.set_lines(0, 1, false, {
'The quick brown fox', 'The quick brown fox',
'jumps over the lazy dog'}) 'jumps over the lazy dog',
})
end) end)
it('gets triggered when search wraps the end', function() it('gets triggered when search wraps the end', function()

View File

@@ -10,24 +10,25 @@ local eval = helpers.eval
local exec = helpers.exec local exec = helpers.exec
local feed = helpers.feed local feed = helpers.feed
describe(":autocmd", function() describe(':autocmd', function()
before_each(function() before_each(function()
clear({ '-u', 'NONE' }) clear({ '-u', 'NONE' })
end) end)
it("should not segfault when you just do autocmd", function() it('should not segfault when you just do autocmd', function()
command ":autocmd" command ':autocmd'
end) end)
it("should filter based on ++once", function() it('should filter based on ++once', function()
command "autocmd! BufEnter" command 'autocmd! BufEnter'
command "autocmd BufEnter * :echo 'Hello'" command "autocmd BufEnter * :echo 'Hello'"
command [[augroup TestingOne]] command [[augroup TestingOne]]
command [[ autocmd BufEnter * :echo "Line 1"]] command [[ autocmd BufEnter * :echo "Line 1"]]
command [[ autocmd BufEnter * :echo "Line 2"]] command [[ autocmd BufEnter * :echo "Line 2"]]
command [[augroup END]] command [[augroup END]]
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
BufEnter BufEnter
@@ -35,7 +36,8 @@ describe(":autocmd", function()
TestingOne BufEnter TestingOne BufEnter
* :echo "Line 1" * :echo "Line 1"
:echo "Line 2"]]), :echo "Line 2"]]),
funcs.execute('autocmd BufEnter')) funcs.execute('autocmd BufEnter')
)
end) end)
it('should not show group information if interrupted', function() it('should not show group information if interrupted', function()
@@ -109,7 +111,8 @@ describe(":autocmd", function()
autocmd User foo call Func() autocmd User foo call Func()
doautocmd User foo doautocmd User foo
]]) ]])
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
test_1 BufEnter test_1 BufEnter
@@ -119,7 +122,9 @@ describe(":autocmd", function()
test_3 BufEnter test_3 BufEnter
D echo 'D' D echo 'D'
E echo 'E' E echo 'E'
F echo 'F']]), eval('g:output')) F echo 'F']]),
eval('g:output')
)
end) end)
it('can filter by pattern #17973', function() it('can filter by pattern #17973', function()
@@ -145,7 +150,8 @@ describe(":autocmd", function()
autocmd User B echo "B3" autocmd User B echo "B3"
augroup END augroup END
]]) ]])
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
test_1 User test_1 User
@@ -153,8 +159,11 @@ describe(":autocmd", function()
test_2 User test_2 User
A echo "A2" A echo "A2"
test_3 User test_3 User
A echo "A3"]]), funcs.execute('autocmd User A')) A echo "A3"]]),
eq(dedent([[ funcs.execute('autocmd User A')
)
eq(
dedent([[
--- Autocommands --- --- Autocommands ---
test_1 BufEnter test_1 BufEnter
@@ -168,14 +177,19 @@ describe(":autocmd", function()
test_2 User test_2 User
B echo "B2" B echo "B2"
test_3 User test_3 User
B echo "B3"]]), funcs.execute('autocmd * B')) B echo "B3"]]),
eq(dedent([[ funcs.execute('autocmd * B')
)
eq(
dedent([[
--- Autocommands --- --- Autocommands ---
test_3 BufEnter test_3 BufEnter
B echo "B3" B echo "B3"
test_3 User test_3 User
B echo "B3"]]), funcs.execute('autocmd test_3 * B')) B echo "B3"]]),
funcs.execute('autocmd test_3 * B')
)
end) end)
it('should skip consecutive patterns', function() it('should skip consecutive patterns', function()
@@ -200,7 +214,8 @@ describe(":autocmd", function()
let g:output = execute('autocmd BufEnter') let g:output = execute('autocmd BufEnter')
]]) ]])
eq(dedent([[ eq(
dedent([[
--- Autocommands --- --- Autocommands ---
test_1 BufEnter test_1 BufEnter
@@ -216,6 +231,8 @@ describe(":autocmd", function()
echo 'C' echo 'C'
D echo 'D' D echo 'D'
echo 'E' echo 'E'
echo 'F']]), eval('g:output')) echo 'F']]),
eval('g:output')
)
end) end)
end) end)

View File

@@ -8,7 +8,9 @@ local next_msg = helpers.next_msg
local is_os = helpers.is_os local is_os = helpers.is_os
local skip = helpers.skip 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) local function posix_kill(signame, pid)
os.execute('kill -s ' .. signame .. ' -- ' .. pid .. ' >/dev/null') os.execute('kill -s ' .. signame .. ' -- ' .. pid .. ' >/dev/null')

View File

@@ -7,62 +7,76 @@ describe('TabClosed', function()
describe('au TabClosed', function() describe('au TabClosed', function()
describe('with * as <afile>', function() describe('with * as <afile>', function()
it('matches when closing any tab', 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 repeat
nvim('command', 'tabnew') nvim('command', 'tabnew')
until nvim('eval', 'tabpagenr()') == 6 -- current tab is now 6 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: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: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: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:1:1:2\ntabclosed:1:1:1', nvim('exec', 'tabonly', true)) -- close tabs 1 and 2
end) end)
it('is triggered when closing a window via bdelete from another tab', function() 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', '1tabedit Xtestfile') nvim('command', '1tabedit Xtestfile')
nvim('command', 'normal! 1gt') nvim('command', 'normal! 1gt')
eq({ 1, 3 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) eq({ 1, 3 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
eq("tabclosed:2:2:1\ntabclosed:2:2:1", nvim('exec', 'bdelete Xtestfile', true)) eq('tabclosed:2:2:1\ntabclosed:2:2:1', nvim('exec', 'bdelete Xtestfile', true))
eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
end) end)
it('is triggered when closing a window via bdelete from current tab', function() 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', 'file Xtestfile1')
nvim('command', '1tabedit Xtestfile2') nvim('command', '1tabedit Xtestfile2')
nvim('command', '1tabedit Xtestfile2') nvim('command', '1tabedit Xtestfile2')
-- Only one tab is closed, and the alternate file is used for the other. -- Only one tab is closed, and the alternate file is used for the other.
eq({ 2, 3 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) 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("")')) eq('Xtestfile1', nvim('eval', 'bufname("")'))
end) end)
end) end)
describe('with NR as <afile>', function() describe('with NR as <afile>', function()
it('matches when closing a tab whose index is NR', 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"') nvim('command', 'au! TabClosed 2 echom "tabclosed:match"')
repeat repeat
nvim('command', 'tabnew') nvim('command', 'tabnew')
until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7 until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7
-- sanity check, we shouldn't match on tabs with numbers other than 2 -- 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 -- 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)
end) end)
describe('with close', function() describe('with close', function()
it('is triggered', 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') nvim('command', 'tabedit Xtestfile')
eq({ 2, 2 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]')) 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("$")]')) eq({ 1, 1 }, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
end) end)
end) end)
end) end)
end) end)

View File

@@ -15,8 +15,8 @@ describe('TabNewEntered', function()
it('matches when entering any new tab', function() it('matches when entering any new tab', function()
clear() clear()
nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")') nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")')
eq("tabnewentered:2:2", nvim('exec', 'tabnew', true)) eq('tabnewentered:2:2', nvim('exec', 'tabnew', true))
eq("tabnewentered:3:3", nvim('exec', 'tabnew test.x2', true)) eq('tabnewentered:3:3', nvim('exec', 'tabnew test.x2', true))
end) end)
end) end)
describe('with FILE as <afile>', function() describe('with FILE as <afile>', function()
@@ -52,8 +52,8 @@ describe('TabEnter', function()
command('augroup TEMP') command('augroup TEMP')
nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')') nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
command('augroup END') command('augroup END')
eq("tabenter:2:1", nvim('exec', 'tabnew', true)) eq('tabenter:2:1', nvim('exec', 'tabnew', true))
eq("tabenter:3:2", nvim('exec', 'tabnew test.x2', true)) eq('tabenter:3:2', nvim('exec', 'tabnew test.x2', true))
command('augroup! TEMP') command('augroup! TEMP')
end) end)
it('has correct previous tab when entering any preexisting tab', function() it('has correct previous tab when entering any preexisting tab', function()
@@ -62,8 +62,8 @@ describe('TabEnter', function()
command('augroup TEMP') command('augroup TEMP')
nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')') nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
command('augroup END') command('augroup END')
eq("tabenter:1:3", nvim('exec', 'tabnext', true)) eq('tabenter:1:3', nvim('exec', 'tabnext', true))
eq("tabenter:2:1", nvim('exec', 'tabnext', true)) eq('tabenter:2:1', nvim('exec', 'tabnext', true))
command('augroup! TEMP') command('augroup! TEMP')
end) end)
end) end)
@@ -78,12 +78,13 @@ describe('tabpage/previous', function()
command('tabnew') command('tabnew')
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
-- Switch to the previous (third) tab -- Switch to the previous (third) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -97,14 +98,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after new tab creation at end', it(
switches_to_previous_after_new_tab_creation_at_end('g<Tab>')) 'switches to previous via g<Tab> after new tab creation at end',
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>')) switches_to_previous_after_new_tab_creation_at_end('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 <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) local function switches_to_previous_after_new_tab_creation_in_middle(characters)
return function() return function()
@@ -118,11 +130,12 @@ describe('tabpage/previous', function()
command('tabnew') command('tabnew')
-- The previous tab is now the second. -- The previous tab is now the second.
eq(2, eval('tabpagenr(\'#\')')) eq(2, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab -- Switch to the previous (second) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -138,17 +151,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after new tab creation in middle', it(
switches_to_previous_after_new_tab_creation_in_middle('g<Tab>')) 'switches to previous via g<Tab> after new tab creation in middle',
it('switches to previous via <C-W>g<Tab> after new tab creation in middle', switches_to_previous_after_new_tab_creation_in_middle('g<Tab>')
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', it(
switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>')) 'switches to previous via <C-W>g<Tab> after new tab creation in middle',
it('switches to previous via :tabn #<CR> after new tab creation in middle', switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>')
switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>')) )
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) local function switches_to_previous_after_switching_to_next_tab(characters)
return function() return function()
@@ -160,12 +181,13 @@ describe('tabpage/previous', function()
command('tabnext') command('tabnext')
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab -- Switch to the previous (fourth) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
# [No Name] # [No Name]
@@ -179,17 +201,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the first. -- The previous tab is now the first.
eq(1, eval('tabpagenr(\'#\')')) eq(1, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after switching to next tab', it(
switches_to_previous_after_switching_to_next_tab('g<Tab>')) 'switches to previous via g<Tab> after switching to next tab',
it('switches to previous via <C-W>g<Tab> after switching to next tab', switches_to_previous_after_switching_to_next_tab('g<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', it(
switches_to_previous_after_switching_to_next_tab('<C-Tab>')) 'switches to previous via <C-W>g<Tab> after switching to next tab',
it('switches to previous via :tabn #<CR> after switching to next tab', switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>')
switches_to_previous_after_switching_to_next_tab(':tabn #<CR>')) )
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) local function switches_to_previous_after_switching_to_last_tab(characters)
return function() return function()
@@ -203,12 +233,13 @@ describe('tabpage/previous', function()
command('tablast') command('tablast')
-- The previous tab is now the second. -- The previous tab is now the second.
eq(1, eval('tabpagenr(\'#\')')) eq(1, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab -- Switch to the previous (second) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
> [No Name] > [No Name]
@@ -222,17 +253,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
end end
end end
it('switches to previous after switching to last tab', it(
switches_to_previous_after_switching_to_last_tab('g<Tab>')) 'switches to previous after switching to last tab',
it('switches to previous after switching to last tab', switches_to_previous_after_switching_to_last_tab('g<Tab>')
switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>')) )
it('switches to previous after switching to last tab', it(
switches_to_previous_after_switching_to_last_tab('<C-Tab>')) 'switches to previous after switching to last tab',
it('switches to previous after switching to last tab', switches_to_previous_after_switching_to_last_tab('<C-W>g<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('<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) local function switches_to_previous_after_switching_to_previous_tab(characters)
return function() return function()
@@ -244,12 +283,13 @@ describe('tabpage/previous', function()
command('tabprevious') command('tabprevious')
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab -- Switch to the previous (fourth) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -263,17 +303,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after switching to previous tab', it(
switches_to_previous_after_switching_to_previous_tab('g<Tab>')) 'switches to previous via g<Tab> after switching to previous tab',
it('switches to previous via <C-W>g<Tab> after switching to previous tab', switches_to_previous_after_switching_to_previous_tab('g<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', it(
switches_to_previous_after_switching_to_previous_tab('<C-Tab>')) 'switches to previous via <C-W>g<Tab> after switching to previous tab',
it('switches to previous via :tabn #<CR> after switching to previous tab', switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>')
switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>')) )
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) local function switches_to_previous_after_switching_to_first_tab(characters)
return function() return function()
@@ -287,12 +335,13 @@ describe('tabpage/previous', function()
command('tabfirst') command('tabfirst')
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
-- Switch to the previous (third) tab -- Switch to the previous (third) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
# [No Name] # [No Name]
@@ -306,17 +355,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the first. -- The previous tab is now the first.
eq(1, eval('tabpagenr(\'#\')')) eq(1, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after switching to first tab', it(
switches_to_previous_after_switching_to_first_tab('g<Tab>')) 'switches to previous via g<Tab> after switching to first tab',
it('switches to previous via <C-W>g<Tab> after switching to first tab', switches_to_previous_after_switching_to_first_tab('g<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', it(
switches_to_previous_after_switching_to_first_tab('<C-Tab>')) 'switches to previous via <C-W>g<Tab> after switching to first tab',
it('switches to previous via :tabn #<CR> after switching to first tab', switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>')
switches_to_previous_after_switching_to_first_tab(':tabn #<CR>')) )
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) local function switches_to_previous_after_numbered_tab_switch(characters)
return function() return function()
@@ -328,12 +385,13 @@ describe('tabpage/previous', function()
command('tabnext 2') command('tabnext 2')
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab -- Switch to the previous (fourth) tab
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -347,17 +405,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the second. -- The previous tab is now the second.
eq(2, eval('tabpagenr(\'#\')')) eq(2, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after numbered tab switch', it(
switches_to_previous_after_numbered_tab_switch('g<Tab>')) 'switches to previous via g<Tab> after numbered tab switch',
it('switches to previous via <C-W>g<Tab> after numbered tab switch', switches_to_previous_after_numbered_tab_switch('g<Tab>')
switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>')) )
it('switches to previous via <C-Tab> after numbered tab switch', it(
switches_to_previous_after_numbered_tab_switch('<C-Tab>')) 'switches to previous via <C-W>g<Tab> after numbered tab switch',
it('switches to previous via :tabn #<CR> after numbered tab switch', switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>')
switches_to_previous_after_numbered_tab_switch(':tabn #<CR>')) )
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) local function switches_to_previous_after_switching_to_previous(characters1, characters2)
return function() return function()
@@ -371,12 +437,13 @@ describe('tabpage/previous', function()
feed(characters1) feed(characters1)
-- The previous tab is now the second. -- The previous tab is now the second.
eq(2, eval('tabpagenr(\'#\')')) eq(2, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab -- Switch to the previous (second) tab
feed(characters2) feed(characters2)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -390,41 +457,73 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the fourth. -- The previous tab is now the fourth.
eq(4, eval('tabpagenr(\'#\')')) eq(4, eval("tabpagenr('#')"))
end end
end end
it('switches to previous via g<Tab> after switching to previous via g<Tab>', it(
switches_to_previous_after_switching_to_previous('g<Tab>', 'g<Tab>')) 'switches to previous via g<Tab> after switching to previous via 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>', '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>', it(
switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>')) 'switches to previous via <C-W>g<Tab> after switching to previous via g<Tab>',
it('switches to previous via :tabn #<CR> after switching to previous via g<Tab>', switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>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>', it(
switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>')) 'switches to previous via <C-Tab> after switching to previous via 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('g<Tab>', '<C-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>', it(
switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>')) 'switches to previous via :tabn #<CR> after switching to previous via g<Tab>',
it('switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>', switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>')
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>', it(
switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>')) 'switches to previous via g<Tab> after switching to previous via <C-W>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-W>g<Tab>', 'g<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>', it(
switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>')) 'switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>',
it('switches to previous via :tabn #<CR> after switching to previous via <C-Tab>', switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<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>', it(
switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>')) 'switches to previous via <C-Tab> after switching to previous via <C-W>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('<C-W>g<Tab>', '<C-Tab>')
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>', it(
switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>')) 'switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>',
it('switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>', switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':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 <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) local function does_not_switch_to_previous_after_closing_current_tab(characters)
return function() return function()
@@ -436,13 +535,14 @@ describe('tabpage/previous', function()
command('wincmd c') command('wincmd c')
-- The previous tab is now the "zeroth" -- there isn't one. -- 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 -- At this point, switching to the "previous" (i.e. fourth) tab would mean
-- switching to either a dangling or a null pointer. -- switching to either a dangling or a null pointer.
feed(characters) feed(characters)
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]
@@ -454,17 +554,25 @@ describe('tabpage/previous', function()
) )
-- The previous tab is now the "zero". -- The previous tab is now the "zero".
eq(0, eval('tabpagenr(\'#\')')) eq(0, eval("tabpagenr('#')"))
end end
end end
it('does not switch to previous via g<Tab> after closing current tab', it(
does_not_switch_to_previous_after_closing_current_tab('g<Tab>')) 'does not switch to previous via g<Tab> after closing current 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('g<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', it(
does_not_switch_to_previous_after_closing_current_tab('<C-Tab>')) 'does not switch to previous via <C-W>g<Tab> after closing current tab',
it('does not switch to previous via :tabn #<CR> after closing current tab', does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>')
does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>')) )
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) local function does_not_switch_to_previous_after_entering_operator_pending(characters)
return function() return function()
@@ -474,7 +582,7 @@ describe('tabpage/previous', function()
command('tabnew') command('tabnew')
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
-- Enter operator pending mode. -- Enter operator pending mode.
feed('d') feed('d')
@@ -491,11 +599,13 @@ describe('tabpage/previous', function()
eq(4, eval('tabpagenr()')) eq(4, eval('tabpagenr()'))
-- The previous tab is still the third. -- The previous tab is still the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
end end
end end
it('does not switch to previous via g<Tab> after entering operator pending', it(
does_not_switch_to_previous_after_entering_operator_pending('g<Tab>')) '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 -- NOTE: When in operator pending mode, attempting to switch to previous has
-- the following effect: -- the following effect:
-- - Ctrl-W exits operator pending mode -- - 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. -- 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', -- 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>')) -- 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', it(
does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>')) '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 -- NOTE: When in operator pending mode, pressing : leaves operator pending
-- mode and enters command mode, so :tabn #<CR> does in fact switch -- mode and enters command mode, so :tabn #<CR> does in fact switch
-- tabs. -- tabs.
@@ -522,7 +634,7 @@ describe('tabpage/previous', function()
command('tabnew') command('tabnew')
-- The previous tab is now the third. -- The previous tab is now the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
-- Edit : command line in command-line window -- Edit : command line in command-line window
feed('q:') feed('q:')
@@ -540,17 +652,19 @@ describe('tabpage/previous', function()
eq(4, eval('tabpagenr()')) eq(4, eval('tabpagenr()'))
-- The previous tab is still the third. -- The previous tab is still the third.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
end end
end end
it('cmdline-win prevents tab switch via g<Tab>', it('cmdline-win prevents tab switch via g<Tab>', cmdline_win_prevents_tab_switch('g<Tab>', 0))
cmdline_win_prevents_tab_switch('g<Tab>', 0)) it(
it('cmdline-win prevents tab switch via <C-W>g<Tab>', 'cmdline-win prevents tab switch via <C-W>g<Tab>',
cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1)) 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 <C-Tab>', cmdline_win_prevents_tab_switch('<C-Tab>', 0))
it('cmdline-win prevents tab switch via :tabn #<CR>', it(
cmdline_win_prevents_tab_switch(':tabn #<CR>', 0)) 'cmdline-win prevents tab switch via :tabn #<CR>',
cmdline_win_prevents_tab_switch(':tabn #<CR>', 0)
)
it(':tabs indicates correct prevtab curwin', function() it(':tabs indicates correct prevtab curwin', function()
-- Add three tabs for a total of four -- Add three tabs for a total of four
@@ -562,9 +676,10 @@ describe('tabpage/previous', function()
command('tabnew') command('tabnew')
-- The previous tab is now the three. -- The previous tab is now the three.
eq(3, eval('tabpagenr(\'#\')')) eq(3, eval("tabpagenr('#')"))
eq(dedent([=[ eq(
dedent([=[
Tab page 1 Tab page 1
[No Name] [No Name]

View File

@@ -2,10 +2,8 @@ local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers') local thelpers = require('test.functional.terminal.helpers')
local clear, command, nvim, testprg = local clear, command, nvim, testprg = helpers.clear, helpers.command, helpers.nvim, helpers.testprg
helpers.clear, helpers.command, helpers.nvim, helpers.testprg local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry
local eval, eq, neq, retry =
helpers.eval, helpers.eq, helpers.neq, helpers.retry
local matches = helpers.matches local matches = helpers.matches
local ok = helpers.ok local ok = helpers.ok
local feed = helpers.feed local feed = helpers.feed
@@ -27,8 +25,10 @@ describe('autocmd TermClose', function()
nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {}) nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
command('autocmd TermClose * bdelete!') command('autocmd TermClose * bdelete!')
command('terminal') command('terminal')
matches('^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://', matches(
pcall_err(command, 'bdelete!')) '^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
pcall_err(command, 'bdelete!')
)
assert_alive() assert_alive()
end end
@@ -46,8 +46,12 @@ describe('autocmd TermClose', function()
command('autocmd TermClose * let g:test_termclose = 23') command('autocmd TermClose * let g:test_termclose = 23')
command('terminal') command('terminal')
-- shell-test exits immediately. -- shell-test exits immediately.
retry(nil, nil, function() neq(-1, eval('jobwait([&channel], 0)[0]')) end) retry(nil, nil, function()
retry(nil, nil, function() eq(23, eval('g:test_termclose')) end) neq(-1, eval('jobwait([&channel], 0)[0]'))
end)
retry(nil, nil, function()
eq(23, eval('g:test_termclose'))
end)
end) end)
it('triggers when long-running terminal job gets stopped', function() 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('autocmd TermClose * let g:test_termclose = 23')
command('terminal') command('terminal')
command('call jobstop(b:terminal_job_id)') 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) end)
it('kills job trapping SIGTERM', function() it('kills job trapping SIGTERM', function()
skip(is_os('win')) skip(is_os('win'))
nvim('set_option_value', 'shell', 'sh', {}) nvim('set_option_value', 'shell', 'sh', {})
nvim('set_option_value', 'shellcmdflag', '-c', {}) 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_stdout': {-> execute('let g:test_job_started = 1')}, ]]
.. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]
retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) )
retry(nil, nil, function()
eq(1, eval('get(g:, "test_job_started", 0)'))
end)
luv.update_time() luv.update_time()
local start = luv.now() local start = luv.now()
command('call jobstop(g:test_job)') 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() luv.update_time()
local duration = luv.now() - start local duration = luv.now() - start
-- Nvim begins SIGTERM after KILL_TIMEOUT_MS. -- Nvim begins SIGTERM after KILL_TIMEOUT_MS.
@@ -83,16 +95,22 @@ describe('autocmd TermClose', function()
skip(is_os('win')) skip(is_os('win'))
nvim('set_option_value', 'shell', 'sh', {}) nvim('set_option_value', 'shell', 'sh', {})
nvim('set_option_value', 'shellcmdflag', '-c', {}) 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,]] .. [[ 'pty': 1,]]
.. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]] .. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]]
.. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]) .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]
retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end) )
retry(nil, nil, function()
eq(1, eval('get(g:, "test_job_started", 0)'))
end)
luv.update_time() luv.update_time()
local start = luv.now() local start = luv.now()
command('call jobstop(g:test_job)') 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() luv.update_time()
local duration = luv.now() - start local duration = luv.now() - start
-- Nvim begins SIGKILL after (2 * KILL_TIMEOUT_MS). -- Nvim begins SIGKILL after (2 * KILL_TIMEOUT_MS).
@@ -109,13 +127,19 @@ describe('autocmd TermClose', function()
eq(2, eval('bufnr("%")')) eq(2, eval('bufnr("%")'))
command('terminal ls') command('terminal ls')
retry(nil, nil, function() eq(3, eval('bufnr("%")')) end) retry(nil, nil, function()
eq(3, eval('bufnr("%")'))
end)
command('buffer 1') command('buffer 1')
retry(nil, nil, function() eq(1, eval('bufnr("%")')) end) retry(nil, nil, function()
eq(1, eval('bufnr("%")'))
end)
command('3bdelete!') 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>') feed('<c-c>:qa!<cr>')
end) end)
@@ -124,10 +148,14 @@ describe('autocmd TermClose', function()
command('autocmd TermClose * let g:status = v:event.status') command('autocmd TermClose * let g:status = v:event.status')
command('terminal 0') 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') 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)
end) end)
@@ -141,10 +169,13 @@ it('autocmd TermEnter, TermLeave', function()
command('terminal') command('terminal')
feed('i') feed('i')
eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, }, eval('g:evs')) eq({ { 'TermOpen', 'n' }, { 'TermEnter', 't' } }, eval('g:evs'))
feed([[<C-\><C-n>]]) feed([[<C-\><C-n>]])
feed('A') 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. -- TermLeave is also triggered by :quit.
command('split foo') command('split foo')
@@ -172,7 +203,9 @@ describe('autocmd TextChangedT', function()
it('works', function() it('works', function()
command('autocmd TextChangedT * ++once let g:called = 1') command('autocmd TextChangedT * ++once let g:called = 1')
thelpers.feed_data('a') 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) end)
it('cannot delete terminal buffer', function() it('cannot delete terminal buffer', function()

View File

@@ -28,7 +28,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(1, eval('g:count')) eq(1, eval('g:count'))
@@ -42,7 +42,7 @@ describe('TextYankPost', function()
regcontents = { 'baz ' }, regcontents = { 'baz ' },
regname = '', regname = '',
regtype = 'v', regtype = 'v',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(2, eval('g:count')) eq(2, eval('g:count'))
@@ -52,8 +52,8 @@ describe('TextYankPost', function()
operator = 'y', operator = 'y',
regcontents = { 'foo', 'baz' }, regcontents = { 'foo', 'baz' },
regname = '', regname = '',
regtype = "\0223", -- ^V + block width regtype = '\0223', -- ^V + block width
visual = true visual = true,
}, eval('g:event')) }, eval('g:event'))
eq(3, eval('g:count')) eq(3, eval('g:count'))
end) end)
@@ -66,7 +66,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
command('set debug=msg') command('set debug=msg')
@@ -97,7 +97,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(1, eval('g:count')) eq(1, eval('g:count'))
eq({ 'foo\nbar' }, funcs.getreg('+', 1, 1)) eq({ 'foo\nbar' }, funcs.getreg('+', 1, 1))
@@ -111,7 +111,7 @@ describe('TextYankPost', function()
regcontents = { 'foo' }, regcontents = { 'foo' },
regname = '', regname = '',
regtype = 'v', regtype = 'v',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(1, eval('g:count')) eq(1, eval('g:count'))
@@ -122,7 +122,7 @@ describe('TextYankPost', function()
regcontents = { '\nbar' }, regcontents = { '\nbar' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(2, eval('g:count')) eq(2, eval('g:count'))
@@ -133,7 +133,7 @@ describe('TextYankPost', function()
regcontents = { 'baz' }, regcontents = { 'baz' },
regname = '', regname = '',
regtype = 'v', regtype = 'v',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(3, eval('g:count')) eq(3, eval('g:count'))
end) end)
@@ -162,7 +162,7 @@ describe('TextYankPost', function()
regcontents = { 'bar' }, regcontents = { 'bar' },
regname = 'b', regname = 'b',
regtype = 'v', regtype = 'v',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
feed('"*yy') feed('"*yy')
@@ -172,10 +172,10 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '*', regname = '*',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
command("set clipboard=unnamed") command('set clipboard=unnamed')
-- regname still shows the name the user requested -- regname still shows the name the user requested
feed('yy') feed('yy')
@@ -185,7 +185,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
feed('"*yy') feed('"*yy')
@@ -195,7 +195,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '*', regname = '*',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
end) end)
@@ -207,7 +207,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' }, regcontents = { 'foo\nbar' },
regname = '+', regname = '+',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(1, eval('g:count')) eq(1, eval('g:count'))
@@ -218,7 +218,7 @@ describe('TextYankPost', function()
regcontents = { 'baz text' }, regcontents = { 'baz text' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(2, eval('g:count')) eq(2, eval('g:count'))
@@ -229,7 +229,7 @@ describe('TextYankPost', function()
regcontents = { 'baz ' }, regcontents = { 'baz ' },
regname = '', regname = '',
regtype = 'v', regtype = 'v',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(3, eval('g:count')) eq(3, eval('g:count'))
@@ -240,7 +240,7 @@ describe('TextYankPost', function()
regcontents = { 'baz text' }, regcontents = { 'baz text' },
regname = '', regname = '',
regtype = 'V', regtype = 'V',
visual = false visual = false,
}, eval('g:event')) }, eval('g:event'))
eq(4, eval('g:count')) eq(4, eval('g:count'))
end) end)

View File

@@ -297,14 +297,20 @@ describe('WinScrolled', function()
eq(0, eval('g:scrolled')) eq(0, eval('g:scrolled'))
local buf = meths.create_buf(true, true) 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, { local win = meths.open_win(buf, false, {
height = 5, height = 5,
width = 10, width = 10,
col = 0, col = 0,
row = 1, row = 1,
relative = 'editor', relative = 'editor',
style = 'minimal' style = 'minimal',
}) })
screen:expect({ any = '@' }) screen:expect({ any = '@' })
local winid_str = tostring(win.id) local winid_str = tostring(win.id)

View File

@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local clear, eq, eval, next_msg, ok, source = helpers.clear, helpers.eq, local clear, eq, eval, next_msg, ok, source =
helpers.eval, helpers.next_msg, helpers.ok, helpers.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 command, funcs, meths = helpers.command, helpers.funcs, helpers.meths
local sleep = helpers.sleep local sleep = helpers.sleep
local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv
@@ -40,7 +40,7 @@ describe('channels', function()
meths.set_var('address', address) meths.set_var('address', address)
command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})") command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})")
local id = eval("g:id") local id = eval('g:id')
ok(id > 0) ok(id > 0)
command("call chansend(g:id, msgpackdump([[2,'nvim_set_var',['code',23]]]))") 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']]]))") command("call chansend(g:id, msgpackdump([[0,0,'nvim_eval',['2+3']]]))")
local res = eval('msgpackdump([[1,0,v:null,5]])')
local res = eval("msgpackdump([[1,0,v:null,5]])") eq({ '\148\001\n\192\005' }, res)
eq({"\148\001\n\192\005"}, res)
eq({ 'notification', 'data', { id, res } }, next_msg()) eq({ 'notification', 'data', { id, res } }, next_msg())
command("call chansend(g:id, msgpackdump([[2,'nvim_command',['quit']]]))") command("call chansend(g:id, msgpackdump([[2,'nvim_command',['quit']]]))")
eq({ 'notification', 'data', { id, { '' } } }, next_msg()) eq({ 'notification', 'data', { id, { '' } } }, next_msg())
@@ -68,8 +67,10 @@ describe('channels', function()
\ 'on_exit': function('OnEvent'), \ 'on_exit': function('OnEvent'),
\ } \ }
]]) ]])
meths.set_var("nvim_prog", nvim_prog) meths.set_var('nvim_prog', nvim_prog)
meths.set_var("code", [[ meths.set_var(
'code',
[[
function! OnEvent(id, data, event) dict function! OnEvent(id, data, event) dict
let text = string([a:id, a:data, a:event]) let text = string([a:id, a:data, a:event])
call chansend(g:x, text) call chansend(g:x, text)
@@ -81,25 +82,31 @@ describe('channels', function()
endfunction endfunction
let g:x = stdioopen({'on_stdin':'OnEvent'}) let g:x = stdioopen({'on_stdin':'OnEvent'})
call chansend(x, "hello") 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) ok(id > 0)
eq({ "notification", "stdout", {id, { "hello" } } }, next_msg()) eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg())
command("call chansend(id, 'howdy')") 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)") command('call chansend(id, 0z686f6c61)')
eq({"notification", "stdout", {id, {"[1, ['hola'], 'stdin']"}}}, next_msg()) eq({ 'notification', 'stdout', { id, { "[1, ['hola'], 'stdin']" } } }, next_msg())
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
expect_twostreams({{"notification", "stdout", {id, {"[1, [''], 'stdin']"}}}, expect_twostreams({
{'notification', 'stdout', {id, {''}}}}, { 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } },
{{"notification", "stderr", {id, {"*dies*"}}}, { 'notification', 'stdout', { id, { '' } } },
{'notification', 'stderr', {id, {''}}}}) }, {
eq({"notification", "exit", {3,0}}, next_msg()) { 'notification', 'stderr', { id, { '*dies*' } } },
{ 'notification', 'stderr', { id, { '' } } },
})
eq({ 'notification', 'exit', { 3, 0 } }, next_msg())
end) end)
it('can use stdio channel and on_print callback', function() it('can use stdio channel and on_print callback', function()
@@ -110,8 +117,10 @@ describe('channels', function()
\ 'on_exit': function('OnEvent'), \ 'on_exit': function('OnEvent'),
\ } \ }
]]) ]])
meths.set_var("nvim_prog", nvim_prog) meths.set_var('nvim_prog', nvim_prog)
meths.set_var("code", [[ meths.set_var(
'code',
[[
function! OnStdin(id, data, event) dict function! OnStdin(id, data, event) dict
echo string([a:id, a:data, a:event]) echo string([a:id, a:data, a:event])
if a:data == [''] if a:data == ['']
@@ -123,24 +132,27 @@ describe('channels', function()
endfunction endfunction
let g:x = stdioopen({'on_stdin': funcref('OnStdin'), 'on_print':'OnPrint'}) let g:x = stdioopen({'on_stdin': funcref('OnStdin'), 'on_print':'OnPrint'})
call chansend(x, "hello") 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) ok(id > 0)
eq({ "notification", "stdout", {id, { "hello" } } }, next_msg()) eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg())
command("call chansend(id, 'howdy')") 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) end)
local function expect_twoline(id, stream, line1, line2, nobr) local function expect_twoline(id, stream, line1, line2, nobr)
local msg = next_msg() local msg = next_msg()
local joined = nobr and { line1 .. line2 } or { line1, line2 } local joined = nobr and { line1 .. line2 } or { line1, line2 }
if not pcall(eq, {"notification", stream, {id, joined}}, msg) then if not pcall(eq, { 'notification', stream, { id, joined } }, msg) then
local sep = (not nobr) and "" or nil local sep = (not nobr) and '' or nil
eq({"notification", stream, {id, {line1, sep}}}, msg) eq({ 'notification', stream, { id, { line1, sep } } }, msg)
eq({"notification", stream, {id, {line2}}}, next_msg()) eq({ 'notification', stream, { id, { line2 } } }, next_msg())
end end
end end
@@ -153,50 +165,52 @@ describe('channels', function()
\ 'pty': v:true, \ 'pty': v:true,
\ } \ }
]]) ]])
meths.set_var("nvim_prog", nvim_prog) meths.set_var('nvim_prog', nvim_prog)
meths.set_var("code", [[ meths.set_var(
'code',
[[
function! OnEvent(id, data, event) dict function! OnEvent(id, data, event) dict
let text = string([a:id, a:data, a:event]) let text = string([a:id, a:data, a:event])
call chansend(g:x, text) call chansend(g:x, text)
endfunction endfunction
let g:x = stdioopen({'on_stdin':'OnEvent'}) 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) ok(id > 0)
command("call chansend(id, 'TEXT\n')") 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)") command('call chansend(id, 0z426c6f6273210a)')
expect_twoline(id, "stdout", "Blobs!\r", "[1, ['Blobs!', ''], 'stdin']") expect_twoline(id, 'stdout', 'Blobs!\r', "[1, ['Blobs!', ''], 'stdin']")
command("call chansend(id, 'neovan')") 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')") 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')") command("call chansend(id, 'incomplet\004')")
local bsdlike = is_os('bsd') or is_os('mac') local bsdlike = is_os('bsd') or is_os('mac')
local extra = bsdlike and "^D\008\008" or "" local extra = bsdlike and '^D\008\008' or ''
expect_twoline(id, "stdout", expect_twoline(id, 'stdout', 'incomplet' .. extra, "[1, ['incomplet'], 'stdin']", true)
"incomplet"..extra, "[1, ['incomplet'], 'stdin']", true)
command("call chansend(id, '\004')") command("call chansend(id, '\004')")
if bsdlike then if bsdlike then
expect_twoline(id, "stdout", extra, "[1, [''], 'stdin']", true) expect_twoline(id, 'stdout', extra, "[1, [''], 'stdin']", true)
else else
eq({"notification", "stdout", {id, {"[1, [''], 'stdin']"}}}, next_msg()) eq({ 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } }, next_msg())
end end
-- channel is still open -- channel is still open
command("call chansend(id, 'hi again!\n')") 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) end)
it('stdio channel can use rpc and stderr simultaneously', function() it('stdio channel can use rpc and stderr simultaneously', function()
skip(is_os('win')) skip(is_os('win'))
source([[ source([[
@@ -206,27 +220,33 @@ describe('channels', function()
\ 'rpc': v:true, \ 'rpc': v:true,
\ } \ }
]]) ]])
meths.set_var("nvim_prog", nvim_prog) meths.set_var('nvim_prog', nvim_prog)
meths.set_var("code", [[ meths.set_var(
'code',
[[
let id = stdioopen({'rpc':v:true}) let id = stdioopen({'rpc':v:true})
call rpcnotify(id,"nvim_call_function", "rpcnotify", [1, "message", "hi there!", id]) call rpcnotify(id,"nvim_call_function", "rpcnotify", [1, "message", "hi there!", id])
call chansend(v:stderr, "trouble!") 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()) command(
eq({"notification", "stderr", {3, {"trouble!"}}}, next_msg()) "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(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\")')") local _, err =
ok(string.find(err,"E906: invalid stream for channel") ~= nil) 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(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')") command("call rpcnotify(id, 'nvim_command', 'quit')")
eq({"notification", "exit", {3, 0}}, next_msg()) eq({ 'notification', 'exit', { 3, 0 } }, next_msg())
end) end)
it('can use buffered output mode', function() it('can use buffered output mode', function()
@@ -239,27 +259,29 @@ describe('channels', function()
\ } \ }
]]) ]])
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") 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")]]) command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]])
sleep(10) sleep(10)
command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]]) command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]])
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
eq({"notification", "stdout", {id, {'10 PRINT "NVIM"', eq({
'20 GOTO 10', ''}}}, next_msg()) 'notification',
eq({"notification", "exit", {id, 0}}, next_msg()) '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)") 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 chansend(id, "is no number\nnot at all")]])
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
-- works correctly with no output -- works correctly with no output
eq({"notification", "stdout", {id, {''}}}, next_msg()) eq({ 'notification', 'stdout', { id, { '' } } }, next_msg())
eq({"notification", "exit", {id, 1}}, next_msg()) eq({ 'notification', 'exit', { id, 1 } }, next_msg())
end) end)
it('can use buffered output mode with no stream callback', function() 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)") 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")]]) command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]])
sleep(10) sleep(10)
command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]]) command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]])
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"', eq({
'20 GOTO 10', ''}}}, next_msg()) 'notification',
'exit',
{ id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } },
}, next_msg())
-- if dict is reused the new value is not stored, -- if dict is reused the new value is not stored,
-- but nvim also does not crash -- but nvim also does not crash
command("let id = jobstart(['cat'], g:job_opts)") command("let id = jobstart(['cat'], g:job_opts)")
id = eval("g:id") id = eval('g:id')
command([[call chansend(id, "cat text\n")]]) command([[call chansend(id, "cat text\n")]])
sleep(10) sleep(10)
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
-- old value was not overwritten -- old value was not overwritten
eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"', eq({
'20 GOTO 10', ''}}}, next_msg()) 'notification',
'exit',
{ id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } },
}, next_msg())
-- and an error was thrown. -- 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 -- reset dictionary
source([[ source([[
@@ -308,13 +339,13 @@ describe('channels', function()
\ } \ }
]]) ]])
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)") 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 chansend(id, "is no number\nnot at all")]])
command("call chanclose(id, 'stdin')") command("call chanclose(id, 'stdin')")
-- works correctly with no output -- works correctly with no output
eq({"notification", "exit", {id, 1, {''}}}, next_msg()) eq({ 'notification', 'exit', { id, 1, { '' } } }, next_msg())
end) end)
end) end)
@@ -325,8 +356,10 @@ describe('loopback', function()
end) end)
it('does not crash when sending raw data', function() it('does not crash when sending raw data', function()
eq("Vim(call):Can't send raw data to rpc channel", eq(
pcall_err(command, "call chansend(chan, 'test')")) "Vim(call):Can't send raw data to rpc channel",
pcall_err(command, "call chansend(chan, 'test')")
)
assert_alive() assert_alive()
end) end)

View File

@@ -59,7 +59,12 @@ end)
describe(':cquit', function() describe(':cquit', function()
local function test_cq(cmdline, exit_code, redir_msg) local function test_cq(cmdline, exit_code, redir_msg)
if redir_msg then 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() poke_eventloop()
assert_alive() assert_alive()
else else

View File

@@ -34,8 +34,7 @@ local spawn = helpers.spawn
local set_session = helpers.set_session local set_session = helpers.set_session
describe('fileio', function() describe('fileio', function()
before_each(function() before_each(function() end)
end)
after_each(function() after_each(function()
check_close() check_close()
os.remove('Xtest_startup_shada') os.remove('Xtest_startup_shada')
@@ -51,7 +50,7 @@ describe('fileio', function()
rmdir('Xtest_backupdir with spaces') rmdir('Xtest_backupdir with spaces')
end) 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. --- Starts a new nvim session and returns an attached screen.
local function startup(extra_args) local function startup(extra_args)
extra_args = extra_args or {} extra_args = extra_args or {}
@@ -61,15 +60,15 @@ describe('fileio', function()
local screen = Screen.new(70, 10) local screen = Screen.new(70, 10)
screen:attach() screen:attach()
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = {foreground = Screen.colors.NvimDarkGrey4}; [1] = { foreground = Screen.colors.NvimDarkGrey4 },
[2] = {background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3}; [2] = { background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3 },
[3] = {foreground = Screen.colors.NvimLightCyan}; [3] = { foreground = Screen.colors.NvimLightCyan },
}) })
return screen return screen
end end
it("fsync() with 'nofsync' #8304", function() 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): -- These cases ALWAYS force fsync (regardless of 'fsync' option):
@@ -102,12 +101,17 @@ describe('fileio', function()
-- 4. Exit caused by deadly signal (+ 'swapfile'). -- 4. Exit caused by deadly signal (+ 'swapfile').
local j = funcs.jobstart(vim.tbl_flatten({ args, '--embed' }), { rpc = true }) 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 set nofsync directory=Xtest_startup_swapdir
edit Xtest_startup_file2 edit Xtest_startup_file2
write write
put ='fsyncd text' put ='fsyncd text'
]], {}) ]],
{}
)
eq('Xtest_startup_swapdir', funcs.rpcrequest(j, 'nvim_eval', '&directory')) eq('Xtest_startup_swapdir', funcs.rpcrequest(j, 'nvim_eval', '&directory'))
funcs.jobstop(j) -- Send deadly signal. funcs.jobstop(j) -- Send deadly signal.
@@ -123,8 +127,14 @@ describe('fileio', function()
it('backup #9709', function() it('backup #9709', function()
skip(is_ci('cirrus')) skip(is_ci('cirrus'))
clear({ args={ '-i', 'Xtest_startup_shada', clear({
'--cmd', 'set directory=Xtest_startup_swapdir' } }) args = {
'-i',
'Xtest_startup_shada',
'--cmd',
'set directory=Xtest_startup_swapdir',
},
})
command('write Xtest_startup_file1') command('write Xtest_startup_file1')
feed('ifoo<esc>') feed('ifoo<esc>')
@@ -137,8 +147,8 @@ describe('fileio', function()
local foobar_contents = trim(read_file('Xtest_startup_file1')) local foobar_contents = trim(read_file('Xtest_startup_file1'))
local bar_contents = trim(read_file('Xtest_startup_file1~')) local bar_contents = trim(read_file('Xtest_startup_file1~'))
eq('foobar', foobar_contents); eq('foobar', foobar_contents)
eq('foo', bar_contents); eq('foo', bar_contents)
end) end)
it('backup with full path #11214', function() it('backup with full path #11214', function()
@@ -154,13 +164,16 @@ describe('fileio', function()
command('write') command('write')
-- Backup filename = fullpath, separators replaced with "%". -- Backup filename = fullpath, separators replaced with "%".
local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1', local backup_file_name = string.gsub(
is_os('win') and '[:/\\]' or '/', '%%') .. '~' currentdir() .. '/Xtest_startup_file1',
is_os('win') and '[:/\\]' or '/',
'%%'
) .. '~'
local foo_contents = trim(read_file('Xtest_backupdir/' .. backup_file_name)) local foo_contents = trim(read_file('Xtest_backupdir/' .. backup_file_name))
local foobar_contents = trim(read_file('Xtest_startup_file1')) local foobar_contents = trim(read_file('Xtest_startup_file1'))
eq('foobar', foobar_contents); eq('foobar', foobar_contents)
eq('foo', foo_contents); eq('foo', foo_contents)
end) end)
it('backup with full path with spaces', function() it('backup with full path with spaces', function()
@@ -176,13 +189,16 @@ describe('fileio', function()
command('write') command('write')
-- Backup filename = fullpath, separators replaced with "%". -- Backup filename = fullpath, separators replaced with "%".
local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1', local backup_file_name = string.gsub(
is_os('win') and '[:/\\]' or '/', '%%') .. '~' currentdir() .. '/Xtest_startup_file1',
is_os('win') and '[:/\\]' or '/',
'%%'
) .. '~'
local foo_contents = trim(read_file('Xtest_backupdir with spaces/' .. backup_file_name)) local foo_contents = trim(read_file('Xtest_backupdir with spaces/' .. backup_file_name))
local foobar_contents = trim(read_file('Xtest_startup_file1')) local foobar_contents = trim(read_file('Xtest_startup_file1'))
eq('foobar', foobar_contents); eq('foobar', foobar_contents)
eq('foo', foo_contents); eq('foo', foo_contents)
end) end)
it('backup symlinked files #11349', function() it('backup symlinked files #11349', function()
@@ -202,11 +218,10 @@ describe('fileio', function()
command('write') command('write')
local backup_raw = read_file(backup_file_name) 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') eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
end) end)
it('backup symlinked files in first available backupdir #11349', function() it('backup symlinked files in first available backupdir #11349', function()
skip(is_ci('cirrus')) skip(is_ci('cirrus'))
clear() clear()
@@ -228,7 +243,7 @@ describe('fileio', function()
command('write') command('write')
local backup_raw = read_file(backup_file_name) 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') eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
end) end)
@@ -247,7 +262,7 @@ describe('fileio', function()
table.insert(text, '') table.insert(text, '')
eq(text, funcs.readfile(fname, 'b')) eq(text, funcs.readfile(fname, 'b'))
end) end)
it('read invalid u8 over INT_MAX doesn\'t segfault', function() it("read invalid u8 over INT_MAX doesn't segfault", function()
clear() clear()
command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")') command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")')
-- This should not segfault -- This should not segfault
@@ -257,18 +272,18 @@ describe('fileio', function()
it(':w! does not show "file has been changed" warning', function() it(':w! does not show "file has been changed" warning', function()
clear() clear()
write_file("Xtest-overwrite-forced", 'foobar') write_file('Xtest-overwrite-forced', 'foobar')
command('set nofixendofline') command('set nofixendofline')
local screen = Screen.new(40, 4) local screen = Screen.new(40, 4)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[1] = { bold = true, foreground = Screen.colors.Blue1 }, [1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, [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() screen:attach()
command("set shortmess-=F") command('set shortmess-=F')
command("e Xtest-overwrite-forced") command('e Xtest-overwrite-forced')
screen:expect([[ screen:expect([[
^foobar | ^foobar |
{1:~ }|*2 {1:~ }|*2
@@ -276,14 +291,14 @@ describe('fileio', function()
]]) ]])
-- Get current unix time. -- 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 local future_time = cur_unix_time + 999999
-- Set the file's access/update time to be -- Set the file's access/update time to be
-- greater than the time at which it was created. -- 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) uv.fs_utime('Xtest-overwrite-forced', future_time, future_time)
-- use async feed_command because nvim basically hangs on the prompt -- use async feed_command because nvim basically hangs on the prompt
feed_command("w") feed_command('w')
screen:expect([[ screen:expect([[
{2:WARNING: The file has been changed since}| {2:WARNING: The file has been changed since}|
{2: reading it!!!} | {2: reading it!!!} |
@@ -291,15 +306,15 @@ describe('fileio', function()
^ | ^ |
]]) ]])
feed("n") feed('n')
feed("<cr>") feed('<cr>')
screen:expect([[ screen:expect([[
^foobar | ^foobar |
{1:~ }|*2 {1:~ }|*2
| |
]]) ]])
-- Use a screen test because the warning does not set v:errmsg. -- Use a screen test because the warning does not set v:errmsg.
command("w!") command('w!')
screen:expect([[ screen:expect([[
^foobar | ^foobar |
{1:~ }|*2 {1:~ }|*2
@@ -333,7 +348,7 @@ describe('tmpdir', function()
end end
it('failure modes', function() 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 is not a directory', testlog)
assert_nolog('tempdir has invalid permissions', testlog) assert_nolog('tempdir has invalid permissions', testlog)
@@ -345,7 +360,7 @@ describe('tmpdir', function()
expect_exit(command, ':qall!') expect_exit(command, ':qall!')
rmdir(tmproot) rmdir(tmproot)
write_file(tmproot, '') -- Not a directory, vim_mktempdir() should skip it. 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(). matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled. -- Assert that broken tmpdir root was handled.
assert_log('tempdir root not a directory', testlog, 100) assert_log('tempdir root not a directory', testlog, 100)
@@ -356,7 +371,7 @@ describe('tmpdir', function()
os.remove(tmproot) os.remove(tmproot)
mkdir(tmproot) mkdir(tmproot)
funcs.setfperm(tmproot, 'rwxr--r--') -- Invalid permissions, vim_mktempdir() should skip it. 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(). matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled. -- Assert that broken tmpdir root was handled.
assert_log('tempdir root has invalid permissions', testlog, 100) assert_log('tempdir root has invalid permissions', testlog, 100)
@@ -365,14 +380,14 @@ describe('tmpdir', function()
it('too long', function() it('too long', function()
local bigname = ('%s/%s'):format(os_tmpdir, ('x'):rep(666)) local bigname = ('%s/%s'):format(os_tmpdir, ('x'):rep(666))
mkdir(bigname) 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(). matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
local len = (funcs.tempname()):len() local len = (funcs.tempname()):len()
ok(len > 4 and len < 256, '4 < len < 256', tostring(len)) ok(len > 4 and len < 256, '4 < len < 256', tostring(len))
end) end)
it('disappeared #1432', function() 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) assert_nolog('tempdir disappeared', testlog)
local function rm_tmpdir() local function rm_tmpdir()
@@ -406,12 +421,13 @@ describe('tmpdir', function()
end) end)
it('$NVIM_APPNAME relative path', function() it('$NVIM_APPNAME relative path', function()
clear({ env={ clear({
env = {
NVIM_APPNAME = 'a/b', NVIM_APPNAME = 'a/b',
NVIM_LOG_FILE = testlog, NVIM_LOG_FILE = testlog,
TMPDIR = os_tmpdir, TMPDIR = os_tmpdir,
} }) },
})
matches([=[.*[/\\]a%%b%.[^/\\]+]=], funcs.tempname()) matches([=[.*[/\\]a%%b%.[^/\\]+]=], funcs.tempname())
end) end)
end) end)

View File

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

View File

@@ -33,27 +33,44 @@ describe('command-line option', function()
it('treats - as stdin', function() it('treats - as stdin', function()
eq(nil, luv.fs_stat(fname)) eq(nil, luv.fs_stat(fname))
funcs.system( funcs.system({
{nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', nvim_prog_abs(),
'--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', '-u',
'-s', '-', fname}, 'NONE',
{':call setline(1, "42")', ':wqall!', ''}) '-i',
'NONE',
'--headless',
'--cmd',
'set noswapfile shortmess+=IFW fileformats=unix',
'-s',
'-',
fname,
}, { ':call setline(1, "42")', ':wqall!', '' })
eq(0, eval('v:shell_error')) eq(0, eval('v:shell_error'))
local attrs = luv.fs_stat(fname) local attrs = luv.fs_stat(fname)
eq(#('42\n'), attrs.size) eq(#'42\n', attrs.size)
end) end)
it('does not expand $VAR', function() it('does not expand $VAR', function()
eq(nil, luv.fs_stat(fname)) eq(nil, luv.fs_stat(fname))
eq(true, not not dollar_fname:find('%$%w+')) eq(true, not not dollar_fname:find('%$%w+'))
write_file(dollar_fname, ':call setline(1, "100500")\n:wqall!\n') write_file(dollar_fname, ':call setline(1, "100500")\n:wqall!\n')
funcs.system( funcs.system({
{nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', nvim_prog_abs(),
'--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', '-u',
'-s', dollar_fname, fname}) 'NONE',
'-i',
'NONE',
'--headless',
'--cmd',
'set noswapfile shortmess+=IFW fileformats=unix',
'-s',
dollar_fname,
fname,
})
eq(0, eval('v:shell_error')) eq(0, eval('v:shell_error'))
local attrs = luv.fs_stat(fname) local attrs = luv.fs_stat(fname)
eq(#('100500\n'), attrs.size) eq(#'100500\n', attrs.size)
end) end)
it('does not crash after reading from stdin in non-headless mode', function() 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) local screen = Screen.new(40, 8)
screen:attach() screen:attach()
local args = { local args = {
nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', nvim_prog_abs(),
'--cmd', '"set noswapfile shortmess+=IFW fileformats=unix notermguicolors"', '-u',
'-s', '-' '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 -- Need to explicitly pipe to stdin so that the embedded Nvim instance doesn't try to read
-- data from the terminal #18181 -- data from the terminal #18181
funcs.termopen(string.format([[echo "" | %s]], table.concat(args, " ")), { funcs.termopen(string.format([[echo "" | %s]], table.concat(args, ' ')), {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
}) })
screen:expect([[ screen:expect(
[[
^ | ^ |
~ |*4 ~ |*4
{1:[No Name] 0,0-1 All}| {1:[No Name] 0,0-1 All}|
|*2 |*2
]], { ]],
[1] = {reverse = true}; {
}) [1] = { reverse = true },
}
)
feed('i:cq<CR>') feed('i:cq<CR>')
screen:expect([[ screen:expect([[
| |
@@ -102,11 +128,21 @@ describe('command-line option', function()
it('errors out when trying to use nonexistent file with -s', function() it('errors out when trying to use nonexistent file with -s', function()
eq( eq(
'Cannot open for reading: "' .. nonexistent_fname .. '": no such file or directory\n', 'Cannot open for reading: "' .. nonexistent_fname .. '": no such file or directory\n',
funcs.system( funcs.system({
{nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', nvim_prog_abs(),
'--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', '-u',
'--cmd', 'language C', 'NONE',
'-s', nonexistent_fname})) '-i',
'NONE',
'--headless',
'--cmd',
'set noswapfile shortmess+=IFW fileformats=unix',
'--cmd',
'language C',
'-s',
nonexistent_fname,
})
)
eq(2, eval('v:shell_error')) eq(2, eval('v:shell_error'))
end) end)
@@ -115,11 +151,24 @@ describe('command-line option', function()
write_file(dollar_fname, ':call setline(1, "2")\n:wqall!\n') write_file(dollar_fname, ':call setline(1, "2")\n:wqall!\n')
eq( eq(
'Attempt to open script file again: "-s ' .. dollar_fname .. '"\n', 'Attempt to open script file again: "-s ' .. dollar_fname .. '"\n',
funcs.system( funcs.system({
{nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless', nvim_prog_abs(),
'--cmd', 'set noswapfile shortmess+=IFW fileformats=unix', '-u',
'--cmd', 'language C', 'NONE',
'-s', fname, '-s', dollar_fname, fname_2})) '-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(2, eval('v:shell_error'))
eq(nil, luv.fs_stat(fname_2)) eq(nil, luv.fs_stat(fname_2))
end) end)

View File

@@ -67,10 +67,10 @@ describe('expand wildcard', function()
it('with special characters #24421', function() it('with special characters #24421', function()
local folders = is_os('win') and { local folders = is_os('win') and {
'{folder}', '{folder}',
'folder$name' 'folder$name',
} or { } or {
'folder-name', 'folder-name',
'folder#name' 'folder#name',
} }
for _, folder in ipairs(folders) do for _, folder in ipairs(folders) do
mkdir(folder) mkdir(folder)
@@ -131,14 +131,30 @@ describe('file search', function()
test_cfile([[c:foo]], [[c]]) test_cfile([[c:foo]], [[c]])
-- Examples from: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#example-ways-to-refer-to-the-same-file -- 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([[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(
test_cfile([[\\LOCALHOST\c$\temp\test-file.txt]], [[LOCALHOST]], [[\\LOCALHOST\c$\temp\test-file.txt]]) [[\\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 -- not supported yet
test_cfile([[\\.\c:\temp\test-file.txt]], [[.]], [[\\.\c]]) test_cfile([[\\.\c:\temp\test-file.txt]], [[.]], [[\\.\c]])
-- not supported yet -- not supported yet
test_cfile([[\\?\c:\temp\test-file.txt]], [[c:]], [[\\]]) 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(
test_cfile([[\\127.0.0.1\c$\temp\test-file.txt]], [[127.0.0.1]], [[\\127.0.0.1\c$\temp\test-file.txt]]) [[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]],
[[.]],
[[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]]
)
test_cfile(
[[\\127.0.0.1\c$\temp\test-file.txt]],
[[127.0.0.1]],
[[\\127.0.0.1\c$\temp\test-file.txt]]
)
end) end)
---@param funcname 'finddir' | 'findfile' ---@param funcname 'finddir' | 'findfile'

View File

@@ -51,7 +51,10 @@ describe('Remote', function()
local client_starter = spawn(new_argv(), false, nil, true) local client_starter = spawn(new_argv(), false, nil, true)
set_session(client_starter) set_session(client_starter)
-- Call jobstart() and jobwait() in the same RPC request to reduce flakiness. -- 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, stdout_buffered = true,
stderr_buffered = true, stderr_buffered = true,
on_stdout = function(_, data, _) on_stdout = function(_, data, _)
@@ -60,7 +63,15 @@ describe('Remote', function()
on_stderr = function(_, data, _) on_stderr = function(_, data, _)
_G.Remote_stderr = table.concat(data, '\n') _G.Remote_stderr = table.concat(data, '\n')
end, end,
}) })]], nvim_prog, '--clean', '--headless', '--server', addr, ...)) }) })]],
nvim_prog,
'--clean',
'--headless',
'--server',
addr,
...
)
)
local res = exec_lua([[return { _G.Remote_stdout, _G.Remote_stderr }]]) local res = exec_lua([[return { _G.Remote_stdout, _G.Remote_stderr }]])
client_starter:close() client_starter:close()
set_session(server) set_session(server)

View File

@@ -25,6 +25,7 @@ describe('spellfile', function()
local spellheader = 'VIMspell\050' local spellheader = 'VIMspell\050'
it('errors out when prefcond section is truncated', function() it('errors out when prefcond section is truncated', function()
meths.set_option_value('runtimepath', testdir, {}) meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl', write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND) -- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero) -- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -35,11 +36,11 @@ describe('spellfile', function()
-- │ │ ┌ Condition regex (missing!) -- │ │ ┌ Condition regex (missing!)
.. '\000\001\001') .. '\000\001\001')
meths.set_option_value('spelllang', 'en', {}) meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E758: Truncated spell file', eq('Vim(set):E758: Truncated spell file', exc_exec('set spell'))
exc_exec('set spell'))
end) end)
it('errors out when prefcond regexp contains NUL byte', function() it('errors out when prefcond regexp contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {}) meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl', write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND) -- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero) -- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -55,11 +56,11 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length -- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000') .. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {}) meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file', eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
exc_exec('set spell'))
end) end)
it('errors out when region contains NUL byte', function() it('errors out when region contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {}) meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl', write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_REGION) -- ┌ Section identifier (#SN_REGION)
-- │ ┌ Section flags (#SNF_REQUIRED or zero) -- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -72,11 +73,11 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length -- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000') .. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {}) meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file', eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
exc_exec('set spell'))
end) end)
it('errors out when SAL section contains NUL byte', function() it('errors out when SAL section contains NUL byte', function()
meths.set_option_value('runtimepath', testdir, {}) meths.set_option_value('runtimepath', testdir, {})
-- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl', write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_SAL) -- ┌ Section identifier (#SN_SAL)
-- │ ┌ Section flags (#SNF_REQUIRED or zero) -- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -96,15 +97,12 @@ describe('spellfile', function()
-- │ │ ┌ PREFIXTREE tree length -- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000') .. '\000\000\000\000\000\000\000\000\000\000\000\000')
meths.set_option_value('spelllang', 'en', {}) meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file', eq('Vim(set):E759: Format error in spell file', exc_exec('set spell'))
exc_exec('set spell'))
end) end)
it('errors out when spell header contains NUL bytes', function() it('errors out when spell header contains NUL bytes', function()
meths.set_option_value('runtimepath', testdir, {}) meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl', write_file(testdir .. '/spell/en.ascii.spl', spellheader:sub(1, -3) .. '\000\000')
spellheader:sub(1, -3) .. '\000\000')
meths.set_option_value('spelllang', 'en', {}) meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E757: This does not look like a spell file', eq('Vim(set):E757: This does not look like a spell file', exc_exec('set spell'))
exc_exec('set spell'))
end) end)
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`. -- K on the text "K_spec_out" resolves to `!echo fnord >> K_spec_out`.
feed('i' .. test_file .. '<ESC>K') 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 .. "')")) eq({ 'fnord' }, eval("readfile('" .. test_file .. "')"))
-- Confirm that Neovim is still in terminal mode after K is pressed (#16692). -- Confirm that Neovim is still in terminal mode after K is pressed (#16692).
helpers.sleep(500) helpers.sleep(500)
@@ -64,5 +66,4 @@ describe('K', function()
feed('K') feed('K')
eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg')) eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
end) end)
end) end)

View File

@@ -57,9 +57,10 @@ describe('completion', function()
it('returns expected dict in normal completion', function() it('returns expected dict in normal completion', function()
feed('ifoo<ESC>o<C-x><C-n>') feed('ifoo<ESC>o<C-x><C-n>')
eq('foo', eval('getline(2)')) eq('foo', eval('getline(2)'))
eq({word = 'foo', abbr = '', menu = '', eq(
info = '', kind = '', user_data = ''}, { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' },
eval('v:completed_item')) eval('v:completed_item')
)
end) end)
it('is readonly', function() it('is readonly', function()
screen:try_resize(80, 8) screen:try_resize(80, 8)
@@ -107,9 +108,14 @@ describe('completion', function()
{0:~ }|*4 {0:~ }|*4
{3:-- Omni completion (^O^N^P) }{4:match 1 of 2} | {3:-- Omni completion (^O^N^P) }{4:match 1 of 2} |
]]) ]])
eq({word = 'foo', abbr = 'bar', menu = 'baz', eq({
info = 'foobar', kind = 'foobaz', user_data = ''}, word = 'foo',
eval('v:completed_item')) abbr = 'bar',
menu = 'baz',
info = 'foobar',
kind = 'foobaz',
user_data = '',
}, eval('v:completed_item'))
end) end)
end) end)
@@ -329,7 +335,7 @@ describe('completion', function()
end end
end) end)
describe("refresh:always", function() describe('refresh:always', function()
before_each(function() before_each(function()
source([[ source([[
function! TestCompletion(findstart, base) abort function! TestCompletion(findstart, base) abort
@@ -402,7 +408,7 @@ describe('completion', function()
expect('August') expect('August')
end) end)
it("repeats correctly after backspace #2674", function () it('repeats correctly after backspace #2674', function()
feed('o<C-x><C-u>Ja') feed('o<C-x><C-u>Ja')
screen:expect([[ screen:expect([[
| |
@@ -471,10 +477,10 @@ describe('completion', function()
return '' return ''
endfunction endfunction
]]) ]])
feed_command("set completeopt=menuone,noselect") feed_command('set completeopt=menuone,noselect')
end) end)
it("works", function() it('works', function()
feed('i<C-r>=TestComplete()<CR>') feed('i<C-r>=TestComplete()<CR>')
screen:expect([[ screen:expect([[
^ | ^ |
@@ -630,7 +636,7 @@ describe('completion', function()
end) end)
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". -- Indents on "ind", unindents on "unind".
source([[ source([[
function! TestIndent() function! TestIndent()
@@ -649,14 +655,14 @@ describe('completion', function()
]]) ]])
-- Give some words to complete. -- Give some words to complete.
feed("iinc uninc indent unindent<CR>") feed('iinc uninc indent unindent<CR>')
-- Does not indent when "ind" is typed. -- 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 -- Completion list is generated incorrectly if we send everything at once
-- via nvim_input(). So poke_eventloop() before sending <BS>. #8480 -- via nvim_input(). So poke_eventloop() before sending <BS>. #8480
poke_eventloop() poke_eventloop()
feed("<BS>d") feed('<BS>d')
screen:expect([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
@@ -667,7 +673,7 @@ describe('completion', function()
]]) ]])
-- Indents when the item is selected -- Indents when the item is selected
feed("<C-Y>") feed('<C-Y>')
screen:expect([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent^ | indent^ |
@@ -675,7 +681,7 @@ describe('completion', function()
{3:-- INSERT --} | {3:-- INSERT --} |
]]) ]])
-- Indents when completion is exited using ESC. -- 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([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent | indent |
@@ -684,9 +690,9 @@ describe('completion', function()
| |
]]) ]])
-- Works for unindenting too. -- Works for unindenting too.
feed("ounin<C-X><C-N>") feed('ounin<C-X><C-N>')
helpers.poke_eventloop() helpers.poke_eventloop()
feed("<BS>d") feed('<BS>d')
screen:expect([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent | indent |
@@ -697,7 +703,7 @@ describe('completion', function()
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]]) ]])
-- Works when going back and forth. -- Works when going back and forth.
feed("<BS>c") feed('<BS>c')
screen:expect([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent | indent |
@@ -707,7 +713,7 @@ describe('completion', function()
{0:~ }|*2 {0:~ }|*2
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]]) ]])
feed("<BS>d") feed('<BS>d')
screen:expect([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent | indent |
@@ -717,7 +723,7 @@ describe('completion', function()
{0:~ }|*2 {0:~ }|*2
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 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([[ screen:expect([[
inc uninc indent unindent | inc uninc indent unindent |
indent | indent |
@@ -729,7 +735,7 @@ describe('completion', function()
end) end)
it('disables folding during completion', function() 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') feed('i<Tab>foo<CR><Tab>bar<Esc>gg')
screen:expect([[ screen:expect([[
^foo | ^foo |
@@ -748,7 +754,7 @@ describe('completion', function()
end) end)
it('popupmenu is not interrupted by events', function() it('popupmenu is not interrupted by events', function()
feed_command("set complete=.") feed_command('set complete=.')
feed('ifoobar fooegg<cr>f<c-p>') feed('ifoobar fooegg<cr>f<c-p>')
screen:expect([[ screen:expect([[
@@ -762,14 +768,17 @@ describe('completion', function()
assert_alive() assert_alive()
-- popupmenu still visible -- popupmenu still visible
screen:expect{grid=[[ screen:expect {
grid = [[
foobar fooegg | foobar fooegg |
fooegg^ | fooegg^ |
{1:foobar }{0: }| {1:foobar }{0: }|
{2:fooegg }{0: }| {2:fooegg }{0: }|
{0:~ }|*3 {0:~ }|*3
{3:-- Keyword completion (^N^P) }{4:match 1 of 2} | {3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
]], unchanged=true} ]],
unchanged = true,
}
feed('<c-p>') feed('<c-p>')
-- Didn't restart completion: old matches still used -- Didn't restart completion: old matches still used
@@ -787,23 +796,28 @@ describe('completion', function()
it('expands when there is only one match', function() it('expands when there is only one match', function()
feed(':lua CURRENT_TESTING_VAR = 1<CR>') feed(':lua CURRENT_TESTING_VAR = 1<CR>')
feed(':lua CURRENT_TESTING_<TAB>') feed(':lua CURRENT_TESTING_<TAB>')
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{0:~ }|*6 {0:~ }|*6
:lua CURRENT_TESTING_VAR^ | :lua CURRENT_TESTING_VAR^ |
]]} ]],
}
end) end)
it('expands when there is only one match', function() it('expands when there is only one match', function()
feed(':lua CURRENT_TESTING_FOO = 1<CR>') feed(':lua CURRENT_TESTING_FOO = 1<CR>')
feed(':lua CURRENT_TESTING_BAR = 1<CR>') feed(':lua CURRENT_TESTING_BAR = 1<CR>')
feed(':lua CURRENT_TESTING_<TAB>') feed(':lua CURRENT_TESTING_<TAB>')
screen:expect{ grid = [[ screen:expect {
grid = [[
| |
{0:~ }|*5 {0:~ }|*5
{10:CURRENT_TESTING_BAR}{9: CURRENT_TESTING_FOO }| {10:CURRENT_TESTING_BAR}{9: CURRENT_TESTING_FOO }|
:lua CURRENT_TESTING_BAR^ | :lua CURRENT_TESTING_BAR^ |
]], unchanged = true } ]],
unchanged = true,
}
end) end)
it('provides completion from `getcompletion()`', function() it('provides completion from `getcompletion()`', function()
@@ -870,7 +884,8 @@ describe('completion', function()
endfunction endfunction
]]) ]])
meths.set_option_value('completeopt', 'menuone,noselect', {}) meths.set_option_value('completeopt', 'menuone,noselect', {})
meths.set_var('_complist', {{ meths.set_var('_complist', {
{
word = 0, word = 0,
abbr = 1, abbr = 1,
menu = 2, menu = 2,
@@ -879,7 +894,8 @@ describe('completion', function()
icase = 5, icase = 5,
dup = 6, dup = 6,
empty = 7, empty = 7,
}}) },
})
end) end)
it('shows correct variant as word', function() it('shows correct variant as word', function()
@@ -897,7 +913,8 @@ describe('completion', function()
feed_command('set ignorecase infercase') feed_command('set ignorecase infercase')
feed_command('edit runtime/doc/backers.txt') feed_command('edit runtime/doc/backers.txt')
feed('oX<C-X><C-N>') feed('oX<C-X><C-N>')
screen:expect{grid=[[ screen:expect {
grid = [[
*backers.txt* Nvim | *backers.txt* Nvim |
Xnull^ | Xnull^ |
{2:Xnull }{6: } | {2:Xnull }{6: } |
@@ -906,7 +923,8 @@ describe('completion', function()
{1:Xpayn }{2: } | {1:Xpayn }{2: } |
{1:Xinity }{2: } | {1:Xinity }{2: } |
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} | {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} |
]]} ]],
}
end) end)
it('CompleteChanged autocommand', function() it('CompleteChanged autocommand', function()
@@ -925,39 +943,45 @@ describe('completion', function()
-- v:event.size should be set with ext_popupmenu #20646 -- v:event.size should be set with ext_popupmenu #20646
screen:set_option('ext_popupmenu', true) screen:set_option('ext_popupmenu', true)
feed('Sf<C-N>') feed('Sf<C-N>')
screen:expect({grid = [[ screen:expect({
grid = [[
foo | foo |
bar | bar |
foobar | foobar |
f^ | f^ |
{0:~ }|*3 {0:~ }|*3
{3:-- Keyword completion (^N^P) }{5:Back at original} | {3:-- Keyword completion (^N^P) }{5:Back at original} |
]], popupmenu = { ]],
popupmenu = {
anchor = { 1, 3, 0 }, anchor = { 1, 3, 0 },
items = { { "foo", "", "", "" }, { "foobar", "", "", "" } }, items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } },
pos = -1 pos = -1,
}}) },
eq({completed_item = {}, width = 0, })
height = 2, size = 2, eq(
col = 0, row = 4, scrollbar = false}, { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
eval('g:event')) eval('g:event')
)
feed('oob') feed('oob')
screen:expect({grid = [[ screen:expect({
grid = [[
foo | foo |
bar | bar |
foobar | foobar |
foob^ | foob^ |
{0:~ }|*3 {0:~ }|*3
{3:-- Keyword completion (^N^P) }{5:Back at original} | {3:-- Keyword completion (^N^P) }{5:Back at original} |
]], popupmenu = { ]],
popupmenu = {
anchor = { 1, 3, 0 }, anchor = { 1, 3, 0 },
items = { { "foobar", "", "", "" } }, items = { { 'foobar', '', '', '' } },
pos = -1 pos = -1,
}}) },
eq({completed_item = {}, width = 0, })
height = 1, size = 1, eq(
col = 0, row = 4, scrollbar = false}, { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false },
eval('g:event')) eval('g:event')
)
feed('<Esc>') feed('<Esc>')
screen:set_option('ext_popupmenu', false) screen:set_option('ext_popupmenu', false)
@@ -972,10 +996,10 @@ describe('completion', function()
{0:~ }| {0:~ }|
{3:-- Keyword completion (^N^P) }{5:Back at original} | {3:-- Keyword completion (^N^P) }{5:Back at original} |
]]) ]])
eq({completed_item = {}, width = 15, eq(
height = 2, size = 2, { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
col = 0, row = 4, scrollbar = false}, eval('g:event')
eval('g:event')) )
feed('<C-N>') feed('<C-N>')
screen:expect([[ screen:expect([[
foo | foo |
@@ -1084,7 +1108,8 @@ describe('completion', function()
screen:try_resize(20, 9) screen:try_resize(20, 9)
command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden') command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden')
feed('i<C-n>') feed('i<C-n>')
screen:expect{grid=[[ screen:expect {
grid = [[
foo^ | foo^ |
{2:foo }{0: }| {2:foo }{0: }|
{1:bar }{0: }| {1:bar }{0: }|
@@ -1092,15 +1117,18 @@ describe('completion', function()
{1:.hidden }{0: }| {1:.hidden }{0: }|
{0:~ }|*3 {0:~ }|*3
{3:-- }{4:match 1 of 4} | {3:-- }{4:match 1 of 4} |
]]} ]],
}
feed('<Esc>ccf<C-n>') feed('<Esc>ccf<C-n>')
screen:expect{grid=[[ screen:expect {
grid = [[
foo^ | foo^ |
{2:foo }{0: }| {2:foo }{0: }|
{1:foa }{0: }| {1:foa }{0: }|
{0:~ }|*5 {0:~ }|*5
{3:-- }{4:match 1 of 2} | {3:-- }{4:match 1 of 2} |
]]} ]],
}
end) end)
it('restores extmarks if original text is restored #23653', function() 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 poke_eventloop = helpers.poke_eventloop
local sleep = helpers.sleep local sleep = helpers.sleep
describe("CTRL-C (mapped)", function() describe('CTRL-C (mapped)', function()
local screen local screen
before_each(function() before_each(function()
@@ -14,7 +14,7 @@ describe("CTRL-C (mapped)", function()
screen:attach() screen:attach()
end) end)
it("interrupts :global", function() it('interrupts :global', function()
-- Crashes luajit. -- Crashes luajit.
if helpers.skip_fragile(pending) then if helpers.skip_fragile(pending) then
return return
@@ -25,7 +25,7 @@ describe("CTRL-C (mapped)", function()
nnoremap <C-C> <NOP> nnoremap <C-C> <NOP>
]]) ]])
command("silent edit! test/functional/fixtures/bigfile.txt") command('silent edit! test/functional/fixtures/bigfile.txt')
screen:expect([[ screen:expect([[
^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; | ^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
@@ -37,10 +37,10 @@ describe("CTRL-C (mapped)", function()
]]) ]])
local function test_ctrl_c(ms) local function test_ctrl_c(ms)
feed(":global/^/p<CR>") feed(':global/^/p<CR>')
screen:sleep(ms) screen:sleep(ms)
feed("<C-C>") feed('<C-C>')
screen:expect{any="Interrupt"} screen:expect { any = 'Interrupt' }
end end
-- The test is time-sensitive. Try different sleep values. -- 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 for i, ms in ipairs(ms_values) do
if i < #ms_values then if i < #ms_values then
local status, _ = pcall(test_ctrl_c, ms) local status, _ = pcall(test_ctrl_c, ms)
if status then break end if status then
break
end
else -- Call the last attempt directly. else -- Call the last attempt directly.
test_ctrl_c(ms) test_ctrl_c(ms)
end end

View File

@@ -13,8 +13,12 @@ describe('Folds', function()
local tempfname = 'Xtest-fold.txt' local tempfname = 'Xtest-fold.txt'
setup(clear) setup(clear)
before_each(function() command('bwipe! | new') end) before_each(function()
after_each(function() os.remove(tempfname) end) command('bwipe! | new')
end)
after_each(function()
os.remove(tempfname)
end)
it('manual folding adjusts with filter', function() it('manual folding adjusts with filter', function()
insert([[ insert([[
@@ -94,7 +98,8 @@ describe('Folds', function()
end end
it('neither closes nor corrupts folds', function() it('neither closes nor corrupts folds', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -112,7 +117,9 @@ a
a a
a a
a a
a]], '7,12m0') a]],
'7,12m0'
)
expect([[ expect([[
a a
a a
@@ -151,7 +158,8 @@ a
end) end)
it("doesn't split a fold when the move is within it", function() it("doesn't split a fold when the move is within it", function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -161,24 +169,30 @@ a
a a
a a
a a
a]], '5m6') a]],
'5m6'
)
eq({ 0, 1, 1, 2, 2, 2, 2, 1, 1, 0 }, get_folds()) eq({ 0, 1, 1, 2, 2, 2, 2, 1, 1, 0 }, get_folds())
end) end)
it('truncates folds that end in the moved range', function() it('truncates folds that end in the moved range', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
a a
a a
a a
a]], '4,5m6') a]],
'4,5m6'
)
eq({ 0, 1, 2, 0, 0, 0, 0 }, get_folds()) eq({ 0, 1, 2, 0, 0, 0, 0 }, get_folds())
end) end)
it('moves folds that start between moved range and destination', function() it('moves folds that start between moved range and destination', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -191,12 +205,15 @@ a
a a
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()) eq({ 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0 }, get_folds())
end) end)
it('does not affect folds outside changed lines', function() it('does not affect folds outside changed lines', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -205,12 +222,15 @@ a
a a
a a
a a
a]], '4m5') a]],
'4m5'
)
eq({ 1, 1, 1, 0, 0, 0, 1, 1, 1 }, get_folds()) eq({ 1, 1, 1, 0, 0, 0, 1, 1, 1 }, get_folds())
end) end)
it('moves and truncates folds that start in moved range', function() it('moves and truncates folds that start in moved range', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -220,34 +240,43 @@ a
a a
a a
a a
a]], '1,3m7') a]],
'1,3m7'
)
eq({ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0 }, get_folds()) eq({ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0 }, get_folds())
end) end)
it('breaks a fold when moving text into it', function() it('breaks a fold when moving text into it', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
a a
a a
a a
a]], '$m4') a]],
'$m4'
)
eq({ 0, 1, 2, 2, 0, 0, 0 }, get_folds()) eq({ 0, 1, 2, 2, 0, 0, 0 }, get_folds())
end) end)
it('adjusts correctly when moving a range backwards', function() it('adjusts correctly when moving a range backwards', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
a a
a]], '2,3m0') a]],
'2,3m0'
)
eq({ 1, 2, 0, 0, 0 }, get_folds()) eq({ 1, 2, 0, 0, 0 }, get_folds())
end) end)
it('handles shifting all remaining folds', function() it('handles shifting all remaining folds', function()
test_move_indent([[ test_move_indent(
[[
a a
a a
a a
@@ -262,18 +291,23 @@ a]], '2,3m0')
a a
a 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()) eq({ 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0 }, get_folds())
end) end)
end) end)
it('updates correctly on :read', function() it('updates correctly on :read', function()
-- luacheck: ignore 621 -- luacheck: ignore 621
helpers.write_file(tempfname, [[ helpers.write_file(
tempfname,
[[
a a
a]]) a]]
)
insert([[ insert([[
a a
a a
@@ -356,7 +390,9 @@ a]], '13m7')
return 0 return 0
endfunction endfunction
]]) ]])
helpers.write_file(tempfname, [[ helpers.write_file(
tempfname,
[[
b b
b b
a a
@@ -364,7 +400,8 @@ a]], '13m7')
d d
a a
a a
c]]) c]]
)
insert([[ insert([[
a a
a a

View File

@@ -60,7 +60,8 @@ describe('jumplist', function()
feed('35gg') feed('35gg')
command('edit ' .. fname2) command('edit ' .. fname2)
feed('<C-O>') feed('<C-O>')
screen:expect{grid=[[ screen:expect {
grid = [[
{1: 24 }foobar | {1: 24 }foobar |
{1: 25 }foobar | {1: 25 }foobar |
{1: 26 }foobar | {1: 26 }foobar |
@@ -86,9 +87,11 @@ describe('jumplist', function()
{1: 46 }foobar | {1: 46 }foobar |
{1: 47 }foobar | {1: 47 }foobar |
| |
]], attr_ids={ ]],
[1] = {foreground = Screen.colors.Brown}; attr_ids = {
}} [1] = { foreground = Screen.colors.Brown },
},
}
end) end)
end) end)
@@ -98,8 +101,7 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
feed(':clearjumps<cr>') feed(':clearjumps<cr>')
-- Add lines so that we have locations to jump to. -- Add lines so that we have locations to jump to.
for i = 1,101,1 for i = 1, 101, 1 do
do
feed('iLine ' .. i .. '<cr><esc>') feed('iLine ' .. i .. '<cr><esc>')
end end
@@ -122,7 +124,8 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
feed('<C-O>') feed('<C-O>')
feed('<C-O>') feed('<C-O>')
eq( '' eq(
''
.. ' jump line col file/text\n' .. ' jump line col file/text\n'
.. ' 4 102 0 \n' .. ' 4 102 0 \n'
.. ' 3 1 0 Line 1\n' .. ' 3 1 0 Line 1\n'
@@ -131,11 +134,13 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. '> 0 30 0 Line 30\n' .. '> 0 30 0 Line 30\n'
.. ' 1 40 0 Line 40\n' .. ' 1 40 0 Line 40\n'
.. ' 2 50 0 Line 50', .. ' 2 50 0 Line 50',
exec_capture('jumps')) exec_capture('jumps')
)
feed('90gg') feed('90gg')
eq( '' eq(
''
.. ' jump line col file/text\n' .. ' jump line col file/text\n'
.. ' 5 102 0 \n' .. ' 5 102 0 \n'
.. ' 4 1 0 Line 1\n' .. ' 4 1 0 Line 1\n'
@@ -143,14 +148,16 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 20 0 Line 20\n' .. ' 2 20 0 Line 20\n'
.. ' 1 30 0 Line 30\n' .. ' 1 30 0 Line 30\n'
.. '>', .. '>',
exec_capture('jumps')) exec_capture('jumps')
)
end) end)
it('does not add the same location twice adjacently', function() it('does not add the same location twice adjacently', function()
feed('60gg') feed('60gg')
feed('60gg') feed('60gg')
eq( '' eq(
''
.. ' jump line col file/text\n' .. ' jump line col file/text\n'
.. ' 7 102 0 \n' .. ' 7 102 0 \n'
.. ' 6 1 0 Line 1\n' .. ' 6 1 0 Line 1\n'
@@ -160,14 +167,16 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 40 0 Line 40\n' .. ' 2 40 0 Line 40\n'
.. ' 1 50 0 Line 50\n' .. ' 1 50 0 Line 50\n'
.. '>', .. '>',
exec_capture('jumps')) exec_capture('jumps')
)
end) end)
it('does add the same location twice nonadjacently', function() it('does add the same location twice nonadjacently', function()
feed('10gg') feed('10gg')
feed('20gg') feed('20gg')
eq( '' eq(
''
.. ' jump line col file/text\n' .. ' jump line col file/text\n'
.. ' 8 102 0 \n' .. ' 8 102 0 \n'
.. ' 7 1 0 Line 1\n' .. ' 7 1 0 Line 1\n'
@@ -178,19 +187,20 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
.. ' 2 50 0 Line 50\n' .. ' 2 50 0 Line 50\n'
.. ' 1 10 0 Line 10\n' .. ' 1 10 0 Line 10\n'
.. '>', .. '>',
exec_capture('jumps')) exec_capture('jumps')
)
end) end)
end) end)
describe("jumpoptions=view", function() describe('jumpoptions=view', function()
local file1 = 'Xtestfile-functional-editor-jumps' local file1 = 'Xtestfile-functional-editor-jumps'
local file2 = 'Xtestfile-functional-editor-jumps-2' local file2 = 'Xtestfile-functional-editor-jumps-2'
local function content() local function content()
local c = {} local c = {}
for i = 1, 30 do for i = 1, 30 do
c[i] = i .. " line" c[i] = i .. ' line'
end end
return table.concat(c, "\n") return table.concat(c, '\n')
end end
before_each(function() before_each(function()
clear() clear()
@@ -206,9 +216,9 @@ describe("jumpoptions=view", function()
it('restores the view', function() it('restores the view', function()
local screen = Screen.new(5, 8) local screen = Screen.new(5, 8)
screen:attach() screen:attach()
command("edit " .. file1) command('edit ' .. file1)
feed("12Gztj") feed('12Gztj')
feed("gg<C-o>") feed('gg<C-o>')
screen:expect([[ screen:expect([[
12 line | 12 line |
^13 line | ^13 line |
@@ -224,10 +234,10 @@ describe("jumpoptions=view", function()
it('restores the view across files', function() it('restores the view across files', function()
local screen = Screen.new(5, 5) local screen = Screen.new(5, 5)
screen:attach() screen:attach()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("12Gzt") feed('12Gzt')
command("next") command('next')
feed("G") feed('G')
screen:expect([[ screen:expect([[
27 line | 27 line |
28 line | 28 line |
@@ -235,7 +245,7 @@ describe("jumpoptions=view", function()
^30 line | ^30 line |
| |
]]) ]])
feed("<C-o><C-o>") feed('<C-o><C-o>')
screen:expect([[ screen:expect([[
^12 line | ^12 line |
13 line | 13 line |
@@ -248,10 +258,10 @@ describe("jumpoptions=view", function()
it('restores the view across files with <C-^>', function() it('restores the view across files with <C-^>', function()
local screen = Screen.new(5, 5) local screen = Screen.new(5, 5)
screen:attach() screen:attach()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("12Gzt") feed('12Gzt')
command("next") command('next')
feed("G") feed('G')
screen:expect([[ screen:expect([[
27 line | 27 line |
28 line | 28 line |
@@ -259,7 +269,7 @@ describe("jumpoptions=view", function()
^30 line | ^30 line |
| |
]]) ]])
feed("<C-^>") feed('<C-^>')
screen:expect([[ screen:expect([[
^12 line | ^12 line |
13 line | 13 line |
@@ -269,11 +279,11 @@ describe("jumpoptions=view", function()
]]) ]])
end) 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) local screen = Screen.new(5, 8)
screen:attach() screen:attach()
command("edit " .. file1) command('edit ' .. file1)
feed("7GzbG") feed('7GzbG')
curbufmeths.set_lines(0, 2, true, {}) 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 -- 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 -- 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 -- 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. -- 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. -- Therefore falls back to standard behavior which is centering the view/line.
feed("<C-o>") feed('<C-o>')
screen:expect([[ screen:expect([[
4 line | 4 line |
5 line | 5 line |

View File

@@ -9,11 +9,11 @@ describe('gu and gU', function()
it('works in any locale with default casemap', function() it('works in any locale with default casemap', function()
eq('internal,keepascii', eval('&casemap')) eq('internal,keepascii', eval('&casemap'))
insert("iI") insert('iI')
feed("VgU") feed('VgU')
expect("II") expect('II')
feed("Vgu") feed('Vgu')
expect("ii") expect('ii')
end) end)
describe('works in Turkish locale', function() 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') local err = exc_exec('lang ctype tr_TR.UTF-8')
if err ~= 0 then 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 return
end end
@@ -32,29 +32,29 @@ describe('gu and gU', function()
it('with default casemap', function() it('with default casemap', function()
eq('internal,keepascii', eval('&casemap')) eq('internal,keepascii', eval('&casemap'))
-- expect ASCII behavior -- expect ASCII behavior
insert("iI") insert('iI')
feed("VgU") feed('VgU')
expect("II") expect('II')
feed("Vgu") feed('Vgu')
expect("ii") expect('ii')
end) end)
it('with casemap=""', function() it('with casemap=""', function()
command('set casemap=') command('set casemap=')
-- expect either Turkish locale behavior or ASCII behavior -- expect either Turkish locale behavior or ASCII behavior
local iupper = eval("toupper('i')") local iupper = eval("toupper('i')")
if iupper == "İ" then if iupper == 'İ' then
insert("iI") insert('iI')
feed("VgU") feed('VgU')
expect("İI") expect('İI')
feed("Vgu") feed('Vgu')
expect("iı") expect('iı')
elseif iupper == "I" then elseif iupper == 'I' then
insert("iI") insert('iI')
feed("VgU") feed('VgU')
expect("II") expect('II')
feed("Vgu") feed('Vgu')
expect("ii") expect('ii')
else else
error("expected toupper('i') to be either 'I' or 'İ'") error("expected toupper('i') to be either 'I' or 'İ'")
end end

View File

@@ -14,13 +14,13 @@ describe("'langmap'", function()
feed('gg0') feed('gg0')
end) end)
it("converts keys in normal mode", function() it('converts keys in normal mode', function()
feed('ix') feed('ix')
expect('iii ww') expect('iii ww')
feed('whello<esc>') feed('whello<esc>')
expect('iii helloww') expect('iii helloww')
end) end)
it("gives characters that are mapped by :nmap.", function() it('gives characters that are mapped by :nmap.', function()
command('map i 0x') command('map i 0x')
feed('w') feed('w')
expect('ii www') expect('ii www')
@@ -32,20 +32,18 @@ describe("'langmap'", function()
it("'langnoremap' is by default ON", function() it("'langnoremap' is by default ON", function()
eq(1, eval('&langnoremap')) eq(1, eval('&langnoremap'))
end) end)
it("Results of maps are not converted when 'langnoremap' ON.", it("Results of maps are not converted when 'langnoremap' ON.", function()
function()
command('nmap x i') command('nmap x i')
feed('xdl<esc>') feed('xdl<esc>')
expect('dliii www') expect('dliii www')
end) 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 l i')
command('nmap w j') command('nmap w j')
feed('ll') feed('ll')
expect('liii www') expect('liii www')
end) end)
it("does not stop applying 'langmap' on first character of a mapping", it("does not stop applying 'langmap' on first character of a mapping", function()
function()
command('1t1') command('1t1')
command('1t1') command('1t1')
command('goto 1') command('goto 1')
@@ -56,8 +54,7 @@ describe("'langmap'", function()
iii www iii www
ihelloii www]]) ihelloii www]])
end) end)
it("Results of maps are converted when 'langnoremap' OFF.", it("Results of maps are converted when 'langnoremap' OFF.", function()
function()
command('set nolangnoremap') command('set nolangnoremap')
command('nmap x i') command('nmap x i')
feed('xdl<esc>') feed('xdl<esc>')
@@ -65,8 +62,7 @@ describe("'langmap'", function()
end) end)
end) end)
-- e.g. CTRL-W_j , mj , 'j and "jp -- e.g. CTRL-W_j , mj , 'j and "jp
it('conversions are applied to keys in middle of command', it('conversions are applied to keys in middle of command', function()
function()
-- Works in middle of window command -- Works in middle of window command
feed('<C-w>s') feed('<C-w>s')
local origwin = curwin() local origwin = curwin()
@@ -193,8 +189,7 @@ describe("'langmap'", function()
eq(1, eval('gotten_one')) eq(1, eval('gotten_one'))
end) end)
end) end)
it('conversions are not applied during setreg()', it('conversions are not applied during setreg()', function()
function()
call('setreg', 'i', 'ww') call('setreg', 'i', 'ww')
eq('ww', eval('@i')) eq('ww', eval('@i'))
end) end)
@@ -214,12 +209,18 @@ describe("'langmap'", function()
end) end)
local function testrecording(command_string, expect_string, setup_function, expect_macro) 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') feed('qa' .. command_string .. 'q')
expect(expect_string) expect(expect_string)
eq(expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true), eq(
eval('@a')) expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true),
if setup_function then setup_function() end eval('@a')
)
if setup_function then
setup_function()
end
-- n.b. may need nvim_replace_termcodes() here. -- n.b. may need nvim_replace_termcodes() here.
feed('@a') feed('@a')
expect(expect_string) expect(expect_string)
@@ -276,5 +277,4 @@ describe("'langmap'", function()
testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]])) testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]]))
testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]])) testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]]))
end) end)
end) end)

View File

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

View File

@@ -9,7 +9,9 @@ local eq = helpers.eq
local feed = helpers.feed local feed = helpers.feed
local write_file = helpers.write_file local write_file = helpers.write_file
local pcall_err = helpers.pcall_err 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() describe('named marks', function()
local file1 = 'Xtestfile-functional-editor-marks' local file1 = 'Xtestfile-functional-editor-marks'
@@ -24,153 +26,153 @@ describe('named marks', function()
os.remove(file2) os.remove(file2)
end) end)
it("can be set", function() it('can be set', function()
command("edit " .. file1) command('edit ' .. file1)
command("mark a") command('mark a')
eq({1, 0}, curbufmeths.get_mark("a")) eq({ 1, 0 }, curbufmeths.get_mark('a'))
feed("jmb") feed('jmb')
eq({2, 0}, curbufmeths.get_mark("b")) eq({ 2, 0 }, curbufmeths.get_mark('b'))
feed("jmB") feed('jmB')
eq({3, 0}, curbufmeths.get_mark("B")) eq({ 3, 0 }, curbufmeths.get_mark('B'))
command("4kc") command('4kc')
eq({4, 0}, curbufmeths.get_mark("c")) eq({ 4, 0 }, curbufmeths.get_mark('c'))
end) end)
it("errors when set out of range with :mark", function() it('errors when set out of range with :mark', function()
command("edit " .. file1) command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "1000mark x") local err = pcall_err(helpers.exec_capture, '1000mark x')
eq("nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x", err) eq('nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x', err)
end) end)
it("errors when set out of range with :k", function() it('errors when set out of range with :k', function()
command("edit " .. file1) command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "1000kx") local err = pcall_err(helpers.exec_capture, '1000kx')
eq("nvim_exec2(): Vim(k):E16: Invalid range: 1000kx", err) eq('nvim_exec2(): Vim(k):E16: Invalid range: 1000kx', err)
end) end)
it("errors on unknown mark name with :mark", function() it('errors on unknown mark name with :mark', function()
command("edit " .. file1) command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "mark #") local err = pcall_err(helpers.exec_capture, 'mark #')
eq("nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err) eq('nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote', err)
end) end)
it("errors on unknown mark name with '", function() it("errors on unknown mark name with '", function()
command("edit " .. file1) command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! '#") 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) end)
it("errors on unknown mark name with `", function() it('errors on unknown mark name with `', function()
command("edit " .. file1) command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! `#") 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) end)
it("errors when moving to a mark that is not set with '", function() 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") 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! '.") 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) end)
it("errors when moving to a mark that is not set with `", function() 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") 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! `>") 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) end)
it("errors when moving to a global mark that is not set with '", function() 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") 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) end)
it("errors when moving to a global mark that is not set with `", function() 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") 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) end)
it("can move to them using '", function() it("can move to them using '", function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("j") feed('j')
feed("ma") feed('ma')
feed("G'a") feed("G'a")
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
feed("mA") feed('mA')
command("next") command('next')
feed("'A") feed("'A")
eq(1, meths.get_current_buf().id) eq(1, meths.get_current_buf().id)
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
end) end)
it("can move to them using `", function() it('can move to them using `', function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("jll") feed('jll')
feed("ma") feed('ma')
feed("G`a") feed('G`a')
eq({ 2, 2 }, cursor()) eq({ 2, 2 }, cursor())
feed("mA") feed('mA')
command("next") command('next')
feed("`A") feed('`A')
eq(1, meths.get_current_buf().id) eq(1, meths.get_current_buf().id)
eq({ 2, 2 }, cursor()) eq({ 2, 2 }, cursor())
end) end)
it("can move to them using g'", function() it("can move to them using g'", function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("jll") feed('jll')
feed("ma") feed('ma')
feed("Gg'a") feed("Gg'a")
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
feed("mA") feed('mA')
command("next") command('next')
feed("g'A") feed("g'A")
eq(1, meths.get_current_buf().id) eq(1, meths.get_current_buf().id)
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
end) end)
it("can move to them using g`", function() it('can move to them using g`', function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("jll") feed('jll')
feed("ma") feed('ma')
feed("Gg`a") feed('Gg`a')
eq({ 2, 2 }, cursor()) eq({ 2, 2 }, cursor())
feed("mA") feed('mA')
command("next") command('next')
feed("g`A") feed('g`A')
eq(1, meths.get_current_buf().id) eq(1, meths.get_current_buf().id)
eq({ 2, 2 }, cursor()) eq({ 2, 2 }, cursor())
end) end)
it("can move to them using :'", function() it("can move to them using :'", function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("j") feed('j')
feed("ma") feed('ma')
feed("G") feed('G')
command("'a") command("'a")
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
feed("mA") feed('mA')
command("next") command('next')
command("'A") command("'A")
eq(1, meths.get_current_buf().id) eq(1, meths.get_current_buf().id)
eq({ 2, 0 }, cursor()) eq({ 2, 0 }, cursor())
end) end)
it("errors when it can't find the buffer", function() it("errors when it can't find the buffer", function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("mA") feed('mA')
command("next") command('next')
command("bw! " .. file1 ) command('bw! ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'A") 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) os.remove(file1)
end) 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') feed('ifoo<Esc>mA')
command('enew') command('enew')
feed('ibar<Esc>') feed('ibar<Esc>')
@@ -178,124 +180,124 @@ describe('named marks', function()
end) end)
it("leave a context mark when moving with '", function() it("leave a context mark when moving with '", function()
command("edit " .. file1) command('edit ' .. file1)
feed("llmamA") feed('llmamA')
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
local pos = cursor() local pos = cursor()
feed("'a") feed("'a")
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
feed("'A") feed("'A")
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("leave a context mark when moving with `", function() it('leave a context mark when moving with `', function()
command("edit " .. file1) command('edit ' .. file1)
feed("llmamA") feed('llmamA')
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
local pos = cursor() local pos = cursor()
feed("`a") feed('`a')
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
feed("`A") feed('`A')
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("leave a context mark when the mark changes buffer with g'", function() it("leave a context mark when the mark changes buffer with g'", function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
local pos local pos
feed("GmA") feed('GmA')
command("next") command('next')
pos = cursor() pos = cursor()
command("clearjumps") command('clearjumps')
feed("g'A") -- since the mark is in another buffer, it leaves a context mark feed("g'A") -- since the mark is in another buffer, it leaves a context mark
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("leave a context mark when the mark changes buffer with g`", function() it('leave a context mark when the mark changes buffer with g`', function()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
local pos local pos
feed("GmA") feed('GmA')
command("next") command('next')
pos = cursor() pos = cursor()
command("clearjumps") command('clearjumps')
feed("g`A") -- since the mark is in another buffer, it leaves a context mark feed('g`A') -- since the mark is in another buffer, it leaves a context mark
feed("<C-o>") feed('<C-o>')
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("do not leave a context mark when moving with g'", function() it("do not leave a context mark when moving with g'", function()
command("edit " .. file1) command('edit ' .. file1)
local pos local pos
feed("ma") feed('ma')
pos = cursor() -- Mark pos pos = cursor() -- Mark pos
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
feed("g'a") feed("g'a")
feed("<C-o>") -- should do nothing feed('<C-o>') -- should do nothing
eq(pos, cursor()) eq(pos, cursor())
feed("mA") feed('mA')
pos = cursor() -- Mark pos pos = cursor() -- Mark pos
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
feed("g'a") feed("g'a")
feed("<C-o>") -- should do nothing feed('<C-o>') -- should do nothing
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("do not leave a context mark when moving with g`", function() it('do not leave a context mark when moving with g`', function()
command("edit " .. file1) command('edit ' .. file1)
local pos local pos
feed("ma") feed('ma')
pos = cursor() -- Mark pos pos = cursor() -- Mark pos
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
feed("g`a") feed('g`a')
feed("<C-o>") -- should do nothing feed('<C-o>') -- should do nothing
eq(pos, cursor()) eq(pos, cursor())
feed("mA") feed('mA')
pos = cursor() -- Mark pos pos = cursor() -- Mark pos
feed("10j0") -- first col, last line feed('10j0') -- first col, last line
feed("g'a") feed("g'a")
feed("<C-o>") -- should do nothing feed('<C-o>') -- should do nothing
eq(pos, cursor()) eq(pos, cursor())
end) end)
it("open folds when moving to them", function() it('open folds when moving to them', function()
command("edit " .. file1) command('edit ' .. file1)
feed("jzfG") -- Fold from the second line to the end feed('jzfG') -- Fold from the second line to the end
command("3mark a") command('3mark a')
feed("G") -- On top of the fold feed('G') -- On top of the fold
assert(funcs.foldclosed('.') ~= -1) -- folded assert(funcs.foldclosed('.') ~= -1) -- folded
feed("'a") feed("'a")
eq(-1, funcs.foldclosed('.')) eq(-1, funcs.foldclosed('.'))
feed("zc") feed('zc')
assert(funcs.foldclosed('.') ~= -1) -- folded assert(funcs.foldclosed('.') ~= -1) -- folded
-- TODO: remove this workaround after fixing #15873 -- TODO: remove this workaround after fixing #15873
feed("k`a") feed('k`a')
eq(-1, funcs.foldclosed('.')) eq(-1, funcs.foldclosed('.'))
feed("zc") feed('zc')
assert(funcs.foldclosed('.') ~= -1) -- folded assert(funcs.foldclosed('.') ~= -1) -- folded
feed("kg'a") feed("kg'a")
eq(-1, funcs.foldclosed('.')) eq(-1, funcs.foldclosed('.'))
feed("zc") feed('zc')
assert(funcs.foldclosed('.') ~= -1) -- folded assert(funcs.foldclosed('.') ~= -1) -- folded
feed("kg`a") feed('kg`a')
eq(-1, funcs.foldclosed('.')) eq(-1, funcs.foldclosed('.'))
end) end)
it("do not open folds when moving to them doesn't move the cursor", function() it("do not open folds when moving to them doesn't move the cursor", function()
command("edit " .. file1) command('edit ' .. file1)
feed("jzfG") -- Fold from the second line to the end feed('jzfG') -- Fold from the second line to the end
assert(funcs.foldclosed('.') == 2) -- folded assert(funcs.foldclosed('.') == 2) -- folded
feed("ma") feed('ma')
feed("'a") feed("'a")
feed("`a") feed('`a')
feed("g'a") feed("g'a")
feed("g`a") feed('g`a')
-- should still be folded -- should still be folded
eq(2, funcs.foldclosed('.')) eq(2, funcs.foldclosed('.'))
end) end)
@@ -328,15 +330,15 @@ describe('named marks view', function()
local function content() local function content()
local c = {} local c = {}
for i = 1, 30 do for i = 1, 30 do
c[i] = i .. " line" c[i] = i .. ' line'
end end
return table.concat(c, "\n") return table.concat(c, '\n')
end end
before_each(function() before_each(function()
clear() clear()
write_file(file1, content(), false, false) write_file(file1, content(), false, false)
write_file(file2, content(), false, false) write_file(file2, content(), false, false)
command("set jumpoptions+=view") command('set jumpoptions+=view')
end) end)
after_each(function() after_each(function()
os.remove(file1) os.remove(file1)
@@ -346,8 +348,8 @@ describe('named marks view', function()
it('is restored in normal mode but not op-pending mode', function() it('is restored in normal mode but not op-pending mode', function()
local screen = Screen.new(5, 8) local screen = Screen.new(5, 8)
screen:attach() screen:attach()
command("edit " .. file1) command('edit ' .. file1)
feed("<C-e>jWma") feed('<C-e>jWma')
feed("G'a") feed("G'a")
local expected = [[ local expected = [[
2 line | 2 line |
@@ -360,7 +362,7 @@ describe('named marks view', function()
| |
]] ]]
screen:expect({ grid = expected }) screen:expect({ grid = expected })
feed("G`a") feed('G`a')
screen:expect([[ screen:expect([[
2 line | 2 line |
3 ^line | 3 ^line |
@@ -372,7 +374,7 @@ describe('named marks view', function()
| |
]]) ]])
-- not in op-pending mode #20886 -- not in op-pending mode #20886
feed("ggj=`a") feed('ggj=`a')
screen:expect([[ screen:expect([[
1 line | 1 line |
^2 line | ^2 line |
@@ -388,8 +390,8 @@ describe('named marks view', function()
it('is restored across files', function() it('is restored across files', function()
local screen = Screen.new(5, 5) local screen = Screen.new(5, 5)
screen:attach() screen:attach()
command("args " .. file1 .. " " .. file2) command('args ' .. file1 .. ' ' .. file2)
feed("<C-e>mA") feed('<C-e>mA')
local mark_view = [[ local mark_view = [[
^2 line | ^2 line |
3 line | 3 line |
@@ -398,7 +400,7 @@ describe('named marks view', function()
| |
]] ]]
screen:expect(mark_view) screen:expect(mark_view)
command("next") command('next')
screen:expect([[ screen:expect([[
^1 line | ^1 line |
2 line | 2 line |
@@ -410,12 +412,12 @@ describe('named marks view', function()
screen:expect(mark_view) screen:expect(mark_view)
end) 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) local screen = Screen.new(10, 10)
screen:attach() screen:attach()
command("edit " .. file1) command('edit ' .. file1)
feed("7GzbmaG") -- Seven lines from the top feed('7GzbmaG') -- Seven lines from the top
command("new") -- Screen size for window is now half the height can't be restored command('new') -- Screen size for window is now half the height can't be restored
feed("<C-w>p'a") feed("<C-w>p'a")
screen:expect([[ screen:expect([[
| |

View File

@@ -66,11 +66,11 @@ describe('meta-keys #8226 #13042', function()
command('inoremap <A-j> alt-j') command('inoremap <A-j> alt-j')
feed('i<M-l> xxx <A-j><M-h>a<A-h>') feed('i<M-l> xxx <A-j><M-h>a<A-h>')
expect('meta-l xxx alt-j') 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. -- Unmapped ALT-chord behaves as ESC+c.
command('iunmap <M-l>') command('iunmap <M-l>')
feed('0i<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> -- Unmapped ALT-chord has same `undo` characteristics as ESC+<key>
command('0,$d') command('0,$d')
feed('ahello<M-.>') 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(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]]))
eq('t', eval('mode(1)')) eq('t', eval('mode(1)'))
feed('<Esc>j') feed('<Esc>j')
eq({ 0, 2, 1, 0, }, funcs.getpos('.')) eq({ 0, 2, 1, 0 }, funcs.getpos('.'))
eq('nt', eval('mode(1)')) eq('nt', eval('mode(1)'))
end) end)

View File

@@ -54,19 +54,23 @@ describe('cmdline', function()
screen:attach() screen:attach()
command('set laststatus=2 statusline=%!mode(1)') command('set laststatus=2 statusline=%!mode(1)')
feed(':') feed(':')
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{0:~ }| {0:~ }|
{1:c }| {1:c }|
:^ | :^ |
]]} ]],
}
feed('<Insert>') feed('<Insert>')
screen:expect{grid=[[ screen:expect {
grid = [[
| |
{0:~ }| {0:~ }|
{1:cr }| {1:cr }|
:^ | :^ |
]]} ]],
}
end) end)
describe('history', function() describe('history', function()

View File

@@ -187,10 +187,10 @@ describe('insert-mode', function()
it('multi-char mapping updates screen properly #25626', function() it('multi-char mapping updates screen properly #25626', function()
local screen = Screen.new(60, 6) local screen = Screen.new(60, 6)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
[1] = {bold = true, reverse = true}; -- StatusLine [1] = { bold = true, reverse = true }, -- StatusLine
[2] = {reverse = true}; -- StatusLineNC [2] = { reverse = true }, -- StatusLineNC
[3] = {bold = true}; -- ModeMsg [3] = { bold = true }, -- ModeMsg
}) })
screen:attach() screen:attach()
command('vnew') command('vnew')
@@ -199,22 +199,26 @@ describe('insert-mode', function()
command('set timeoutlen=10000') command('set timeoutlen=10000')
command('inoremap jk <Esc>') command('inoremap jk <Esc>')
feed('i<CR>βββ<Left><Left>j') feed('i<CR>βββ<Left><Left>j')
screen:expect{grid=[[ screen:expect {
grid = [[
foo │ | foo │ |
foo │β^jβ | foo │β^jβ |
foo │{0:~ }| foo │{0:~ }|
{0:~ }│{0:~ }| {0:~ }│{0:~ }|
{2:[No Name] [+] }{1:[No Name] [+] }| {2:[No Name] [+] }{1:[No Name] [+] }|
{3:-- INSERT --} | {3:-- INSERT --} |
]]} ]],
}
feed('k') feed('k')
screen:expect{grid=[[ screen:expect {
grid = [[
foo │ | foo │ |
foo │^βββ | foo │^βββ |
foo │{0:~ }| foo │{0:~ }|
{0:~ }│{0:~ }| {0:~ }│{0:~ }|
{2:[No Name] [+] }{1:[No Name] [+] }| {2:[No Name] [+] }{1:[No Name] [+] }|
| |
]]} ]],
}
end) end)
end) end)

View File

@@ -51,7 +51,9 @@ describe('put command', function()
-- {{{ Where test definitions are run -- {{{ Where test definitions are run
local function run_test_variations(test_variations, extra_setup) local function run_test_variations(test_variations, extra_setup)
reset() reset()
if extra_setup then extra_setup() end if extra_setup then
extra_setup()
end
local init_contents = curbuf_contents() local init_contents = curbuf_contents()
local init_cursorpos = funcs.getcurpos() local init_cursorpos = funcs.getcurpos()
local assert_no_change = function(exception_table, after_undo) local assert_no_change = function(exception_table, after_undo)
@@ -69,7 +71,9 @@ describe('put command', function()
for _, test in pairs(test_variations) do for _, test in pairs(test_variations) do
it(test.description, function() it(test.description, function()
if extra_setup then extra_setup() end if extra_setup then
extra_setup()
end
local orig_dotstr = funcs.getreg('.') local orig_dotstr = funcs.getreg('.')
helpers.ok(visual_marks_zero()) helpers.ok(visual_marks_zero())
-- Make sure every test starts from the same conditions -- Make sure every test starts from the same conditions
@@ -115,8 +119,13 @@ describe('put command', function()
end -- run_test_variations() end -- run_test_variations()
-- }}} -- }}}
local function create_test_defs(test_defs, command_base, command_creator, -- {{{ local function create_test_defs(
expect_base, expect_creator) test_defs,
command_base,
command_creator, -- {{{
expect_base,
expect_creator
)
local rettab = {} local rettab = {}
local exceptions local exceptions
for _, v in pairs(test_defs) do for _, v in pairs(test_defs) do
@@ -125,8 +134,7 @@ describe('put command', function()
else else
exceptions = {} exceptions = {}
end end
table.insert(rettab, table.insert(rettab, {
{
test_action = command_creator(command_base, v[1]), test_action = command_creator(command_base, v[1]),
test_assertions = expect_creator(expect_base, v[2]), test_assertions = expect_creator(expect_base, v[2]),
description = v[3], description = v[3],
@@ -300,14 +308,15 @@ describe('put command', function()
} }
local function non_dotdefs(def_table) 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 end
-- }}} -- }}}
-- Conversion functions {{{ -- Conversion functions {{{
local function convert_charwise(expect_base, conversion_table, local function convert_charwise(expect_base, conversion_table, virtualedit_end, visual_put)
virtualedit_end, visual_put)
expect_base = dedent(expect_base) expect_base = dedent(expect_base)
-- There is no difference between 'P' and 'p' when VIsual_active -- There is no difference between 'P' and 'p' when VIsual_active
if not visual_put then 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) return orig_line:sub(1, prev_end - 1) .. 'x' .. orig_line:sub(prev_end)
end end
local function convert_blockwise(expect_base, conversion_table, visual, local function convert_blockwise(
use_b, trailing_whitespace) expect_base,
conversion_table,
visual,
use_b,
trailing_whitespace
)
expect_base = dedent(expect_base) expect_base = dedent(expect_base)
local p_str = 'test_string"' local p_str = 'test_string"'
if use_b then if use_b then
@@ -452,11 +466,9 @@ describe('put command', function()
if conversion_table.count and conversion_table.count > 1 then if conversion_table.count and conversion_table.count > 1 then
local p_pattern = p_str:gsub('%.', '%%.') local p_pattern = p_str:gsub('%.', '%%.')
expect_base = expect_base:gsub(p_pattern, expect_base = expect_base:gsub(p_pattern, p_str:rep(conversion_table.count))
p_str:rep(conversion_table.count)) expect_base =
expect_base = expect_base:gsub('test_stringx([b".])', expect_base:gsub('test_stringx([b".])', p_str:rep(conversion_table.count - 1) .. '%0')
p_str:rep(conversion_table.count - 1)
.. '%0')
end end
if conversion_table.cursor_after then if conversion_table.cursor_after then
@@ -496,8 +508,13 @@ describe('put command', function()
-- }}} -- }}}
-- Convenience functions {{{ -- Convenience functions {{{
local function run_normal_mode_tests(test_string, base_map, extra_setup, local function run_normal_mode_tests(
virtualedit_end, selection_string) test_string,
base_map,
extra_setup,
virtualedit_end,
selection_string
)
local function convert_closure(e, c) local function convert_closure(e, c)
return convert_charwise(e, c, virtualedit_end, selection_string) return convert_charwise(e, c, virtualedit_end, selection_string)
end end
@@ -532,8 +549,12 @@ describe('put command', function()
local function run_linewise_tests(expect_base, base_command, extra_setup) local function run_linewise_tests(expect_base, base_command, extra_setup)
local linewise_test_defs = create_test_defs( local linewise_test_defs = create_test_defs(
ex_command_defs, base_command, ex_command_defs,
create_put_action, expect_base, convert_linewiseer) base_command,
create_put_action,
expect_base,
convert_linewiseer
)
run_test_variations(linewise_test_defs, extra_setup) run_test_variations(linewise_test_defs, extra_setup)
end -- run_linewise_tests() end -- run_linewise_tests()
-- }}} -- }}}
@@ -545,7 +566,8 @@ describe('put command', function()
Line of words 2]] Line of words 2]]
run_normal_mode_tests(expect_string, 'p') run_normal_mode_tests(expect_string, 'p')
run_linewise_tests([[ run_linewise_tests(
[[
Line of words 1 Line of words 1
xtest_string" xtest_string"
Line of words 2]], Line of words 2]],
@@ -585,11 +607,12 @@ describe('put command', function()
run_test_variations( run_test_variations(
create_test_defs( create_test_defs(
linewise_put_defs, linewise_put_defs,
'put a', create_put_action, 'put a',
base_expect_string, convert_linewiseer create_put_action,
base_expect_string,
convert_linewiseer
) )
) )
end) end)
describe('blockwise register', function() describe('blockwise register', function()
@@ -600,18 +623,13 @@ describe('put command', function()
test_stringb]] test_stringb]]
local function expect_block_creator(expect_base, conversion_table) local function expect_block_creator(expect_base, conversion_table)
return expect_creator(function(e,c) return convert_blockwise(e,c,nil,true) end, return expect_creator(function(e, c)
expect_base, conversion_table) return convert_blockwise(e, c, nil, true)
end, expect_base, conversion_table)
end end
run_test_variations( run_test_variations(
create_test_defs( create_test_defs(blockwise_put_defs, '"bp', create_p_action, test_base, expect_block_creator)
blockwise_put_defs,
'"bp',
create_p_action,
test_base,
expect_block_creator
)
) )
end) end)
@@ -632,12 +650,12 @@ describe('put command', function()
describe('linewise paste with autoindent', function() describe('linewise paste with autoindent', function()
-- luacheck: ignore -- luacheck: ignore
run_linewise_tests([[ run_linewise_tests(
[[
Line of words 1 Line of words 1
Line of words 2 Line of words 2
xtest_string"]], xtest_string"]],
'put' 'put',
,
function() function()
funcs.setline('$', ' Line of words 2') funcs.setline('$', ' Line of words 2')
-- Set curswant to '8' to be at the end of the tab character -- 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' local test_string = 'Line of test_stringx"Line of words 2'
run_normal_mode_tests(test_string, 'v$p', function() run_normal_mode_tests(test_string, 'v$p', function()
funcs.setpos('.', { 0, 1, 9, 0, 9 }) funcs.setpos('.', { 0, 1, 9, 0, 9 })
end, end, nil, 'words 1\n')
nil,
'words 1\n')
end) end)
describe('linewise mode', function() describe('linewise mode', function()
local test_string = [[ local test_string = [[
@@ -693,8 +709,7 @@ describe('put command', function()
local function expect_vis_linewise(expect_base, conversion_table) local function expect_vis_linewise(expect_base, conversion_table)
return expect_creator(function(e, c) return expect_creator(function(e, c)
return convert_linewise(e, c, nil, nil) return convert_linewise(e, c, nil, nil)
end, end, expect_base, conversion_table)
expect_base, conversion_table)
end end
run_test_variations( run_test_variations(
create_test_defs( create_test_defs(
@@ -704,15 +719,16 @@ describe('put command', function()
test_string, test_string,
expect_vis_linewise 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() describe('with whitespace at bol', function()
local function expect_vis_lineindented(expect_base, conversion_table) local function expect_vis_lineindented(expect_base, conversion_table)
local test_expect = expect_creator(function(e, c) local test_expect = expect_creator(function(e, c)
return convert_linewise(e, c, nil, nil, ' ') return convert_linewise(e, c, nil, nil, ' ')
end, end, expect_base, conversion_table)
expect_base, conversion_table)
return function(exception_table, after_redo) return function(exception_table, after_redo)
test_expect(exception_table, after_redo) test_expect(exception_table, after_redo)
if not conversion_table.put_backwards then if not conversion_table.put_backwards then
@@ -737,7 +753,6 @@ describe('put command', function()
end end
) )
end) end)
end) end)
describe('blockwise visual mode', function() describe('blockwise visual mode', function()
@@ -766,7 +781,6 @@ describe('put command', function()
) )
run_test_variations(select_down_test_defs) run_test_variations(select_down_test_defs)
-- Undo and redo of a visual block put leave the cursor in the top -- 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 -- left of the visual block area no matter where the cursor was
-- when it started. -- when it started.
@@ -778,8 +792,7 @@ describe('put command', function()
rettab[4].undo_position = true rettab[4].undo_position = true
rettab[4].redo_position = true rettab[4].redo_position = true
return rettab return rettab
end, end, normal_command_defs)
normal_command_defs)
-- Selection direction doesn't matter -- Selection direction doesn't matter
run_test_variations( run_test_variations(
@@ -790,7 +803,9 @@ describe('put command', function()
test_base, test_base,
expect_block_creator 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() describe('blockwise cursor after undo', function()
@@ -812,50 +827,33 @@ describe('put command', function()
end end
run_test_variations( run_test_variations(
create_test_defs( create_test_defs(undo_redo_no, '<C-v>kllp', create_p_action, test_base, assertion_creator),
undo_redo_no, function()
'<C-v>kllp', funcs.setpos('.', { 0, 2, 1, 0, 1 })
create_p_action, end
test_base,
assertion_creator
),
function() funcs.setpos('.', {0, 2, 1, 0, 1}) end
) )
end) end)
end) end)
describe("with 'virtualedit'", function() describe("with 'virtualedit'", function()
describe('splitting a tab character', function() describe('splitting a tab character', function()
local base_expect_string = [[ local base_expect_string = [[
Line of words 1 Line of words 1
test_stringx" Line of words 2]] test_stringx" Line of words 2]]
run_normal_mode_tests( run_normal_mode_tests(base_expect_string, 'vp', function()
base_expect_string,
'vp',
function()
funcs.setline('$', ' Line of words 2') funcs.setline('$', ' Line of words 2')
command('setlocal virtualedit=all') command('setlocal virtualedit=all')
funcs.setpos('.', { 0, 2, 1, 2, 3 }) funcs.setpos('.', { 0, 2, 1, 2, 3 })
end, end, nil, ' ')
nil,
' '
)
end) end)
describe('after end of line', function() describe('after end of line', function()
local base_expect_string = [[ local base_expect_string = [[
Line of words 1 test_stringx" Line of words 1 test_stringx"
Line of words 2]] Line of words 2]]
run_normal_mode_tests( run_normal_mode_tests(base_expect_string, 'vp', function()
base_expect_string,
'vp',
function()
command('setlocal virtualedit=all') command('setlocal virtualedit=all')
funcs.setpos('.', { 0, 1, 16, 2, 18 }) funcs.setpos('.', { 0, 1, 16, 2, 18 })
end, end, true, ' ')
true,
' '
)
end) end)
end) end)
end) end)
@@ -873,9 +871,12 @@ describe('put command', function()
Line of words 1 Line of words 1
Line of words 2]]) Line of words 2]])
feed('u1go<C-v>j".p') feed('u1go<C-v>j".p')
eq([[ eq(
[[
ine of words 1 ine of words 1
ine of words 2]], curbuf_contents()) ine of words 2]],
curbuf_contents()
)
end) end)
local screen local screen
@@ -891,7 +892,8 @@ describe('put command', function()
end end
helpers.ok(not screen.bell and not screen.visualbell) helpers.ok(not screen.bell and not screen.visualbell)
actions() actions()
screen:expect{condition=function() screen:expect {
condition = function()
if should_ring then if should_ring then
if not screen.bell and not screen.visualbell then if not screen.bell and not screen.visualbell then
error('Bell was not rung after action') error('Bell was not rung after action')
@@ -901,23 +903,31 @@ describe('put command', function()
error('Bell was rung after action') error('Bell was rung after action')
end end
end end
end, unchanged=(not should_ring)} end,
unchanged = not should_ring,
}
screen.bell = false screen.bell = false
screen.visualbell = false screen.visualbell = false
end end
it('should not ring the bell with gp at end of line', function() 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. -- Even if the last character is a multibyte character.
reset() reset()
funcs.setline(1, 'helloม') funcs.setline(1, 'helloม')
bell_test(function() feed('$".gp') end) bell_test(function()
feed('$".gp')
end)
end) end)
it('should not ring the bell with gp and end of file', function() it('should not ring the bell with gp and end of file', function()
funcs.setpos('.', { 0, 2, 1, 0 }) funcs.setpos('.', { 0, 2, 1, 0 })
bell_test(function() feed('$vl".gp') end) bell_test(function()
feed('$vl".gp')
end)
end) end)
it('should ring the bell when deleting if not appropriate', function() it('should ring the bell when deleting if not appropriate', function()
@@ -926,7 +936,9 @@ describe('put command', function()
expect([[ expect([[
ine of words 1 ine of words 1
Line of words 2]]) Line of words 2]])
bell_test(function() feed('".P') end, true) bell_test(function()
feed('".P')
end, true)
end) end)
it('should restore cursor position after undo of ".p', function() it('should restore cursor position after undo of ".p', function()
@@ -946,4 +958,3 @@ describe('put command', function()
end) end)
end) end)
end) end)

View File

@@ -8,10 +8,7 @@ describe('search (/)', function()
before_each(clear) before_each(clear)
it('fails with huge column (%c) value #9930', function() it('fails with huge column (%c) value #9930', function()
eq([[Vim:E951: \% value too large]], eq([[Vim:E951: \% value too large]], pcall_err(command, '/\\v%18446744071562067968c'))
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%2147483648c"))
end) end)
end) end)

View File

@@ -58,7 +58,9 @@ describe('tabpage', function()
end) end)
it('no segfault with strange WinClosed autocommand #20290', function() it('no segfault with strange WinClosed autocommand #20290', function()
pcall(exec, [[ pcall(
exec,
[[
set nohidden set nohidden
edit Xa edit Xa
split Xb split Xb
@@ -66,7 +68,8 @@ describe('tabpage', function()
new new
autocmd WinClosed * tabprev | bwipe! autocmd WinClosed * tabprev | bwipe!
close close
]]) ]]
)
assert_alive() assert_alive()
end) end)
@@ -130,7 +133,7 @@ describe('tabpage', function()
]]) ]])
end) end)
it(":tabmove handles modifiers and addr", function() it(':tabmove handles modifiers and addr', function()
command('tabnew | tabnew | tabnew') command('tabnew | tabnew | tabnew')
eq(4, funcs.nvim_tabpage_get_number(0)) eq(4, funcs.nvim_tabpage_get_number(0))
command(' silent :keepalt :: ::: silent! - tabmove') command(' silent :keepalt :: ::: silent! - tabmove')

View File

@@ -21,15 +21,23 @@ describe('u CTRL-R g- g+', function()
before_each(clear) before_each(clear)
local function create_history(num_steps) local function create_history(num_steps)
if num_steps == 0 then return end if num_steps == 0 then
return
end
insert('1') insert('1')
if num_steps == 1 then return end if num_steps == 1 then
return
end
feed('o2<esc>') feed('o2<esc>')
feed('o3<esc>') feed('o3<esc>')
feed('u') feed('u')
if num_steps == 2 then return end if num_steps == 2 then
return
end
feed('o4<esc>') feed('o4<esc>')
if num_steps == 3 then return end if num_steps == 3 then
return
end
feed('u') feed('u')
end end
@@ -57,13 +65,23 @@ describe('u CTRL-R g- g+', function()
undo_and_redo(2, 'g-', 'g+', '1') undo_and_redo(2, 'g-', 'g+', '1')
end) end)
it('undoes properly around a branch point', function() it('undoes properly around a branch point', function()
undo_and_redo(3, 'u', '<C-r>', [[ undo_and_redo(
3,
'u',
'<C-r>',
[[
1 1
2]]) 2]]
undo_and_redo(3, 'g-', 'g+', [[ )
undo_and_redo(
3,
'g-',
'g+',
[[
1 1
2 2
3]]) 3]]
)
end) end)
it('can find the previous sequence after undoing to a branch', function() it('can find the previous sequence after undoing to a branch', function()
undo_and_redo(4, 'u', '<C-r>', '1') 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 -- Used to crash because this invokes history processing which uses
-- hist_char2type which after fdb68e35e4c729c7ed097d8ade1da29e5b3f4b31 -- hist_char2type which after fdb68e35e4c729c7ed097d8ade1da29e5b3f4b31
-- crashed. -- crashed.
it(cmd .. 's' .. prep .. ' the current line by default when feeding', it(cmd .. 's' .. prep .. ' the current line by default when feeding', function()
function()
feed(':' .. cmd .. '\nabc\ndef\n.\n') feed(':' .. cmd .. '\nabc\ndef\n.\n')
eq(ret1, buffer_contents()) eq(ret1, buffer_contents())
end) 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 eq, command, funcs = helpers.eq, helpers.command, helpers.funcs
local ok = helpers.ok local ok = helpers.ok
local clear = helpers.clear local clear = helpers.clear
describe(":argument", function() describe(':argument', function()
before_each(function() before_each(function()
clear() clear()
end) end)
it("does not restart :terminal buffer", function() it('does not restart :terminal buffer', function()
command("terminal") command('terminal')
helpers.feed([[<C-\><C-N>]]) helpers.feed([[<C-\><C-N>]])
command("argadd") command('argadd')
helpers.feed([[<C-\><C-N>]]) helpers.feed([[<C-\><C-N>]])
local bufname_before = funcs.bufname("%") local bufname_before = funcs.bufname('%')
local bufnr_before = funcs.bufnr("%") local bufnr_before = funcs.bufnr('%')
helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
command("argument 1") command('argument 1')
helpers.feed([[<C-\><C-N>]]) helpers.feed([[<C-\><C-N>]])
local bufname_after = funcs.bufname("%") local bufname_after = funcs.bufname('%')
local bufnr_after = funcs.bufnr("%") local bufnr_after = funcs.bufnr('%')
eq("["..bufname_before.."]", helpers.eval('trim(execute("args"))')) eq('[' .. bufname_before .. ']', helpers.eval('trim(execute("args"))'))
ok(funcs.line('$') > 1) ok(funcs.line('$') > 1)
eq(bufname_before, bufname_after) eq(bufname_before, bufname_after)
eq(bufnr_before, bufnr_after) eq(bufnr_before, bufnr_after)

View File

@@ -21,14 +21,26 @@ local directories = {
} }
-- Shorthand writing to get the current working directory -- Shorthand writing to get the current working directory
local cwd = function(...) return call('getcwd', ...) end -- effective working dir local cwd = function(...)
local wcwd = function() return cwd(0) end -- window dir return call('getcwd', ...)
local tcwd = function() return cwd(-1, 0) end -- tab dir 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 -- Same, except these tell us if there is a working directory at all
local lwd = function(...) return call('haslocaldir', ...) end -- effective working dir local lwd = function(...)
local wlwd = function() return lwd(0) end -- window dir return call('haslocaldir', ...)
local tlwd = function() return lwd(-1, 0) end -- tab dir 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 --local glwd = function() return eval('haslocaldir(-1, -1)') end -- global dir
-- Test both the `cd` and `chdir` variants -- Test both the `cd` and `chdir` variants
@@ -271,7 +283,7 @@ for _, cmd in ipairs {'getcwd', 'haslocaldir'} do
end) end)
end end
describe("getcwd()", function () describe('getcwd()', function()
before_each(function() before_each(function()
clear() clear()
mkdir(directories.global) mkdir(directories.global)
@@ -281,11 +293,11 @@ describe("getcwd()", function ()
helpers.rmdir(directories.global) helpers.rmdir(directories.global)
end) 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')) skip(is_os('win'))
command("cd "..directories.global) command('cd ' .. directories.global)
command("call delete('../" .. directories.global .. "', 'd')") command("call delete('../" .. directories.global .. "', 'd')")
eq("", helpers.eval("getcwd()")) eq('', helpers.eval('getcwd()'))
end) end)
it("works with 'autochdir' after local directory was set (#9892)", function() it("works with 'autochdir' after local directory was set (#9892)", function()

View File

@@ -57,7 +57,7 @@ describe('mappings with <Cmd>', function()
feed('gg') feed('gg')
cmdmap('<F8>', 'startinsert') cmdmap('<F8>', 'startinsert')
cmdmap('<F9>', 'stopinsert') cmdmap('<F9>', 'stopinsert')
command("abbr foo <Cmd>let g:y = 17<cr>bar") command('abbr foo <Cmd>let g:y = 17<cr>bar')
end) end)
after_each(function() after_each(function()
@@ -160,7 +160,7 @@ describe('mappings with <Cmd>', function()
eq('n', eval('mode(1)')) eq('n', eval('mode(1)'))
-- operator-pending mode -- operator-pending mode
feed("d<F3>") feed('d<F3>')
eq('no', eval('m')) eq('no', eval('m'))
-- did leave operator-pending mode -- did leave operator-pending mode
eq('n', eval('mode(1)')) eq('n', eval('mode(1)'))
@@ -171,21 +171,21 @@ describe('mappings with <Cmd>', function()
eq('i', eval('mode(1)')) eq('i', eval('mode(1)'))
-- replace mode -- replace mode
feed("<Ins><F3>") feed('<Ins><F3>')
eq('R', eval('m')) eq('R', eval('m'))
eq('R', eval('mode(1)')) eq('R', eval('mode(1)'))
feed('<esc>') feed('<esc>')
eq('n', eval('mode(1)')) eq('n', eval('mode(1)'))
-- virtual replace mode -- virtual replace mode
feed("gR<F3>") feed('gR<F3>')
eq('Rv', eval('m')) eq('Rv', eval('m'))
eq('Rv', eval('mode(1)')) eq('Rv', eval('mode(1)'))
feed('<esc>') feed('<esc>')
eq('n', eval('mode(1)')) eq('n', eval('mode(1)'))
-- langmap works, but is not distinguished in 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('m'))
eq('i', eval('mode(1)')) eq('i', eval('mode(1)'))
feed('<esc>') feed('<esc>')
@@ -270,9 +270,11 @@ describe('mappings with <Cmd>', function()
command('noremap ,f <Cmd>nosuchcommand<cr>') command('noremap ,f <Cmd>nosuchcommand<cr>')
command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<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 ,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([[ screen:expect([[
^some short lines | ^some short lines |
aa | aa |
@@ -282,9 +284,9 @@ describe('mappings with <Cmd>', function()
:normal ,x | :normal ,x |
]]) ]])
eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec("normal ,f")) eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec('normal ,f'))
eq('very error', exc_exec("normal ,e")) eq('very error', exc_exec('normal ,e'))
eq('Vim(echoerr):The message.', exc_exec("normal ,m")) eq('Vim(echoerr):The message.', exc_exec('normal ,m'))
feed('w') feed('w')
screen:expect([[ screen:expect([[
some ^short lines | some ^short lines |
@@ -296,7 +298,7 @@ describe('mappings with <Cmd>', function()
]]) ]])
command(':%d') command(':%d')
eq('Vim(echoerr):Err', exc_exec("normal ,w")) eq('Vim(echoerr):Err', exc_exec('normal ,w'))
screen:expect([[ screen:expect([[
^ | ^ |
0 | 0 |
@@ -468,7 +470,6 @@ describe('mappings with <Cmd>', function()
eq('i', eval('mode(1)')) eq('i', eval('mode(1)'))
end) end)
it('works in operator-pending mode', function() it('works in operator-pending mode', function()
feed('d<F4>') feed('d<F4>')
expect([[ expect([[
@@ -514,7 +515,6 @@ describe('mappings with <Cmd>', function()
end) end)
it('works in insert mode', function() it('works in insert mode', function()
-- works the same as <c-o>w<c-o>w -- works the same as <c-o>w<c-o>w
feed('iindeed <F4>little ') feed('iindeed <F4>little ')
screen:expect([[ screen:expect([[
@@ -535,7 +535,6 @@ describe('mappings with <Cmd>', function()
{3:Press ENTER or type command to continue}^ | {3:Press ENTER or type command to continue}^ |
]]) ]])
feed('<cr>') feed('<cr>')
eq('E605: Exception not caught: very error', eval('v:errmsg')) eq('E605: Exception not caught: very error', eval('v:errmsg'))
-- still in insert -- still in insert
@@ -704,7 +703,6 @@ describe('mappings with <Cmd>', function()
]]) ]])
eq('i', eval('mode(1)')) eq('i', eval('mode(1)'))
eq(9, eval('g:y')) eq(9, eval('g:y'))
end) end)
it("doesn't crash when invoking cmdline mode recursively #8859", function() it("doesn't crash when invoking cmdline mode recursively #8859", function()
@@ -726,18 +724,20 @@ describe('mappings with <Cmd>', function()
]]) ]])
end) end)
it("works with <SID> mappings", function() it('works with <SID> mappings', function()
command('new!') command('new!')
write_file(tmpfile, [[ write_file(
tmpfile,
[[
map <f2> <Cmd>call <SID>do_it()<Cr> map <f2> <Cmd>call <SID>do_it()<Cr>
function! s:do_it() function! s:do_it()
let g:x = 10 let g:x = 10
endfunction endfunction
]]) ]]
)
command('source ' .. tmpfile) command('source ' .. tmpfile)
feed('<f2>') feed('<f2>')
eq('', eval('v:errmsg')) eq('', eval('v:errmsg'))
eq(10, eval('g:x')) eq(10, eval('g:x'))
end) end)
end) end)

View File

@@ -8,7 +8,6 @@ local exec_lua = helpers.exec_lua
local command = helpers.command local command = helpers.command
local eval = helpers.eval local eval = helpers.eval
describe('Vimscript dictionary notifications', function() describe('Vimscript dictionary notifications', function()
local channel local channel
@@ -29,9 +28,9 @@ describe('Vimscript dictionary notifications', function()
key = 'watched' key = 'watched'
end end
if opval == '' then if opval == '' then
command(('unlet %s[\'%s\']'):format(dict_expr, key)) command(("unlet %s['%s']"):format(dict_expr, key))
else else
command(('let %s[\'%s\'] %s'):format(dict_expr, key, opval)) command(("let %s['%s'] %s"):format(dict_expr, key, opval))
end end
end end
@@ -40,9 +39,9 @@ describe('Vimscript dictionary notifications', function()
key = 'watched' key = 'watched'
end end
if opval == '' then if opval == '' then
exec_lua(('vim.api.nvim_del_var(\'%s\')'):format(key)) exec_lua(("vim.api.nvim_del_var('%s')"):format(key))
else 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
end end
@@ -247,14 +246,14 @@ describe('Vimscript dictionary notifications', function()
{ '= 3', { new = 3 } }, { '= 3', { new = 3 } },
{ '= 6', { old = 3, new = 6 } }, { '= 6', { old = 3, new = 6 } },
{ '+= 3', { old = 6, new = 9 } }, { '+= 3', { old = 6, new = 9 } },
{'', {old = 9}} { '', { old = 9 } },
}) })
test_updates({ test_updates({
{ '= "str"', { new = 'str' } }, { '= "str"', { new = 'str' } },
{ '= "str2"', { old = 'str', new = 'str2' } }, { '= "str2"', { old = 'str', new = 'str2' } },
{ '.= "2str"', { old = 'str2', new = 'str22str' } }, { '.= "2str"', { old = 'str2', new = 'str22str' } },
{'', {old = 'str22str'}} { '', { old = 'str22str' } },
}) })
test_updates({ test_updates({
@@ -262,7 +261,7 @@ describe('Vimscript dictionary notifications', function()
{ '= [1, 2, 3]', { old = { 1, 2 }, new = { 1, 2, 3 } } }, { '= [1, 2, 3]', { old = { 1, 2 }, new = { 1, 2, 3 } } },
-- the += will update the list in place, so old and new are the same -- 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 } } }, { '+= [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({ test_updates({
@@ -315,8 +314,10 @@ describe('Vimscript dictionary notifications', function()
call rpcnotify(g:channel, '1', a:key, a:value) call rpcnotify(g:channel, '1', a:key, a:value)
endfunction endfunction
]]) ]])
eq('Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"', eq(
exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')) 'Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"',
exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')
)
end) end)
describe('errors', function() describe('errors', function()
@@ -333,13 +334,17 @@ describe('Vimscript dictionary notifications', function()
-- WARNING: This suite depends on the above tests -- WARNING: This suite depends on the above tests
it('fails to remove if no watcher with matching callback is found', function() 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", eq(
exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")')) "Vim(call):Couldn't find a watcher matching key and callback",
exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")')
)
end) end)
it('fails to remove if no watcher with matching key is found', function() 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", eq(
exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")')) "Vim(call):Couldn't find a watcher matching key and callback",
exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")')
)
end) end)
it("does not fail to add/remove if the callback doesn't exist", function() it("does not fail to add/remove if the callback doesn't exist", function()
@@ -348,8 +353,10 @@ describe('Vimscript dictionary notifications', function()
end) end)
it('fails to remove watcher from v:_null_dict', function() it('fails to remove watcher from v:_null_dict', function()
eq("Vim(call):Couldn't find a watcher matching key and callback", eq(
exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")')) "Vim(call):Couldn't find a watcher matching key and callback",
exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")')
)
end) end)
--[[ --[[
@@ -412,12 +419,11 @@ describe('Vimscript dictionary notifications', function()
call dictwatcheradd(b:, 'changedtick', 'OnTickChanged') call dictwatcheradd(b:, 'changedtick', 'OnTickChanged')
]]) ]])
insert('t'); insert('t')
eq({'notification', 'SendChangeTick', {'changedtick', {old = 2, new = 3}}}, eq({ 'notification', 'SendChangeTick', { 'changedtick', { old = 2, new = 3 } } }, next_msg())
next_msg())
command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]]) command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]])
insert('t'); insert('t')
assert_alive() assert_alive()
end) end)
@@ -479,7 +485,7 @@ describe('Vimscript dictionary notifications', function()
let g:d.foo = 23 let g:d.foo = 23
]]) ]])
eq(23, eval('g:d.foo')) eq(23, eval('g:d.foo'))
eq({"W1"}, eval('g:calls')) eq({ 'W1' }, eval('g:calls'))
end) end)
it('calls watcher deleted in callback', function() it('calls watcher deleted in callback', function()
@@ -507,7 +513,6 @@ describe('Vimscript dictionary notifications', function()
let g:d.foo = 123 let g:d.foo = 123
]]) ]])
eq(123, eval('g:d.foo')) eq(123, eval('g:d.foo'))
eq({"W1", "W2", "W2", "W1"}, eval('g:calls')) eq({ 'W1', 'W2', 'W2', 'W1' }, eval('g:calls'))
end) end)
end) end)

View File

@@ -3,7 +3,7 @@ local command = helpers.command
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command
describe(":drop", function() describe(':drop', function()
local screen local screen
before_each(function() before_each(function()
@@ -16,11 +16,11 @@ describe(":drop", function()
[2] = { reverse = true }, [2] = { reverse = true },
[3] = { bold = true }, [3] = { bold = true },
}) })
command("set laststatus=2 shortmess-=F") command('set laststatus=2 shortmess-=F')
end) end)
it("works like :e when called with only one window open", function() it('works like :e when called with only one window open', function()
feed_command("drop tmp1.vim") feed_command('drop tmp1.vim')
screen:expect([[ screen:expect([[
^ | ^ |
{0:~ }|*7 {0:~ }|*7
@@ -29,11 +29,11 @@ describe(":drop", function()
]]) ]])
end) end)
it("switches to an open window showing the buffer", function() it('switches to an open window showing the buffer', function()
feed_command("edit tmp1") feed_command('edit tmp1')
feed_command("vsplit") feed_command('vsplit')
feed_command("edit tmp2") feed_command('edit tmp2')
feed_command("drop tmp1") feed_command('drop tmp1')
screen:expect([[ screen:expect([[
│^ | │^ |
{0:~ }│{0:~ }|*7 {0:~ }│{0:~ }|*7
@@ -43,12 +43,12 @@ describe(":drop", function()
end) end)
it("splits off a new window when a buffer can't be abandoned", function() it("splits off a new window when a buffer can't be abandoned", function()
command("set nohidden") command('set nohidden')
feed_command("edit tmp1") feed_command('edit tmp1')
feed_command("vsplit") feed_command('vsplit')
feed_command("edit tmp2") feed_command('edit tmp2')
feed("iABC<esc>") feed('iABC<esc>')
feed_command("drop tmp3") feed_command('drop tmp3')
screen:expect([[ screen:expect([[
^ │ | ^ │ |
{0:~ }│{0:~ }|*3 {0:~ }│{0:~ }|*3
@@ -59,5 +59,4 @@ describe(":drop", function()
"tmp3" [New] | "tmp3" [New] |
]]) ]])
end) end)
end) end)

View File

@@ -85,14 +85,12 @@ describe(':echo :echon :echomsg :echoerr', function()
eq('v:null', funcs.StringErr(NIL)) eq('v:null', funcs.StringErr(NIL))
end) end)
it('dumps values with at most six digits after the decimal point', it('dumps values with at most six digits after the decimal point', function()
function()
assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020) assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020)
assert_same_echo_dump('1.234568', 1.23456789123456789123456789) assert_same_echo_dump('1.234568', 1.23456789123456789123456789)
end) end)
it('dumps values with at most seven digits before the decimal point', it('dumps values with at most seven digits before the decimal point', function()
function()
assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789) assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789)
assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789) assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789)
end) end)
@@ -198,75 +196,95 @@ describe(':echo :echon :echomsg :echoerr', function()
let TestDictRef = function('TestDict', d) let TestDictRef = function('TestDict', d)
let d.tdr = TestDictRef let d.tdr = TestDictRef
]]) ]])
eq(dedent([[ eq(
dedent([[
function('TestDict', {'tdr': function('TestDict', {...@1})})]]), function('TestDict', {'tdr': function('TestDict', {...@1})})]]),
exec_capture('echo String(d.tdr)')) exec_capture('echo String(d.tdr)')
)
end) end)
it('dumps automatically created partials', function() it('dumps automatically created partials', function()
assert_same_echo_dump( assert_same_echo_dump(
"function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})", "function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})",
'{"f": Test2_f}.f', '{"f": Test2_f}.f',
true) true
)
assert_same_echo_dump( assert_same_echo_dump(
"function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})", "function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})",
'{"f": function(Test2_f, [1])}.f', '{"f": function(Test2_f, [1])}.f',
true) true
)
end) end)
it('dumps manually created partials', function() it('dumps manually created partials', function()
assert_same_echo_dump("function('Test3', [1, 2], {})", assert_same_echo_dump("function('Test3', [1, 2], {})", "function('Test3', [1, 2], {})", true)
"function('Test3', [1, 2], {})", true) assert_same_echo_dump("function('Test3', [1, 2])", "function('Test3', [1, 2])", true)
assert_same_echo_dump("function('Test3', [1, 2])", assert_same_echo_dump("function('Test3', {})", "function('Test3', {})", true)
"function('Test3', [1, 2])", true)
assert_same_echo_dump("function('Test3', {})",
"function('Test3', {})", true)
end) end)
it('does not crash or halt when dumping partials with reference cycles in self', it('does not crash or halt when dumping partials with reference cycles in self', function()
function()
meths.set_var('d', { v = true }) meths.set_var('d', { v = true })
eq(dedent([[ eq(
{'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]), dedent(
exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) [[
{'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) end)
it('does not show errors when dumping partials referencing the same dictionary', it('does not show errors when dumping partials referencing the same dictionary', function()
function()
command('let d = {}') command('let d = {}')
-- Regression for “eval/typval_encode: Dump empty dictionary before -- Regression for “eval/typval_encode: Dump empty dictionary before
-- checking for refcycle”, results in error. -- 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) -- Regression for “eval: Work with reference cycles in partials (self)
-- properly”, results in crash. -- properly”, results in crash.
eval('extend(d, {"a": 1})') 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) end)
it('does not crash or halt when dumping partials with reference cycles in arguments', it('does not crash or halt when dumping partials with reference cycles in arguments', function()
function()
meths.set_var('l', {}) meths.set_var('l', {})
eval('add(l, l)') eval('add(l, l)')
-- Regression: the below line used to crash (add returns original list and -- Regression: the below line used to crash (add returns original list and
-- there was error in dumping partials). Tested explicitly in -- there was error in dumping partials). Tested explicitly in
-- test/unit/api/private_helpers_spec.lua. -- test/unit/api/private_helpers_spec.lua.
eval('add(l, function("Test1", l))') eval('add(l, function("Test1", l))')
eq(dedent([=[ eq(
function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]), dedent(
exec_capture('echo String(function("Test1", l))')) [=[
function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]
),
exec_capture('echo String(function("Test1", l))')
)
end) 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() function()
meths.set_var('d', { v = true }) meths.set_var('d', { v = true })
meths.set_var('l', {}) meths.set_var('l', {})
eval('add(l, l)') eval('add(l, l)')
eval('add(l, function("Test1", l))') eval('add(l, function("Test1", l))')
eval('add(l, function("Test1", d))') eval('add(l, function("Test1", d))')
eq(dedent([=[ eq(
{'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}]=]), dedent(
exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) [=[
end) {'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) end)
describe('used to represent lists', function() 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() it('dumps list with two same empty dictionaries, also in partials', function()
command('let d = {}') command('let d = {}')
assert_same_echo_dump('[{}, {}]', '[d, d]', true) assert_same_echo_dump('[{}, {}]', '[d, d]', true)
eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) eq("[function('tr', {}), {}]", eval('String([function("tr", d), d])'))
eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) eq("[{}, function('tr', {})]", eval('String([d, function("tr", d)])'))
end) end)
it('dumps non-empty dictionary', function() it('dumps non-empty dictionary', function()
@@ -325,10 +343,8 @@ describe(':echo :echon :echomsg :echoerr', function()
it('dumps recursive dictionaries without the error', function() it('dumps recursive dictionaries without the error', function()
meths.set_var('d', { d = 1 }) meths.set_var('d', { d = 1 })
eval('extend(d, {"d": d})') eval('extend(d, {"d": d})')
eq('{\'d\': {...@0}}', eq("{'d': {...@0}}", exec_capture('echo String(d)'))
exec_capture('echo String(d)')) eq("{'out': {'d': {...@1}}}", exec_capture('echo String({"out": d})'))
eq('{\'out\': {\'d\': {...@1}}}',
exec_capture('echo String({"out": d})'))
end) end)
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 eq, command, funcs = helpers.eq, helpers.command, helpers.funcs
local ok = helpers.ok local ok = helpers.ok
local clear = helpers.clear local clear = helpers.clear
local feed = helpers.feed local feed = helpers.feed
describe(":edit", function() describe(':edit', function()
before_each(function() before_each(function()
clear() clear()
end) end)
it("without arguments does not restart :terminal buffer", function() it('without arguments does not restart :terminal buffer', function()
command("terminal") command('terminal')
feed([[<C-\><C-N>]]) feed([[<C-\><C-N>]])
local bufname_before = funcs.bufname("%") local bufname_before = funcs.bufname('%')
local bufnr_before = funcs.bufnr("%") local bufnr_before = funcs.bufnr('%')
helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
command("edit") command('edit')
local bufname_after = funcs.bufname("%") local bufname_after = funcs.bufname('%')
local bufnr_after = funcs.bufnr("%") local bufnr_after = funcs.bufnr('%')
ok(funcs.line('$') > 1) ok(funcs.line('$') > 1)
eq(bufname_before, bufname_after) eq(bufname_before, bufname_after)
eq(bufnr_before, bufnr_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 local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
describe('&encoding', function() describe('&encoding', function()
before_each(function() before_each(function()
clear() clear()
-- sanity check: tests should run with encoding=utf-8 -- 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() it('can be set to utf-8 without error', function()
feed_command('set encoding=utf-8') feed_command('set encoding=utf-8')
eq("", eval('v:errmsg')) eq('', eval('v:errmsg'))
clear('--cmd', 'set enc=utf-8') clear('--cmd', 'set enc=utf-8')
eq("", eval('v:errmsg')) eq('', eval('v:errmsg'))
end) 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 command = helpers.command local command = helpers.command
local eq = helpers.eq local eq = helpers.eq
local clear = helpers.clear local clear = helpers.clear
@@ -20,15 +20,25 @@ describe('Ex cmds', function()
command(':later 9999999999999999999999999999999999999999') command(':later 9999999999999999999999999999999999999999')
command(':echo expand("#<9999999999999999999999999999999999999999")') command(':echo expand("#<9999999999999999999999999999999999999999")')
command(':lockvar 9999999999999999999999999999999999999999') command(':lockvar 9999999999999999999999999999999999999999')
command(':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999') command(
check_excmd_err(':tabnext 9999999999999999999999999999999999999999', ':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999'
'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999') )
check_excmd_err(':N 9999999999999999999999999999999999999999', check_excmd_err(
'Vim(Next):E939: Positive count required') ':tabnext 9999999999999999999999999999999999999999',
check_excmd_err(':bdelete 9999999999999999999999999999999999999999', 'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999'
'Vim(bdelete):E939: Positive count required') )
eq('Vim(menu):E329: No menu "9999999999999999999999999999999999999999"', check_excmd_err(
pcall_err(command, ':menu 9999999999999999999999999999999999999999')) ':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() assert_alive()
end) end)

View File

@@ -19,7 +19,7 @@ describe(':file', function()
rmdir(swapdir) rmdir(swapdir)
end) end)
it("rename does not lose swapfile #6487", function() it('rename does not lose swapfile #6487', function()
local testfile = 'test-file_spec' local testfile = 'test-file_spec'
local testfile_renamed = testfile .. '-renamed' local testfile_renamed = testfile .. '-renamed'
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
@@ -30,7 +30,6 @@ describe(':file', function()
command('edit! ' .. testfile) command('edit! ' .. testfile)
-- Before #6487 this gave "E301: Oops, lost the swap file !!!" on Windows. -- Before #6487 this gave "E301: Oops, lost the swap file !!!" on Windows.
command('file ' .. testfile_renamed) command('file ' .. testfile_renamed)
eq(testfile_renamed..'.swp', eq(testfile_renamed .. '.swp', string.match(funcs.execute('swapname'), '[^%%]+$'))
string.match(funcs.execute('swapname'), '[^%%]+$'))
end) end)
end) end)

View File

@@ -1,5 +1,5 @@
local Screen = require('test.functional.ui.screen') 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 eq, command = helpers.eq, helpers.command
local clear = helpers.clear local clear = helpers.clear
local eval, exc_exec = helpers.eval, helpers.exc_exec local eval, exc_exec = helpers.eval, helpers.exc_exec
@@ -17,15 +17,18 @@ describe(':highlight', function()
end) end)
it('invalid color name', function() it('invalid color name', function()
eq('Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818', eq(
exc_exec("highlight normal ctermfg=#181818")) 'Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818',
eq('Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818', exc_exec('highlight normal ctermfg=#181818')
exc_exec("highlight normal ctermbg=#181818")) )
eq(
'Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818',
exc_exec('highlight normal ctermbg=#181818')
)
end) end)
it('invalid group name', function() it('invalid group name', function()
eq('Vim(highlight):E411: Highlight group not found: foo', eq('Vim(highlight):E411: Highlight group not found: foo', exc_exec('highlight foo'))
exc_exec("highlight foo"))
end) end)
it('"Normal" foreground with red', function() 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 ... ')) eq('\n 3 %aF ', string.match(ls_output, '^\n *3 ... '))
end) end)
end) end)
end) end)

View File

@@ -14,7 +14,7 @@ describe(':make', function()
describe('with powershell', function() describe('with powershell', function()
if not has_powershell() then if not has_powershell() then
pending("not tested; powershell was not found", function() end) pending('not tested; powershell was not found', function() end)
return return
end end
before_each(function() before_each(function()
@@ -25,7 +25,10 @@ describe(':make', function()
nvim('set_option_value', 'makeprg', testprg('shell-test') .. ' foo', {}) nvim('set_option_value', 'makeprg', testprg('shell-test') .. ' foo', {})
local out = eval('execute("make")') local out = eval('execute("make")')
-- Error message is captured in the file and printed in the footer -- 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) end)
it('captures stderr & zero exit code #14349', function() it('captures stderr & zero exit code #14349', function()
@@ -36,7 +39,5 @@ describe(':make', function()
matches('LastExitCode%s+ready [$]%s+[(]', out) matches('LastExitCode%s+ready [$]%s+[(]', out)
matches('\n.*%: ready [$]', out) matches('\n.*%: ready [$]', out)
end) end)
end) 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 Screen = require('test.functional.ui.screen')
local eq = helpers.eq local eq = helpers.eq
@@ -33,23 +33,27 @@ describe(':*map', function()
it('shows <Nop> as mapping rhs', function() it('shows <Nop> as mapping rhs', function()
command('nmap asdf <Nop>') command('nmap asdf <Nop>')
eq([[ eq(
[[
n asdf <Nop>]], n asdf <Nop>]],
exec_capture('nmap asdf')) exec_capture('nmap asdf')
)
end) end)
it('mappings with description can be filtered', function() it('mappings with description can be filtered', function()
meths.set_keymap('n', 'asdf1', 'qwert', { desc = 'do the one thing' }) 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', 'asdf2', 'qwert', { desc = 'doesnot really do anything' })
meths.set_keymap('n', 'asdf3', 'qwert', { desc = 'do the other thing' }) meths.set_keymap('n', 'asdf3', 'qwert', { desc = 'do the other thing' })
eq([[ eq(
[[
n asdf3 qwert n asdf3 qwert
do the other thing do the other thing
n asdf1 qwert n asdf1 qwert
do the one thing]], do the one thing]],
exec_capture('filter the nmap')) exec_capture('filter the nmap')
)
end) end)
it('<Plug> mappings ignore nore', function() it('<Plug> mappings ignore nore', function()
@@ -75,7 +79,7 @@ n asdf1 qwert
nmap increase_x_remap x<Plug>(Increase_x)x nmap increase_x_remap x<Plug>(Increase_x)x
nnoremap increase_x_noremap 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('.')")) eq('Some text', eval("getline('.')"))
feed('increase_x_remap') 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 eq, eval = helpers.eq, helpers.eval
local funcs = helpers.funcs local funcs = helpers.funcs
describe(':emenu', function() describe(':emenu', function()
before_each(function() before_each(function()
clear() clear()
command('nnoremenu Test.Test inormal<ESC>') command('nnoremenu Test.Test inormal<ESC>')
@@ -60,7 +58,6 @@ describe(':emenu', function()
end) end)
describe('menu_get', function() describe('menu_get', function()
before_each(function() before_each(function()
clear() clear()
command([=[ command([=[
@@ -83,12 +80,12 @@ describe('menu_get', function()
end) end)
it("path='', modes='a'", function() 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: -- HINT: To print the expected table and regenerate the tests:
-- print(require('vim.inspect')(m)) -- print(require('vim.inspect')(m))
local expected = { local expected = {
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
submenus = { submenus = {
{ {
@@ -97,176 +94,45 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "insert", rhs = 'insert',
silent = 0 silent = 0,
}, },
s = { s = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "x", rhs = 'x',
silent = 0 silent = 0,
}, },
n = { n = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "inormal<Esc>", rhs = 'inormal<Esc>',
silent = 0 silent = 0,
}, },
v = { v = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "x", rhs = 'x',
silent = 0 silent = 0,
}, },
c = { c = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "cmdmode", rhs = 'cmdmode',
silent = 0 silent = 0,
} },
}, },
priority = 500, priority = 500,
name = "Test", 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",
hidden = 0, hidden = 0,
name = "Script",
priority = 500,
mappings = {
n = {
sid = 1,
noremap = 1,
enabled = 1,
rhs = "p",
silent = 0
}
}
}
},
hidden = 0
}, },
{ {
priority = 500, priority = 500,
name = "Edit", name = 'Nested',
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 = { submenus = {
{ {
mappings = { mappings = {
@@ -274,72 +140,207 @@ describe('menu_get', function()
sid = 0, sid = 0,
noremap = 0, noremap = 0,
enabled = 1, enabled = 1,
rhs = "thisoneshouldbehidden", rhs = 'level1',
silent = 0 silent = 0,
}, },
v = { v = {
sid = 0, sid = 0,
noremap = 0, noremap = 0,
enabled = 1, enabled = 1,
rhs = "thisoneshouldbehidden", rhs = 'level1',
silent = 0 silent = 0,
}, },
s = { s = {
sid = 0, sid = 0,
noremap = 0, noremap = 0,
enabled = 1, enabled = 1,
rhs = "thisoneshouldbehidden", rhs = 'level1',
silent = 0 silent = 0,
}, },
n = { n = {
sid = 0, sid = 0,
noremap = 0, noremap = 0,
enabled = 1, enabled = 1,
rhs = "thisoneshouldbehidden", rhs = 'level1',
silent = 0 silent = 0,
} },
}, },
priority = 500, priority = 500,
name = "hidden", name = 'test',
hidden = 0 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) eq(expected, m)
end) end)
it('matching path, all modes', function() it('matching path, all modes', function()
local m = funcs.menu_get("Export", "a") local m = funcs.menu_get('Export', 'a')
local expected = { { local expected = {
{
hidden = 0, hidden = 0,
name = "Export", name = 'Export',
priority = 500, priority = 500,
submenus = { { submenus = {
tooltip = "This is the tooltip", {
tooltip = 'This is the tooltip',
hidden = 0, hidden = 0,
name = "Script", name = 'Script',
priority = 500, priority = 500,
mappings = { mappings = {
n = { n = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "p", rhs = 'p',
silent = 0 silent = 0,
},
},
},
},
},
} }
}
} }
} }
eq(expected, m) eq(expected, m)
end) end)
it('no path, matching modes', function() it('no path, matching modes', function()
local m = funcs.menu_get("","i") local m = funcs.menu_get('', 'i')
local expected = { local expected = {
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
submenus = { submenus = {
{ {
@@ -348,27 +349,27 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "insert", rhs = 'insert',
silent = 0 silent = 0,
}
},
priority = 500,
name = "Test",
hidden = 0
}, },
}, },
priority = 500, priority = 500,
name = "Test" name = 'Test',
} hidden = 0,
},
},
priority = 500,
name = 'Test',
},
} }
eq(expected, m) eq(expected, m)
end) end)
it('matching path and modes', function() it('matching path and modes', function()
local m = funcs.menu_get("Test","i") local m = funcs.menu_get('Test', 'i')
local expected = { local expected = {
{ {
shortcut = "T", shortcut = 'T',
submenus = { submenus = {
{ {
mappings = { mappings = {
@@ -376,26 +377,25 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "insert", rhs = 'insert',
silent = 0 silent = 0,
}, },
}, },
priority = 500, priority = 500,
name = "Test", name = 'Test',
hidden = 0 hidden = 0,
}, },
}, },
priority = 500, priority = 500,
name = "Test", name = 'Test',
hidden = 0 hidden = 0,
} },
} }
eq(expected, m) eq(expected, m)
end) end)
end) end)
describe('menu_get', function() describe('menu_get', function()
before_each(function() before_each(function()
clear() clear()
command('aunmenu *') command('aunmenu *')
@@ -412,10 +412,10 @@ describe('menu_get', function()
command('nnoremenu &Test.Test8 <NoP>') command('nnoremenu &Test.Test8 <NoP>')
command('nnoremenu &Test.Test9 ""') command('nnoremenu &Test.Test9 ""')
local m = funcs.menu_get(""); local m = funcs.menu_get('')
local expected = { local expected = {
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
submenus = { submenus = {
{ {
@@ -425,12 +425,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "inormal<Esc>", rhs = 'inormal<Esc>',
silent = 0 silent = 0,
}
}, },
name = "Test", },
hidden = 0 name = 'Test',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -439,12 +439,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "<Tab><Esc>", rhs = '<Tab><Esc>',
silent = 0 silent = 0,
}
}, },
name = "Test2", },
hidden = 0 name = 'Test2',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -453,19 +453,19 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "yA<C-R>0<Tab>xyz<Esc>", rhs = 'yA<C-R>0<Tab>xyz<Esc>',
silent = 0 silent = 0,
}, },
v = { v = {
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "yA<C-R>0<Tab>xyz<Esc>", rhs = 'yA<C-R>0<Tab>xyz<Esc>',
silent = 0 silent = 0,
}
}, },
name = "Test3", },
hidden = 0 name = 'Test3',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -474,12 +474,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "<C-R>*", rhs = '<C-R>*',
silent = 0 silent = 0,
}
}, },
name = "Test4", },
hidden = 0 name = 'Test4',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -488,12 +488,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "<C-R>+", rhs = '<C-R>+',
silent = 0 silent = 0,
}
}, },
name = "Test5", },
hidden = 0 name = 'Test5',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -502,12 +502,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "", rhs = '',
silent = 0 silent = 0,
}
}, },
name = "Test6", },
hidden = 0 name = 'Test6',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -516,12 +516,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "", rhs = '',
silent = 0 silent = 0,
}
}, },
name = "Test7", },
hidden = 0 name = 'Test7',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -530,12 +530,12 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "", rhs = '',
silent = 0 silent = 0,
}
}, },
name = "Test8", },
hidden = 0 name = 'Test8',
hidden = 0,
}, },
{ {
priority = 500, priority = 500,
@@ -544,17 +544,17 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "\"\"", rhs = '""',
silent = 0 silent = 0,
} },
},
name = 'Test9',
hidden = 0,
}, },
name = "Test9",
hidden = 0
}
}, },
priority = 500, priority = 500,
name = "Test" name = 'Test',
} },
} }
eq(m, expected) eq(m, expected)
@@ -565,12 +565,12 @@ describe('menu_get', function()
command('nnoremenu &Test\\ 1.Test\\ 2 Wargl') command('nnoremenu &Test\\ 1.Test\\ 2 Wargl')
command('nnoremenu &Test4.Test<Tab>3 i space<Esc>') command('nnoremenu &Test4.Test<Tab>3 i space<Esc>')
local m = funcs.menu_get(""); local m = funcs.menu_get('')
local expected = { local expected = {
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
actext = "Y", actext = 'Y',
submenus = { submenus = {
{ {
mappings = { mappings = {
@@ -578,21 +578,21 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "inormal<Alt-j>", rhs = 'inormal<Alt-j>',
silent = 0 silent = 0,
} },
}, },
hidden = 0, hidden = 0,
actext = "X x", actext = 'X x',
priority = 500, priority = 500,
name = "Test" name = 'Test',
} },
}, },
priority = 500, priority = 500,
name = "Test" name = 'Test',
}, },
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
submenus = { submenus = {
{ {
@@ -602,19 +602,19 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "Wargl", rhs = 'Wargl',
silent = 0 silent = 0,
} },
},
name = 'Test 2',
hidden = 0,
}, },
name = "Test 2",
hidden = 0
}
}, },
priority = 500, priority = 500,
name = "Test 1" name = 'Test 1',
}, },
{ {
shortcut = "T", shortcut = 'T',
hidden = 0, hidden = 0,
submenus = { submenus = {
{ {
@@ -623,19 +623,19 @@ describe('menu_get', function()
sid = 1, sid = 1,
noremap = 1, noremap = 1,
enabled = 1, enabled = 1,
rhs = "i space<Esc>", rhs = 'i space<Esc>',
silent = 0 silent = 0,
} },
}, },
hidden = 0, hidden = 0,
actext = "3", actext = '3',
priority = 500, priority = 500,
name = "Test" name = 'Test',
} },
}, },
priority = 500, priority = 500,
name = "Test4" name = 'Test4',
} },
} }
eq(m, expected) eq(m, expected)

View File

@@ -18,7 +18,9 @@ local mkdir = helpers.mkdir
local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' 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() describe(':mksession', function()
local session_file = file_prefix .. '.vim' local session_file = file_prefix .. '.vim'

View File

@@ -29,8 +29,7 @@ describe(':mkview', function()
it('viewoption curdir restores local current directory', function() it('viewoption curdir restores local current directory', function()
local cwd_dir = funcs.getcwd() local cwd_dir = funcs.getcwd()
local set_view_dir_command = 'set viewdir=' .. cwd_dir .. local set_view_dir_command = 'set viewdir=' .. cwd_dir .. get_pathsep() .. view_dir
get_pathsep() .. view_dir
-- By default the local current directory should save -- By default the local current directory should save
command(set_view_dir_command) command(set_view_dir_command)
@@ -63,5 +62,4 @@ describe(':mkview', function()
-- The view's local directory should have been saved -- The view's local directory should have been saved
eq(cwd_dir .. get_pathsep() .. local_dir, funcs.getcwd()) eq(cwd_dir .. get_pathsep() .. local_dir, funcs.getcwd())
end) end)
end) end)

View File

@@ -12,9 +12,15 @@ local eval = helpers.eval
local shada_file = 'Xtest.shada' local shada_file = 'Xtest.shada'
local function _clear() local function _clear()
clear{args={'-i', shada_file, -- Need shada for these tests. clear {
'--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}, args = {
args_rm={'-i', '--cmd'}} '-i',
shada_file, -- Need shada for these tests.
'--cmd',
'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler',
},
args_rm = { '-i', '--cmd' },
}
end end
describe(':oldfiles', function() describe(':oldfiles', function()

View File

@@ -1,6 +1,5 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local clear, eq, command, funcs = local clear, eq, command, funcs = helpers.clear, helpers.eq, helpers.command, helpers.funcs
helpers.clear, helpers.eq, helpers.command, helpers.funcs
describe(':z^', function() describe(':z^', function()
before_each(clear) before_each(clear)

View File

@@ -20,15 +20,19 @@ for _, c in ipairs({'l', 'c'}) do
local filecmd = c .. 'file' local filecmd = c .. 'file'
local getfcmd = c .. 'getfile' local getfcmd = c .. 'getfile'
local addfcmd = c .. 'addfile' local addfcmd = c .. 'addfile'
local getlist = (c == 'c') and funcs.getqflist or ( local getlist = (c == 'c') and funcs.getqflist or function()
function() return funcs.getloclist(0) end) return funcs.getloclist(0)
end
describe((':%s*file commands'):format(c), function() describe((':%s*file commands'):format(c), function()
before_each(function() before_each(function()
write_file(file, ([[ write_file(
file,
([[
%s-1.res:700:10:Line 700 %s-1.res:700:10:Line 700
%s-2.res:800:15:Line 800 %s-2.res:800:15:Line 800
]]):format(file, file)) ]]):format(file, file)
)
end) end)
after_each(function() after_each(function()
os.remove(file) 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 -- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual
-- results. First line (i.e. `{lnum=…`) was obtained from legacy test. -- results. First line (i.e. `{lnum=…`) was obtained from legacy test.
local list = { 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 = 700,
{lnum=800, end_lnum=0, col=15, end_col=0, text='Line 800', module='', end_lnum = 0,
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, 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(list, getlist())
eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) 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('set nohidden')
command('enew!') command('enew!')
curbufmeths.set_lines(1, 1, true, { 'Quickfix' }) curbufmeths.set_lines(1, 1, true, { 'Quickfix' })
eq(('Vim(%s):E37: No write since last change (add ! to override)'):format( eq(
filecmd), ('Vim(%s):E37: No write since last change (add ! to override)'):format(filecmd),
exc_exec(('%s %s'):format(filecmd, file))) exc_exec(('%s %s'):format(filecmd, file))
)
write_file(file, ([[ write_file(
file,
([[
%s-3.res:900:30:Line 900 %s-3.res:900:30:Line 900
]]):format(file)) ]]):format(file)
)
command(('%s %s'):format(addfcmd, file)) command(('%s %s'):format(addfcmd, file))
list[#list + 1] = { list[#list + 1] = {
lnum=900, end_lnum=0, col=30, end_col=0, text='Line 900', module='', lnum = 900,
nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='', 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(list, getlist())
eq(('%s-3.res'):format(file), funcs.bufname(list[3].bufnr)) 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-1.res:222:77:Line 222
%s-2.res:333:88:Line 333 %s-2.res:333:88:Line 333
]]):format(file, file)) ]]):format(file, file)
)
command('enew!') command('enew!')
command(('%s %s'):format(getfcmd, file)) command(('%s %s'):format(getfcmd, file))
list = { 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 = 222,
{lnum=333, end_lnum=0, col=88, end_col=0, text='Line 333', module='', end_lnum = 0,
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''}, 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(list, getlist())
eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr)) eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr))
@@ -127,7 +196,10 @@ describe('quickfix', function()
end) end)
it(':vimgrep can specify Unicode pattern without delimiters', function() 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) local screen = Screen.new(40, 6)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText

View File

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

View File

@@ -30,29 +30,48 @@ describe('script_get-based command', function()
local function test_garbage_exec(cmd, check_neq) local function test_garbage_exec(cmd, check_neq)
describe(cmd, function() describe(cmd, function()
it('works correctly when skipping oneline variant', function() it('works correctly when skipping oneline variant', function()
eq(true, pcall(source, (dedent([[ eq(
true,
pcall(
source,
(dedent([[
if 0 if 0
%s %s %s %s
endif endif
]])):format(cmd, garbage))) ]])):format(cmd, garbage)
)
)
eq('', exec_capture('messages')) eq('', exec_capture('messages'))
if check_neq then if check_neq then
neq(0, exc_exec(dedent([[ neq(
0,
exc_exec(dedent([[
%s %s %s %s
]])):format(cmd, garbage)) ]])):format(cmd, garbage)
)
end end
end) end)
it('works correctly when skipping HEREdoc variant', function() it('works correctly when skipping HEREdoc variant', function()
eq(true, pcall(source, (dedent([[ eq(
true,
pcall(
source,
(dedent([[
if 0 if 0
%s << EOF %s << EOF
%s %s
EOF EOF
endif endif
]])):format(cmd, garbage))) ]])):format(cmd, garbage)
)
)
eq('', exec_capture('messages')) eq('', exec_capture('messages'))
if check_neq then if check_neq then
eq(true, pcall(source, (dedent([[ eq(
true,
pcall(
source,
(dedent([[
let g:exc = 0 let g:exc = 0
try try
%s << EOF %s << EOF
@@ -61,7 +80,9 @@ describe('script_get-based command', function()
catch catch
let g:exc = v:exception let g:exc = v:exception
endtry endtry
]])):format(cmd, garbage))) ]])):format(cmd, garbage)
)
)
neq(0, meths.get_var('exc')) neq(0, meths.get_var('exc'))
end end
end) end)

View File

@@ -16,8 +16,8 @@ describe('sign', function()
nvim('command', 'sign place 34 line=3 name=Foo buffer=' .. buf2) nvim('command', 'sign place 34 line=3 name=Foo buffer=' .. buf2)
-- now unplace without specifying a buffer -- now unplace without specifying a buffer
nvim('command', 'sign unplace 34') nvim('command', 'sign unplace 34')
eq("--- Signs ---\n", nvim('exec', 'sign place buffer='..buf1, true)) 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=' .. buf2, true))
end) end)
end) end)
end) end)

View File

@@ -52,13 +52,16 @@ describe(':source', function()
meths.set_option_value('shellslash', false, {}) meths.set_option_value('shellslash', false, {})
mkdir('Xshellslash') mkdir('Xshellslash')
write_file([[Xshellslash/Xstack.vim]], [[ write_file(
[[Xshellslash/Xstack.vim]],
[[
let g:stack1 = expand('<stack>') let g:stack1 = expand('<stack>')
set shellslash set shellslash
let g:stack2 = expand('<stack>') let g:stack2 = expand('<stack>')
set noshellslash set noshellslash
let g:stack3 = expand('<stack>') let g:stack3 = expand('<stack>')
]]) ]]
)
for _ = 1, 2 do for _ = 1, 2 do
command([[source Xshellslash/Xstack.vim]]) command([[source Xshellslash/Xstack.vim]])
@@ -67,13 +70,16 @@ describe(':source', function()
matches([[Xshellslash\Xstack%.vim]], meths.get_var('stack3')) matches([[Xshellslash\Xstack%.vim]], meths.get_var('stack3'))
end end
write_file([[Xshellslash/Xstack.lua]], [[ write_file(
[[Xshellslash/Xstack.lua]],
[[
vim.g.stack1 = vim.fn.expand('<stack>') vim.g.stack1 = vim.fn.expand('<stack>')
vim.o.shellslash = true vim.o.shellslash = true
vim.g.stack2 = vim.fn.expand('<stack>') vim.g.stack2 = vim.fn.expand('<stack>')
vim.o.shellslash = false vim.o.shellslash = false
vim.g.stack3 = vim.fn.expand('<stack>') vim.g.stack3 = vim.fn.expand('<stack>')
]]) ]]
)
for _ = 1, 2 do for _ = 1, 2 do
command([[source Xshellslash/Xstack.lua]]) command([[source Xshellslash/Xstack.lua]])
@@ -101,11 +107,11 @@ describe(':source', function()
eq("{'k': 'v'}", exec_capture('echo b')) eq("{'k': 'v'}", exec_capture('echo b'))
-- Script items are created only on script var access -- Script items are created only on script var access
eq("1", exec_capture('echo c')) eq('1', exec_capture('echo c'))
eq("0zBEEFCAFE", exec_capture('echo d')) eq('0zBEEFCAFE', exec_capture('echo d'))
exec('set cpoptions+=C') 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) end)
it('selection in current buffer', function() it('selection in current buffer', function()
@@ -132,14 +138,14 @@ describe(':source', function()
feed_command(':source') feed_command(':source')
eq('4', exec_capture('echo a')) eq('4', exec_capture('echo a'))
eq("{'K': 'V'}", exec_capture('echo b')) 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 -- Source last line only
feed_command(':$source') feed_command(':$source')
eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()')) eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()'))
exec('set cpoptions+=C') 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) end)
it('does not break if current buffer is modified while sourced', function() 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() it('can source lua files', function()
local test_file = 'test.lua' local test_file = 'test.lua'
write_file(test_file, [[ write_file(
test_file,
[[
vim.g.sourced_lua = 1 vim.g.sourced_lua = 1
vim.g.sfile_value = vim.fn.expand('<sfile>') vim.g.sfile_value = vim.fn.expand('<sfile>')
vim.g.stack_value = vim.fn.expand('<stack>') vim.g.stack_value = vim.fn.expand('<stack>')
vim.g.script_value = vim.fn.expand('<script>') vim.g.script_value = vim.fn.expand('<script>')
]]) ]]
)
command('set shellslash') command('set shellslash')
command('source ' .. test_file) command('source ' .. test_file)
@@ -245,22 +254,22 @@ describe(':source', function()
local test_file = 'test.lua' local test_file = 'test.lua'
-- Does throw E484 for unreadable files -- 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) eq(false, ok)
neq(nil, result:find("E484")) neq(nil, result:find('E484'))
-- Doesn't throw for parsing error -- Doesn't throw for parsing error
write_file (test_file, "vim.g.c = ") write_file(test_file, 'vim.g.c = ')
ok, result = pcall(exec_capture, ":source "..test_file) ok, result = pcall(exec_capture, ':source ' .. test_file)
eq(false, ok) eq(false, ok)
eq(nil, result:find("E484")) eq(nil, result:find('E484'))
os.remove(test_file) os.remove(test_file)
-- Doesn't throw for runtime error -- Doesn't throw for runtime error
write_file(test_file, "error('Cause error anyway :D')") 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(false, ok)
eq(nil, result:find("E484")) eq(nil, result:find('E484'))
os.remove(test_file) os.remove(test_file)
end) end)
end) end)

View File

@@ -1,8 +1,7 @@
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local luv = require('luv') local luv = require('luv')
local eq, eval, expect, exec = local eq, eval, expect, exec = helpers.eq, helpers.eval, helpers.expect, helpers.exec
helpers.eq, helpers.eval, helpers.expect, helpers.exec
local assert_alive = helpers.assert_alive local assert_alive = helpers.assert_alive
local clear = helpers.clear local clear = helpers.clear
local command = helpers.command local command = helpers.command
@@ -32,14 +31,14 @@ describe(':recover', function()
it('fails if given a non-existent swapfile', function() it('fails if given a non-existent swapfile', function()
local swapname = 'bogus_swapfile' local swapname = 'bogus_swapfile'
local swapname2 = 'bogus_swapfile.swp' local swapname2 = 'bogus_swapfile.swp'
eq('Vim(recover):E305: No swap file found for '..swapname, eq(
pcall_err(command, 'recover '..swapname)) -- Should not segfault. #2117 '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 -- Also check filename ending with ".swp". #9504
eq('Vim(recover):E306: Cannot open '..swapname2, eq('Vim(recover):E306: Cannot open ' .. swapname2, pcall_err(command, 'recover ' .. swapname2)) -- Should not segfault. #2117
pcall_err(command, 'recover '..swapname2)) -- Should not segfault. #2117
assert_alive() assert_alive()
end) end)
end) end)
describe("preserve and (R)ecover with custom 'directory'", function() describe("preserve and (R)ecover with custom 'directory'", function()
@@ -116,7 +115,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
screen0:attach() screen0:attach()
local child_server = new_pipename() local child_server = new_pipename()
funcs.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server }, { funcs.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server }, {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
}) })
screen0:expect({ any = pesc('[No Name]') }) -- Wait for the child process to start. screen0:expect({ any = pesc('[No Name]') }) -- Wait for the child process to start.
local child_session = helpers.connect(child_server) 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. screen0:expect({ any = pesc('[Process exited 1]') }) -- Wait for the child process to stop.
test_recover(swappath1) test_recover(swappath1)
end) end)
end) end)
describe('swapfile detection', function() describe('swapfile detection', function()
@@ -178,44 +176,65 @@ describe('swapfile detection', function()
-- With shortmess+=F -- With shortmess+=F
command('set shortmess+=F') command('set shortmess+=F')
feed(':edit ' .. testfile .. '<CR>') feed(':edit ' .. testfile .. '<CR>')
screen2:expect{any=[[E325: ATTENTION.*]]..'\n'..[[Found a swap file by the name ".*]] screen2:expect {
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} any = [[E325: ATTENTION.*]]
.. '\n'
.. [[Found a swap file by the name ".*]]
.. [[Xtest_swapdialog_dir[/\].*]]
.. testfile
.. [[%.swp"]],
}
feed('e') -- Chose "Edit" at the swap dialog. feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog) screen2:expect(expected_no_dialog)
-- With :silent and shortmess+=F -- With :silent and shortmess+=F
feed(':silent edit %<CR>') feed(':silent edit %<CR>')
screen2:expect{any=[[Found a swap file by the name ".*]] screen2:expect {
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} any = [[Found a swap file by the name ".*]]
.. [[Xtest_swapdialog_dir[/\].*]]
.. testfile
.. [[%.swp"]],
}
feed('e') -- Chose "Edit" at the swap dialog. feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog) screen2:expect(expected_no_dialog)
-- With :silent! and shortmess+=F -- With :silent! and shortmess+=F
feed(':silent! edit %<CR>') feed(':silent! edit %<CR>')
screen2:expect{any=[[Found a swap file by the name ".*]] screen2:expect {
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} any = [[Found a swap file by the name ".*]]
.. [[Xtest_swapdialog_dir[/\].*]]
.. testfile
.. [[%.swp"]],
}
feed('e') -- Chose "Edit" at the swap dialog. feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog) screen2:expect(expected_no_dialog)
-- With API (via eval/Vimscript) call and shortmess+=F -- With API (via eval/Vimscript) call and shortmess+=F
feed(':call nvim_command("edit %")<CR>') feed(':call nvim_command("edit %")<CR>')
screen2:expect{any=[[Found a swap file by the name ".*]] screen2:expect {
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} any = [[Found a swap file by the name ".*]]
.. [[Xtest_swapdialog_dir[/\].*]]
.. testfile
.. [[%.swp"]],
}
feed('e') -- Chose "Edit" at the swap dialog. feed('e') -- Chose "Edit" at the swap dialog.
feed('<c-c>') feed('<c-c>')
screen2:expect(expected_no_dialog) screen2:expect(expected_no_dialog)
-- With API call and shortmess+=F -- With API call and shortmess+=F
async_meths.command('edit %') async_meths.command('edit %')
screen2:expect{any=[[Found a swap file by the name ".*]] screen2:expect {
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} any = [[Found a swap file by the name ".*]]
.. [[Xtest_swapdialog_dir[/\].*]]
.. testfile
.. [[%.swp"]],
}
feed('e') -- Chose "Edit" at the swap dialog. feed('e') -- Chose "Edit" at the swap dialog.
expect_msg_seq({ expect_msg_seq({
ignore = { 'redraw' }, ignore = { 'redraw' },
seqs = { seqs = {
{ {'notification', 'nvim_error_event', {0, 'Vim(edit):E325: ATTENTION'}}, { { 'notification', 'nvim_error_event', { 0, 'Vim(edit):E325: ATTENTION' } } },
} },
}
}) })
feed('<cr>') feed('<cr>')
@@ -260,7 +279,7 @@ describe('swapfile detection', function()
feed(':split Xfile1\n') feed(':split Xfile1\n')
-- The default SwapExists handler does _not_ skip this prompt. -- The default SwapExists handler does _not_ skip this prompt.
screen:expect({ 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('q')
feed(':<CR>') feed(':<CR>')
@@ -282,7 +301,7 @@ describe('swapfile detection', function()
screen:expect({ any = pesc('{1:-- More --}^') }) screen:expect({ any = pesc('{1:-- More --}^') })
feed('<Space>') feed('<Space>')
screen:expect({ 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('q')
command([[echo 'hello']]) command([[echo 'hello']])
@@ -361,10 +380,12 @@ describe('swapfile detection', function()
luv.fs_utime(swname, atime, atime) luv.fs_utime(swname, atime, atime)
feed(':edit Xswaptest<CR>') feed(':edit Xswaptest<CR>')
screen:expect({any = table.concat({ screen:expect({
any = table.concat({
pesc('{2:E325: ATTENTION}'), pesc('{2:E325: ATTENTION}'),
pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: }^'), pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: }^'),
}, '.*')}) }, '.*'),
})
feed('e') feed('e')
end end
@@ -372,12 +393,14 @@ describe('swapfile detection', function()
-- oldtest: Test_nocatch_process_still_running() -- oldtest: Test_nocatch_process_still_running()
it('swapfile created before boot vim-patch:8.2.2586', function() it('swapfile created before boot vim-patch:8.2.2586', function()
test_swapfile_after_reboot(false, function(screen) test_swapfile_after_reboot(false, function(screen)
screen:expect({any = table.concat({ screen:expect({
any = table.concat({
pesc('{2:E325: ATTENTION}'), pesc('{2:E325: ATTENTION}'),
'file name: .*Xswaptest', 'file name: .*Xswaptest',
'process ID: %d* %(STILL RUNNING%)', 'process ID: %d* %(STILL RUNNING%)',
pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'), pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
}, '.*')}) }, '.*'),
})
end) end)
end) end)
@@ -386,7 +409,6 @@ describe('swapfile detection', function()
screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' }) screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' })
end) end)
end) end)
end) end)
describe('quitting swapfile dialog on startup stops TUI properly', function() 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 } }) clear({ args = { '--cmd', init_dir, '--cmd', init_set } })
rmdir(swapdir) rmdir(swapdir)
mkdir(swapdir) mkdir(swapdir)
write_file(testfile, [[ write_file(
testfile,
[[
first first
second second
third third
]]) ]]
)
command('edit! ' .. testfile) command('edit! ' .. testfile)
feed('Gisometext<esc>') feed('Gisometext<esc>')
poke_eventloop() poke_eventloop()
@@ -422,63 +447,100 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
end) end)
it('(Q)uit at first file argument', function() it('(Q)uit at first file argument', function()
local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', local chan = funcs.termopen(
'--cmd', init_dir, '--cmd', init_set, { nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', init_dir, '--cmd', init_set, testfile },
testfile}, { {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
}) }
)
retry(nil, nil, function() retry(nil, nil, function()
eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', eq(
eval("getline('$')->trim(' ', 2)")) '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
eval("getline('$')->trim(' ', 2)")
)
end) end)
meths.chan_send(chan, 'q') meths.chan_send(chan, 'q')
retry(nil, nil, function() retry(nil, nil, function()
eq({'', '[Process exited 1]', ''}, eq(
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) { '', '[Process exited 1]', '' },
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
)
end) end)
end) end)
it('(A)bort at second file argument with -p', function() it('(A)bort at second file argument with -p', function()
local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', local chan = funcs.termopen({
'--cmd', init_dir, '--cmd', init_set, nvim_prog,
'-p', otherfile, testfile}, { '-u',
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } 'NONE',
'-i',
'NONE',
'--cmd',
init_dir,
'--cmd',
init_set,
'-p',
otherfile,
testfile,
}, {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
}) })
retry(nil, nil, function() retry(nil, nil, function()
eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', eq(
eval("getline('$')->trim(' ', 2)")) '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
eval("getline('$')->trim(' ', 2)")
)
end) end)
meths.chan_send(chan, 'a') meths.chan_send(chan, 'a')
retry(nil, nil, function() retry(nil, nil, function()
eq({'', '[Process exited 1]', ''}, eq(
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) { '', '[Process exited 1]', '' },
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
)
end) end)
end) end)
it('(Q)uit at file opened by -t', function() it('(Q)uit at file opened by -t', function()
write_file(otherfile, ([[ write_file(
otherfile,
([[
!_TAG_FILE_ENCODING utf-8 // !_TAG_FILE_ENCODING utf-8 //
first %s /^ \zsfirst$/ first %s /^ \zsfirst$/
second %s /^ \zssecond$/ second %s /^ \zssecond$/
third %s /^ \zsthird$/]]):format(testfile, testfile, testfile)) third %s /^ \zsthird$/]]):format(testfile, testfile, testfile)
local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', )
'--cmd', init_dir, '--cmd', init_set, local chan = funcs.termopen({
'--cmd', 'set tags='..otherfile, '-tsecond'}, { nvim_prog,
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } '-u',
'NONE',
'-i',
'NONE',
'--cmd',
init_dir,
'--cmd',
init_set,
'--cmd',
'set tags=' .. otherfile,
'-tsecond',
}, {
env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
}) })
retry(nil, nil, function() retry(nil, nil, function()
eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', eq(
eval("getline('$')->trim(' ', 2)")) '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
eval("getline('$')->trim(' ', 2)")
)
end) end)
meths.chan_send(chan, 'q') meths.chan_send(chan, 'q')
retry(nil, nil, function() retry(nil, nil, function()
eq('Press ENTER or type command to continue', eq('Press ENTER or type command to continue', eval("getline('$')->trim(' ', 2)"))
eval("getline('$')->trim(' ', 2)"))
end) end)
meths.chan_send(chan, '\r') meths.chan_send(chan, '\r')
retry(nil, nil, function() retry(nil, nil, function()
eq({'', '[Process exited 1]', ''}, eq(
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")) { '', '[Process exited 1]', '' },
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
)
end) end)
end) end)
end) end)

View File

@@ -8,10 +8,11 @@ describe(':syntax', function()
before_each(clear) before_each(clear)
describe('keyword', function() describe('keyword', function()
it('does not crash when group name contains unprintable characters', it('does not crash when group name contains unprintable characters', function()
function() eq(
eq('Vim(syntax):E669: Unprintable character in group name', 'Vim(syntax):E669: Unprintable character in group name',
exc_exec('syntax keyword \024 foo bar')) exc_exec('syntax keyword \024 foo bar')
)
end) end)
end) end)
end) end)

View File

@@ -72,7 +72,10 @@ describe(':trust', function()
local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust') local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(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') trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust)) eq(string.format(''), vim.trim(trust))
end) end)

View File

@@ -17,7 +17,9 @@ local function last_set_tests(cmd)
current_dir = call_viml_function('fnamemodify', { current_dir, ':~' }) current_dir = call_viml_function('fnamemodify', { current_dir, ':~' })
script_location = table.concat { current_dir, helpers.get_pathsep(), script_file } script_location = table.concat { current_dir, helpers.get_pathsep(), script_file }
write_file(script_file, [[ write_file(
script_file,
[[
vim.api.nvim_set_option_value('hlsearch', false, {}) vim.api.nvim_set_option_value('hlsearch', false, {})
vim.bo.expandtab = true vim.bo.expandtab = true
vim.opt.number = true vim.opt.number = true
@@ -45,7 +47,8 @@ function! s:return80()\
endfunction\ endfunction\
let &tw = s:return80()\ let &tw = s:return80()\
", true) ", true)
]]) ]]
)
exec(cmd .. ' ' .. script_file) exec(cmd .. ' ' .. script_file)
end) end)
@@ -55,54 +58,84 @@ let &tw = s:return80()\
it('"Last set" for option set by Lua', function() it('"Last set" for option set by Lua', function()
local result = exec_capture(':verbose set hlsearch?') local result = exec_capture(':verbose set hlsearch?')
eq(string.format([[ eq(
string.format(
[[
nohlsearch nohlsearch
Last set from %s line 1]], Last set from %s line 1]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for option set by vim.o', function() it('"Last set" for option set by vim.o', function()
local result = exec_capture(':verbose set expandtab?') local result = exec_capture(':verbose set expandtab?')
eq(string.format([[ eq(
string.format(
[[
expandtab expandtab
Last set from %s line 2]], Last set from %s line 2]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for option set by vim.opt', function() it('"Last set" for option set by vim.opt', function()
local result = exec_capture(':verbose set number?') local result = exec_capture(':verbose set number?')
eq(string.format([[ eq(
string.format(
[[
number number
Last set from %s line 3]], Last set from %s line 3]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for mapping set by Lua', function() it('"Last set" for mapping set by Lua', function()
local result = exec_capture(':verbose map <leader>key1') local result = exec_capture(':verbose map <leader>key1')
eq(string.format([[ eq(
string.format(
[[
n \key1 * :echo "test"<CR> n \key1 * :echo "test"<CR>
Last set from %s line 4]], Last set from %s line 4]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for mapping set by vim.keymap', function() it('"Last set" for mapping set by vim.keymap', function()
local result = exec_capture(':verbose map <leader>key2') local result = exec_capture(':verbose map <leader>key2')
eq(string.format([[ eq(
string.format(
[[
n \key2 * :echo "test"<CR> n \key2 * :echo "test"<CR>
Last set from %s line 5]], Last set from %s line 5]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for autocmd by vim.api.nvim_exec', function() it('"Last set" for autocmd by vim.api.nvim_exec', function()
local result = exec_capture(':verbose autocmd test_group Filetype c') local result = exec_capture(':verbose autocmd test_group Filetype c')
eq(string.format([[ eq(
string.format(
[[
--- Autocommands --- --- Autocommands ---
test_group FileType test_group FileType
c setl cindent c setl cindent
Last set from %s line 7]], Last set from %s line 7]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for command defined by nvim_command', function() 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') pending('nvim_command does not set the script context')
end end
local result = exec_capture(':verbose command Bdelete') local result = exec_capture(':verbose command Bdelete')
eq(string.format([[ eq(
string.format(
[[
Name Args Address Complete Definition Name Args Address Complete Definition
Bdelete 0 :bd Bdelete 0 :bd
Last set from %s line 13]], Last set from %s line 13]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for command defined by nvim_create_user_command', function() it('"Last set" for command defined by nvim_create_user_command', function()
local result = exec_capture(':verbose command TestCommand') local result = exec_capture(':verbose command TestCommand')
eq(string.format([[ eq(
string.format(
[[
Name Args Address Complete Definition Name Args Address Complete Definition
TestCommand 0 :echo 'Hello' TestCommand 0 :echo 'Hello'
Last set from %s line 14]], Last set from %s line 14]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" for function', function() it('"Last set" for function', function()
local result = exec_capture(':verbose function Close_Window') local result = exec_capture(':verbose function Close_Window')
eq(string.format([[ eq(
string.format(
[[
function Close_Window() abort function Close_Window() abort
Last set from %s line 16 Last set from %s line 16
1 wincmd - 1 wincmd -
endfunction]], endfunction]],
script_location), result) script_location
),
result
)
end) end)
it('"Last set" works with anonymous sid', function() it('"Last set" works with anonymous sid', function()
local result = exec_capture(':verbose set tw?') local result = exec_capture(':verbose set tw?')
eq(string.format([[ eq(
string.format(
[[
textwidth=80 textwidth=80
Last set from %s line 22]], Last set from %s line 22]],
script_location), result) script_location
),
result
)
end) end)
end end
@@ -159,9 +212,12 @@ describe('lua verbose:', function()
setup(function() setup(function()
clear() clear()
script_file = 'test_luafile.lua' script_file = 'test_luafile.lua'
write_file(script_file, [[ write_file(
script_file,
[[
vim.api.nvim_set_option_value('hlsearch', false, {}) vim.api.nvim_set_option_value('hlsearch', false, {})
]]) ]]
)
exec(':source ' .. script_file) exec(':source ' .. script_file)
end) end)
@@ -171,9 +227,11 @@ describe('lua verbose:', function()
it('is disabled when verbose = 0', function() it('is disabled when verbose = 0', function()
local result = exec_capture(':verbose set hlsearch?') local result = exec_capture(':verbose set hlsearch?')
eq([[ eq(
[[
nohlsearch nohlsearch
Last set from Lua]], result) Last set from Lua]],
result
)
end) 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 clear = helpers.clear local clear = helpers.clear
local eq = helpers.eq local eq = helpers.eq
local funcs = helpers.funcs local funcs = helpers.funcs

View File

@@ -1,8 +1,7 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local luv = require('luv') local luv = require('luv')
local eq, eval, clear, write_file, source, insert = local eq, eval, clear, write_file, source, insert =
helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.source, helpers.insert
helpers.source, helpers.insert
local pcall_err = helpers.pcall_err local pcall_err = helpers.pcall_err
local command = helpers.command local command = helpers.command
local feed_command = helpers.feed_command local feed_command = helpers.feed_command
@@ -40,9 +39,9 @@ describe(':write', function()
command('set backupcopy=auto') command('set backupcopy=auto')
write_file('test_bkc_file.txt', 'content0') write_file('test_bkc_file.txt', 'content0')
if is_os('win') then 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 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 end
if eval('v:shell_error') ~= 0 then if eval('v:shell_error') ~= 0 then
pending('Cannot create symlink') pending('Cannot create symlink')
@@ -61,9 +60,9 @@ describe(':write', function()
command('set backupcopy=no') command('set backupcopy=no')
write_file('test_bkc_file.txt', 'content0') write_file('test_bkc_file.txt', 'content0')
if is_os('win') then 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 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 end
if eval('v:shell_error') ~= 0 then if eval('v:shell_error') ~= 0 then
pending('Cannot create symlink') pending('Cannot create symlink')
@@ -77,46 +76,50 @@ describe(':write', function()
eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')")) eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')"))
end) end)
it("appends FIFO file", function() it('appends FIFO file', function()
-- mkfifo creates read-only .lnk files on Windows -- mkfifo creates read-only .lnk files on Windows
if is_os('win') or eval("executable('mkfifo')") == 0 then if is_os('win') or eval("executable('mkfifo')") == 0 then
pending('missing "mkfifo" command') pending('missing "mkfifo" command')
end end
local text = "some fifo text from write_spec" local text = 'some fifo text from write_spec'
assert(os.execute("mkfifo test_fifo")) assert(os.execute('mkfifo test_fifo'))
insert(text) insert(text)
-- Blocks until a consumer reads the FIFO. -- 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. -- Read the FIFO, this will unblock the :write above.
local fifo = assert(io.open("test_fifo")) local fifo = assert(io.open('test_fifo'))
eq(text.."\n", fifo:read("*all")) eq(text .. '\n', fifo:read('*all'))
fifo:close() fifo:close()
end) end)
it("++p creates missing parent directories", function() it('++p creates missing parent directories', function()
eq(0, eval("filereadable('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')")) eq(1, eval("filereadable('p_opt.txt')"))
os.remove("p_opt.txt") os.remove('p_opt.txt')
eq(0, eval("filereadable('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')")) 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')")) 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(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 if not is_os('win') then
eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), eq(
pcall_err(command, 'write ++p .')) ('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'),
eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), pcall_err(command, 'write ++p .')
pcall_err(command, 'write ++p ./')) )
eq(
('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'),
pcall_err(command, 'write ++p ./')
)
end end
end) end)
@@ -126,24 +129,27 @@ describe(':write', function()
eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~')) eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~'))
-- Message from check_overwrite -- Message from check_overwrite
if not is_os('win') then if not is_os('win') then
eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'), eq(
pcall_err(command, 'write .')) ('Vim(write):E17: "' .. funcs.fnamemodify('.', ':p:h') .. '" is a directory'),
pcall_err(command, 'write .')
)
end end
meths.set_option_value('writeany', true, {}) meths.set_option_value('writeany', true, {})
-- Message from buf_write -- 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) funcs.mkdir(fname_bak)
meths.set_option_value('backupdir', '.', {}) meths.set_option_value('backupdir', '.', {})
meths.set_option_value('backup', true, {}) meths.set_option_value('backup', true, {})
write_file(fname, 'content0') write_file(fname, 'content0')
command('edit ' .. fname) command('edit ' .. fname)
funcs.setline(1, 'TTY') funcs.setline(1, 'TTY')
eq('Vim(write):E510: Can\'t make backup file (add ! to override)', eq("Vim(write):E510: Can't make backup file (add ! to override)", pcall_err(command, 'write'))
pcall_err(command, 'write'))
meths.set_option_value('backup', false, {}) meths.set_option_value('backup', false, {})
funcs.setfperm(fname, 'r--------') funcs.setfperm(fname, 'r--------')
eq('Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)', eq(
pcall_err(command, 'write')) 'Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)',
pcall_err(command, 'write')
)
if is_os('win') then if is_os('win') then
eq(0, os.execute('del /q/f ' .. fname)) eq(0, os.execute('del /q/f ' .. fname))
eq(0, os.execute('rd /q/s ' .. fname_bak)) eq(0, os.execute('rd /q/s ' .. fname_bak))
@@ -154,7 +160,6 @@ describe(':write', function()
write_file(fname_bak, 'TTYX') write_file(fname_bak, 'TTYX')
skip(is_os('win'), [[FIXME: exc_exec('write!') outputs 0 in Windows]]) skip(is_os('win'), [[FIXME: exc_exec('write!') outputs 0 in Windows]])
luv.fs_symlink(fname_bak .. ('/xxxxx'):rep(20), fname) luv.fs_symlink(fname_bak .. ('/xxxxx'):rep(20), fname)
eq('Vim(write):E166: Can\'t open linked file for writing', eq("Vim(write):E166: Can't open linked file for writing", pcall_err(command, 'write!'))
pcall_err(command, 'write!'))
end) end)
end) end)

View File

@@ -2,9 +2,12 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local command, clear, eval, spawn, nvim_prog, set_session = local command, clear, eval, spawn, nvim_prog, set_session =
helpers.command, helpers.clear, helpers.eval, helpers.spawn, helpers.command,
helpers.nvim_prog, helpers.set_session helpers.clear,
helpers.eval,
helpers.spawn,
helpers.nvim_prog,
helpers.set_session
describe(':wundo', function() describe(':wundo', function()
before_each(clear) before_each(clear)
@@ -21,8 +24,16 @@ end)
describe('u_* functions', function() describe('u_* functions', function()
it('safely fail on new, non-empty buffer', function() it('safely fail on new, non-empty buffer', function()
local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', local session = spawn({
'-c', 'set undodir=. undofile'}) nvim_prog,
'-u',
'NONE',
'-i',
'NONE',
'--embed',
'-c',
'set undodir=. undofile',
})
set_session(session) set_session(session)
command('echo "True"') -- Should not error out due to crashed Neovim command('echo "True"') -- Should not error out due to crashed Neovim
session:close() session:close()

View File

@@ -1,8 +1,7 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local luv = require('luv') local luv = require('luv')
local clear = helpers.clear local clear = helpers.clear
local command, eq, neq, write_file = local command, eq, neq, write_file = helpers.command, helpers.eq, helpers.neq, helpers.write_file
helpers.command, helpers.eq, helpers.neq, helpers.write_file
local read_file = helpers.read_file local read_file = helpers.read_file
local is_os = helpers.is_os local is_os = helpers.is_os
@@ -10,10 +9,16 @@ describe(':wshada', function()
local shada_file = 'wshada_test' local shada_file = 'wshada_test'
before_each(function() 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. -- Need 'swapfile' for these tests.
'--cmd', 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'}, '--cmd',
args_rm={'-n', '-i', '--cmd'}} 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler',
},
args_rm = { '-n', '-i', '--cmd' },
}
end) end)
after_each(function() after_each(function()
os.remove(shada_file) os.remove(shada_file)
@@ -44,7 +49,6 @@ describe(':wshada', function()
local char1 = fp:read(1) local char1 = fp:read(1)
fp:close() fp:close()
-- ShaDa file starts with a “header” entry -- ShaDa file starts with a “header” entry
assert(char1:byte() == 0x01, assert(char1:byte() == 0x01, shada_file .. ' should be a shada file')
shada_file..' should be a shada file')
end) end)
end) end)

View File

@@ -16,7 +16,7 @@ describe('example', function()
screen:attach() screen:attach()
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[0] = { bold = true, foreground = Screen.colors.Blue }, [0] = { bold = true, foreground = Screen.colors.Blue },
[1] = {bold=true, foreground=Screen.colors.Brown} [1] = { bold = true, foreground = Screen.colors.Brown },
}) })
end) end)
@@ -60,13 +60,14 @@ describe('example', function()
command('tabedit foo') command('tabedit foo')
-- Use screen:expect{condition=…} to check the result. -- Use screen:expect{condition=…} to check the result.
screen:expect{condition=function() screen:expect {
condition = function()
eq({ id = 2 }, event_curtab) eq({ id = 2 }, event_curtab)
eq({ eq({
{ tab = { id = 1 }, name = '[No Name]' }, { tab = { id = 1 }, name = '[No Name]' },
{ tab = { id = 2 }, name = 'foo' }, { tab = { id = 2 }, name = 'foo' },
}, }, event_tabs)
event_tabs) end,
end} }
end) 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