aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/ftplugin/man.vim2
-rw-r--r--scripts/gendispatch.lua102
-rw-r--r--src/nvim/CMakeLists.txt10
-rw-r--r--src/nvim/api/private/dispatch.c45
-rw-r--r--src/nvim/api/private/dispatch.h1
-rw-r--r--src/nvim/api/private/helpers.c21
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/os/fs.c8
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test_history.vim65
-rw-r--r--src/nvim/version.c8
-rw-r--r--src/nvim/window.c14
-rw-r--r--test/functional/core/job_spec.lua8
-rw-r--r--test/functional/ex_cmds/write_spec.lua41
-rw-r--r--test/functional/legacy/assert_spec.lua15
-rw-r--r--test/functional/legacy/quickfix_spec.lua117
-rw-r--r--test/functional/terminal/api_spec.lua12
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua48
18 files changed, 400 insertions, 119 deletions
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 02d2b4e557..f6fefd0155 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -21,7 +21,7 @@ if has('vim_starting')
" all caps it is impossible to tell what the original capitilization was.
let ref = tolower(matchstr(getline(1), '^\S\+'))
let b:man_sect = man#extract_sect_and_name_ref(ref)[0]
- execute 'file man://'.ref
+ execute 'silent file man://'.ref
endif
setlocal buftype=nofile
diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua
index 96cf2d3a11..94789e1ef0 100644
--- a/scripts/gendispatch.lua
+++ b/scripts/gendispatch.lua
@@ -52,16 +52,18 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path
-- names of all headers relative to the source root (for inclusion in the
-- generated file)
headers = {}
--- output c file(dispatch function + metadata serialized with msgpack)
-outputf = arg[#arg-1]
--- output mpack file (metadata)
+-- output h file with generated dispatch functions
+dispatch_outputf = arg[#arg-2]
+-- output h file with packed metadata
+funcs_metadata_outputf = arg[#arg-1]
+-- output metadata mpack file, for use by other build scripts
mpack_outputf = arg[#arg]
-- set of function names, used to detect duplicates
function_names = {}
-- read each input file, parse and append to the api metadata
-for i = 2, #arg - 2 do
+for i = 2, #arg - 3 do
local full_path = arg[i]
local parts = {}
for part in string.gmatch(full_path, '[^/]+') do
@@ -165,66 +167,27 @@ for _,f in ipairs(functions) do
end
--- start building the output
-output = io.open(outputf, 'wb')
-
-output:write([[
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <assert.h>
-#include <msgpack.h>
-
-#include "nvim/map.h"
-#include "nvim/log.h"
-#include "nvim/vim.h"
-#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/api/private/dispatch.h"
-#include "nvim/api/private/helpers.h"
-#include "nvim/api/private/defs.h"
+funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb')
+funcs_metadata_output:write([[
+static const uint8_t funcs_metadata[] = {
]])
-for i = 1, #headers do
- if headers[i]:sub(-12) ~= '.generated.h' then
- output:write('\n#include "nvim/'..headers[i]..'"')
- end
-end
-
-output:write([[
-
-
-static const uint8_t msgpack_metadata[] = {
-
-]])
-- serialize the API metadata using msgpack and embed into the resulting
-- binary for easy querying by clients
packed_exported_functions = mpack.pack(exported_functions)
for i = 1, #packed_exported_functions do
- output:write(string.byte(packed_exported_functions, i)..', ')
+ funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ')
if i % 10 == 0 then
- output:write('\n ')
+ funcs_metadata_output:write('\n ')
end
end
-output:write([[
+funcs_metadata_output:write([[
};
-
-void msgpack_rpc_init_function_metadata(Dictionary *metadata)
-{
- msgpack_unpacked unpacked;
- msgpack_unpacked_init(&unpacked);
- if (msgpack_unpack_next(&unpacked,
- (const char *)msgpack_metadata,
- sizeof(msgpack_metadata),
- NULL) != MSGPACK_UNPACK_SUCCESS) {
- abort();
- }
- Object functions;
- msgpack_rpc_to_object(&unpacked.data, &functions);
- msgpack_unpacked_destroy(&unpacked);
- PUT(*metadata, "functions", functions);
-}
-
]])
+funcs_metadata_output:close()
+
+-- start building the dispatch wrapper output
+output = io.open(dispatch_outputf, 'wb')
local function real_type(type)
local rv = type
@@ -336,22 +299,12 @@ end
-- Generate a function that initializes method names with handler functions
output:write([[
-static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
-
-void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler)
-{
- map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
-}
-
void msgpack_rpc_init_method_table(void)
{
methods = map_new(String, MsgpackRpcRequestHandler)();
]])
--- Keep track of the maximum method name length in order to avoid walking
--- strings longer than that when searching for a method handler
-local max_fname_len = 0
for i = 1, #functions do
local fn = functions[i]
output:write(' msgpack_rpc_add_method_handler('..
@@ -360,32 +313,9 @@ for i = 1, #functions do
'(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name)..
', .async = '..tostring(fn.async)..'});\n')
- if #fn.name > max_fname_len then
- max_fname_len = #fn.name
- end
end
output:write('\n}\n\n')
-
-output:write([[
-MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
- size_t name_len)
-{
- String m = {
- .data=(char *)name,
- .size=MIN(name_len, ]]..max_fname_len..[[)
- };
- MsgpackRpcRequestHandler rv =
- map_get(String, MsgpackRpcRequestHandler)(methods, m);
-
- if (!rv.fn) {
- rv.fn = msgpack_rpc_handle_missing_method;
- }
-
- return rv;
-}
-]])
-
output:close()
mpack_output = io.open(mpack_outputf, 'wb')
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index cbea6a05c9..49edfda838 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -18,7 +18,8 @@ set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua)
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
-set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch.c)
+set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
+set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
@@ -197,8 +198,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
${UNICODE_FILES}
)
-add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA}
- COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA}
+add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
+ ${API_METADATA}
+ COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
+ ${API_HEADERS} ${GENERATED_API_DISPATCH}
+ ${GENERATED_FUNCS_METADATA} ${API_METADATA}
DEPENDS
${API_HEADERS}
${MSGPACK_RPC_HEADERS}
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
new file mode 100644
index 0000000000..9b3bcc380a
--- /dev/null
+++ b/src/nvim/api/private/dispatch.c
@@ -0,0 +1,45 @@
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <assert.h>
+#include <msgpack.h>
+
+#include "nvim/map.h"
+#include "nvim/log.h"
+#include "nvim/vim.h"
+#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/api/private/dispatch.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/private/defs.h"
+
+#include "nvim/api/buffer.h"
+#include "nvim/api/tabpage.h"
+#include "nvim/api/ui.h"
+#include "nvim/api/vim.h"
+#include "nvim/api/window.h"
+
+static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
+
+static void msgpack_rpc_add_method_handler(String method,
+ MsgpackRpcRequestHandler handler)
+{
+ map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
+}
+
+MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
+ size_t name_len)
+{
+ String m = { .data = (char *)name, .size = name_len };
+ MsgpackRpcRequestHandler rv =
+ map_get(String, MsgpackRpcRequestHandler)(methods, m);
+
+ if (!rv.fn) {
+ rv.fn = msgpack_rpc_handle_missing_method;
+ }
+
+ return rv;
+}
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+#include "api/private/dispatch_wrappers.generated.h"
+#endif
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index a4840c1e46..39aabd708a 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -17,6 +17,7 @@ typedef struct {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/dispatch.h.generated.h"
+# include "api/private/dispatch_wrappers.h.generated.h"
#endif
#endif // NVIM_API_PRIVATE_DISPATCH_H
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index d80ee7dc67..c0ee735d1a 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -7,6 +7,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/handle.h"
+#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/ascii.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
@@ -27,6 +28,7 @@ typedef struct {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/helpers.c.generated.h"
+# include "api/private/funcs_metadata.generated.h"
#endif
/// Start block that may cause vimscript exceptions
@@ -761,7 +763,7 @@ Dictionary api_metadata(void)
static Dictionary metadata = ARRAY_DICT_INIT;
if (!metadata.size) {
- msgpack_rpc_init_function_metadata(&metadata);
+ init_function_metadata(&metadata);
init_error_type_metadata(&metadata);
init_type_metadata(&metadata);
}
@@ -769,6 +771,22 @@ Dictionary api_metadata(void)
return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary;
}
+static void init_function_metadata(Dictionary *metadata)
+{
+ msgpack_unpacked unpacked;
+ msgpack_unpacked_init(&unpacked);
+ if (msgpack_unpack_next(&unpacked,
+ (const char *)funcs_metadata,
+ sizeof(funcs_metadata),
+ NULL) != MSGPACK_UNPACK_SUCCESS) {
+ abort();
+ }
+ Object functions;
+ msgpack_rpc_to_object(&unpacked.data, &functions);
+ msgpack_unpacked_destroy(&unpacked);
+ PUT(*metadata, "functions", functions);
+}
+
static void init_error_type_metadata(Dictionary *metadata)
{
Dictionary types = ARRAY_DICT_INIT;
@@ -784,6 +802,7 @@ static void init_error_type_metadata(Dictionary *metadata)
PUT(*metadata, "error_types", DICTIONARY_OBJ(types));
}
+
static void init_type_metadata(Dictionary *metadata)
{
Dictionary types = ARRAY_DICT_INIT;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 4254697241..7444eb8a38 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -4396,6 +4396,7 @@ static HistoryType hist_char2type(const int c)
case '>': {
return HIST_DEBUG;
}
+ case NUL:
case '/':
case '?': {
return HIST_SEARCH;
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 008952fa97..3c821936e9 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -163,8 +163,12 @@ int os_nodetype(const char *name)
// saves us the hassle.
int nodetype = NODE_WRITABLE;
- int fd = os_open(name, O_RDONLY, 0);
- switch(uv_guess_handle(fd)) {
+ int fd = os_open(name, O_RDONLY
+#ifdef O_NONBLOCK
+ | O_NONBLOCK
+#endif
+ , 0);
+ switch (uv_guess_handle(fd)) {
case UV_TTY: // FILE_TYPE_CHAR
nodetype = NODE_WRITABLE;
break;
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 4d21887240..67e7c97905 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -34,6 +34,7 @@ NEW_TESTS = \
test_cscope.res \
test_hardcopy.res \
test_help_tagjump.res \
+ test_history.res \
test_langmap.res \
test_syntax.res \
test_usercommands.res \
diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim
new file mode 100644
index 0000000000..ee6acfffc3
--- /dev/null
+++ b/src/nvim/testdir/test_history.vim
@@ -0,0 +1,65 @@
+" Tests for the history functions
+
+if !has('cmdline_hist')
+ finish
+endif
+
+set history=7
+
+function History_Tests(hist)
+ " First clear the history
+ call histadd(a:hist, 'dummy')
+ call assert_true(histdel(a:hist))
+ call assert_equal(-1, histnr(a:hist))
+ call assert_equal('', histget(a:hist))
+
+ call assert_true(histadd(a:hist, 'ls'))
+ call assert_true(histadd(a:hist, 'buffers'))
+ call assert_equal('buffers', histget(a:hist))
+ call assert_equal('ls', histget(a:hist, -2))
+ call assert_equal('ls', histget(a:hist, 1))
+ call assert_equal('', histget(a:hist, 5))
+ call assert_equal('', histget(a:hist, -5))
+ call assert_equal(2, histnr(a:hist))
+ call assert_true(histdel(a:hist, 2))
+ call assert_false(histdel(a:hist, 7))
+ call assert_equal(1, histnr(a:hist))
+ call assert_equal('ls', histget(a:hist, -1))
+
+ call assert_true(histadd(a:hist, 'buffers'))
+ call assert_true(histadd(a:hist, 'ls'))
+ call assert_equal('ls', histget(a:hist, -1))
+ call assert_equal(4, histnr(a:hist))
+
+ " Test for removing entries matching a pattern
+ for i in range(1, 3)
+ call histadd(a:hist, 'text_' . i)
+ endfor
+ call assert_true(histdel(a:hist, 'text_\d\+'))
+ call assert_equal('ls', histget(a:hist, -1))
+
+ " Test for freeing the entire history list
+ for i in range(1, 7)
+ call histadd(a:hist, 'text_' . i)
+ endfor
+ call histdel(a:hist)
+ for i in range(1, 7)
+ call assert_equal('', histget(a:hist, i))
+ call assert_equal('', histget(a:hist, i - 7 - 1))
+ endfor
+endfunction
+
+function Test_History()
+ for h in ['cmd', ':', '', 'search', '/', '?', 'expr', '=', 'input', '@', 'debug', '>']
+ call History_Tests(h)
+ endfor
+
+ " Negative tests
+ call assert_false(histdel('abc'))
+ call assert_equal('', histget('abc'))
+ call assert_fails('call histdel([])', 'E730:')
+ call assert_equal('', histget(10))
+ call assert_fails('call histget([])', 'E730:')
+ call assert_equal(-1, histnr('abc'))
+ call assert_fails('call histnr([])', 'E730:')
+endfunction
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 0bc55df585..b8dd2c2a47 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -739,7 +739,7 @@ static int included_patches[] = {
// 1707,
// 1706 NA
// 1705 NA
- // 1704,
+ 1704,
1703,
// 1702,
// 1701,
@@ -855,7 +855,7 @@ static int included_patches[] = {
// 1591,
// 1590,
// 1589,
- // 1588,
+ 1588,
// 1587 NA
// 1586,
// 1585,
@@ -878,7 +878,7 @@ static int included_patches[] = {
1568,
1567,
// 1566 NA
- // 1565,
+ 1565,
// 1564,
// 1563,
// 1562 NA
@@ -949,7 +949,7 @@ static int included_patches[] = {
// 1497 NA
// 1496 NA
// 1495 NA
- // 1494,
+ 1494,
// 1493 NA
1492,
1491,
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 29c670322a..03a2e9a842 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -278,10 +278,11 @@ newwindow:
/* cursor to last accessed (previous) window */
case 'p':
case Ctrl_P:
- if (prevwin == NULL)
+ if (!win_valid(prevwin)) {
beep_flush();
- else
+ } else {
win_goto(prevwin);
+ }
break;
/* exchange current and next window */
@@ -3768,8 +3769,15 @@ win_free (
hash_init(&wp->w_vars->dv_hashtab);
unref_var_dict(wp->w_vars);
- if (prevwin == wp)
+ if (prevwin == wp) {
prevwin = NULL;
+ }
+ FOR_ALL_TABS(ttp) {
+ if (ttp->tp_prevwin == wp) {
+ ttp->tp_prevwin = NULL;
+ }
+ }
+
win_free_lsize(wp);
for (i = 0; i < wp->w_tagstacklen; ++i)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index adbe17d4b5..5872ebe8ee 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -121,14 +121,14 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can preserve newlines', function()
+ it('preserves newlines', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")')
eq({'notification', 'stdout',
{0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg())
end)
- it('can preserve NULs', function()
+ it('preserves NULs', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])')
eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}},
@@ -137,7 +137,7 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can avoid sending final newline', function()
+ it('avoids sending final newline', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobsend(j, ["some data", "without\nfinal nl"])')
eq({'notification', 'stdout', {0, {'some data', 'without\nfinal nl'}}},
@@ -146,7 +146,7 @@ describe('jobs', function()
eq({'notification', 'exit', {0, 0}}, next_msg())
end)
- it('can close the job streams with jobclose', function()
+ it('closes the job streams with jobclose', function()
nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
nvim('command', 'call jobclose(j, "stdin")')
eq({'notification', 'exit', {0, 0}}, next_msg())
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index c1bc5d3140..4ac9f312ef 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -1,20 +1,26 @@
--- Specs for :write
-
local helpers = require('test.functional.helpers')(after_each)
-local eq, eval, clear, write_file, execute, source =
- helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
- helpers.execute, helpers.source
+local eq, eval, clear, write_file, execute, source, insert =
+ helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
+ helpers.execute, helpers.source, helpers.insert
if helpers.pending_win32(pending) then return end
describe(':write', function()
- after_each(function()
+ local function cleanup()
os.remove('test_bkc_file.txt')
os.remove('test_bkc_link.txt')
+ os.remove('test_fifo')
+ end
+ before_each(function()
+ clear()
+ cleanup()
+ end)
+ after_each(function()
+ cleanup()
end)
it('&backupcopy=auto preserves symlinks', function()
- clear('--cmd', 'set backupcopy=auto')
+ execute('set backupcopy=auto')
write_file('test_bkc_file.txt', 'content0')
execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
source([[
@@ -27,7 +33,7 @@ describe(':write', function()
end)
it('&backupcopy=no replaces symlink with new file', function()
- clear('--cmd', 'set backupcopy=no')
+ execute('set backupcopy=no')
write_file('test_bkc_file.txt', 'content0')
execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
source([[
@@ -38,4 +44,23 @@ describe(':write', function()
eq(eval("['content0']"), eval("readfile('test_bkc_file.txt')"))
eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')"))
end)
+
+ it("appends FIFO file", function()
+ if eval("executable('mkfifo')") == 0 then
+ pending('missing "mkfifo" command', function()end)
+ return
+ end
+
+ local text = "some fifo text from write_spec"
+ assert(os.execute("mkfifo test_fifo"))
+ insert(text)
+
+ -- Blocks until a consumer reads the FIFO.
+ execute("write >> test_fifo")
+
+ -- Read the FIFO, this will unblock the :write above.
+ local fifo = assert(io.open("test_fifo"))
+ eq(text.."\n", fifo:read("*all"))
+ fifo:close()
+ end)
end)
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 42dd25023a..8a042be7f7 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local nvim, call = helpers.meths, helpers.call
local clear, eq = helpers.clear, helpers.eq
local source, execute = helpers.source, helpers.execute
+local exc_exec = helpers.exc_exec
local function expected_errors(errors)
eq(errors, nvim.get_vvar('errors'))
@@ -62,6 +63,20 @@ describe('assert function:', function()
call('assert_equal', 'true', 'false')
expected_errors({"Expected 'true' but got 'false'"})
end)
+
+ it('should change v:errors when expected is not equal to actual', function()
+ source([[
+ function CheckAssert()
+ let s:v = {}
+ let s:x = {"a": s:v}
+ let s:v["b"] = s:x
+ let s:w = {"c": s:x, "d": ''}
+ call assert_equal(s:w, '')
+ endfunction
+ ]])
+ eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call CheckAssert()'))
+ end)
end)
-- assert_notequal({expected}, {actual}[, {msg}])
diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua
index df8f2625db..7657b8641b 100644
--- a/test/functional/legacy/quickfix_spec.lua
+++ b/test/functional/legacy/quickfix_spec.lua
@@ -277,6 +277,118 @@ describe('helpgrep', function()
augroup! testgroup
endfunction
+
+ " This will test for problems in quickfix:
+ " A. incorrectly copying location lists which caused the location list to show
+ " a different name than the file that was actually being displayed.
+ " B. not reusing the window for which the location list window is opened but
+ " instead creating new windows.
+ " C. make sure that the location list window is not reused instead of the
+ " window it belongs to.
+ "
+ " Set up the test environment:
+ function! ReadTestProtocol(name)
+ let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
+ let word = substitute(base, '\v(.*)\..*', '\1', '')
+
+ setl modifiable
+ setl noreadonly
+ setl noswapfile
+ setl bufhidden=delete
+ %del _
+ " For problem 2:
+ " 'buftype' has to be set to reproduce the constant opening of new windows
+ setl buftype=nofile
+
+ call setline(1, word)
+
+ setl nomodified
+ setl nomodifiable
+ setl readonly
+ exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
+ endfunction
+
+ function Test_locationlist()
+ enew
+
+ augroup testgroup
+ au!
+ autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
+ augroup END
+
+ let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
+
+ let qflist = []
+ for word in words
+ call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
+ " NOTE: problem 1:
+ " intentionally not setting 'lnum' so that the quickfix entries are not
+ " valid
+ call setloclist(0, qflist, ' ')
+ endfor
+
+ " Test A
+ lrewind
+ enew
+ lopen
+ lnext
+ lnext
+ lnext
+ lnext
+ vert split
+ wincmd L
+ lopen
+ wincmd p
+ lnext
+ let fileName = expand("%")
+ wincmd p
+ let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
+ let fileName = substitute(fileName, '\\', '/', 'g')
+ let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
+ call assert_equal("test://bar.txt", fileName)
+ call assert_equal("test://bar.txt", locationListFileName)
+
+ wincmd n | only
+
+ " Test B:
+ lrewind
+ lopen
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ call assert_equal(2, winnr('$'))
+ wincmd n | only
+
+ " Test C:
+ lrewind
+ lopen
+ " Let's move the location list window to the top to check whether it (the
+ " first window found) will be reused when we try to open new windows:
+ wincmd K
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ 1wincmd w
+ call assert_equal('quickfix', &buftype)
+ 2wincmd w
+ let bufferName = expand("%")
+ let bufferName = substitute(bufferName, '\\', '/', 'g')
+ call assert_equal('test://quux.txt', bufferName)
+
+ wincmd n | only
+
+ augroup! testgroup
+ endfunction
]])
end)
@@ -339,4 +451,9 @@ describe('helpgrep', function()
call('Test_locationlist_curwin_was_closed')
expected_empty()
end)
+
+ it('checks locationlist protocol read', function()
+ call('Test_locationlist')
+ expected_empty()
+ end)
end)
diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua
index 58d6c75940..045bdb0749 100644
--- a/test/functional/terminal/api_spec.lua
+++ b/test/functional/terminal/api_spec.lua
@@ -22,7 +22,7 @@ describe('api', function()
-- Start the socket from the child nvim.
child_session.feed_data(":echo serverstart('"..socket_name.."')\n")
- -- Wait for socket creation by abusing expect().
+ -- Wait for socket creation.
screen:expect([[
{1: } |
{4:~ }|
@@ -37,6 +37,16 @@ describe('api', function()
local socket_session2 = helpers.connect(socket_name)
child_session.feed_data("i[tui] insert-mode")
+ -- Wait for stdin to be processed.
+ screen:expect([[
+ [tui] insert-mode{1: } |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
ok(socket_session1:request("nvim_ui_attach", 42, 6, {rgb=true}))
ok(socket_session2:request("nvim_ui_attach", 25, 30, {rgb=true}))
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 09b4eaa8d5..4247be0417 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -13,6 +13,42 @@ describe(':terminal', function()
clear()
screen = Screen.new(50, 4)
screen:attach({rgb=false})
+ end)
+
+ it("does not interrupt Press-ENTER prompt #2748", function()
+ -- Ensure that :messages shows Press-ENTER.
+ source([[
+ echomsg "msg1"
+ echomsg "msg2"
+ ]])
+ -- Invoke a command that emits frequent terminal activity.
+ execute([[terminal while true; do echo X; done]])
+ helpers.feed([[<C-\><C-N>]])
+ screen:expect([[
+ X |
+ X |
+ ^X |
+ |
+ ]])
+ helpers.sleep(10) -- Let some terminal activity happen.
+ execute("messages")
+ screen:expect([[
+ X |
+ msg1 |
+ msg2 |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+
+end)
+
+describe(':terminal (with fake shell)', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 4)
+ screen:attach({rgb=false})
-- shell-test.c is a fake shell that prints its arguments and exits.
nvim('set_option', 'shell', nvim_dir..'/shell-test')
nvim('set_option', 'shellcmdflag', 'EXE')
@@ -20,12 +56,12 @@ describe(':terminal', function()
-- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints
-- the {cmd} and exits immediately .
- local function terminal_run_fake_shell_cmd(cmd)
+ local function terminal_with_fake_shell(cmd)
execute("terminal "..(cmd and cmd or ""))
end
it('with no argument, acts like termopen()', function()
- terminal_run_fake_shell_cmd()
+ terminal_with_fake_shell()
wait()
screen:expect([[
ready $ |
@@ -36,7 +72,7 @@ describe(':terminal', function()
end)
it('executes a given command through the shell', function()
- terminal_run_fake_shell_cmd('echo hi')
+ terminal_with_fake_shell('echo hi')
wait()
screen:expect([[
ready $ echo hi |
@@ -47,7 +83,7 @@ describe(':terminal', function()
end)
it('allows quotes and slashes', function()
- terminal_run_fake_shell_cmd([[echo 'hello' \ "world"]])
+ terminal_with_fake_shell([[echo 'hello' \ "world"]])
wait()
screen:expect([[
ready $ echo 'hello' \ "world" |
@@ -66,14 +102,14 @@ describe(':terminal', function()
end)
it('ignores writes if the backing stream closes', function()
- terminal_run_fake_shell_cmd()
+ terminal_with_fake_shell()
helpers.feed('iiXXXXXXX')
wait()
-- Race: Though the shell exited (and streams were closed by SIGCHLD
-- handler), :terminal cleanup is pending on the main-loop.
-- This write should be ignored (not crash, #5445).
helpers.feed('iiYYYYYYY')
- wait()
+ eq(2, eval("1+1")) -- Still alive?
end)
end)