aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/notes.md5
-rw-r--r--CMakeLists.txt12
-rw-r--r--MAINTAIN.md2
-rw-r--r--contrib/luarc.json1
-rw-r--r--runtime/doc/lua.txt53
-rw-r--r--runtime/doc/options.txt4
-rw-r--r--runtime/doc/various.txt6
-rw-r--r--runtime/filetype.lua2
-rw-r--r--runtime/lua/vim/filetype.lua100
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim3
-rw-r--r--src/man/Makefile (renamed from man/Makefile)0
-rw-r--r--src/man/nvim.1 (renamed from man/nvim.1)0
-rw-r--r--src/nvim/api/autocmd.c58
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/ex_cmds.c38
-rw-r--r--src/nvim/ex_docmd.c19
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/spell.c12
-rw-r--r--src/nvim/testdir/test_cmdline.vim6
-rw-r--r--src/nvim/testdir/test_quickfix.vim16
-rw-r--r--src/nvim/testdir/test_spell.vim10
-rw-r--r--src/nvim/testdir/test_spell_utf8.vim42
-rw-r--r--test/functional/api/autocmd_spec.lua22
-rw-r--r--test/functional/api/vim_spec.lua3
-rw-r--r--test/functional/autocmd/termxx_spec.lua6
-rw-r--r--test/functional/core/job_spec.lua7
-rw-r--r--test/functional/ex_cmds/ls_spec.lua4
-rw-r--r--test/functional/ex_cmds/make_spec.lua6
-rw-r--r--test/functional/fixtures/CMakeLists.txt2
-rw-r--r--test/functional/helpers.lua29
-rw-r--r--test/functional/lua/filetype_spec.lua15
-rw-r--r--test/functional/terminal/cursor_spec.lua4
-rw-r--r--test/functional/terminal/edit_spec.lua4
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua10
-rw-r--r--test/functional/terminal/helpers.lua4
-rw-r--r--test/functional/terminal/highlight_spec.lua8
-rw-r--r--test/functional/terminal/scrollback_spec.lua12
-rw-r--r--test/functional/terminal/tui_spec.lua8
-rw-r--r--test/functional/ui/hlstate_spec.lua4
-rw-r--r--test/functional/ui/inccommand_spec.lua4
-rw-r--r--test/functional/ui/output_spec.lua10
-rw-r--r--test/functional/ui/searchhl_spec.lua4
-rw-r--r--test/functional/ui/wildmode_spec.lua4
-rw-r--r--test/functional/vimscript/let_spec.lua4
-rw-r--r--test/functional/vimscript/system_spec.lua62
45 files changed, 438 insertions, 191 deletions
diff --git a/.github/workflows/notes.md b/.github/workflows/notes.md
index 86f9e8e618..d752f10609 100644
--- a/.github/workflows/notes.md
+++ b/.github/workflows/notes.md
@@ -21,8 +21,9 @@ ${NVIM_VERSION}
### macOS
1. Download **nvim-macos.tar.gz**
-2. Extract: `tar xzvf nvim-macos.tar.gz`
-3. Run `./nvim-macos/bin/nvim`
+2. Run `xattr -c ./nvim-macos.tar.gz` (to avoid "unknown developer" warning)
+3. Extract: `tar xzvf nvim-macos.tar.gz`
+4. Run `./nvim-macos/bin/nvim`
### Linux (x64)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dad0093cf0..8434a8824c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -444,7 +444,7 @@ if(TS_HAS_SET_ALLOCATOR)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_ALLOCATOR")
endif()
-# Note: The test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
+# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
if(PREFER_LUA)
@@ -573,11 +573,7 @@ endif()
message(STATUS "Using Lua interpreter: ${LUA_PRG}")
-if(DEBUG)
- option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" OFF)
-else()
- option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON)
-endif()
+option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON)
if(COMPILE_LUA AND NOT WIN32)
if(PREFER_LUA)
@@ -645,7 +641,7 @@ endif()
include(InstallHelpers)
install_helper(
- FILES ${CMAKE_SOURCE_DIR}/man/nvim.1
+ FILES ${CMAKE_SOURCE_DIR}/src/man/nvim.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
#
@@ -678,7 +674,7 @@ if(BUSTED_PRG)
list(APPEND TEST_TARGET_ARGS "USES_TERMINAL")
set(UNITTEST_PREREQS nvim-test unittest-headers)
- set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test streams-test tty-test ${GENERATED_HELP_TAGS})
+ set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test pwsh-test streams-test tty-test ${GENERATED_HELP_TAGS})
set(BENCHMARK_PREREQS nvim tty-test)
check_lua_module(${LUA_PRG} "ffi" LUA_HAS_FFI)
diff --git a/MAINTAIN.md b/MAINTAIN.md
index c644b88ad7..3bf5ab3c85 100644
--- a/MAINTAIN.md
+++ b/MAINTAIN.md
@@ -52,7 +52,7 @@ has a major bug:
3. Cut a release from `release-x.y`.
- Run `./scripts/release.sh`
- Update (force-push) the remote `stable` tag.
- - The [nightly job](https://github.com/neovim/neovim/blob/master/.github/workflows/release.yml#L4)
+ - The [CI job](https://github.com/neovim/neovim/blob/3d45706478cd030c3ee05b4f336164bb96138095/.github/workflows/release.yml#L11-L13)
will update the release assets based on the `stable` tag.
The neovim repository includes a backport [github action](https://github.com/zeebe-io/backport-action).
diff --git a/contrib/luarc.json b/contrib/luarc.json
index 770b023ac6..8d76d1261d 100644
--- a/contrib/luarc.json
+++ b/contrib/luarc.json
@@ -5,6 +5,7 @@
"globals": [
"vim",
"describe",
+ "pending",
"it",
"before_each",
"after_each",
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 9f8d4a8479..b79699c89b 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -2064,14 +2064,55 @@ add({filetypes}) *vim.filetype.add()*
{filetypes} (table) A table containing new filetype maps
(see example).
-match({name}, {bufnr}) *vim.filetype.match()*
- Find the filetype for the given filename and buffer.
+match({arg}) *vim.filetype.match()*
+ Perform filetype detection.
+
+ The filetype can be detected using one of three methods:
+ 1. Using an existing buffer
+ 2. Using only a file name
+ 3. Using only file contents
+
+ Of these, option 1 provides the most accurate result as it
+ uses both the buffer's filename and (optionally) the buffer
+ contents. Options 2 and 3 can be used without an existing
+ buffer, but may not always provide a match in cases where the
+ filename (or contents) cannot unambiguously determine the
+ filetype.
+
+ Each of the three options is specified using a key to the
+ single argument of this function. Example:
+>
+
+ -- Using a buffer number
+ vim.filetype.match({ buf = 42 })
+
+ -- Override the filename of the given buffer
+ vim.filetype.match({ buf = 42, filename = 'foo.c' })
+
+ -- Using a filename without a buffer
+ vim.filetype.match({ filename = 'main.lua' })
+
+ -- Using file contents
+ vim.filetype.match({ contents = {'#!/usr/bin/env bash'} })
+<
Parameters: ~
- {name} (string) File name (can be an absolute or
- relative path)
- {bufnr} (number|nil) The buffer to set the filetype for.
- Defaults to the current buffer.
+ {arg} (table) Table specifying which matching strategy to
+ use. Accepted keys are:
+ • buf (number): Buffer number to use for matching.
+ Mutually exclusive with {contents}
+ • filename (string): Filename to use for matching.
+ When {buf} is given, defaults to the filename of
+ the given buffer number. The file need not
+ actually exist in the filesystem. When used
+ without {buf} only the name of the file is used
+ for filetype matching. This may result in failure
+ to detect the filetype in cases where the
+ filename alone is not enough to disambiguate the
+ filetype.
+ • contents (table): An array of lines representing
+ file contents to use for matching. Can be used
+ with {filename}. Mutually exclusive with {buf}.
Return: ~
(string|nil) If a match was found, the matched filetype.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 20805377d8..4d86f792da 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5292,9 +5292,9 @@ A jump table for the options with a short description can be found at |Q_op|.
unescaping, so to keep yourself sane use |:let-&| like shown above.
*shell-powershell*
To use PowerShell: >
- let &shell = has('win32') ? 'powershell' : 'pwsh'
+ let &shell = executable('pwsh') ? 'pwsh' : 'powershell'
let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;'
- let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
+ let &shellredir = '-RedirectStandardOutput %s -NoNewWindow -Wait'
let &shellpipe = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
set shellquote= shellxquote=
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 562faeaa2c..9eb6470962 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -346,7 +346,11 @@ g8 Print the hex values of the bytes used in the
Only string variables can be used. After the
redirection starts, if the variable is removed or
locked or the variable type is changed, then further
- command output messages will cause errors.
+ command output messages will cause errors. When using
+ a local variable (l:var in a function or s:var in a
+ script) and another `:redir` causes the current one to
+ end, the scope might be different and the assignment
+ fails.
To get the output of one command the |execute()|
function can be used instead of redirection.
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index b002b8971b..35bb31edce 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -12,7 +12,7 @@ vim.api.nvim_create_augroup('filetypedetect', { clear = false })
vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
group = 'filetypedetect',
callback = function(args)
- local ft, on_detect = vim.filetype.match(args.file, args.buf)
+ local ft, on_detect = vim.filetype.match({ buf = args.buf })
if ft then
vim.api.nvim_buf_set_option(args.buf, 'filetype', ft)
if on_detect then
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 6c4894208f..73605413ee 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -2047,7 +2047,7 @@ local pattern = {
end
end, { priority = -math.huge + 1 }),
['XF86Config.*'] = starsetf(function(path, bufnr)
- return require('vim.filetype.detect').xfree86(bufnr)
+ return require('vim.filetype.detect').xfree86()
end),
['%.zcompdump.*'] = starsetf('zsh'),
-- .zlog* and zlog*
@@ -2185,17 +2185,24 @@ end
local function dispatch(ft, path, bufnr, ...)
local on_detect
if type(ft) == 'function' then
- ft, on_detect = ft(path, bufnr, ...)
+ if bufnr then
+ ft, on_detect = ft(path, bufnr, ...)
+ else
+ -- If bufnr is nil (meaning we are matching only against the filename), set it to an invalid
+ -- value (-1) and catch any errors from the filetype detection function. If the function tries
+ -- to use the buffer then it will fail, but this enables functions which do not need a buffer
+ -- to still work.
+ local ok
+ ok, ft, on_detect = pcall(ft, path, -1, ...)
+ if not ok then
+ return
+ end
+ end
end
if type(ft) == 'string' then
return ft, on_detect
end
-
- -- Any non-falsey value (that is, anything other than 'nil' or 'false') will
- -- end filetype matching. This is useful for e.g. the dist#ft functions that
- -- return 0, but set the buffer's filetype themselves
- return ft
end
---@private
@@ -2214,29 +2221,86 @@ local function match_pattern(name, path, tail, pat)
return matches
end
---- Find the filetype for the given filename and buffer.
+--- Perform filetype detection.
+---
+--- The filetype can be detected using one of three methods:
+--- 1. Using an existing buffer
+--- 2. Using only a file name
+--- 3. Using only file contents
+---
+--- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and
+--- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but
+--- may not always provide a match in cases where the filename (or contents) cannot unambiguously
+--- determine the filetype.
+---
+--- Each of the three options is specified using a key to the single argument of this function.
+--- Example:
+---
+--- <pre>
+--- -- Using a buffer number
+--- vim.filetype.match({ buf = 42 })
+---
+--- -- Override the filename of the given buffer
+--- vim.filetype.match({ buf = 42, filename = 'foo.c' })
---
----@param name string File name (can be an absolute or relative path)
----@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer.
+--- -- Using a filename without a buffer
+--- vim.filetype.match({ filename = 'main.lua' })
+---
+--- -- Using file contents
+--- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} })
+--- </pre>
+---
+---@param arg table Table specifying which matching strategy to use. Accepted keys are:
+--- * buf (number): Buffer number to use for matching. Mutually exclusive with
+--- {contents}
+--- * filename (string): Filename to use for matching. When {buf} is given,
+--- defaults to the filename of the given buffer number. The
+--- file need not actually exist in the filesystem. When used
+--- without {buf} only the name of the file is used for
+--- filetype matching. This may result in failure to detect
+--- the filetype in cases where the filename alone is not
+--- enough to disambiguate the filetype.
+--- * contents (table): An array of lines representing file contents to use for
+--- matching. Can be used with {filename}. Mutually exclusive
+--- with {buf}.
---@return string|nil If a match was found, the matched filetype.
---@return function|nil A function that modifies buffer state when called (for example, to set some
--- filetype specific buffer variables). The function accepts a buffer number as
--- its only argument.
-function M.match(name, bufnr)
+function M.match(arg)
vim.validate({
- name = { name, 's' },
- bufnr = { bufnr, 'n', true },
+ arg = { arg, 't' },
})
- -- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use
- -- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers
- -- wish to perform filetype detection on buffers other than the current one.
- bufnr = bufnr or api.nvim_get_current_buf()
+ if not (arg.buf or arg.filename or arg.contents) then
+ error('At least one of "buf", "filename", or "contents" must be given')
+ end
+
+ if arg.buf and arg.contents then
+ error('Only one of "buf" or "contents" must be given')
+ end
+
+ local bufnr = arg.buf
+ local name = arg.filename
+ local contents = arg.contents
+
+ if bufnr and not name then
+ name = api.nvim_buf_get_name(bufnr)
+ end
- name = normalize_path(name)
+ if name then
+ name = normalize_path(name)
+ end
local ft, on_detect
+ if contents then
+ -- Sanity check: this should not happen
+ assert(not bufnr, '"buf" and "contents" are mutually exclusive')
+ -- TODO: "scripts.lua" content matching
+ return
+ end
+
-- First check for the simple case where the full path exists as a key
local path = vim.fn.resolve(vim.fn.fnamemodify(name, ':p'))
ft, on_detect = dispatch(filename[path], path, bufnr)
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index f76bdebe9b..c4e90eb373 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -2,7 +2,7 @@
"
" Author: Bram Moolenaar
" Copyright: Vim license applies, see ":help license"
-" Last Change: 2022 Jun 22
+" Last Change: 2022 Jun 24
"
" WORK IN PROGRESS - The basics works stable, more to come
" Note: In general you need at least GDB 7.12 because this provides the
@@ -539,6 +539,7 @@ func TermDebugSendCommand(cmd)
endif
sleep 10m
endif
+ " TODO: should we prepend CTRL-U to clear the command?
call chansend(s:gdb_job_id, a:cmd . "\r")
if do_continue
Continue
diff --git a/man/Makefile b/src/man/Makefile
index 3c0457e2ab..3c0457e2ab 100644
--- a/man/Makefile
+++ b/src/man/Makefile
diff --git a/man/nvim.1 b/src/man/nvim.1
index 9f35014ee8..9f35014ee8 100644
--- a/man/nvim.1
+++ b/src/man/nvim.1
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 3a35e49dc8..bf6402f938 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -549,9 +549,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
int retval;
- for (size_t i = 0; i < patterns.size; i++) {
- Object pat = patterns.items[i];
-
+ FOREACH_ITEM(patterns, pat, {
// See: TODO(sctx)
WITH_SCRIPT_CONTEXT(channel_id, {
retval = autocmd_register(autocmd_id,
@@ -569,7 +567,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
api_set_error(err, kErrorTypeException, "Failed to set autocmd");
goto cleanup;
}
- }
+ })
});
cleanup:
@@ -781,14 +779,12 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
bool modeline = true;
buf_T *buf = curbuf;
- bool set_buf = false;
-
- char *pattern = NULL;
- Object *data = NULL;
- bool set_pattern = false;
+ Array patterns = ARRAY_DICT_INIT;
Array event_array = ARRAY_DICT_INIT;
+ Object *data = NULL;
+
if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
goto cleanup;
}
@@ -826,21 +822,18 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
}
buf = find_buffer_by_handle((Buffer)buf_obj.data.integer, err);
- set_buf = true;
if (ERROR_SET(err)) {
goto cleanup;
}
}
- if (opts->pattern.type != kObjectTypeNil) {
- if (opts->pattern.type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation, "'pattern' must be a string");
- goto cleanup;
- }
+ if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
+ goto cleanup;
+ }
- pattern = string_to_cstr(opts->pattern.data.string);
- set_pattern = true;
+ if (patterns.size == 0) {
+ ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("")));
}
if (opts->data.type != kObjectTypeNil) {
@@ -849,16 +842,15 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
- if (set_pattern && set_buf) {
- api_set_error(err, kErrorTypeValidation, "must not set 'buffer' and 'pattern'");
- goto cleanup;
- }
-
bool did_aucmd = false;
FOREACH_ITEM(event_array, event_str, {
GET_ONE_EVENT(event_nr, event_str, cleanup)
- did_aucmd |= apply_autocmds_group(event_nr, pattern, NULL, true, au_group, buf, NULL, data);
+ FOREACH_ITEM(patterns, pat, {
+ char *fname = opts->buffer.type == kObjectTypeNil ? pat.data.string.data : NULL;
+ did_aucmd |=
+ apply_autocmds_group(event_nr, fname, NULL, true, au_group, buf, NULL, data);
+ })
})
if (did_aucmd && modeline) {
@@ -867,13 +859,13 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
cleanup:
api_free_array(event_array);
- XFREE_CLEAR(pattern);
+ api_free_array(patterns);
}
static bool check_autocmd_string_array(Array arr, char *k, Error *err)
{
- for (size_t i = 0; i < arr.size; i++) {
- if (arr.items[i].type != kObjectTypeString) {
+ FOREACH_ITEM(arr, entry, {
+ if (entry.type != kObjectTypeString) {
api_set_error(err,
kErrorTypeValidation,
"All entries in '%s' must be strings",
@@ -882,13 +874,13 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err)
}
// Disallow newlines in the middle of the line.
- const String l = arr.items[i].data.string;
+ const String l = entry.data.string;
if (memchr(l.data, NL, l.size)) {
api_set_error(err, kErrorTypeValidation,
"String cannot contain newlines");
return false;
}
- }
+ })
return true;
}
@@ -975,8 +967,8 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob
}
Array array = v->data.array;
- for (size_t i = 0; i < array.size; i++) {
- char *pat = array.items[i].data.string.data;
+ FOREACH_ITEM(array, entry, {
+ char *pat = entry.data.string.data;
size_t patlen = aucmd_pattern_length(pat);
while (patlen) {
ADD(*patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen)));
@@ -984,15 +976,15 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob
pat = aucmd_next_pattern(pat, patlen);
patlen = aucmd_pattern_length(pat);
}
- }
+ })
} else {
api_set_error(err,
kErrorTypeValidation,
- "'pattern' must be a string");
+ "'pattern' must be a string or table");
return false;
}
} else if (buffer.type != kObjectTypeNil) {
- if (buffer.type != kObjectTypeInteger) {
+ if (buffer.type != kObjectTypeInteger && buffer.type != kObjectTypeBuffer) {
api_set_error(err,
kErrorTypeValidation,
"'buffer' must be an integer");
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index be2df9488e..7b6e954b3a 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -469,7 +469,9 @@ void eval_clear(void)
hash_clear(&compat_hashtab);
free_scriptnames();
+# ifdef HAVE_WORKING_LIBINTL
free_locales();
+# endif
// global variables
vars_clear(&globvarht);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5b0ce1418e..92c1b5d2c7 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1568,14 +1568,18 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
#else
false;
#endif
+ bool is_pwsh = STRNCMP(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
+ || STRNCMP(invocation_path_tail(p_sh, NULL), "powershell", 10) == 0;
size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL.
len += is_fish_shell ? sizeof("begin; " "; end") - 1
- : sizeof("(" ")") - 1;
+ : is_pwsh ? sizeof("Start-Process ")
+ : sizeof("(" ")") - 1;
if (itmp != NULL) {
- len += STRLEN(itmp) + sizeof(" { " " < " " } ") - 1;
+ len += is_pwsh ? STRLEN(itmp) + sizeof(" -RedirectStandardInput ")
+ : STRLEN(itmp) + sizeof(" { " " < " " } ") - 1;
}
if (otmp != NULL) {
len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "),
@@ -1585,7 +1589,10 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
#if defined(UNIX)
// Put delimiters around the command (for concatenated commands) when
// redirecting input and/or output.
- if (itmp != NULL || otmp != NULL) {
+ if (is_pwsh) {
+ xstrlcpy(buf, "Start-Process ", len);
+ xstrlcat(buf, cmd, len);
+ } else if (itmp != NULL || otmp != NULL) {
char *fmt = is_fish_shell ? "begin; %s; end"
: "(%s)";
vim_snprintf(buf, len, fmt, cmd);
@@ -1594,13 +1601,22 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
}
if (itmp != NULL) {
- xstrlcat(buf, " < ", len - 1);
- xstrlcat(buf, (const char *)itmp, len - 1);
+ if (is_pwsh) {
+ xstrlcat(buf, " -RedirectStandardInput ", len - 1);
+ } else {
+ xstrlcat(buf, " < ", len - 1);
+ }
+ xstrlcat(buf, itmp, len - 1);
}
#else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
- xstrlcpy(buf, (char *)cmd, len);
+ if (is_pwsh) {
+ xstrlcpy(buf, "Start-Process ", len);
+ xstrlcat(buf, cmd, len);
+ } else {
+ xstrlcpy(buf, cmd, len);
+ }
if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the
@@ -1611,10 +1627,14 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
*p = NUL;
}
}
- xstrlcat(buf, " < ", len);
- xstrlcat(buf, (const char *)itmp, len);
+ if (is_pwsh) {
+ xstrlcat(buf, " -RedirectStandardInput ", len);
+ } else {
+ xstrlcat(buf, " < ", len);
+ }
+ xstrlcat(buf, itmp, len);
if (*p_shq == NUL) {
- const char *const p = find_pipe((const char *)cmd);
+ const char *const p = find_pipe(cmd);
if (p != NULL) {
xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS
xstrlcat(buf, p, len - 1);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 671e83def6..00aadc2af5 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -82,8 +82,13 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-static char *e_no_such_user_defined_command_str = N_("E184: No such user-defined command: %s");
-static char *e_no_such_user_defined_command_in_current_buffer_str
+static char e_no_such_user_defined_command_str[]
+ = N_("E184: No such user-defined command: %s");
+static char e_ambiguous_use_of_user_defined_command[]
+ = N_("E464: Ambiguous use of user-defined command");
+static char e_not_an_editor_command[]
+ = N_("E492: Not an editor command");
+static char e_no_such_user_defined_command_in_current_buffer_str[]
= N_("E1237: No such user-defined command in current buffer: %s");
static int quitmore = 0;
@@ -1439,6 +1444,10 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
eap->cmd = skipwhite(eap->cmd + 1);
}
p = find_ex_command(eap, NULL);
+ if (p == NULL) {
+ *errormsg = _(e_ambiguous_use_of_user_defined_command);
+ return false;
+ }
// Set command address type and parse command range
set_cmd_addr_type(eap, (char_u *)p);
@@ -1455,7 +1464,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
}
// Fail if command is invalid
if (eap->cmdidx == CMD_SIZE) {
- STRCPY(IObuff, _("E492: Not an editor command"));
+ STRCPY(IObuff, _(e_not_an_editor_command));
// If the modifier was parsed OK the error must be in the following command
char *cmdname = after_modifier ? after_modifier : cmdline;
append_command(cmdname);
@@ -1886,14 +1895,14 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
if (p == NULL) {
if (!ea.skip) {
- errormsg = _("E464: Ambiguous use of user-defined command");
+ errormsg = _(e_ambiguous_use_of_user_defined_command);
}
goto doend;
}
// Check for wrong commands.
if (ea.cmdidx == CMD_SIZE) {
if (!ea.skip) {
- STRCPY(IObuff, _("E492: Not an editor command"));
+ STRCPY(IObuff, _(e_not_an_editor_command));
// If the modifier was parsed OK the error must be in the following
// command
char *cmdname = after_modifier ? after_modifier : *cmdlinep;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 633fbe0517..8cd9b5aead 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2596,6 +2596,8 @@ ambw_end:
// only encoding=utf-8 allowed
if (STRCMP(p_enc, "utf-8") != 0) {
errmsg = e_unsupportedoption;
+ } else {
+ spell_reload();
}
}
}
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 8f84204481..8ae846e074 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -3663,6 +3663,12 @@ static void suggest_try_change(suginfo_T *su)
p = su->su_badptr + su->su_badlen;
(void)spell_casefold(curwin, p, (int)STRLEN(p), fword + n, MAXWLEN - n);
+ // Make sure the resulting text is not longer than the original text.
+ n = (int)STRLEN(su->su_badptr);
+ if (n < MAXWLEN) {
+ fword[n] = NUL;
+ }
+
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
@@ -4375,7 +4381,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
#endif
++depth;
sp = &stack[depth];
- ++sp->ts_fidx;
+ if (fword[sp->ts_fidx] != NUL) {
+ sp->ts_fidx++;
+ }
tword[sp->ts_twordlen++] = c;
sp->ts_arridx = idxs[arridx];
if (newscore == SCORE_SUBST) {
@@ -4391,7 +4399,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_fcharstart = sp->ts_fidx - 1;
sp->ts_isdiff = (newscore != 0)
? DIFF_YES : DIFF_NONE;
- } else if (sp->ts_isdiff == DIFF_INSERT) {
+ } else if (sp->ts_isdiff == DIFF_INSERT && sp->ts_fidx > 0) {
// When inserting trail bytes don't advance in the
// bad word.
sp->ts_fidx--;
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 887c8e1593..8d1746be2f 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -305,7 +305,7 @@ func Test_getcompletion()
call assert_equal([], l)
let l = getcompletion('', 'dir')
- call assert_true(index(l, expand('sautest/')) >= 0)
+ call assert_true(index(l, 'sautest/') >= 0)
let l = getcompletion('NoMatch', 'dir')
call assert_equal([], l)
@@ -415,7 +415,7 @@ func Test_getcompletion()
" Command line completion tests
let l = getcompletion('cd ', 'cmdline')
- call assert_true(index(l, expand('sautest/')) >= 0)
+ call assert_true(index(l, 'sautest/') >= 0)
let l = getcompletion('cd NoMatch', 'cmdline')
call assert_equal([], l)
let l = getcompletion('let v:n', 'cmdline')
@@ -539,7 +539,7 @@ func Test_expand_star_star()
call mkdir('a/b', 'p')
call writefile(['asdfasdf'], 'a/b/fileXname')
call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt')
- call assert_equal('find '.expand('a/b/fileXname'), getreg(':'))
+ call assert_equal('find a/b/fileXname', getreg(':'))
bwipe!
call delete('a', 'rf')
endfunc
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index e43db4d692..5826666cbb 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1060,17 +1060,17 @@ func s:dir_stack_tests(cchar)
let qf = g:Xgetlist()
- call assert_equal(expand('dir1/a/habits2.txt'), bufname(qf[1].bufnr))
+ call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr))
call assert_equal(1, qf[1].lnum)
- call assert_equal(expand('dir1/a/b/habits3.txt'), bufname(qf[3].bufnr))
+ call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr))
call assert_equal(2, qf[3].lnum)
- call assert_equal(expand('dir1/a/habits2.txt'), bufname(qf[4].bufnr))
+ call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr))
call assert_equal(7, qf[4].lnum)
- call assert_equal(expand('dir1/c/habits4.txt'), bufname(qf[6].bufnr))
+ call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr))
call assert_equal(3, qf[6].lnum)
call assert_equal('habits1.txt', bufname(qf[9].bufnr))
call assert_equal(4, qf[9].lnum)
- call assert_equal(expand('dir2/habits5.txt'), bufname(qf[11].bufnr))
+ call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr))
call assert_equal(5, qf[11].lnum)
let &efm=save_efm
@@ -1300,7 +1300,7 @@ func Test_efm2()
call assert_equal(8, len(l))
call assert_equal(89, l[4].lnum)
call assert_equal(1, l[4].valid)
- call assert_equal(expand('unittests/dbfacadeTest.py'), bufname(l[4].bufnr))
+ call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
call assert_equal('W', l[4].type)
" Test for %o
@@ -2074,11 +2074,11 @@ func Test_two_windows()
laddexpr 'one.txt:3:one one one'
let loc_one = getloclist(one_id)
- call assert_equal(expand('Xone/a/one.txt'), bufname(loc_one[1].bufnr))
+ call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
call assert_equal(3, loc_one[1].lnum)
let loc_two = getloclist(two_id)
- call assert_equal(expand('Xtwo/a/two.txt'), bufname(loc_two[1].bufnr))
+ call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
call assert_equal(5, loc_two[1].lnum)
call win_gotoid(one_id)
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index ce21b8bdc9..215d4387d6 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -72,6 +72,16 @@ func Test_z_equal_on_invalid_utf8_word()
bwipe!
endfunc
+func Test_z_equal_on_single_character()
+ " this was decrementing the index below zero
+ new
+ norm a0\
+ norm zW
+ norm z=
+
+ bwipe!
+endfunc
+
" Test spellbadword() with argument
func Test_spellbadword()
set spell
diff --git a/src/nvim/testdir/test_spell_utf8.vim b/src/nvim/testdir/test_spell_utf8.vim
index 1d323df67e..3c07e0782b 100644
--- a/src/nvim/testdir/test_spell_utf8.vim
+++ b/src/nvim/testdir/test_spell_utf8.vim
@@ -576,7 +576,6 @@ endfunc
"Compound words
func Test_spell_compound()
- throw 'skipped: TODO: '
call LoadAffAndDic(g:test_data_aff3, g:test_data_dic3)
call RunGoodBad("foo m\u00EF foobar foofoobar barfoo barbarfoo",
\ "bad: bar la foom\u00EF barm\u00EF m\u00EFfoo m\u00EFbar m\u00EFm\u00EF lala m\u00EFla lam\u00EF foola labar",
@@ -624,14 +623,14 @@ endfunc
" Test affix flags with two characters
func Test_spell_affix()
- throw 'skipped: TODO: '
+ CheckNotMSWindows " FIXME: Why does this fail with MSVC?
call LoadAffAndDic(g:test_data_aff5, g:test_data_dic5)
call RunGoodBad("fooa1 fooa\u00E9 bar prebar barbork prebarbork startprebar start end startend startmiddleend nouend",
\ "bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart startprobar startnouend",
\ ["bar", "barbork", "end", "fooa1", "fooa\u00E9", "nouend", "prebar", "prebarbork", "start"],
\ [
\ ["bad", ["bar", "end", "fooa1"]],
- \ ["foo", ["fooa1", "fooa\u00E9", "bar"]],
+ \ ["foo", ["fooa1", "bar", "end"]],
\ ["fooa2", ["fooa1", "fooa\u00E9", "bar"]],
\ ["prabar", ["prebar", "bar", "bar bar"]],
\ ["probarbirk", ["prebarbork"]],
@@ -649,7 +648,7 @@ func Test_spell_affix()
\ ["bar", "barbork", "end", "lead", "meea1", "meea\u00E9", "prebar", "prebarbork"],
\ [
\ ["bad", ["bar", "end", "lead"]],
- \ ["mee", ["meea1", "meea\u00E9", "bar"]],
+ \ ["mee", ["meea1", "bar", "end"]],
\ ["meea2", ["meea1", "meea\u00E9", "lead"]],
\ ["prabar", ["prebar", "bar", "leadbar"]],
\ ["probarbirk", ["prebarbork"]],
@@ -666,7 +665,7 @@ func Test_spell_affix()
\ ["bar", "barmeat", "lead", "meea1", "meea\u00E9", "meezero", "prebar", "prebarmeat", "tail"],
\ [
\ ["bad", ["bar", "lead", "tail"]],
- \ ["mee", ["meea1", "meea\u00E9", "bar"]],
+ \ ["mee", ["meea1", "bar", "lead"]],
\ ["meea2", ["meea1", "meea\u00E9", "lead"]],
\ ["prabar", ["prebar", "bar", "leadbar"]],
\ ["probarmaat", ["prebarmeat"]],
@@ -700,7 +699,6 @@ endfunc
" Affix flags
func Test_spell_affix_flags()
- throw 'skipped: TODO: '
call LoadAffAndDic(g:test_data_aff10, g:test_data_dic10)
call RunGoodBad("drink drinkable drinkables drinktable drinkabletable",
\ "bad: drinks drinkstable drinkablestable",
@@ -761,11 +759,30 @@ func Test_spell_sal_and_addition()
set spl=Xtest_ca.utf-8.spl
call assert_equal("elequint", FirstSpellWord())
call assert_equal("elekwint", SecondSpellWord())
+
+ set spellfile=
+ set spl&
endfunc
func Test_spellfile_value()
set spellfile=Xdir/Xtest.utf-8.add
set spellfile=Xdir/Xtest.utf-8.add,Xtest_other.add
+ set spellfile=
+endfunc
+
+func Test_no_crash_with_weird_text()
+ new
+ let lines =<< trim END
+ r<sfile>
+ €
+
+
+ €
+ END
+ call setline(1, lines)
+ exe "%norm \<C-v>ez=>\<C-v>wzG"
+
+ bwipe!
endfunc
" Invalid bytes may cause trouble when creating the word list.
@@ -773,5 +790,18 @@ func Test_check_for_valid_word()
call assert_fails("spellgood! 0\xac", 'E1280:')
endfunc
+" This was going over the end of the word
+func Test_word_index()
+ new
+ norm R0
+ spellgood! fl0
+ sil norm z=
+
+ bwipe!
+ " clear the word list
+ set enc=utf-8
+ call delete('Xtmpfile')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 5dfcd09438..a923f5df0e 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -686,6 +686,26 @@ describe('autocmd api', function()
eq(true, meths.get_var("autocmd_executed"))
end)
+ it("can trigger multiple patterns", function()
+ meths.set_var("autocmd_executed", 0)
+
+ meths.create_autocmd("BufReadPost", {
+ pattern = "*",
+ command = "let g:autocmd_executed += 1",
+ })
+
+ meths.exec_autocmds("BufReadPost", { pattern = { "*.lua", "*.vim" } })
+ eq(2, meths.get_var("autocmd_executed"))
+
+ meths.create_autocmd("BufReadPre", {
+ pattern = { "bar", "foo" },
+ command = "let g:autocmd_executed += 10",
+ })
+
+ meths.exec_autocmds("BufReadPre", { pattern = { "foo", "bar", "baz", "frederick" }})
+ eq(22, meths.get_var("autocmd_executed"))
+ end)
+
it("can pass the buffer", function()
meths.set_var("buffer_executed", -1)
eq(-1, meths.get_var("buffer_executed"))
@@ -742,7 +762,7 @@ describe('autocmd api', function()
meths.exec_autocmds("CursorHoldI", { buffer = 1 })
eq('none', meths.get_var("filename_executed"))
- meths.exec_autocmds("CursorHoldI", { buffer = tonumber(meths.get_current_buf()) })
+ meths.exec_autocmds("CursorHoldI", { buffer = meths.get_current_buf() })
eq('__init__.py', meths.get_var("filename_executed"))
-- Reset filename
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index ef6798dea3..c05345dd4c 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -3520,6 +3520,9 @@ describe('API', function()
pcall_err(meths.parse_cmd, 'Fubar!', {}))
eq('Error while parsing command line: E481: No range allowed',
pcall_err(meths.parse_cmd, '4,6Fubar', {}))
+ command('command! Foobar echo foo')
+ eq('Error while parsing command line: E464: Ambiguous use of user-defined command',
+ pcall_err(meths.parse_cmd, 'F', {}))
end)
end)
describe('nvim_cmd', function()
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index 1e8f981437..c418a12faf 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -1,8 +1,8 @@
local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each)
-local clear, command, nvim, nvim_dir =
- helpers.clear, helpers.command, helpers.nvim, helpers.nvim_dir
+local clear, command, nvim, testprg =
+ helpers.clear, helpers.command, helpers.nvim, helpers.testprg
local eval, eq, neq, retry =
helpers.eval, helpers.eq, helpers.neq, helpers.retry
local ok = helpers.ok
@@ -12,7 +12,7 @@ local iswin = helpers.iswin
describe('autocmd TermClose', function()
before_each(function()
clear()
- nvim('set_option', 'shell', nvim_dir .. '/shell-test')
+ nvim('set_option', 'shell', testprg('shell-test'))
command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
end)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 461a69f357..a6763ba3c7 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -1,9 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim,
- nvim_dir, ok, source, write_file, mkdir, rmdir = helpers.clear,
+ testprg, ok, source, write_file, mkdir, rmdir = helpers.clear,
helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed,
helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
- helpers.nvim_dir, helpers.ok, helpers.source,
+ helpers.testprg, helpers.ok, helpers.source,
helpers.write_file, helpers.mkdir, helpers.rmdir
local assert_alive = helpers.assert_alive
local command = helpers.command
@@ -1043,8 +1043,7 @@ describe('jobs', function()
return a:data
endfunction
]])
- local ext = iswin() and '.exe' or ''
- insert(nvim_dir..'/tty-test'..ext) -- Full path to tty-test.
+ insert(testprg('tty-test'))
nvim('command', 'let g:job_opts.pty = 1')
nvim('command', 'let exec = [expand("<cfile>:p")]')
nvim('command', "let j = jobstart(exec, g:job_opts)")
diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua
index 9853084c47..2583d80269 100644
--- a/test/functional/ex_cmds/ls_spec.lua
+++ b/test/functional/ex_cmds/ls_spec.lua
@@ -5,7 +5,7 @@ local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
local nvim = helpers.nvim
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local retry = helpers.retry
describe(':ls', function()
@@ -14,7 +14,7 @@ describe(':ls', function()
end)
it('R, F for :terminal buffers', function()
- nvim('set_option', 'shell', string.format('"%s" INTERACT', nvim_dir..'/shell-test'))
+ nvim('set_option', 'shell', string.format('"%s" INTERACT', testprg('shell-test')))
command('edit foo')
command('set hidden')
diff --git a/test/functional/ex_cmds/make_spec.lua b/test/functional/ex_cmds/make_spec.lua
index 3b4d22ab38..bf585ee44c 100644
--- a/test/functional/ex_cmds/make_spec.lua
+++ b/test/functional/ex_cmds/make_spec.lua
@@ -4,7 +4,7 @@ local eval = helpers.eval
local has_powershell = helpers.has_powershell
local matches = helpers.matches
local nvim = helpers.nvim
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
describe(':make', function()
clear()
@@ -22,7 +22,7 @@ describe(':make', function()
end)
it('captures stderr & non zero exit code #14349', function ()
- nvim('set_option', 'makeprg', nvim_dir..'/shell-test foo')
+ nvim('set_option', 'makeprg', testprg('shell-test')..' foo')
local out = eval('execute("make")')
-- Make program exit code correctly captured
matches('\nshell returned 3', out)
@@ -31,7 +31,7 @@ describe(':make', function()
end)
it('captures stderr & zero exit code #14349', function ()
- nvim('set_option', 'makeprg', nvim_dir..'/shell-test')
+ nvim('set_option', 'makeprg', testprg('shell-test'))
local out = eval('execute("make")')
-- Ensure there are no "shell returned X" messages between
-- command and last line (indicating zero exit)
diff --git a/test/functional/fixtures/CMakeLists.txt b/test/functional/fixtures/CMakeLists.txt
index 6010fcaf1e..a5410c2f8c 100644
--- a/test/functional/fixtures/CMakeLists.txt
+++ b/test/functional/fixtures/CMakeLists.txt
@@ -2,6 +2,8 @@ add_executable(tty-test EXCLUDE_FROM_ALL tty-test.c)
target_link_libraries(tty-test ${LIBUV_LIBRARIES})
add_executable(shell-test EXCLUDE_FROM_ALL shell-test.c)
+# Fake pwsh (powershell) for testing make_filter_cmd(). #16271
+add_executable(pwsh-test EXCLUDE_FROM_ALL shell-test.c)
add_executable(printargs-test EXCLUDE_FROM_ALL printargs-test.c)
add_executable(printenv-test EXCLUDE_FROM_ALL printenv-test.c)
if(MINGW)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index d31d337b63..0c616e73fb 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -515,9 +515,17 @@ function module.has_powershell()
return module.eval('executable("'..(iswin() and 'powershell' or 'pwsh')..'")') == 1
end
-function module.set_shell_powershell()
- local shell = iswin() and 'powershell' or 'pwsh'
- assert(module.has_powershell())
+--- Sets Nvim shell to powershell.
+---
+--- @param fake (boolean) If true, a fake will be used if powershell is not
+--- found on the system.
+--- @returns true if powershell was found on the system, else false.
+function module.set_shell_powershell(fake)
+ local found = module.has_powershell()
+ if not fake then
+ assert(found)
+ end
+ local shell = found and (iswin() and 'powershell' or 'pwsh') or module.testprg('pwsh-test')
local set_encoding = '[Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;'
local cmd = set_encoding..'Remove-Item -Force '..table.concat(iswin()
and {'alias:cat', 'alias:echo', 'alias:sleep'}
@@ -525,10 +533,11 @@ function module.set_shell_powershell()
module.exec([[
let &shell = ']]..shell..[['
set shellquote= shellxquote=
- let &shellpipe = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
- let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command ]]..cmd..[['
+ let &shellpipe = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
+ let &shellredir = '-RedirectStandardOutput %s -NoNewWindow -Wait'
]])
+ return found
end
function module.nvim(method, ...)
@@ -784,11 +793,21 @@ function module.get_pathsep()
return iswin() and '\\' or '/'
end
+--- Gets the filesystem root dir, namely "/" or "C:/".
function module.pathroot()
local pathsep = package.config:sub(1,1)
return iswin() and (module.nvim_dir:sub(1,2)..pathsep) or '/'
end
+--- Gets the full `…/build/bin/{name}` path of a test program produced by
+--- `test/functional/fixtures/CMakeLists.txt`.
+---
+--- @param name (string) Name of the test program.
+function module.testprg(name)
+ local ext = module.iswin() and '.exe' or ''
+ return ('%s/%s%s'):format(module.nvim_dir, name, ext)
+end
+
-- Returns a valid, platform-independent Nvim listen address.
-- Useful for communicating with child instances.
function module.new_pipename()
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
index d0cef53c4b..be57b2db31 100644
--- a/test/functional/lua/filetype_spec.lua
+++ b/test/functional/lua/filetype_spec.lua
@@ -3,6 +3,7 @@ local exec_lua = helpers.exec_lua
local eq = helpers.eq
local clear = helpers.clear
local pathroot = helpers.pathroot
+local command = helpers.command
local root = pathroot()
@@ -23,7 +24,7 @@ describe('vim.filetype', function()
rs = 'radicalscript',
},
})
- return vim.filetype.match('main.rs')
+ return vim.filetype.match({ filename = 'main.rs' })
]])
end)
@@ -37,7 +38,7 @@ describe('vim.filetype', function()
['main.rs'] = 'somethingelse',
},
})
- return vim.filetype.match('main.rs')
+ return vim.filetype.match({ filename = 'main.rs' })
]])
end)
@@ -48,7 +49,7 @@ describe('vim.filetype', function()
['s_O_m_e_F_i_l_e'] = 'nim',
},
})
- return vim.filetype.match('s_O_m_e_F_i_l_e')
+ return vim.filetype.match({ filename = 's_O_m_e_F_i_l_e' })
]])
eq('dosini', exec_lua([[
@@ -59,7 +60,7 @@ describe('vim.filetype', function()
[root .. '/.config/fun/config'] = 'dosini',
},
})
- return vim.filetype.match(root .. '/.config/fun/config')
+ return vim.filetype.match({ filename = root .. '/.config/fun/config' })
]], root))
end)
@@ -72,11 +73,13 @@ describe('vim.filetype', function()
['~/blog/.*%.txt'] = 'markdown',
}
})
- return vim.filetype.match('~/blog/why_neovim_is_awesome.txt')
+ return vim.filetype.match({ filename = '~/blog/why_neovim_is_awesome.txt' })
]], root))
end)
it('works with functions', function()
+ command('new')
+ command('file relevant_to_me')
eq('foss', exec_lua [[
vim.filetype.add({
pattern = {
@@ -87,7 +90,7 @@ describe('vim.filetype', function()
end,
}
})
- return vim.filetype.match('relevant_to_me')
+ return vim.filetype.match({ buf = 0 })
]])
end)
end)
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index 6e06304acd..2d1c790d2f 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
-local nvim_dir, command = helpers.nvim_dir, helpers.command
+local testprg, command = helpers.testprg, helpers.command
local nvim_prog = helpers.nvim_prog
local eq, eval = helpers.eq, helpers.eval
local matches = helpers.matches
@@ -150,7 +150,7 @@ describe('cursor with customized highlighting', function()
[3] = {bold = true},
})
screen:attach({rgb=false})
- command('call termopen(["'..nvim_dir..'/tty-test"])')
+ command('call termopen(["'..testprg('tty-test')..'"])')
feed_command('startinsert')
end)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index e7025d6739..aeb4b7cc2e 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -3,7 +3,7 @@ local screen = require('test.functional.ui.screen')
local curbufmeths = helpers.curbufmeths
local curwinmeths = helpers.curwinmeths
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local command = helpers.command
local funcs = helpers.funcs
local meths = helpers.meths
@@ -21,7 +21,7 @@ describe(':edit term://*', function()
before_each(function()
clear()
- meths.set_option('shell', nvim_dir .. '/shell-test')
+ meths.set_option('shell', testprg('shell-test'))
meths.set_option('shellcmdflag', 'EXE')
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index b4f29a586a..23b69319f0 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local assert_alive = helpers.assert_alive
local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim
-local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
+local testprg, source, eq = helpers.testprg, helpers.source, helpers.eq
local feed = helpers.feed
local feed_command, eval = helpers.feed_command, helpers.eval
local funcs = helpers.funcs
@@ -28,7 +28,7 @@ describe(':terminal', function()
echomsg "msg3"
]])
-- Invoke a command that emits frequent terminal activity.
- feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 9999 !terminal_output!<cr>]])
+ feed([[:terminal "]]..testprg('shell-test')..[[" REP 9999 !terminal_output!<cr>]])
feed([[<C-\><C-N>]])
poke_eventloop()
-- Wait for some terminal activity.
@@ -131,7 +131,7 @@ describe(':terminal (with fake shell)', function()
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', 'shell', testprg('shell-test'))
nvim('set_option', 'shellcmdflag', 'EXE')
end)
@@ -167,7 +167,7 @@ describe(':terminal (with fake shell)', function()
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
if helpers.pending_win32(pending) then return end
- nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
+ nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
terminal_with_fake_shell()
screen:expect([[
^jeff $ |
@@ -191,7 +191,7 @@ describe(':terminal (with fake shell)', function()
it("executes a given command through the shell, when 'shell' has arguments", function()
if helpers.pending_win32(pending) then return end
- nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
+ nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
screen:expect([[
diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua
index 51ecae663a..bcfd3559e6 100644
--- a/test/functional/terminal/helpers.lua
+++ b/test/functional/terminal/helpers.lua
@@ -3,7 +3,7 @@
-- operate on the _host_ session, _not_ the child session.
local helpers = require('test.functional.helpers')(nil)
local Screen = require('test.functional.ui.screen')
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local feed_command, nvim = helpers.feed_command, helpers.nvim
local function feed_data(data)
@@ -37,7 +37,7 @@ local function clear_attrs() feed_termcode('[0;10m') end
local function enable_mouse() feed_termcode('[?1002h') end
local function disable_mouse() feed_termcode('[?1002l') end
-local default_command = '["'..nvim_dir..'/tty-test'..'"]'
+local default_command = '["'..testprg('tty-test')..'"]'
local function screen_setup(extra_rows, command, cols, opts)
extra_rows = extra_rows and extra_rows or 0
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 2a63971d48..1eb7223dce 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
-local nvim_dir, command = helpers.nvim_dir, helpers.command
+local testprg, command = helpers.testprg, helpers.command
local nvim_prog_abs = helpers.nvim_prog_abs
local eq, eval = helpers.eq, helpers.eval
local funcs = helpers.funcs
@@ -28,7 +28,7 @@ describe(':terminal highlight', function()
[11] = {background = 11},
})
screen:attach({rgb=false})
- command('enew | call termopen(["'..nvim_dir..'/tty-test"])')
+ command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i')
screen:expect([[
tty ready |
@@ -173,7 +173,7 @@ describe(':terminal highlight forwarding', function()
[4] = {{foreground = tonumber('0xff8000')}, {}},
})
screen:attach()
- command('enew | call termopen(["'..nvim_dir..'/tty-test"])')
+ command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i')
screen:expect([[
tty ready |
@@ -225,7 +225,7 @@ describe(':terminal highlight with custom palette', function()
})
screen:attach({rgb=true})
nvim('set_var', 'terminal_color_3', '#123456')
- command('enew | call termopen(["'..nvim_dir..'/tty-test"])')
+ command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i')
screen:expect([[
tty ready |
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index b1d3b502b2..b491cb2735 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -2,7 +2,7 @@ local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
-local feed, nvim_dir, feed_command = helpers.feed, helpers.nvim_dir, helpers.feed_command
+local feed, testprg, feed_command = helpers.feed, helpers.testprg, helpers.feed_command
local iswin = helpers.iswin
local eval = helpers.eval
local command = helpers.command
@@ -350,7 +350,7 @@ describe(':terminal prints more lines than the screen height and exits', functio
clear()
local screen = Screen.new(30, 7)
screen:attach({rgb=false})
- feed_command('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert')
+ feed_command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test')))
poke_eventloop()
screen:expect([[
line6 |
@@ -382,7 +382,7 @@ describe("'scrollback' option", function()
local function set_fake_shell()
-- shell-test.c is a fake shell that prints its arguments and exits.
- nvim('set_option', 'shell', nvim_dir..'/shell-test')
+ nvim('set_option', 'shell', testprg('shell-test'))
nvim('set_option', 'shellcmdflag', 'EXE')
end
@@ -403,7 +403,7 @@ describe("'scrollback' option", function()
end
curbufmeths.set_option('scrollback', 0)
- feed_data(nvim_dir..'/shell-test REP 31 line'..(iswin() and '\r' or '\n'))
+ feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n'))
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(7) end)
end)
@@ -423,7 +423,7 @@ describe("'scrollback' option", function()
-- Wait for prompt.
screen:expect{any='%$'}
- feed_data(nvim_dir.."/shell-test REP 31 line"..(iswin() and '\r' or '\n'))
+ feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n'))
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(33, 2) end)
@@ -436,7 +436,7 @@ describe("'scrollback' option", function()
-- 'scrollback' option is synchronized with the internal sb_buffer.
command('sleep 100m')
- feed_data(nvim_dir.."/shell-test REP 41 line"..(iswin() and '\r' or '\n'))
+ feed_data(('%s REP 41 line%s'):format(testprg('shell-test'), iswin() and '\r' or '\n'))
if iswin() then
screen:expect{grid=[[
37: line |
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 8c6cba4def..89704be820 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -14,7 +14,7 @@ local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
local clear = helpers.clear
local command = helpers.command
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local retry = helpers.retry
local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
@@ -385,7 +385,7 @@ describe('TUI', function()
return
end
feed_data(':set statusline=^^^^^^^\n')
- feed_data(':terminal '..nvim_dir..'/tty-test\n')
+ feed_data(':terminal '..testprg('tty-test')..'\n')
feed_data('i')
screen:expect{grid=[[
tty ready |
@@ -903,7 +903,7 @@ describe('TUI', function()
feed_data(':set statusline=^^^^^^^\n')
feed_data(':set termguicolors\n')
- feed_data(':terminal '..nvim_dir..'/tty-test\n')
+ feed_data(':terminal '..testprg('tty-test')..'\n')
-- Depending on platform the above might or might not fit in the cmdline
-- so clear it for consistent behavior.
feed_data(':\027')
@@ -1130,7 +1130,7 @@ describe('TUI FocusGained/FocusLost', function()
end)
it('in terminal-mode', function()
- feed_data(':set shell='..nvim_dir..'/shell-test\n')
+ feed_data(':set shell='..testprg('shell-test')..'\n')
feed_data(':set noshowmode laststatus=0\n')
feed_data(':terminal\n')
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 925af11627..df7f34aa7f 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -5,7 +5,7 @@ local clear, insert = helpers.clear, helpers.insert
local command = helpers.command
local meths = helpers.meths
local iswin = helpers.iswin
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local thelpers = require('test.functional.terminal.helpers')
describe('ext_hlstate detailed highlights', function()
@@ -191,7 +191,7 @@ describe('ext_hlstate detailed highlights', function()
[6] = {{foreground = tonumber('0x40ffff'), fg_indexed=true}, {5, 1}},
[7] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
})
- command('enew | call termopen(["'..nvim_dir..'/tty-test"])')
+ command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
screen:expect([[
^tty ready |
{1: } |
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 98ed564966..7a42e72732 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -17,7 +17,7 @@ local source = helpers.source
local poke_eventloop = helpers.poke_eventloop
local nvim = helpers.nvim
local sleep = helpers.sleep
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local assert_alive = helpers.assert_alive
local default_text = [[
@@ -2875,7 +2875,7 @@ it(':substitute with inccommand during :terminal activity', function()
clear()
command("set cmdwinheight=3")
- feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 xxx<cr>]])
+ feed(([[:terminal "%s" REP 5000 xxx<cr>]]):format(testprg('shell-test')))
command('file term')
feed('G') -- Follow :terminal output.
command('new')
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 50e5dfac84..71c6410013 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -9,6 +9,7 @@ local feed_command = helpers.feed_command
local iswin = helpers.iswin
local clear = helpers.clear
local command = helpers.command
+local testprg = helpers.testprg
local nvim_dir = helpers.nvim_dir
local has_powershell = helpers.has_powershell
local set_shell_powershell = helpers.set_shell_powershell
@@ -54,7 +55,7 @@ describe("shell command :!", function()
if 'openbsd' == helpers.uname() then
pending('FIXME #10804')
end
- child_session.feed_data(":!"..nvim_dir.."/shell-test REP 30001 foo\n")
+ child_session.feed_data((":!%s REP 30001 foo\n"):format(testprg('shell-test')))
-- If we observe any line starting with a dot, then throttling occurred.
-- Avoid false failure on slow systems.
@@ -207,12 +208,7 @@ describe("shell command :!", function()
it('handles multibyte sequences split over buffer boundaries', function()
command('cd '..nvim_dir)
- local cmd
- if iswin() then
- cmd = '!shell-test UTF-8 '
- else
- cmd = '!./shell-test UTF-8'
- end
+ local cmd = iswin() and '!shell-test UTF-8 ' or '!./shell-test UTF-8'
feed_command(cmd)
-- Note: only the first example of split composed char works
screen:expect([[
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index cdb6256f77..c3b9af5e72 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local feed_command = helpers.feed_command
local eq = helpers.eq
local eval = helpers.eval
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
describe('search highlighting', function()
local screen
@@ -305,7 +305,7 @@ describe('search highlighting', function()
end)
it('is preserved during :terminal activity', function()
- feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 foo<cr>]])
+ feed((':terminal "%s" REP 5000 foo<cr>'):format(testprg('shell-test')))
feed(':file term<CR>')
feed('G') -- Follow :terminal output.
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 65c6fabfa8..98398bc7a1 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -7,7 +7,7 @@ local meths = helpers.meths
local eq = helpers.eq
local eval = helpers.eval
local retry = helpers.retry
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
describe("'wildmenu'", function()
local screen
@@ -114,7 +114,7 @@ describe("'wildmenu'", function()
it('is preserved during :terminal activity', function()
command('set wildmenu wildmode=full')
command('set scrollback=4')
- feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 !terminal_output!<cr>]])
+ feed((':terminal "%s" REP 5000 !terminal_output!<cr>'):format(testprg('shell-test')))
feed('G') -- Follow :terminal output.
feed([[:sign <Tab>]]) -- Invoke wildmenu.
-- NB: in earlier versions terminal output was redrawn during cmdline mode.
diff --git a/test/functional/vimscript/let_spec.lua b/test/functional/vimscript/let_spec.lua
index 6e93655e32..85c9c690f9 100644
--- a/test/functional/vimscript/let_spec.lua
+++ b/test/functional/vimscript/let_spec.lua
@@ -7,7 +7,7 @@ local eval = helpers.eval
local meths = helpers.meths
local exec_capture = helpers.exec_capture
local source = helpers.source
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
before_each(clear)
@@ -59,7 +59,7 @@ describe(':let', function()
end)
it("multibyte env var to child process #8398 #9267", function()
- local cmd_get_child_env = "let g:env_from_child = system(['"..nvim_dir.."/printenv-test', 'NVIM_TEST_LET'])"
+ local cmd_get_child_env = ("let g:env_from_child = system(['%s', 'NVIM_TEST_LET'])"):format(testprg('printenv-test'))
command("let $NVIM_TEST_LET = 'AìaB'")
command(cmd_get_child_env)
eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child'))
diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua
index 9cc6424d31..c915556c57 100644
--- a/test/functional/vimscript/system_spec.lua
+++ b/test/functional/vimscript/system_spec.lua
@@ -1,11 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
local assert_alive = helpers.assert_alive
-local nvim_dir = helpers.nvim_dir
+local testprg = helpers.testprg
local eq, call, clear, eval, feed_command, feed, nvim =
helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command,
helpers.feed, helpers.nvim
local command = helpers.command
+local insert = helpers.insert
+local expect = helpers.expect
local exc_exec = helpers.exc_exec
local iswin = helpers.iswin
local os_kill = helpers.os_kill
@@ -30,10 +32,6 @@ describe('system()', function()
before_each(clear)
describe('command passed as a List', function()
- local function printargs_path()
- return nvim_dir..'/printargs-test' .. (iswin() and '.exe' or '')
- end
-
it('throws error if cmd[0] is not executable', function()
eq("Vim:E475: Invalid value for argument cmd: 'this-should-not-exist' is not executable",
pcall_err(call, 'system', { 'this-should-not-exist' }))
@@ -66,23 +64,23 @@ describe('system()', function()
it('quotes arguments correctly #5280', function()
local out = call('system',
- { printargs_path(), [[1]], [[2 "3]], [[4 ' 5]], [[6 ' 7']] })
+ { testprg('printargs-test'), [[1]], [[2 "3]], [[4 ' 5]], [[6 ' 7']] })
eq(0, eval('v:shell_error'))
eq([[arg1=1;arg2=2 "3;arg3=4 ' 5;arg4=6 ' 7';]], out)
- out = call('system', { printargs_path(), [['1]], [[2 "3]] })
+ out = call('system', { testprg('printargs-test'), [['1]], [[2 "3]] })
eq(0, eval('v:shell_error'))
eq([[arg1='1;arg2=2 "3;]], out)
- out = call('system', { printargs_path(), "A\nB" })
+ out = call('system', { testprg('printargs-test'), "A\nB" })
eq(0, eval('v:shell_error'))
eq("arg1=A\nB;", out)
end)
it('calls executable in $PATH', function()
- if 0 == eval("executable('python')") then pending("missing `python`") end
- eq("foo\n", eval([[system(['python', '-c', 'print("foo")'])]]))
+ if 0 == eval("executable('python3')") then pending("missing `python3`") end
+ eq("foo\n", eval([[system(['python3', '-c', 'print("foo")'])]]))
eq(0, eval('v:shell_error'))
end)
@@ -167,7 +165,7 @@ describe('system()', function()
end
end)
- it('works with powershell', function()
+ it('with powershell', function()
helpers.set_shell_powershell()
eq('a\nb\n', eval([[system('Write-Output a b')]]))
eq('C:\\\n', eval([[system('cd c:\; (Get-Location).Path')]]))
@@ -175,12 +173,11 @@ describe('system()', function()
end)
end
- it('works with powershell w/ UTF-8 text (#13713)', function()
+ it('powershell w/ UTF-8 text #13713', function()
if not helpers.has_powershell() then
- pending("not tested; powershell was not found", function() end)
+ pending("powershell not found", function() end)
return
end
- -- Should work with recommended config used in helper
helpers.set_shell_powershell()
eq('ああ\n', eval([[system('Write-Output "ああ"')]]))
-- Sanity test w/ default encoding
@@ -430,7 +427,7 @@ describe('system()', function()
end)
it("with a program that doesn't close stdout will exit properly after passing input", function()
- local out = eval(string.format("system('%s', 'clip-data')", nvim_dir..'/streams-test'))
+ local out = eval(string.format("system('%s', 'clip-data')", testprg('streams-test')))
assert(out:sub(0, 5) == 'pid: ', out)
os_kill(out:match("%d+"))
end)
@@ -609,17 +606,16 @@ describe('systemlist()', function()
end)
it("with a program that doesn't close stdout will exit properly after passing input", function()
- local out = eval(string.format("systemlist('%s', 'clip-data')", nvim_dir..'/streams-test'))
+ local out = eval(string.format("systemlist('%s', 'clip-data')", testprg('streams-test')))
assert(out[1]:sub(0, 5) == 'pid: ', out)
os_kill(out[1]:match("%d+"))
end)
- it('works with powershell w/ UTF-8 text (#13713)', function()
+ it('powershell w/ UTF-8 text #13713', function()
if not helpers.has_powershell() then
- pending("not tested; powershell was not found", function() end)
+ pending("powershell not found", function() end)
return
end
- -- Should work with recommended config used in helper
helpers.set_shell_powershell()
eq({iswin() and 'あ\r' or 'あ'}, eval([[systemlist('Write-Output あ')]]))
-- Sanity test w/ default encoding
@@ -630,3 +626,31 @@ describe('systemlist()', function()
end)
end)
+
+describe('shell :!', function()
+ before_each(clear)
+
+ it(':{range}! with powershell filter/redirect #16271', function()
+ local screen = Screen.new(500, 8)
+ screen:attach()
+ local found = helpers.set_shell_powershell(true)
+ insert([[
+ 3
+ 1
+ 4
+ 2]])
+ feed(':4verbose %!sort<cr>')
+ screen:expect{
+ any=[[Executing command: .?Start%-Process sort %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]]
+ }
+ feed('<CR>')
+ if found then
+ -- Not using fake powershell, so we can test the result.
+ expect([[
+ 1
+ 2
+ 3
+ 4]])
+ end
+ end)
+end)