aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--ci/build.ps12
-rw-r--r--cmake/FindLibLUV.cmake6
-rw-r--r--cmake/FindLibTermkey.cmake6
-rw-r--r--cmake/FindLibUV.cmake9
-rw-r--r--cmake/FindLibVterm.cmake33
-rw-r--r--cmake/FindLuaJit.cmake7
-rw-r--r--cmake/FindMsgpack.cmake7
-rw-r--r--config/CMakeLists.txt1
-rw-r--r--config/config.h.in1
-rw-r--r--contrib/local.mk.example12
-rw-r--r--runtime/doc/if_lua.txt18
-rw-r--r--runtime/doc/job_control.txt2
-rw-r--r--src/nvim/eval.c9
-rw-r--r--src/nvim/event/libuv_process.c6
-rw-r--r--src/nvim/event/process.c6
-rw-r--r--src/nvim/event/process.h1
-rw-r--r--src/nvim/ex_docmd.c7
-rw-r--r--src/nvim/fileio.c120
-rw-r--r--src/nvim/globals.h10
-rw-r--r--src/nvim/iconv.h46
-rw-r--r--src/nvim/lua/executor.c65
-rw-r--r--src/nvim/main.c3
-rw-r--r--src/nvim/mbyte.c198
-rw-r--r--src/nvim/mbyte.h2
-rw-r--r--src/nvim/os/pty_process_unix.c2
-rw-r--r--src/nvim/os/pty_process_win.c2
-rw-r--r--src/nvim/search.c1
-rw-r--r--src/nvim/spell.c6
-rw-r--r--src/nvim/terminal.c2
-rw-r--r--src/nvim/testdir/test_spell.vim54
-rw-r--r--src/nvim/version.c6
-rw-r--r--test/functional/core/job_spec.lua21
-rw-r--r--test/functional/fixtures/shell-test.c19
-rw-r--r--test/functional/helpers.lua365
-rw-r--r--test/functional/lua/utility_functions_spec.lua55
-rw-r--r--test/functional/shada/buffers_spec.lua42
-rw-r--r--test/functional/shada/helpers.lua59
-rw-r--r--test/functional/shada/marks_spec.lua34
-rw-r--r--test/functional/shada/registers_spec.lua11
-rw-r--r--test/functional/shada/shada_spec.lua4
-rw-r--r--test/functional/shada/variables_spec.lua19
-rw-r--r--test/functional/ui/output_spec.lua15
43 files changed, 572 insertions, 733 deletions
diff --git a/Makefile b/Makefile
index 97bb3f43ae..fff0ffef28 100644
--- a/Makefile
+++ b/Makefile
@@ -141,6 +141,11 @@ lualint: | build/.ran-cmake deps
pylint:
flake8 contrib/ scripts/ src/ test/
+# Run pylint only if flake8 is installed.
+_opt_pylint:
+ @command -v flake8 && { $(MAKE) pylint; exit $$?; } \
+ || echo "SKIP: pylint (flake8 not found)"
+
unittest: | nvim
+$(BUILD_CMD) -C build unittest
@@ -182,11 +187,7 @@ appimage:
appimage-%:
bash scripts/genappimage.sh $*
-lint: check-single-includes clint lualint
- @# Run pylint only if flake8 is installed.
- @command -v flake8 \
- && { $(MAKE) pylint; exit $$?; } \
- || echo "SKIP: pylint (flake8 not found)"
+lint: check-single-includes clint lualint _opt_pylint
# Generic pattern rules, allowing for `make build/bin/nvim` etc.
# Does not work with "Unix Makefiles".
diff --git a/ci/build.ps1 b/ci/build.ps1
index da1ad2f4b6..42066c462b 100644
--- a/ci/build.ps1
+++ b/ci/build.ps1
@@ -137,8 +137,10 @@ if ($uploadToCodecov) {
# Old tests
# Add MSYS to path, required for e.g. `find` used in test scripts.
# But would break functionaltests, where its `more` would be used then.
+$OldPath = $env:PATH
$env:PATH = "C:\msys64\usr\bin;$env:PATH"
& "C:\msys64\mingw$bits\bin\mingw32-make.exe" -C $(Convert-Path ..\src\nvim\testdir) VERBOSE=1
+$env:PATH = $OldPath
if ($uploadToCodecov) {
bash -l /c/projects/neovim/ci/common/submit_coverage.sh oldtest
diff --git a/cmake/FindLibLUV.cmake b/cmake/FindLibLUV.cmake
index 66f827214e..784e3fd249 100644
--- a/cmake/FindLibLUV.cmake
+++ b/cmake/FindLibLUV.cmake
@@ -14,12 +14,6 @@ set(LIBLUV_DEFINITIONS ${PC_LIBLUV_CFLAGS_OTHER})
find_path(LIBLUV_INCLUDE_DIR luv/luv.h
PATHS ${PC_LIBLUV_INCLUDEDIR} ${PC_LIBLUV_INCLUDE_DIRS})
-# If we're asked to use static linkage, add libluv.a as a preferred library name.
-if(LIBLUV_USE_STATIC)
- list(APPEND LIBLUV_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}luv${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif()
-
list(APPEND LIBLUV_NAMES luv)
find_library(LIBLUV_LIBRARY NAMES ${LIBLUV_NAMES}
diff --git a/cmake/FindLibTermkey.cmake b/cmake/FindLibTermkey.cmake
index 6e09a692c8..3e0c7f1bfd 100644
--- a/cmake/FindLibTermkey.cmake
+++ b/cmake/FindLibTermkey.cmake
@@ -14,12 +14,6 @@ set(LIBTERMKEY_DEFINITIONS ${PC_LIBTERMKEY_CFLAGS_OTHER})
find_path(LIBTERMKEY_INCLUDE_DIR termkey.h
PATHS ${PC_LIBTERMKEY_INCLUDEDIR} ${PC_LIBTERMKEY_INCLUDE_DIRS})
-# If we're asked to use static linkage, add libuv.a as a preferred library name.
-if(LIBTERMKEY_USE_STATIC)
- list(APPEND LIBTERMKEY_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}termkey${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif()
-
list(APPEND LIBTERMKEY_NAMES termkey)
find_library(LIBTERMKEY_LIBRARY NAMES ${LIBTERMKEY_NAMES}
diff --git a/cmake/FindLibUV.cmake b/cmake/FindLibUV.cmake
index e94a243ec6..951fb0435e 100644
--- a/cmake/FindLibUV.cmake
+++ b/cmake/FindLibUV.cmake
@@ -4,9 +4,6 @@
# LIBUV_FOUND - system has libuv
# LIBUV_INCLUDE_DIRS - the libuv include directories
# LIBUV_LIBRARIES - link these to use libuv
-#
-# Set the LIBUV_USE_STATIC variable to specify if static libraries should
-# be preferred to shared ones.
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
@@ -16,12 +13,6 @@ endif()
find_path(LIBUV_INCLUDE_DIR uv.h
HINTS ${PC_LIBUV_INCLUDEDIR} ${PC_LIBUV_INCLUDE_DIRS})
-# If we're asked to use static linkage, add libuv.a as a preferred library name.
-if(LIBUV_USE_STATIC)
- list(APPEND LIBUV_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}uv${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif(LIBUV_USE_STATIC)
-
list(APPEND LIBUV_NAMES uv)
find_library(LIBUV_LIBRARY NAMES ${LIBUV_NAMES}
diff --git a/cmake/FindLibVterm.cmake b/cmake/FindLibVterm.cmake
index e11d1caddc..469494ddfd 100644
--- a/cmake/FindLibVterm.cmake
+++ b/cmake/FindLibVterm.cmake
@@ -4,34 +4,7 @@
# LIBVTERM_INCLUDE_DIRS - The libvterm include directories
# LIBVTERM_LIBRARIES - The libraries needed to use libvterm
-find_package(PkgConfig)
-if (PKG_CONFIG_FOUND)
- pkg_check_modules(PC_LIBVTERM QUIET vterm)
-endif()
+include(LibFindMacros)
-set(LIBVTERM_DEFINITIONS ${PC_LIBVTERM_CFLAGS_OTHER})
-
-find_path(LIBVTERM_INCLUDE_DIR vterm.h
- PATHS ${PC_LIBVTERM_INCLUDEDIR} ${PC_LIBVTERM_INCLUDE_DIRS})
-
-# If we're asked to use static linkage, add libuv.a as a preferred library name.
-if(LIBVTERM_USE_STATIC)
- list(APPEND LIBVTERM_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}vterm${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif()
-
-list(APPEND LIBVTERM_NAMES vterm)
-
-find_library(LIBVTERM_LIBRARY NAMES ${LIBVTERM_NAMES}
- HINTS ${PC_LIBVTERM_LIBDIR} ${PC_LIBVTERM_LIBRARY_DIRS})
-
-set(LIBVTERM_LIBRARIES ${LIBVTERM_LIBRARY})
-set(LIBVTERM_INCLUDE_DIRS ${LIBVTERM_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-# handle the QUIETLY and REQUIRED arguments and set LIBVTERM_FOUND to TRUE
-# if all listed variables are TRUE
-find_package_handle_standard_args(LibVterm DEFAULT_MSG
- LIBVTERM_LIBRARY LIBVTERM_INCLUDE_DIR)
-
-mark_as_advanced(LIBVTERM_INCLUDE_DIR LIBVTERM_LIBRARY)
+libfind_pkg_detect(LIBVTERM vterm FIND_PATH vterm.h FIND_LIBRARY vterm)
+libfind_process(LIBVTERM REQUIRED)
diff --git a/cmake/FindLuaJit.cmake b/cmake/FindLuaJit.cmake
index d60b6f09be..72795afefd 100644
--- a/cmake/FindLuaJit.cmake
+++ b/cmake/FindLuaJit.cmake
@@ -15,13 +15,6 @@ find_path(LUAJIT_INCLUDE_DIR luajit.h
PATHS ${PC_LUAJIT_INCLUDEDIR} ${PC_LUAJIT_INCLUDE_DIRS}
PATH_SUFFIXES luajit-2.0 luajit-2.1)
-# If we're asked to use static linkage, add libluajit-5.1.a as a preferred
-# library name.
-if(LUAJIT_USE_STATIC)
- list(APPEND LUAJIT_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}luajit-5.1${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif()
-
if(MSVC)
list(APPEND LUAJIT_NAMES lua51)
elseif(MINGW)
diff --git a/cmake/FindMsgpack.cmake b/cmake/FindMsgpack.cmake
index df4efa9c41..26eb19d498 100644
--- a/cmake/FindMsgpack.cmake
+++ b/cmake/FindMsgpack.cmake
@@ -26,13 +26,6 @@ else()
set(MSGPACK_VERSION_STRING)
endif()
-# If we're asked to use static linkage, add libmsgpack{,c}.a as a preferred library name.
-if(MSGPACK_USE_STATIC)
- list(APPEND MSGPACK_NAMES
- "${CMAKE_STATIC_LIBRARY_PREFIX}msgpackc${CMAKE_STATIC_LIBRARY_SUFFIX}"
- "${CMAKE_STATIC_LIBRARY_PREFIX}msgpack${CMAKE_STATIC_LIBRARY_SUFFIX}")
-endif()
-
if(MSVC)
# The import library for the msgpack DLL has a different name
list(APPEND MSGPACK_NAMES msgpackc_import)
diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt
index 82cb4d31ad..0ca41d5dfd 100644
--- a/config/CMakeLists.txt
+++ b/config/CMakeLists.txt
@@ -20,7 +20,6 @@ endif()
check_symbol_exists(_NSGetEnviron crt_externs.h HAVE__NSGETENVIRON)
# Headers
-check_include_files(iconv.h HAVE_ICONV_H)
check_include_files(langinfo.h HAVE_LANGINFO_H)
check_include_files(locale.h HAVE_LOCALE_H)
check_include_files(pwd.h HAVE_PWD_H)
diff --git a/config/config.h.in b/config/config.h.in
index 40baff95e8..3216ab7556 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -22,7 +22,6 @@
#cmakedefine HAVE_GETPWNAM
#cmakedefine HAVE_GETPWUID
#cmakedefine HAVE_ICONV
-#cmakedefine HAVE_ICONV_H
#cmakedefine HAVE_LANGINFO_H
#cmakedefine HAVE_LOCALE_H
#cmakedefine HAVE_NL_LANGINFO_CODESET
diff --git a/contrib/local.mk.example b/contrib/local.mk.example
index a8c8e9cefb..5a31ded59b 100644
--- a/contrib/local.mk.example
+++ b/contrib/local.mk.example
@@ -47,18 +47,6 @@
#
# DEPS_CMAKE_FLAGS += -DUSE_BUNDLED=OFF
-# By default, bundled libraries are statically linked to nvim.
-# This has no effect for non-bundled deps, which are always dynamically linked.
-# Uncomment these entries to instead use dynamic linking.
-#
-# CMAKE_EXTRA_FLAGS += -DLIBTERMKEY_USE_STATIC=OFF
-# CMAKE_EXTRA_FLAGS += -DLIBUNIBILIUM_USE_STATIC=OFF
-# CMAKE_EXTRA_FLAGS += -DLIBUV_USE_STATIC=OFF
-# CMAKE_EXTRA_FLAGS += -DLIBVTERM_USE_STATIC=OFF
-# CMAKE_EXTRA_FLAGS += -DLUAJIT_USE_STATIC=OFF
-# CMAKE_EXTRA_FLAGS += -DMSGPACK_USE_STATIC=OFF
-#
-#
# .DEFAULT_GOAL := nvim
#
# Run doxygen over the source code.
diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt
index 7ddcb6cc92..a9b8c5fae8 100644
--- a/runtime/doc/if_lua.txt
+++ b/runtime/doc/if_lua.txt
@@ -459,6 +459,24 @@ vim.stricmp({a}, {b}) *vim.stricmp()*
are equal, {a} is greater than {b} or {a} is lesser than {b},
respectively.
+vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
+ Convert byte index to UTF-32 and UTF-16 indicies. If {index} is not
+ supplied, the length of the string is used. All indicies are zero-based.
+ Returns two values: the UTF-32 and UTF-16 indicies respectively.
+
+ Embedded NUL bytes are treated as terminating the string. Invalid
+ UTF-8 bytes, and embedded surrogates are counted as one code
+ point each. An {index} in the middle of a UTF-8 sequence is rounded
+ upwards to the end of that sequence.
+
+vim.str_byteindex({str}, {index}[, {use_utf16}]) *vim.str_byteindex()*
+ Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not
+ supplied, it defaults to false (use UTF-32). Returns the byte index.
+
+ Invalid UTF-8 and NUL is treated like by |vim.str_byteindex()|. An {index}
+ in the middle of a UTF-16 sequence is rounded upwards to the end of that
+ sequence.
+
vim.schedule({callback}) *vim.schedule()*
Schedules {callback} to be invoked soon by the main event-loop. Useful
to avoid |textlock| or other temporary restrictions.
diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt
index e5cd765e83..ae208c0755 100644
--- a/runtime/doc/job_control.txt
+++ b/runtime/doc/job_control.txt
@@ -67,7 +67,7 @@ For |on_stdout| and |on_stderr| see |channel-callback|.
*on_exit*
Arguments passed to on_exit callback:
0: |job-id|
- 1: Exit-code of the process.
+ 1: Exit-code of the process, or 128+SIGNUM if by signal (e.g. 143 on SIGTERM).
2: Event type: "exit"
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index fabd26ce47..31a49faaf3 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -11260,7 +11260,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"fork",
#endif
"gettext",
-#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
+#if defined(HAVE_ICONV)
"iconv",
#endif
"insert_expand",
@@ -11373,10 +11373,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = stdout_isatty;
} else if (STRICMP(name, "multi_byte_encoding") == 0) {
n = has_mbyte != 0;
-#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
- } else if (STRICMP(name, "iconv") == 0) {
- n = iconv_enabled(false);
-#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
#ifdef UNIX
@@ -12359,7 +12355,6 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
-
Channel *data = find_job(argvars[0].vval.v_number, true);
if (!data) {
return;
@@ -16764,6 +16759,8 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
}
str += len;
+ capcol -= len;
+ len = 0;
}
}
}
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index ffe2db9b76..63efee59a8 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -101,6 +101,10 @@ static void close_cb(uv_handle_t *handle)
static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
{
Process *proc = handle->data;
- proc->status = (int)status;
+#if defined(WIN32)
+ // Use stored/expected signal.
+ term_signal = proc->exit_signal;
+#endif
+ proc->status = term_signal ? 128 + term_signal : (int)status;
proc->internal_exit_cb(proc);
}
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 4410deadef..c31ecdaddf 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -159,7 +159,7 @@ void process_close_streams(Process *proc) FUNC_ATTR_NONNULL_ALL
/// 0 for no wait. -1 to wait until the process quits.
/// @return Exit code of the process. proc->status will have the same value.
/// -1 if the timeout expired while the process is still running.
-/// -2 if the user interruped the wait.
+/// -2 if the user interrupted the wait.
int process_wait(Process *proc, int ms, MultiQueue *events)
FUNC_ATTR_NONNULL_ARG(1)
{
@@ -220,6 +220,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
return;
}
proc->stopped_time = os_hrtime();
+ proc->exit_signal = SIGTERM;
switch (proc->type) {
case kProcessTypeUv:
@@ -253,8 +254,10 @@ static void children_kill_cb(uv_timer_t *handle)
}
uint64_t term_sent = UINT64_MAX == proc->stopped_time;
if (kProcessTypePty != proc->type || term_sent) {
+ proc->exit_signal = SIGKILL;
os_proc_tree_kill(proc->pid, SIGKILL);
} else {
+ proc->exit_signal = SIGTERM;
os_proc_tree_kill(proc->pid, SIGTERM);
proc->stopped_time = UINT64_MAX; // Flag: SIGTERM was sent.
// Restart timer.
@@ -403,4 +406,3 @@ static void on_process_stream_close(Stream *stream, void *data)
Process *proc = data;
decref(proc);
}
-
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 13dc3839ce..ef9d953ab7 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -19,6 +19,7 @@ struct process {
Loop *loop;
void *data;
int pid, status, refcount;
+ uint8_t exit_signal; // Signal used when killing (on Windows).
uint64_t stopped_time; // process_stop() timestamp
const char *cwd;
char **argv;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 85952a6cbf..0f345df22b 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4061,10 +4061,9 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep)
return p;
}
-/*
- * Expand file name in Ex command argument.
- * Return FAIL for failure, OK otherwise.
- */
+// Expand file name in Ex command argument.
+// When an error is detected, "errormsgp" is set to a non-NULL pointer.
+// Return FAIL for failure, OK otherwise.
int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
{
int has_wildcards; /* need to expand wildcards */
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 9531c13356..d2620376c6 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -164,22 +164,22 @@ typedef struct AutoPatCmd {
* Structure to pass arguments from buf_write() to buf_write_bytes().
*/
struct bw_info {
- int bw_fd; /* file descriptor */
- char_u *bw_buf; /* buffer with data to be written */
- int bw_len; /* length of data */
+ int bw_fd; // file descriptor
+ char_u *bw_buf; // buffer with data to be written
+ int bw_len; // length of data
#ifdef HAS_BW_FLAGS
- int bw_flags; /* FIO_ flags */
+ int bw_flags; // FIO_ flags
#endif
- char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
- int bw_restlen; /* nr of bytes in bw_rest[] */
- int bw_first; /* first write call */
- char_u *bw_conv_buf; /* buffer for writing converted chars */
- int bw_conv_buflen; /* size of bw_conv_buf */
- int bw_conv_error; /* set for conversion error */
- linenr_T bw_conv_error_lnum; /* first line with error or zero */
- linenr_T bw_start_lnum; /* line number at start of buffer */
-# ifdef USE_ICONV
- iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
+ char_u bw_rest[CONV_RESTLEN]; // not converted bytes
+ int bw_restlen; // nr of bytes in bw_rest[]
+ int bw_first; // first write call
+ char_u *bw_conv_buf; // buffer for writing converted chars
+ int bw_conv_buflen; // size of bw_conv_buf
+ int bw_conv_error; // set for conversion error
+ linenr_T bw_conv_error_lnum; // first line with error or zero
+ linenr_T bw_start_lnum; // line number at start of buffer
+# ifdef HAVE_ICONV
+ iconv_t bw_iconv_fd; // descriptor for iconv() or -1
# endif
};
@@ -328,10 +328,10 @@ readfile(
char_u *fenc_next = NULL; // next item in 'fencs' or NULL
bool advance_fenc = false;
long real_size = 0;
-# ifdef USE_ICONV
- iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
- int did_iconv = FALSE; /* TRUE when iconv() failed and trying
- 'charconvert' next */
+# ifdef HAVE_ICONV
+ iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
+ int did_iconv = false; // TRUE when iconv() failed and trying
+ // 'charconvert' next
# endif
int converted = FALSE; /* TRUE if conversion done */
int notconverted = FALSE; /* TRUE if conversion wanted but it
@@ -842,7 +842,7 @@ retry:
fileformat = EOL_UNKNOWN; /* detect from file */
}
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
/* aborted conversion with iconv(), close the descriptor */
iconv_close(iconv_fd);
@@ -909,15 +909,14 @@ retry:
-# ifdef USE_ICONV
- /*
- * Try using iconv() if we can't convert internally.
- */
+# ifdef HAVE_ICONV
+ // Try using iconv() if we can't convert internally.
if (fio_flags == 0
&& !did_iconv
- )
+ ) {
iconv_fd = (iconv_t)my_iconv_open(
enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
+ }
# endif
/*
@@ -926,12 +925,12 @@ retry:
*/
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
&& !read_fifo
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
&& iconv_fd == (iconv_t)-1
# endif
) {
-# ifdef USE_ICONV
- did_iconv = FALSE;
+# ifdef HAVE_ICONV
+ did_iconv = false;
# endif
/* Skip conversion when it's already done (retry for wrong
* "fileformat"). */
@@ -951,7 +950,7 @@ retry:
}
} else {
if (fio_flags == 0
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
&& iconv_fd == (iconv_t)-1
# endif
) {
@@ -1024,20 +1023,23 @@ retry:
* ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
* multiple of 4 */
real_size = (int)size;
-# ifdef USE_ICONV
- if (iconv_fd != (iconv_t)-1)
+# ifdef HAVE_ICONV
+ if (iconv_fd != (iconv_t)-1) {
size = size / ICONV_MULT;
- else
+ } else {
# endif
- if (fio_flags & FIO_LATIN1)
+ if (fio_flags & FIO_LATIN1) {
size = size / 2;
- else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
+ } else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
size = (size * 2 / 3) & ~1;
- else if (fio_flags & FIO_UCS4)
+ } else if (fio_flags & FIO_UCS4) {
size = (size * 2 / 3) & ~3;
- else if (fio_flags == FIO_UCSBOM)
- size = size / ICONV_MULT; /* worst case */
-
+ } else if (fio_flags == FIO_UCSBOM) {
+ size = size / ICONV_MULT; // worst case
+ }
+# ifdef HAVE_ICONV
+ }
+# endif
if (conv_restlen > 0) {
// Insert unconverted bytes from previous line.
memmove(ptr, conv_rest, conv_restlen); // -V614
@@ -1113,7 +1115,7 @@ retry:
/* When we did a conversion report an error. */
if (fio_flags != 0
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
|| iconv_fd != (iconv_t)-1
# endif
) {
@@ -1136,7 +1138,7 @@ retry:
* leave the UTF8 checking code to do it, as it
* works slightly differently. */
if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
|| iconv_fd != (iconv_t)-1
# endif
)) {
@@ -1145,8 +1147,8 @@ retry:
--conv_restlen;
}
}
- fio_flags = 0; /* don't convert this */
-# ifdef USE_ICONV
+ fio_flags = 0; // don't convert this
+# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
@@ -1217,7 +1219,7 @@ retry:
if (size <= 0)
break;
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
/*
* Attempt conversion of the read bytes to 'encoding' using
@@ -1475,10 +1477,11 @@ retry:
* file is more likely than a conversion error. */
if (can_retry && !incomplete_tail)
break;
-# ifdef USE_ICONV
- /* When we did a conversion report an error. */
- if (iconv_fd != (iconv_t)-1 && conv_error == 0)
+# ifdef HAVE_ICONV
+ // When we did a conversion report an error.
+ if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
conv_error = readfile_linenr(linecnt, ptr, p);
+ }
# endif
/* Remember the first linenr with an illegal byte */
if (conv_error == 0 && illegal_byte == 0)
@@ -1498,15 +1501,18 @@ retry:
if (p < ptr + size && !incomplete_tail) {
/* Detected a UTF-8 error. */
rewind_retry:
- /* Retry reading with another conversion. */
-# ifdef USE_ICONV
- if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
- /* iconv() failed, try 'charconvert' */
- did_iconv = TRUE;
- else
+ // Retry reading with another conversion.
+# ifdef HAVE_ICONV
+ if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
+ // iconv() failed, try 'charconvert'
+ did_iconv = true;
+ } else {
# endif
// use next item from 'fileencodings'
advance_fenc = true;
+# ifdef HAVE_ICONV
+ }
+# endif
file_rewind = true;
goto retry;
}
@@ -1711,7 +1717,7 @@ failed:
}
if (fenc_alloced)
xfree(fenc);
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
# ifndef __clang_analyzer__
@@ -2295,7 +2301,7 @@ buf_write(
write_info.bw_conv_error = FALSE;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
write_info.bw_iconv_fd = (iconv_t)-1;
# endif
@@ -3016,7 +3022,7 @@ nobackup:
if (converted && wb_flags == 0) {
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
// Use iconv() conversion when conversion is needed and it's not done
// internally.
write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
@@ -3046,7 +3052,7 @@ nobackup:
}
}
if (converted && wb_flags == 0
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
# endif
&& wfname == fname
@@ -3574,7 +3580,7 @@ nofail:
xfree(buffer);
xfree(fenc_tofree);
xfree(write_info.bw_conv_buf);
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
if (write_info.bw_iconv_fd != (iconv_t)-1) {
iconv_close(write_info.bw_iconv_fd);
write_info.bw_iconv_fd = (iconv_t)-1;
@@ -3949,7 +3955,7 @@ static int buf_write_bytes(struct bw_info *ip)
}
}
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
if (ip->bw_iconv_fd != (iconv_t)-1) {
const char *from;
size_t fromlen;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 4524c4b2c0..b095e759d9 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -655,16 +655,6 @@ EXTERN int inhibit_delete_count INIT(= 0);
/// Encoding used when 'fencs' is set to "default"
EXTERN char_u *fenc_default INIT(= NULL);
-# if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
-/* Pointers to functions and variables to be loaded at runtime */
-EXTERN size_t (*iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft);
-EXTERN iconv_t (*iconv_open)(const char *tocode, const char *fromcode);
-EXTERN int (*iconv_close)(iconv_t cd);
-EXTERN int (*iconvctl)(iconv_t cd, int request, void *argument);
-EXTERN int* (*iconv_errno)(void);
-# endif
-
/// "State" is the main state of Vim.
/// There are other variables that modify the state:
/// Visual_mode: When State is NORMAL or INSERT.
diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h
index d7234090c4..a7c9ad4040 100644
--- a/src/nvim/iconv.h
+++ b/src/nvim/iconv.h
@@ -1,52 +1,20 @@
#ifndef NVIM_ICONV_H
#define NVIM_ICONV_H
-// iconv can be linked at compile-time as well as loaded at runtime. In the
-// latter case, some function pointers need to be initialized after loading
-// the library (see `iconv_enabled()` in mbyte.c). These function pointers
-// are stored in globals.h. Since globals.h includes iconv.h to get the
-// definition of USE_ICONV, we can't include it from iconv.h. One way to
-// solve this conundrum would be perhaps to let cmake decide the value of
-// USE_ICONV, or to put the USE_ICONV definition in config.h.in directly. As
-// it stands, globals.h needs to be included alongside iconv.h.
-
#include "auto/config.h"
-// Use iconv() when it's available, either by linking to the library at
-// compile time or by loading it at runtime.
-#if (defined(HAVE_ICONV_H) && defined(HAVE_ICONV)) || defined(DYNAMIC_ICONV)
-# define USE_ICONV
-#endif
-
-// If we don't have the actual iconv header files present but USE_ICONV was
-// defined, we provide a type shim (pull in errno.h and define iconv_t).
-// This enables us to still load and use iconv dynamically at runtime.
-#ifdef USE_ICONV
+#ifdef HAVE_ICONV
# include <errno.h>
-# ifdef HAVE_ICONV_H
-# include <iconv.h>
-# else
-typedef void *iconv_t;
-# endif
-#endif
+# include <iconv.h>
// define some missing constants if necessary
-# ifdef USE_ICONV
# ifndef EILSEQ
# define EILSEQ 123
# endif
-# ifdef DYNAMIC_ICONV
-// on win32 iconv.dll is dynamically loaded
-# define ICONV_ERRNO (*iconv_errno())
-# define ICONV_E2BIG 7
-# define ICONV_EINVAL 22
-# define ICONV_EILSEQ 42
-# else
-# define ICONV_ERRNO errno
-# define ICONV_E2BIG E2BIG
-# define ICONV_EINVAL EINVAL
-# define ICONV_EILSEQ EILSEQ
-# endif
-# endif
+# define ICONV_ERRNO errno
+# define ICONV_E2BIG E2BIG
+# define ICONV_EINVAL EINVAL
+# define ICONV_EILSEQ EILSEQ
+#endif
#endif // NVIM_ICONV_H
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 6f1d7996a5..3de1b531e6 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -113,6 +113,65 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
return 1;
}
+/// convert byte index to UTF-32 and UTF-16 indicies
+///
+/// Expects a string and an optional index. If no index is supplied, the length
+/// of the string is returned.
+///
+/// Returns two values: the UTF-32 and UTF-16 indicies.
+static int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
+{
+ size_t s1_len;
+ const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
+ intptr_t idx;
+ if (lua_gettop(lstate) >= 2) {
+ idx = luaL_checkinteger(lstate, 2);
+ if (idx < 0 || idx > (intptr_t)s1_len) {
+ return luaL_error(lstate, "index out of range");
+ }
+ } else {
+ idx = (intptr_t)s1_len;
+ }
+
+ size_t codepoints = 0, codeunits = 0;
+ mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits);
+
+ lua_pushinteger(lstate, (long)codepoints);
+ lua_pushinteger(lstate, (long)codeunits);
+
+ return 2;
+}
+
+/// convert UTF-32 or UTF-16 indicies to byte index.
+///
+/// Expects up to three args: string, index and use_utf16.
+/// If use_utf16 is not supplied it defaults to false (use UTF-32)
+///
+/// Returns the byte index.
+static int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
+{
+ size_t s1_len;
+ const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
+ intptr_t idx = luaL_checkinteger(lstate, 2);
+ if (idx < 0) {
+ return luaL_error(lstate, "index out of range");
+ }
+ bool use_utf16 = false;
+ if (lua_gettop(lstate) >= 3) {
+ use_utf16 = lua_toboolean(lstate, 3);
+ }
+
+ ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len,
+ (size_t)idx, use_utf16);
+ if (byteidx == -1) {
+ return luaL_error(lstate, "index out of range");
+ }
+
+ lua_pushinteger(lstate, (long)byteidx);
+
+ return 1;
+}
+
static void nlua_luv_error_event(void **argv)
{
char *error = (char *)argv[0];
@@ -221,6 +280,12 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
// stricmp
lua_pushcfunction(lstate, &nlua_stricmp);
lua_setfield(lstate, -2, "stricmp");
+ // str_utfindex
+ lua_pushcfunction(lstate, &nlua_str_utfindex);
+ lua_setfield(lstate, -2, "str_utfindex");
+ // str_byteindex
+ lua_pushcfunction(lstate, &nlua_str_byteindex);
+ lua_setfield(lstate, -2, "str_byteindex");
// schedule
lua_pushcfunction(lstate, &nlua_schedule);
lua_setfield(lstate, -2, "schedule");
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 9c342e62c0..6bb3c37b92 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -664,9 +664,6 @@ void getout(int exitval)
ui_call_set_title(cstr_as_string((char *)p_titleold));
}
-#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
- iconv_end();
-#endif
cs_end();
if (garbage_collect_at_exit) {
garbage_collect(false);
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index bf8ce46113..fae7635d34 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1470,6 +1470,31 @@ void mb_utflen(const char_u *s, size_t len, size_t *codepoints,
*codeunits += count + extra;
}
+ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len,
+ size_t index, bool use_utf16_units)
+ FUNC_ATTR_NONNULL_ALL
+{
+ size_t count = 0;
+ size_t clen, i;
+ if (index == 0) {
+ return 0;
+ }
+ for (i = 0; i < len && s[i] != NUL; i += clen) {
+ clen = utf_ptr2len_len(s+i, len-i);
+ // NB: gets the byte value of invalid sequence bytes.
+ // we only care whether the char fits in the BMP or not
+ int c = (clen > 1) ? utf_ptr2char(s+i) : s[i];
+ count++;
+ if (use_utf16_units && c > 0xFFFF) {
+ count++;
+ }
+ if (count >= index) {
+ return i+clen;
+ }
+ }
+ return -1;
+}
+
/*
* Version of strnicmp() that handles multi-byte characters.
@@ -2037,7 +2062,7 @@ enc_locale_copy_enc:
return enc_canonize((char_u *)buf);
}
-# if defined(USE_ICONV)
+# if defined(HAVE_ICONV)
/*
@@ -2058,13 +2083,6 @@ void * my_iconv_open(char_u *to, char_u *from)
if (iconv_working == kBroken)
return (void *)-1; /* detected a broken iconv() previously */
-#ifdef DYNAMIC_ICONV
- // Check if the iconv.dll can be found.
- if (!iconv_enabled(true)) {
- return (void *)-1;
- }
-#endif
-
fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
if (fd != (iconv_t)-1 && iconv_working == kUnknown) {
@@ -2171,152 +2189,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str,
return result;
}
-# if defined(DYNAMIC_ICONV)
-// Dynamically load the "iconv.dll" on Win32.
-
-#ifndef DYNAMIC_ICONV // just generating prototypes
-# define HINSTANCE int
-#endif
-static HINSTANCE hIconvDLL = 0;
-static HINSTANCE hMsvcrtDLL = 0;
-
-# ifndef DYNAMIC_ICONV_DLL
-# define DYNAMIC_ICONV_DLL "iconv.dll"
-# define DYNAMIC_ICONV_DLL_ALT "libiconv-2.dll"
-# endif
-# ifndef DYNAMIC_MSVCRT_DLL
-# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
-# endif
-
-/*
- * Get the address of 'funcname' which is imported by 'hInst' DLL.
- */
-static void * get_iconv_import_func(HINSTANCE hInst,
- const char *funcname)
-{
- PBYTE pImage = (PBYTE)hInst;
- PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst;
- PIMAGE_NT_HEADERS pPE;
- PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
- PIMAGE_THUNK_DATA pIAT; /* Import Address Table */
- PIMAGE_THUNK_DATA pINT; /* Import Name Table */
- PIMAGE_IMPORT_BY_NAME pImpName;
-
- if (pDOS->e_magic != IMAGE_DOS_SIGNATURE)
- return NULL;
- pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew);
- if (pPE->Signature != IMAGE_NT_SIGNATURE)
- return NULL;
- pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage
- + pPE->OptionalHeader.DataDirectory[
- IMAGE_DIRECTORY_ENTRY_IMPORT]
- .VirtualAddress);
- for (; pImpDesc->FirstThunk; ++pImpDesc) {
- if (!pImpDesc->OriginalFirstThunk)
- continue;
- pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk);
- pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk);
- for (; pIAT->u1.Function; ++pIAT, ++pINT) {
- if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal))
- continue;
- pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage
- + (UINT_PTR)(pINT->u1.AddressOfData));
- if (strcmp(pImpName->Name, funcname) == 0)
- return (void *)pIAT->u1.Function;
- }
- }
- return NULL;
-}
-
-// Load library "name".
-HINSTANCE vimLoadLib(char *name)
-{
- HINSTANCE dll = NULL;
-
- // NOTE: Do not use mch_dirname() and mch_chdir() here, they may call
- // vimLoadLib() recursively, which causes a stack overflow.
- wchar_t old_dirw[MAXPATHL];
-
- // Path to exe dir.
- char *buf = xstrdup((char *)get_vim_var_str(VV_PROGPATH));
- // ptrdiff_t len = ;
- // assert(len > 0);
- buf[path_tail_with_sep(buf) - buf] = '\0';
-
- if (GetCurrentDirectoryW(MAXPATHL, old_dirw) != 0) {
- // Change directory to where the executable is, both to make
- // sure we find a .dll there and to avoid looking for a .dll
- // in the current directory.
- SetCurrentDirectory((LPCSTR)buf);
- // TODO(justinmk): use uv_dlopen instead. see os_libcall
- dll = LoadLibrary(name);
- SetCurrentDirectoryW(old_dirw);
- }
-
- return dll;
-}
-
-
-/*
- * Try opening the iconv.dll and return TRUE if iconv() can be used.
- */
-bool iconv_enabled(bool verbose)
-{
- if (hIconvDLL != 0 && hMsvcrtDLL != 0)
- return true;
- hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL);
- if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */
- hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT);
- if (hIconvDLL != 0)
- hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL);
- if (hIconvDLL == 0 || hMsvcrtDLL == 0) {
- /* Only give the message when 'verbose' is set, otherwise it might be
- * done whenever a conversion is attempted. */
- if (verbose && p_verbose > 0) {
- verbose_enter();
- EMSG2(_(e_loadlib),
- hIconvDLL == 0 ? DYNAMIC_ICONV_DLL : DYNAMIC_MSVCRT_DLL);
- verbose_leave();
- }
- iconv_end();
- return false;
- }
-
- iconv = (void *)GetProcAddress(hIconvDLL, "libiconv");
- iconv_open = (void *)GetProcAddress(hIconvDLL, "libiconv_open");
- iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close");
- iconvctl = (void *)GetProcAddress(hIconvDLL, "libiconvctl");
- iconv_errno = get_iconv_import_func(hIconvDLL, "_errno");
- if (iconv_errno == NULL)
- iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno");
- if (iconv == NULL || iconv_open == NULL || iconv_close == NULL
- || iconvctl == NULL || iconv_errno == NULL) {
- iconv_end();
- if (verbose && p_verbose > 0) {
- verbose_enter();
- EMSG2(_(e_loadfunc), "for libiconv");
- verbose_leave();
- }
- return false;
- }
- return true;
-}
-
-void iconv_end(void)
-{
- if (hIconvDLL != 0) {
- // TODO(justinmk): use uv_dlclose instead.
- FreeLibrary(hIconvDLL);
- }
- if (hMsvcrtDLL != 0) {
- FreeLibrary(hMsvcrtDLL);
- }
- hIconvDLL = 0;
- hMsvcrtDLL = 0;
-}
-
-# endif /* DYNAMIC_ICONV */
-# endif /* USE_ICONV */
+# endif // HAVE_ICONV
@@ -2347,10 +2220,11 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
int from_is_utf8;
int to_is_utf8;
- /* Reset to no conversion. */
-# ifdef USE_ICONV
- if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1)
+ // Reset to no conversion.
+# ifdef HAVE_ICONV
+ if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) {
iconv_close(vcp->vc_fd);
+ }
# endif
*vcp = (vimconv_T)MBYTE_NONE_CONV;
@@ -2385,9 +2259,9 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
/* Internal utf-8 -> latin9 conversion. */
vcp->vc_type = CONV_TO_LATIN9;
}
-# ifdef USE_ICONV
- else {
- /* Use iconv() for conversion. */
+# ifdef HAVE_ICONV
+ else { // NOLINT(readability/braces)
+ // Use iconv() for conversion.
vcp->vc_fd = (iconv_t)my_iconv_open(
to_is_utf8 ? (char_u *)"utf-8" : to,
from_is_utf8 ? (char_u *)"utf-8" : from);
@@ -2539,8 +2413,8 @@ char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
*lenp = (size_t)(d - retval);
break;
-# ifdef USE_ICONV
- case CONV_ICONV: /* conversion with vcp->vc_fd */
+# ifdef HAVE_ICONV
+ case CONV_ICONV: // conversion with vcp->vc_fd
retval = iconv_string(vcp, ptr, len, unconvlenp, lenp);
break;
# endif
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index ed48705c6d..536d58be1f 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -63,7 +63,7 @@ typedef enum {
typedef struct {
int vc_type; ///< Zero or more ConvFlags.
int vc_factor; ///< Maximal expansion factor.
-# ifdef USE_ICONV
+# ifdef HAVE_ICONV
iconv_t vc_fd; ///< Value for CONV_ICONV.
# endif
bool vc_fail; ///< What to do with invalid characters: if true, fail,
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index 5fdf0e6181..f0bc13783c 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -288,7 +288,7 @@ static void chld_handler(uv_signal_t *handle, int signum)
if (WIFEXITED(stat)) {
proc->status = WEXITSTATUS(stat);
} else if (WIFSIGNALED(stat)) {
- proc->status = WTERMSIG(stat);
+ proc->status = 128 + WTERMSIG(stat);
}
proc->internal_exit_cb(proc);
}
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index c5f8efadff..290668bca3 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -252,7 +252,7 @@ static void pty_process_finish2(PtyProcess *ptyproc)
DWORD exit_code = 0;
GetExitCodeProcess(ptyproc->process_handle, &exit_code);
- proc->status = (int)exit_code;
+ proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code;
CloseHandle(ptyproc->process_handle);
ptyproc->process_handle = NULL;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 7d46b3b4d5..fe4fdf57ba 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4242,6 +4242,7 @@ static void search_stat(int dirc, pos_T *pos,
// STRNICMP ignores case, but we should not ignore case.
// Unfortunately, there is no STRNICMP function.
if (!(chgtick == buf_get_changedtick(curbuf)
+ && lastpat != NULL // supress clang/NULL passed as nonnull parameter
&& STRNICMP(lastpat, spats[last_idx].pat, STRLEN(lastpat)) == 0
&& STRLEN(lastpat) == STRLEN(spats[last_idx].pat)
&& equalpos(lastpos, curwin->w_cursor)
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 5bf315cdc3..8d800843f8 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1808,9 +1808,11 @@ void count_common_word(slang_T *lp, char_u *word, int len, int count)
char_u buf[MAXWLEN];
char_u *p;
- if (len == -1)
+ if (len == -1) {
p = word;
- else {
+ } else if (len >= MAXWLEN) {
+ return;
+ } else {
STRLCPY(buf, word, len + 1);
p = buf;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index e503efe46e..5aeea3223b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -1307,7 +1307,7 @@ static void refresh_screen(Terminal *term, buf_T *buf)
static void adjust_topline(Terminal *term, buf_T *buf, long added)
{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == buf) {
linenr_T ml_end = buf->b_ml.ml_line_count;
bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end?
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index b3438cc649..230cb72335 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -1,4 +1,5 @@
" Test spell checking
+" Note: this file uses latin1 encoding, but is used with utf-8 encoding.
if !has('spell')
finish
@@ -68,6 +69,47 @@ func Test_z_equal_on_invalid_utf8_word()
bwipe!
endfunc
+" Test spellbadword() with argument
+func Test_spellbadword()
+ set spell
+
+ call assert_equal(['bycycle', 'bad'], spellbadword('My bycycle.'))
+ call assert_equal(['another', 'caps'], spellbadword('A sentence. another sentence'))
+
+ set spelllang=en
+ call assert_equal(['', ''], spellbadword('centre'))
+ call assert_equal(['', ''], spellbadword('center'))
+ set spelllang=en_us
+ call assert_equal(['centre', 'local'], spellbadword('centre'))
+ call assert_equal(['', ''], spellbadword('center'))
+ set spelllang=en_gb
+ call assert_equal(['', ''], spellbadword('centre'))
+ call assert_equal(['center', 'local'], spellbadword('center'))
+
+ " Create a small word list to test that spellbadword('...')
+ " can return ['...', 'rare'].
+ e Xwords
+ insert
+foo
+foobar/?
+.
+ w!
+ mkspell! Xwords.spl Xwords
+ set spelllang=Xwords.spl
+ call assert_equal(['foobar', 'rare'], spellbadword('foo foobar'))
+
+ " Typo should not be detected without the 'spell' option.
+ set spelllang=en_gb nospell
+ call assert_equal(['', ''], spellbadword('centre'))
+ call assert_equal(['', ''], spellbadword('My bycycle.'))
+ call assert_equal(['', ''], spellbadword('A sentence. another sentence'))
+
+ call delete('Xwords.spl')
+ call delete('Xwords')
+ set spelllang&
+ set spell&
+endfunc
+
func Test_spellreall()
new
set spell
@@ -351,6 +393,18 @@ func Test_zeq_crash()
bwipe!
endfunc
+" Check handling a word longer than MAXWLEN.
+func Test_spell_long_word()
+ set enc=utf-8
+ new
+ call setline(1, "d\xCC\xB4\xCC\xBD\xCD\x88\xCD\x94a\xCC\xB5\xCD\x84\xCD\x84\xCC\xA8\xCD\x9Cr\xCC\xB5\xCC\x8E\xCD\x85\xCD\x85k\xCC\xB6\xCC\x89\xCC\x9D \xCC\xB6\xCC\x83\xCC\x8F\xCC\xA4\xCD\x8Ef\xCC\xB7\xCC\x81\xCC\x80\xCC\xA9\xCC\xB0\xCC\xAC\xCC\xA2\xCD\x95\xCD\x87\xCD\x8D\xCC\x9E\xCD\x99\xCC\xAD\xCC\xAB\xCC\x97\xCC\xBBo\xCC\xB6\xCC\x84\xCC\x95\xCC\x8C\xCC\x8B\xCD\x9B\xCD\x9C\xCC\xAFr\xCC\xB7\xCC\x94\xCD\x83\xCD\x97\xCC\x8C\xCC\x82\xCD\x82\xCD\x80\xCD\x91\xCC\x80\xCC\xBE\xCC\x82\xCC\x8F\xCC\xA3\xCD\x85\xCC\xAE\xCD\x8D\xCD\x99\xCC\xBC\xCC\xAB\xCC\xA7\xCD\x88c\xCC\xB7\xCD\x83\xCC\x84\xCD\x92\xCC\x86\xCC\x83\xCC\x88\xCC\x92\xCC\x94\xCC\xBE\xCC\x9D\xCC\xAF\xCC\x98\xCC\x9D\xCC\xBB\xCD\x8E\xCC\xBB\xCC\xB3\xCC\xA3\xCD\x8E\xCD\x99\xCC\xA5\xCC\xAD\xCC\x99\xCC\xB9\xCC\xAE\xCC\xA5\xCC\x9E\xCD\x88\xCC\xAE\xCC\x9E\xCC\xA9\xCC\x97\xCC\xBC\xCC\x99\xCC\xA5\xCD\x87\xCC\x97\xCD\x8E\xCD\x94\xCC\x99\xCC\x9D\xCC\x96\xCD\x94\xCC\xAB\xCC\xA7\xCC\xA5\xCC\x98\xCC\xBB\xCC\xAF\xCC\xABe\xCC\xB7\xCC\x8E\xCC\x82\xCD\x86\xCD\x9B\xCC\x94\xCD\x83\xCC\x85\xCD\x8A\xCD\x8C\xCC\x8B\xCD\x92\xCD\x91\xCC\x8F\xCC\x81\xCD\x95\xCC\xA2\xCC\xB9\xCC\xB2\xCD\x9C\xCC\xB1\xCC\xA6\xCC\xB3\xCC\xAF\xCC\xAE\xCC\x9C\xCD\x99s\xCC\xB8\xCC\x8C\xCC\x8E\xCC\x87\xCD\x81\xCD\x82\xCC\x86\xCD\x8C\xCD\x8C\xCC\x8B\xCC\x84\xCC\x8C\xCD\x84\xCD\x9B\xCD\x86\xCC\x93\xCD\x90\xCC\x85\xCC\x94\xCD\x98\xCD\x84\xCD\x92\xCD\x8B\xCC\x90\xCC\x83\xCC\x8F\xCD\x84\xCD\x81\xCD\x9B\xCC\x90\xCD\x81\xCC\x8F\xCC\xBD\xCC\x88\xCC\xBF\xCC\x88\xCC\x84\xCC\x8E\xCD\x99\xCD\x94\xCC\x99\xCD\x99\xCC\xB0\xCC\xA8\xCC\xA3\xCC\xA8\xCC\x96\xCC\x99\xCC\xAE\xCC\xBC\xCC\x99\xCD\x9A\xCC\xB2\xCC\xB1\xCC\x9F\xCC\xBB\xCC\xA6\xCD\x85\xCC\xAA\xCD\x89\xCC\x9D\xCC\x99\xCD\x96\xCC\xB1\xCC\xB1\xCC\x99\xCC\xA6\xCC\xA5\xCD\x95\xCC\xB2\xCC\xA0\xCD\x99 within")
+ set spell spelllang=en
+ redraw
+ redraw!
+ bwipe!
+ set nospell
+endfunc
+
func LoadAffAndDic(aff_contents, dic_contents)
throw 'skipped: Nvim does not support enc=latin1'
set enc=latin1
diff --git a/src/nvim/version.c b/src/nvim/version.c
index e07865a410..74a4852def 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -52,12 +52,8 @@ static char *features[] = {
"-acl",
#endif
-#if (defined(HAVE_ICONV_H) && defined(USE_ICONV)) || defined(DYNAMIC_ICONV)
-# ifdef DYNAMIC_ICONV
-"+iconv/dyn",
-# else
+#if defined(HAVE_ICONV)
"+iconv",
-# endif
#else
"-iconv",
#endif
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 212b76b5d9..180ed9aa02 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -183,7 +183,7 @@ describe('jobs', function()
)
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
+ eq({'notification', 'exit', {0, 143}}, next_msg())
end)
it('preserves NULs', function()
@@ -217,7 +217,7 @@ describe('jobs', function()
eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
+ eq({'notification', 'exit', {0, 143}}, next_msg())
end)
it('preserves newlines', function()
@@ -234,7 +234,7 @@ describe('jobs', function()
next_msg())
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
+ eq({'notification', 'exit', {0, 143}}, next_msg())
end)
it('avoids sending final newline', function()
@@ -244,7 +244,7 @@ describe('jobs', function()
next_msg())
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, iswin() and 15 or 0}}, next_msg())
+ eq({'notification', 'exit', {0, 143}}, next_msg())
end)
it('closes the job streams with jobclose', function()
@@ -284,18 +284,7 @@ describe('jobs', function()
neq(NIL, meths.get_proc(pid))
nvim('command', 'call jobstop(j)')
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- if iswin() then
- expect_msg_seq(
- -- win64
- { {'notification', 'exit', {0, 1}}
- },
- -- win32
- { {'notification', 'exit', {0, 15}}
- }
- )
- else
- eq({'notification', 'exit', {0, 0}}, next_msg())
- end
+ eq({'notification', 'exit', {0, 143}}, next_msg())
eq(NIL, meths.get_proc(pid))
end)
diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c
index f1357c5dbb..550e5dd997 100644
--- a/test/functional/fixtures/shell-test.c
+++ b/test/functional/fixtures/shell-test.c
@@ -40,6 +40,7 @@ static void help(void)
puts(" 0: foo bar");
puts(" ...");
puts(" 96: foo bar");
+ puts(" shell-test REP_NODELAY N {text}");
puts(" shell-test INTERACT");
puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
}
@@ -66,7 +67,8 @@ int main(int argc, char **argv)
if (argc >= 3) {
fprintf(stderr, "%s\n", argv[2]);
}
- } else if (strcmp(argv[1], "REP") == 0) {
+ } else if (strcmp(argv[1], "REP") == 0 ||
+ strcmp(argv[1], "REP_NODELAY") == 0) {
if (argc != 4) {
fprintf(stderr, "REP expects exactly 3 arguments\n");
return 4;
@@ -76,10 +78,17 @@ int main(int argc, char **argv)
fprintf(stderr, "Invalid count: %s\n", argv[2]);
return 4;
}
- for (int i = 0; i < count; i++) {
- printf("%d: %s\n", i, argv[3]);
- fflush(stdout);
- usleep(1000); // Wait 1 ms (simulate typical output).
+ if (strcmp(argv[1], "REP_NODELAY") == 0) {
+ for (int i = 0; i < count; i++) {
+ printf("%d: %s\n", i, argv[3]);
+ fflush(stdout);
+ }
+ } else {
+ for (int i = 0; i < count; i++) {
+ printf("%d: %s\n", i, argv[3]);
+ fflush(stdout);
+ usleep(1000); // Wait 1 ms (simulate typical output).
+ }
}
} else if (strcmp(argv[1], "UTF-8") == 0) {
// test split-up UTF-8 sequence
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 8223290760..d4ace3030c 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -1,6 +1,7 @@
require('coxpcall')
local luv = require('luv')
local lfs = require('lfs')
+local mpack = require('mpack')
local global_helpers = require('test.helpers')
-- nvim client: Found in .deps/usr/share/lua/<version>/nvim/ if "bundled".
@@ -20,26 +21,32 @@ local sleep = global_helpers.sleep
local tbl_contains = global_helpers.tbl_contains
local write_file = global_helpers.write_file
+local module = {
+ NIL = mpack.NIL,
+ mkdir = lfs.mkdir,
+}
+
local start_dir = lfs.currentdir()
-- XXX: NVIM_PROG takes precedence, QuickBuild sets it.
-local nvim_prog = (
+module.nvim_prog = (
os.getenv('NVIM_PROG')
or os.getenv('NVIM_PRG')
or global_helpers.test_build_dir .. '/bin/nvim'
)
-- Default settings for the test session.
-local nvim_set = 'set shortmess+=IS background=light noswapfile noautoindent'
- ..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
- ..' belloff= wildoptions-=pum noshowcmd noruler nomore'
-local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', nvim_set, '--embed'}
+module.nvim_set = (
+ 'set shortmess+=IS background=light noswapfile noautoindent'
+ ..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
+ ..' belloff= wildoptions-=pum noshowcmd noruler nomore')
+module.nvim_argv = {
+ module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
+ '--cmd', module.nvim_set, '--embed'}
-- Directory containing nvim.
-local nvim_dir = nvim_prog:gsub("[/\\][^/\\]+$", "")
-if nvim_dir == nvim_prog then
- nvim_dir = "."
+module.nvim_dir = module.nvim_prog:gsub("[/\\][^/\\]+$", "")
+if module.nvim_dir == module.nvim_prog then
+ module.nvim_dir = "."
end
-local mpack = require('mpack')
local tmpname = global_helpers.tmpname
local uname = global_helpers.uname
local prepend_argv
@@ -69,26 +76,27 @@ if prepend_argv then
for i = 1, len do
new_nvim_argv[i] = prepend_argv[i]
end
- for i = 1, #nvim_argv do
- new_nvim_argv[i + len] = nvim_argv[i]
+ for i = 1, #module.nvim_argv do
+ new_nvim_argv[i + len] = module.nvim_argv[i]
end
- nvim_argv = new_nvim_argv
+ module.nvim_argv = new_nvim_argv
+ module.prepend_argv = prepend_argv
end
local session, loop_running, last_error, method_error
-local function get_session()
+function module.get_session()
return session
end
-local function set_session(s, keep)
+function module.set_session(s, keep)
if session and not keep then
session:close()
end
session = s
end
-local function request(method, ...)
+function module.request(method, ...)
local status, rv = session:request(method, ...)
if not status then
if loop_running then
@@ -101,14 +109,14 @@ local function request(method, ...)
return rv
end
-local function next_msg(timeout)
+function module.next_msg(timeout)
return session:next_message(timeout and timeout or 10000)
end
-local function expect_twostreams(msgs1, msgs2)
+function module.expect_twostreams(msgs1, msgs2)
local pos1, pos2 = 1, 1
while pos1 <= #msgs1 or pos2 <= #msgs2 do
- local msg = next_msg()
+ local msg = module.next_msg()
if pos1 <= #msgs1 and pcall(eq, msgs1[pos1], msg) then
pos1 = pos1 + 1
elseif pos2 <= #msgs2 then
@@ -131,7 +139,7 @@ end
--
-- ignore: List of ignored event names.
-- seqs: List of one or more potential event sequences.
-local function expect_msg_seq(...)
+function module.expect_msg_seq(...)
if select('#', ...) < 1 then
error('need at least 1 argument')
end
@@ -157,11 +165,12 @@ local function expect_msg_seq(...)
end
return string.format('%s\n%s\n%s', err1, string.rep('=', 78), err2)
end
+ local msg_timeout = module.load_adjust(10000) -- Big timeout for ASAN/valgrind.
for anum = 1, #seqs do
local expected_seq = seqs[anum]
-- Collect enough messages to compare the next expected sequence.
while #actual_seq < #expected_seq do
- local msg = next_msg(10000) -- Big timeout for ASAN/valgrind.
+ local msg = module.next_msg(msg_timeout)
local msg_type = msg and msg[2] or nil
if msg == nil then
error(cat_err(final_error,
@@ -192,11 +201,11 @@ local function call_and_stop_on_error(lsession, ...)
return result
end
-local function set_method_error(err)
+function module.set_method_error(err)
method_error = err
end
-local function run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
+function module.run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
local on_request, on_notification, on_setup
if request_cb then
@@ -232,43 +241,43 @@ local function run_session(lsession, request_cb, notification_cb, setup_cb, time
end
end
-local function run(request_cb, notification_cb, setup_cb, timeout)
- run_session(session, request_cb, notification_cb, setup_cb, timeout)
+function module.run(request_cb, notification_cb, setup_cb, timeout)
+ module.run_session(session, request_cb, notification_cb, setup_cb, timeout)
end
-local function stop()
+function module.stop()
session:stop()
end
-local function nvim_prog_abs()
+function module.nvim_prog_abs()
-- system(['build/bin/nvim']) does not work for whatever reason. It must
-- be executable searched in $PATH or something starting with / or ./.
- if nvim_prog:match('[/\\]') then
- return request('nvim_call_function', 'fnamemodify', {nvim_prog, ':p'})
+ if module.nvim_prog:match('[/\\]') then
+ return module.request('nvim_call_function', 'fnamemodify', {module.nvim_prog, ':p'})
else
- return nvim_prog
+ return module.nvim_prog
end
end
-- Executes an ex-command. VimL errors manifest as client (lua) errors, but
-- v:errmsg will not be updated.
-local function nvim_command(cmd)
- request('nvim_command', cmd)
+function module.command(cmd)
+ module.request('nvim_command', cmd)
end
-- Evaluates a VimL expression.
-- Fails on VimL error, but does not update v:errmsg.
-local function nvim_eval(expr)
- return request('nvim_eval', expr)
+function module.eval(expr)
+ return module.request('nvim_eval', expr)
end
-local os_name = (function()
+module.os_name = (function()
local name = nil
return (function()
if not name then
- if nvim_eval('has("win32")') == 1 then
+ if module.eval('has("win32")') == 1 then
name = 'windows'
- elseif nvim_eval('has("macunix")') == 1 then
+ elseif module.eval('has("macunix")') == 1 then
name = 'osx'
else
name = 'unix'
@@ -278,38 +287,38 @@ local os_name = (function()
end)
end)()
-local function iswin()
+function module.iswin()
return package.config:sub(1,1) == '\\'
end
-- Executes a VimL function.
-- Fails on VimL error, but does not update v:errmsg.
-local function nvim_call(name, ...)
- return request('nvim_call_function', name, {...})
+function module.call(name, ...)
+ return module.request('nvim_call_function', name, {...})
end
-- Sends user input to Nvim.
-- Does not fail on VimL error, but v:errmsg will be updated.
local function nvim_feed(input)
while #input > 0 do
- local written = request('nvim_input', input)
+ local written = module.request('nvim_input', input)
input = input:sub(written + 1)
end
end
-local function feed(...)
+function module.feed(...)
for _, v in ipairs({...}) do
nvim_feed(dedent(v))
end
end
-local function rawfeed(...)
+function module.rawfeed(...)
for _, v in ipairs({...}) do
nvim_feed(dedent(v))
end
end
-local function merge_args(...)
+function module.merge_args(...)
local i = 1
local argv = {}
for anum = 1,select('#', ...) do
@@ -361,15 +370,15 @@ local function remove_args(args, args_rm)
return new_args
end
-local function spawn(argv, merge, env)
+function module.spawn(argv, merge, env)
local child_stream = ChildProcessStream.spawn(
- merge and merge_args(prepend_argv, argv) or argv,
+ merge and module.merge_args(prepend_argv, argv) or argv,
env)
return Session.new(child_stream)
end
-- Creates a new Session connected by domain socket (named pipe) or TCP.
-local function connect(file_or_address)
+function module.connect(file_or_address)
local addr, port = string.match(file_or_address, "(.*):(%d+)")
local stream = (addr and port) and TcpStream.open(addr, port) or
SocketStream.open(file_or_address)
@@ -378,7 +387,7 @@ end
-- Calls fn() until it succeeds, up to `max` times or until `max_ms`
-- milliseconds have passed.
-local function retry(max, max_ms, fn)
+function module.retry(max, max_ms, fn)
assert(max == nil or max > 0)
assert(max_ms == nil or max_ms > 0)
local tries = 1
@@ -410,8 +419,16 @@ end
-- Example:
-- clear('-e')
-- clear{args={'-e'}, args_rm={'-i'}, env={TERM=term}}
-local function clear(...)
- local args = {unpack(nvim_argv)}
+function module.clear(...)
+ local argv, env = module.new_argv(...)
+ module.set_session(module.spawn(argv, nil, env))
+end
+
+-- Builds an argument list for use in clear().
+--
+--@see clear() for parameters.
+function module.new_argv(...)
+ local args = {unpack(module.nvim_argv)}
table.insert(args, '--headless')
local new_args
local env = nil
@@ -450,21 +467,21 @@ local function clear(...)
for _, arg in ipairs(new_args) do
table.insert(args, arg)
end
- set_session(spawn(args, nil, env))
+ return args, env
end
-local function insert(...)
+function module.insert(...)
nvim_feed('i')
for _, v in ipairs({...}) do
local escaped = v:gsub('<', '<lt>')
- rawfeed(escaped)
+ module.rawfeed(escaped)
end
nvim_feed('<ESC>')
end
-- Executes an ex-command by user input. Because nvim_input() is used, VimL
-- errors will not manifest as client (lua) errors. Use command() for that.
-local function feed_command(...)
+function module.feed_command(...)
for _, v in ipairs({...}) do
if v:sub(1, 1) ~= '/' then
-- not a search command, prefix with colon
@@ -476,10 +493,10 @@ local function feed_command(...)
end
local sourced_fnames = {}
-local function source(code)
+function module.source(code)
local fname = tmpname()
write_file(fname, code)
- nvim_command('source '..fname)
+ module.command('source '..fname)
-- DO NOT REMOVE FILE HERE.
-- do_source() has a habit of checking whether files are “same” by using inode
-- and device IDs. If you run two source() calls in quick succession there is
@@ -495,76 +512,76 @@ local function source(code)
return fname
end
-local function set_shell_powershell()
- source([[
+function module.set_shell_powershell()
+ module.source([[
set shell=powershell shellquote=( shellpipe=\| shellredir=> shellxquote=
let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command Remove-Item -Force alias:sleep; Remove-Item -Force alias:cat;'
]])
end
-local function nvim(method, ...)
- return request('nvim_'..method, ...)
+function module.nvim(method, ...)
+ return module.request('nvim_'..method, ...)
end
local function ui(method, ...)
- return request('nvim_ui_'..method, ...)
+ return module.request('nvim_ui_'..method, ...)
end
-local function nvim_async(method, ...)
+function module.nvim_async(method, ...)
session:notify('nvim_'..method, ...)
end
-local function buffer(method, ...)
- return request('nvim_buf_'..method, ...)
+function module.buffer(method, ...)
+ return module.request('nvim_buf_'..method, ...)
end
-local function window(method, ...)
- return request('nvim_win_'..method, ...)
+function module.window(method, ...)
+ return module.request('nvim_win_'..method, ...)
end
-local function tabpage(method, ...)
- return request('nvim_tabpage_'..method, ...)
+function module.tabpage(method, ...)
+ return module.request('nvim_tabpage_'..method, ...)
end
-local function curbuf(method, ...)
+function module.curbuf(method, ...)
if not method then
- return nvim('get_current_buf')
+ return module.nvim('get_current_buf')
end
- return buffer(method, 0, ...)
+ return module.buffer(method, 0, ...)
end
-local function wait()
+function module.wait()
-- Execute 'nvim_eval' (a deferred function) to block
-- until all pending input is processed.
session:request('nvim_eval', '1')
end
-local function curbuf_contents()
- wait() -- Before inspecting the buffer, process all input.
- return table.concat(curbuf('get_lines', 0, -1, true), '\n')
+function module.curbuf_contents()
+ module.wait() -- Before inspecting the buffer, process all input.
+ return table.concat(module.curbuf('get_lines', 0, -1, true), '\n')
end
-local function curwin(method, ...)
+function module.curwin(method, ...)
if not method then
- return nvim('get_current_win')
+ return module.nvim('get_current_win')
end
- return window(method, 0, ...)
+ return module.window(method, 0, ...)
end
-local function curtab(method, ...)
+function module.curtab(method, ...)
if not method then
- return nvim('get_current_tabpage')
+ return module.nvim('get_current_tabpage')
end
- return tabpage(method, 0, ...)
+ return module.tabpage(method, 0, ...)
end
-local function expect(contents)
- return eq(dedent(contents), curbuf_contents())
+function module.expect(contents)
+ return eq(dedent(contents), module.curbuf_contents())
end
-local function expect_any(contents)
+function module.expect_any(contents)
contents = dedent(contents)
- return ok(nil ~= string.find(curbuf_contents(), contents, 1, true))
+ return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true))
end
local function do_rmdir(path)
@@ -584,8 +601,8 @@ local function do_rmdir(path)
else
-- Try Nvim delete(): it handles `readonly` attribute on Windows,
-- and avoids Lua cross-version/platform incompatibilities.
- if -1 == nvim_call('delete', abspath) then
- local hint = (os_name() == 'windows'
+ if -1 == module.call('delete', abspath) then
+ local hint = (module.os_name() == 'windows'
and ' (hint: try :%bwipeout! before rmdir())' or '')
error('delete() failed'..hint..': '..abspath)
end
@@ -600,12 +617,12 @@ local function do_rmdir(path)
end
end
-local function rmdir(path)
+function module.rmdir(path)
local ret, _ = pcall(do_rmdir, path)
- if not ret and os_name() == "windows" then
+ if not ret and module.os_name() == "windows" then
-- Maybe "Permission denied"; try again after changing the nvim
-- process to the top-level directory.
- nvim_command([[exe 'cd '.fnameescape(']]..start_dir.."')")
+ module.command([[exe 'cd '.fnameescape(']]..start_dir.."')")
ret, _ = pcall(do_rmdir, path)
end
-- During teardown, the nvim process may not exit quickly enough, then rmdir()
@@ -616,20 +633,20 @@ local function rmdir(path)
end
end
-local exc_exec = function(cmd)
- nvim_command(([[
+function module.exc_exec(cmd)
+ module.command(([[
try
execute "%s"
catch
let g:__exception = v:exception
endtry
]]):format(cmd:gsub('\n', '\\n'):gsub('[\\"]', '\\%0')))
- local ret = nvim_eval('get(g:, "__exception", 0)')
- nvim_command('unlet! g:__exception')
+ local ret = module.eval('get(g:, "__exception", 0)')
+ module.command('unlet! g:__exception')
return ret
end
-local function create_callindex(func)
+function module.create_callindex(func)
local table = {}
setmetatable(table, {
__index = function(tbl, arg1)
@@ -643,7 +660,7 @@ end
-- Helper to skip tests. Returns true in Windows systems.
-- pending_fn is pending() from busted
-local function pending_win32(pending_fn)
+function module.pending_win32(pending_fn)
if uname() == 'Windows' then
if pending_fn ~= nil then
pending_fn('FIXME: Windows', function() end)
@@ -656,7 +673,7 @@ end
-- Calls pending() and returns `true` if the system is too slow to
-- run fragile or expensive tests. Else returns `false`.
-local function skip_fragile(pending_fn, cond)
+function module.skip_fragile(pending_fn, cond)
if pending_fn == nil or type(pending_fn) ~= type(function()end) then
error("invalid pending_fn")
end
@@ -670,7 +687,7 @@ local function skip_fragile(pending_fn, cond)
return false
end
-local function meth_pcall(...)
+function module.meth_pcall(...)
local ret = {pcall(...)}
if type(ret[2]) == 'string' then
ret[2] = ret[2]:gsub('^[^:]+:%d+: ', '')
@@ -678,66 +695,66 @@ local function meth_pcall(...)
return ret
end
-local funcs = create_callindex(nvim_call)
-local meths = create_callindex(nvim)
-local uimeths = create_callindex(ui)
-local bufmeths = create_callindex(buffer)
-local winmeths = create_callindex(window)
-local tabmeths = create_callindex(tabpage)
-local curbufmeths = create_callindex(curbuf)
-local curwinmeths = create_callindex(curwin)
-local curtabmeths = create_callindex(curtab)
+module.funcs = module.create_callindex(module.call)
+module.meths = module.create_callindex(module.nvim)
+module.uimeths = module.create_callindex(ui)
+module.bufmeths = module.create_callindex(module.buffer)
+module.winmeths = module.create_callindex(module.window)
+module.tabmeths = module.create_callindex(module.tabpage)
+module.curbufmeths = module.create_callindex(module.curbuf)
+module.curwinmeths = module.create_callindex(module.curwin)
+module.curtabmeths = module.create_callindex(module.curtab)
-local function exec_lua(code, ...)
- return meths.execute_lua(code, {...})
+function module.exec_lua(code, ...)
+ return module.meths.execute_lua(code, {...})
end
-local function redir_exec(cmd)
- meths.set_var('__redir_exec_cmd', cmd)
- nvim_command([[
+function module.redir_exec(cmd)
+ module.meths.set_var('__redir_exec_cmd', cmd)
+ module.command([[
redir => g:__redir_exec_output
silent! execute g:__redir_exec_cmd
redir END
]])
- local ret = meths.get_var('__redir_exec_output')
- meths.del_var('__redir_exec_output')
- meths.del_var('__redir_exec_cmd')
+ local ret = module.meths.get_var('__redir_exec_output')
+ module.meths.del_var('__redir_exec_output')
+ module.meths.del_var('__redir_exec_cmd')
return ret
end
-local function get_pathsep()
- return iswin() and '\\' or '/'
+function module.get_pathsep()
+ return module.iswin() and '\\' or '/'
end
-local function pathroot()
+function module.pathroot()
local pathsep = package.config:sub(1,1)
- return iswin() and (nvim_dir:sub(1,2)..pathsep) or '/'
+ return module.iswin() and (module.nvim_dir:sub(1,2)..pathsep) or '/'
end
-- Returns a valid, platform-independent $NVIM_LISTEN_ADDRESS.
-- Useful for communicating with child instances.
-local function new_pipename()
+function module.new_pipename()
-- HACK: Start a server temporarily, get the name, then stop it.
- local pipename = nvim_eval('serverstart()')
- funcs.serverstop(pipename)
+ local pipename = module.eval('serverstart()')
+ module.funcs.serverstop(pipename)
return pipename
end
-local function missing_provider(provider)
+function module.missing_provider(provider)
if provider == 'ruby' or provider == 'node' then
- local prog = funcs['provider#' .. provider .. '#Detect']()
+ local prog = module.funcs['provider#' .. provider .. '#Detect']()
return prog == '' and (provider .. ' not detected') or false
elseif provider == 'python' or provider == 'python3' then
local py_major_version = (provider == 'python3' and 3 or 2)
- local errors = funcs['provider#pythonx#Detect'](py_major_version)[2]
+ local errors = module.funcs['provider#pythonx#Detect'](py_major_version)[2]
return errors ~= '' and errors or false
else
assert(false, 'Unknown provider: ' .. provider)
end
end
-local function alter_slashes(obj)
- if not iswin() then
+function module.alter_slashes(obj)
+ if not module.iswin() then
return obj
end
if type(obj) == 'string' then
@@ -746,7 +763,7 @@ local function alter_slashes(obj)
elseif type(obj) == 'table' then
local ret = {}
for k, v in pairs(obj) do
- ret[k] = alter_slashes(v)
+ ret[k] = module.alter_slashes(v)
end
return ret
else
@@ -754,23 +771,23 @@ local function alter_slashes(obj)
end
end
-
-local load_factor = nil
-local function load_adjust(num)
- if load_factor == nil then -- Compute load factor only once.
- clear()
- request('nvim_command', 'source src/nvim/testdir/load.vim')
- load_factor = request('nvim_eval', 'g:test_load_factor')
- end
+local load_factor = 1
+if global_helpers.isCI() then
+ -- Compute load factor only once (but outside of any tests).
+ module.clear()
+ module.request('nvim_command', 'source src/nvim/testdir/load.vim')
+ load_factor = module.request('nvim_eval', 'g:test_load_factor')
+end
+function module.load_adjust(num)
return math.ceil(num * load_factor)
end
-local function parse_context(ctx)
+function module.parse_context(ctx)
local parsed = {}
for _, item in ipairs({'regs', 'jumps', 'buflist', 'gvars'}) do
parsed[item] = filter(function(v)
return type(v) == 'table'
- end, nvim_call('msgpackparse', ctx[item]))
+ end, module.call('msgpackparse', ctx[item]))
end
parsed['buflist'] = parsed['buflist'][1]
return map(function(v)
@@ -781,78 +798,6 @@ local function parse_context(ctx)
end, parsed)
end
-local module = {
- NIL = mpack.NIL,
- alter_slashes = alter_slashes,
- buffer = buffer,
- bufmeths = bufmeths,
- call = nvim_call,
- create_callindex = create_callindex,
- clear = clear,
- command = nvim_command,
- connect = connect,
- curbuf = curbuf,
- curbuf_contents = curbuf_contents,
- curbufmeths = curbufmeths,
- curtab = curtab,
- curtabmeths = curtabmeths,
- curwin = curwin,
- curwinmeths = curwinmeths,
- eval = nvim_eval,
- exc_exec = exc_exec,
- exec_lua = exec_lua,
- expect = expect,
- expect_any = expect_any,
- expect_msg_seq = expect_msg_seq,
- expect_twostreams = expect_twostreams,
- feed = feed,
- feed_command = feed_command,
- funcs = funcs,
- get_pathsep = get_pathsep,
- get_session = get_session,
- insert = insert,
- iswin = iswin,
- merge_args = merge_args,
- meth_pcall = meth_pcall,
- meths = meths,
- missing_provider = missing_provider,
- mkdir = lfs.mkdir,
- load_adjust = load_adjust,
- new_pipename = new_pipename,
- next_msg = next_msg,
- nvim = nvim,
- nvim_argv = nvim_argv,
- nvim_async = nvim_async,
- nvim_dir = nvim_dir,
- nvim_prog = nvim_prog,
- nvim_prog_abs = nvim_prog_abs,
- nvim_set = nvim_set,
- os_name = os_name,
- parse_context = parse_context,
- pathroot = pathroot,
- pending_win32 = pending_win32,
- prepend_argv = prepend_argv,
- rawfeed = rawfeed,
- redir_exec = redir_exec,
- request = request,
- retry = retry,
- rmdir = rmdir,
- run = run,
- run_session = run_session,
- set_session = set_session,
- set_method_error = set_method_error,
- set_shell_powershell = set_shell_powershell,
- skip_fragile = skip_fragile,
- source = source,
- spawn = spawn,
- stop = stop,
- tabmeths = tabmeths,
- tabpage = tabpage,
- uimeths = uimeths,
- wait = wait,
- window = window,
- winmeths = winmeths,
-}
module = global_helpers.tbl_extend('error', module, global_helpers)
return function(after_each)
diff --git a/test/functional/lua/utility_functions_spec.lua b/test/functional/lua/utility_functions_spec.lua
index 780d3a1565..0d93914119 100644
--- a/test/functional/lua/utility_functions_spec.lua
+++ b/test/functional/lua/utility_functions_spec.lua
@@ -2,12 +2,12 @@
local helpers = require('test.functional.helpers')(after_each)
local funcs = helpers.funcs
-local meths = helpers.meths
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
local meth_pcall = helpers.meth_pcall
+local exec_lua = helpers.exec_lua
before_each(clear)
@@ -110,28 +110,53 @@ describe('lua function', function()
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
end)
+ it("vim.str_utfindex/str_byteindex", function()
+ exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
+ local indicies32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48}
+ local indicies16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48}
+ for i,k in pairs(indicies32) do
+ eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ...)", i), i)
+ end
+ for i,k in pairs(indicies16) do
+ eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ..., true)", i), i)
+ end
+ local i32, i16 = 0, 0
+ for k = 0,48 do
+ if indicies32[i32] < k then
+ i32 = i32 + 1
+ end
+ if indicies16[i16] < k then
+ i16 = i16 + 1
+ if indicies16[i16+1] == indicies16[i16] then
+ i16 = i16 + 1
+ end
+ end
+ eq({i32, i16}, exec_lua("return {vim.str_utfindex(_G.test_text, ...)}", k), k)
+ end
+ end)
+
it("vim.schedule", function()
- meths.execute_lua([[
+ exec_lua([[
test_table = {}
vim.schedule(function()
table.insert(test_table, "xx")
end)
table.insert(test_table, "yy")
- ]], {})
- eq({"yy","xx"}, meths.execute_lua("return test_table", {}))
+ ]])
+ eq({"yy","xx"}, exec_lua("return test_table"))
-- type checked args
eq({false, 'Error executing lua: vim.schedule: expected function'},
- meth_pcall(meths.execute_lua, "vim.schedule('stringly')", {}))
+ meth_pcall(exec_lua, "vim.schedule('stringly')"))
eq({false, 'Error executing lua: vim.schedule: expected function'},
- meth_pcall(meths.execute_lua, "vim.schedule()", {}))
+ meth_pcall(exec_lua, "vim.schedule()"))
- meths.execute_lua([[
+ exec_lua([[
vim.schedule(function()
error("big failure\nvery async")
end)
- ]], {})
+ ]])
feed("<cr>")
eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', eval("v:errmsg"))
@@ -139,7 +164,7 @@ describe('lua function', function()
it("vim.split", function()
local split = function(str, sep)
- return meths.execute_lua('return vim.split(...)', {str, sep})
+ return exec_lua('return vim.split(...)', str, sep)
end
local tests = {
@@ -172,7 +197,7 @@ describe('lua function', function()
it('vim.trim', function()
local trim = function(s)
- return meths.execute_lua('return vim.trim(...)', { s })
+ return exec_lua('return vim.trim(...)', s)
end
local trims = {
@@ -194,7 +219,7 @@ describe('lua function', function()
it('vim.inspect', function()
-- just make sure it basically works, it has its own test suite
local inspect = function(t, opts)
- return meths.execute_lua('return vim.inspect(...)', { t, opts })
+ return exec_lua('return vim.inspect(...)', t, opts)
end
eq('2', inspect(2))
@@ -202,18 +227,18 @@ describe('lua function', function()
inspect({ a = { b = 1 } }, { newline = '+', indent = '' }))
-- special value vim.inspect.KEY works
- eq('{ KEY_a = "x", KEY_b = "y"}', meths.execute_lua([[
+ eq('{ KEY_a = "x", KEY_b = "y"}', exec_lua([[
return vim.inspect({a="x", b="y"}, {newline = '', process = function(item, path)
if path[#path] == vim.inspect.KEY then
return 'KEY_'..item
end
return item
end})
- ]], {}))
+ ]]))
end)
it("vim.deepcopy", function()
- local is_dc = meths.execute_lua([[
+ local is_dc = exec_lua([[
local a = { x = { 1, 2 }, y = 5}
local b = vim.deepcopy(a)
@@ -222,7 +247,7 @@ describe('lua function', function()
return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and count == 2
and tostring(a) ~= tostring(b)
- ]], {})
+ ]])
assert(is_dc)
end)
diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua
index a4746c2205..04c9c01d7c 100644
--- a/test/functional/shada/buffers_spec.lua
+++ b/test/functional/shada/buffers_spec.lua
@@ -1,26 +1,22 @@
--- ShaDa buffer list saving/reading support
+-- shada buffer list saving/reading support
local helpers = require('test.functional.helpers')(after_each)
local nvim_command, funcs, eq, curbufmeths =
helpers.command, helpers.funcs, helpers.eq, helpers.curbufmeths
local shada_helpers = require('test.functional.shada.helpers')
-local reset, set_additional_cmd, clear =
- shada_helpers.reset, shada_helpers.set_additional_cmd,
- shada_helpers.clear
+local reset, clear = shada_helpers.reset, shada_helpers.clear
-describe('ShaDa support code', function()
+describe('shada support code', function()
local testfilename = 'Xtestfile-functional-shada-buffers'
local testfilename_2 = 'Xtestfile-functional-shada-buffers-2'
- before_each(reset)
after_each(clear)
it('is able to dump and restore buffer list', function()
- set_additional_cmd('set shada+=%')
- reset()
+ reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
nvim_command('qall')
- reset()
+ reset('set shada+=%')
eq(3, funcs.bufnr('$'))
eq('', funcs.bufname(1))
eq(testfilename, funcs.bufname(2))
@@ -28,11 +24,9 @@ describe('ShaDa support code', function()
end)
it('does not restore buffer list without % in &shada', function()
- set_additional_cmd('set shada+=%')
- reset()
+ reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- set_additional_cmd('')
nvim_command('qall')
reset()
eq(1, funcs.bufnr('$'))
@@ -40,61 +34,57 @@ describe('ShaDa support code', function()
end)
it('does not dump buffer list without % in &shada', function()
+ reset()
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- set_additional_cmd('set shada+=%')
nvim_command('qall')
- reset()
+ reset('set shada+=%')
eq(1, funcs.bufnr('$'))
eq('', funcs.bufname(1))
end)
it('does not dump unlisted buffer', function()
- set_additional_cmd('set shada+=%')
- reset()
+ reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
curbufmeths.set_option('buflisted', false)
nvim_command('qall')
- reset()
+ reset('set shada+=%')
eq(2, funcs.bufnr('$'))
eq('', funcs.bufname(1))
eq(testfilename, funcs.bufname(2))
end)
it('does not dump quickfix buffer', function()
- set_additional_cmd('set shada+=%')
- reset()
+ reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
curbufmeths.set_option('buftype', 'quickfix')
nvim_command('qall')
- reset()
+ reset('set shada+=%')
eq(2, funcs.bufnr('$'))
eq('', funcs.bufname(1))
eq(testfilename, funcs.bufname(2))
end)
it('does not dump unnamed buffers', function()
- set_additional_cmd('set shada+=% hidden')
- reset()
+ reset('set shada+=% hidden')
curbufmeths.set_lines(0, 1, true, {'foo'})
nvim_command('enew')
curbufmeths.set_lines(0, 1, true, {'bar'})
eq(2, funcs.bufnr('$'))
nvim_command('qall!')
- reset()
+ reset('set shada+=% hidden')
eq(1, funcs.bufnr('$'))
eq('', funcs.bufname(1))
end)
it('restores 1 buffer with %1 in &shada, #5759', function()
- set_additional_cmd('set shada+=%1')
- reset()
+ reset('set shada+=%1')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
nvim_command('qall')
- reset()
+ reset('set shada+=%1')
eq(2, funcs.bufnr('$'))
eq('', funcs.bufname(1))
eq(testfilename, funcs.bufname(2))
diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/helpers.lua
index d5e061bb50..fb3ec4a87c 100644
--- a/test/functional/shada/helpers.lua
+++ b/test/functional/shada/helpers.lua
@@ -1,47 +1,39 @@
local helpers = require('test.functional.helpers')(nil)
-local spawn, set_session, meths, nvim_prog =
- helpers.spawn, helpers.set_session, helpers.meths, helpers.nvim_prog
-local write_file, merge_args = helpers.write_file, helpers.merge_args
+local meths = helpers.meths
+local write_file = helpers.write_file
+local concat_tables = helpers.concat_tables
local mpack = require('mpack')
local tmpname = helpers.tmpname()
-local append_argv = nil
-local function nvim_argv(shada_file, embed)
- if embed == nil then
- embed = true
+-- o={
+-- args=…,
+-- args_rm=…,
+-- shadafile=…,
+-- }
+local function reset(o)
+ assert(o == nil or type(o) == 'table' or type(o) == 'string')
+ o = o and o or {}
+ local args_rm = o.args_rm or {}
+ table.insert(args_rm, '-i')
+ local args={
+ '-i', o.shadafile or tmpname,
+ }
+ if type(o) == 'string' then
+ args = concat_tables(args, {'--cmd', o})
+ elseif o.args then
+ args = concat_tables(args, o.args)
end
- local argv = {nvim_prog, '-u', 'NONE', '-i', shada_file or tmpname, '-N',
- '--cmd', 'set shortmess+=I background=light noswapfile',
- '--headless', embed and '--embed' or nil}
- if helpers.prepend_argv or append_argv then
- return merge_args(helpers.prepend_argv, argv, append_argv)
- else
- return argv
- end
-end
-
-local reset = function(shada_file)
- set_session(spawn(nvim_argv(shada_file)))
+ helpers.clear{
+ args_rm=args_rm,
+ args=args,
+ }
meths.set_var('tmpname', tmpname)
end
-local set_additional_cmd = function(s)
- append_argv = {'--cmd', s}
-end
-
-local function add_argv(...)
- if select('#', ...) == 0 then
- append_argv = nil
- else
- append_argv = {...}
- end
-end
-
local clear = function()
os.remove(tmpname)
- append_argv = nil
end
local get_shada_rw = function(fname)
@@ -89,10 +81,7 @@ end
return {
reset=reset,
- set_additional_cmd=set_additional_cmd,
- add_argv=add_argv,
clear=clear,
get_shada_rw=get_shada_rw,
read_shada_file=read_shada_file,
- nvim_argv=nvim_argv,
}
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index e6450e68b3..e319fd9e6b 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -6,11 +6,7 @@ local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq =
local exc_exec, redir_exec = helpers.exc_exec, helpers.redir_exec
local shada_helpers = require('test.functional.shada.helpers')
-local reset, set_additional_cmd, clear =
- shada_helpers.reset, shada_helpers.set_additional_cmd,
- shada_helpers.clear
-local add_argv = shada_helpers.add_argv
-local nvim_argv = shada_helpers.nvim_argv
+local reset, clear = shada_helpers.reset, shada_helpers.clear
local nvim_current_line = function()
return curwinmeths.get_cursor()[1]
@@ -71,8 +67,7 @@ describe('ShaDa support code', function()
nvim_command('2')
nvim_command('kB')
nvim_command('wshada')
- set_additional_cmd('set shada=\'0,f0')
- reset()
+ reset('set shada=\'0,f0')
nvim_command('language C')
nvim_command('normal! `A')
eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
@@ -223,17 +218,32 @@ describe('ShaDa support code', function()
-- during -c used to add item with zero lnum to jump list.
it('does not create incorrect file for non-existent buffers when writing from -c',
function()
- add_argv('--cmd', 'silent edit ' .. non_existent_testfilename, '-c', 'qall')
- local argv = nvim_argv(nil, false) -- no --embed
+ local argv = helpers.new_argv{
+ args_rm={
+ '-i',
+ '--embed', -- no --embed
+ },
+ args={
+ '-i', meths.get_var('tmpname'), -- Use same shada file as parent.
+ '--cmd', 'silent edit '..non_existent_testfilename,
+ '-c', 'qall'},
+ }
eq('', funcs.system(argv))
eq(0, exc_exec('rshada'))
end)
it('does not create incorrect file for non-existent buffers opened from -c',
function()
- add_argv('-c', 'silent edit ' .. non_existent_testfilename,
- '-c', 'autocmd VimEnter * qall')
- local argv = nvim_argv(nil, false) -- no --embed
+ local argv = helpers.new_argv{
+ args_rm={
+ '-i',
+ '--embed', -- no --embed
+ },
+ args={
+ '-i', meths.get_var('tmpname'), -- Use same shada file as parent.
+ '-c', 'silent edit '..non_existent_testfilename,
+ '-c', 'autocmd VimEnter * qall'},
+ }
eq('', funcs.system(argv))
eq(0, exc_exec('rshada'))
end)
diff --git a/test/functional/shada/registers_spec.lua b/test/functional/shada/registers_spec.lua
index 71af14aba8..1f06cbe350 100644
--- a/test/functional/shada/registers_spec.lua
+++ b/test/functional/shada/registers_spec.lua
@@ -3,9 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local nvim_command, funcs, eq = helpers.command, helpers.funcs, helpers.eq
local shada_helpers = require('test.functional.shada.helpers')
-local reset, set_additional_cmd, clear =
- shada_helpers.reset, shada_helpers.set_additional_cmd,
- shada_helpers.clear
+local reset, clear = shada_helpers.reset, shada_helpers.clear
local setreg = function(name, contents, typ)
if type(contents) == 'string' then
@@ -52,9 +50,8 @@ describe('ShaDa support code', function()
setreg('c', {'d', 'e', ''}, 'c')
setreg('l', {'a', 'b', 'cde'}, 'l')
setreg('b', {'bca', 'abc', 'cba'}, 'b3')
- set_additional_cmd('set shada=\'0,<0')
nvim_command('qall')
- reset()
+ reset('set shada=\'0,<0')
eq({{'d', 'e', ''}, 'v'}, getreg('c'))
eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
@@ -76,9 +73,8 @@ describe('ShaDa support code', function()
setreg('c', {'d', 'e', ''}, 'c')
setreg('l', {'a', 'b', 'cde'}, 'l')
setreg('b', {'bca', 'abc', 'cba'}, 'b3')
- set_additional_cmd('set shada=\'0,\\"0')
nvim_command('qall')
- reset()
+ reset('set shada=\'0,\\"0')
eq({{'d', 'e', ''}, 'v'}, getreg('c'))
eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
@@ -142,7 +138,6 @@ describe('ShaDa support code', function()
reset()
-- \171 is U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK in latin1
setreg('e', {'\171«'}, 'c')
- set_additional_cmd('')
nvim_command('qall')
reset()
eq({{'\171«'}, 'v'}, getreg('e'))
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index 5f7daf73e5..ff63aed235 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -15,7 +15,6 @@ local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
local read_shada_file = shada_helpers.read_shada_file
-local set_additional_cmd = shada_helpers.set_additional_cmd
local wshada, _, shada_fname, clean =
get_shada_rw('Xtest-functional-shada-shada.shada')
@@ -244,8 +243,7 @@ describe('ShaDa support code', function()
funcs.mkdir(dirname, '', 0)
eq(0, funcs.filewritable(dirname))
- set_additional_cmd('set shada=')
- reset(dirshada)
+ reset{shadafile=dirshada, args={'--cmd', 'set shada='}}
meths.set_option('shada', '\'10')
eq('Vim(wshada):E886: System error while opening ShaDa file '
.. 'Xtest-functional-shada-shada.d/main.shada for reading to merge '
diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua
index f817bcef74..74bbceddcc 100644
--- a/test/functional/shada/variables_spec.lua
+++ b/test/functional/shada/variables_spec.lua
@@ -4,9 +4,7 @@ local meths, funcs, nvim_command, eq, exc_exec =
helpers.meths, helpers.funcs, helpers.command, helpers.eq, helpers.exc_exec
local shada_helpers = require('test.functional.shada.helpers')
-local reset, set_additional_cmd, clear =
- shada_helpers.reset, shada_helpers.set_additional_cmd,
- shada_helpers.clear
+local reset, clear = shada_helpers.reset, shada_helpers.clear
describe('ShaDa support code', function()
before_each(reset)
@@ -25,8 +23,7 @@ describe('ShaDa support code', function()
local autotest = function(tname, varname, varval, val_is_expr)
it('is able to dump and read back ' .. tname .. ' variable automatically',
function()
- set_additional_cmd('set shada+=!')
- reset()
+ reset('set shada+=!')
if val_is_expr then
nvim_command('let g:' .. varname .. ' = ' .. varval)
varval = meths.get_var(varname)
@@ -36,7 +33,7 @@ describe('ShaDa support code', function()
-- Exit during `reset` is not a regular exit: it does not write shada
-- automatically
nvim_command('qall')
- reset()
+ reset('set shada+=!')
eq(varval, meths.get_var(varname))
end)
end
@@ -55,8 +52,7 @@ describe('ShaDa support code', function()
meths.set_var('STRVAR', 'foo')
nvim_command('set shada+=!')
nvim_command('wshada')
- set_additional_cmd('set shada-=!')
- reset()
+ reset('set shada-=!')
nvim_command('rshada')
eq(0, funcs.exists('g:STRVAR'))
end)
@@ -98,7 +94,6 @@ describe('ShaDa support code', function()
meths.set_var('LSTVAR', {'«'})
meths.set_var('DCTVAR', {['«']='«'})
meths.set_var('NESTEDVAR', {['«']={{'«'}, {['«']='«'}, {a='Test'}}})
- set_additional_cmd('')
nvim_command('qall')
reset()
eq('«', meths.get_var('STRVAR'))
@@ -131,11 +126,10 @@ describe('ShaDa support code', function()
nvim_command('let F = function("tr")')
meths.set_var('U', '10')
nvim_command('set shada+=!')
- set_additional_cmd('set shada+=!')
eq('Vim(wshada):E5004: Error while dumping variable g:F, itself: attempt to dump function reference',
exc_exec('wshada'))
meths.set_option('shada', '')
- reset()
+ reset('set shada+=!')
eq('10', meths.get_var('U'))
end)
@@ -148,8 +142,7 @@ describe('ShaDa support code', function()
eq('Vim(wshada):E5005: Unable to dump variable g:L: container references itself in index 0',
exc_exec('wshada'))
meths.set_option('shada', '')
- set_additional_cmd('set shada+=!')
- reset()
+ reset('set shada+=!')
eq('10', meths.get_var('U'))
end)
end)
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 9a30ea73c4..24bf66e2d8 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -51,12 +51,7 @@ describe("shell command :!", function()
end)
it("throttles shell-command output greater than ~10KB", function()
- if helpers.skip_fragile(pending,
- (helpers.isCI('travis') and helpers.os_name() == 'osx')) then
- return
- end
- child_session.feed_data(
- ":!for i in $(seq 2 30000); do echo XXXXXXXXXX $i; done\n")
+ child_session.feed_data(":!"..nvim_dir.."/shell-test REP_NODELAY 30001 foo\n")
-- If we observe any line starting with a dot, then throttling occurred.
-- Avoid false failure on slow systems.
@@ -65,10 +60,10 @@ describe("shell command :!", function()
-- Final chunk of output should always be displayed, never skipped.
-- (Throttling is non-deterministic, this test is merely a sanity check.)
screen:expect([[
- XXXXXXXXXX 29997 |
- XXXXXXXXXX 29998 |
- XXXXXXXXXX 29999 |
- XXXXXXXXXX 30000 |
+ 29997: foo |
+ 29998: foo |
+ 29999: foo |
+ 30000: foo |
|
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |