aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/health/nvim.vim12
-rw-r--r--runtime/autoload/health/provider.vim18
-rw-r--r--runtime/doc/builtin.txt25
-rw-r--r--runtime/doc/eval.txt2
-rw-r--r--runtime/doc/message.txt3
-rw-r--r--runtime/doc/options.txt2
-rwxr-xr-xscripts/gen_vimdoc.py1
-rw-r--r--src/nvim/api/private/helpers.c19
-rw-r--r--src/nvim/api/window.c9
-rw-r--r--src/nvim/autocmd.c12
-rw-r--r--src/nvim/autocmd.h1
-rw-r--r--src/nvim/debugger.c4
-rw-r--r--src/nvim/eval.c17
-rw-r--r--src/nvim/eval/funcs.c36
-rw-r--r--src/nvim/ex_cmds.c4
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/ex_eval.c8
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/fileio.c4
-rw-r--r--src/nvim/if_cscope.c6
-rw-r--r--src/nvim/lua/executor.c4
-rw-r--r--src/nvim/message.c9
-rw-r--r--src/nvim/move.c6
-rw-r--r--src/nvim/normal.c19
-rw-r--r--src/nvim/ops.c36
-rw-r--r--src/nvim/option.c20
-rw-r--r--src/nvim/popupmnu.c8
-rw-r--r--src/nvim/screen.c4
-rw-r--r--src/nvim/sign.c8
-rw-r--r--src/nvim/testdir/check.vim17
-rw-r--r--src/nvim/testdir/shared.vim9
-rw-r--r--src/nvim/testdir/test_alot_utf8.vim1
-rw-r--r--src/nvim/testdir/test_autocmd.vim10
-rw-r--r--src/nvim/testdir/test_cscope.vim4
-rw-r--r--src/nvim/testdir/test_execute_func.vim27
-rw-r--r--src/nvim/testdir/test_expand.vim83
-rw-r--r--src/nvim/testdir/test_functions.vim69
-rw-r--r--src/nvim/testdir/test_number.vim4
-rw-r--r--src/nvim/testdir/test_put.vim35
-rw-r--r--src/nvim/testdir/test_quickfix.vim1
-rw-r--r--src/nvim/testdir/test_rename.vim4
-rw-r--r--src/nvim/testdir/test_search_stat.vim67
-rw-r--r--src/nvim/testdir/test_source_utf8.vim27
-rw-r--r--src/nvim/testdir/test_swap.vim20
-rw-r--r--src/nvim/testdir/test_utf8_comparisons.vim5
-rw-r--r--src/nvim/testdir/test_writefile.vim2
-rw-r--r--src/nvim/tui/input.c1
-rw-r--r--src/nvim/version.c2
-rw-r--r--src/nvim/window.c53
-rw-r--r--src/nvim/window.h33
-rw-r--r--test/functional/autocmd/focus_spec.lua2
-rw-r--r--test/functional/legacy/expand_spec.lua129
-rw-r--r--test/functional/legacy/search_stat_spec.lua121
-rw-r--r--test/functional/lua/vim_spec.lua80
-rw-r--r--test/functional/plugin/health_spec.lua11
-rw-r--r--test/functional/ui/input_spec.lua2
-rw-r--r--test/helpers.lua2
57 files changed, 754 insertions, 367 deletions
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim
index ef680097d5..961f83d926 100644
--- a/runtime/autoload/health/nvim.vim
+++ b/runtime/autoload/health/nvim.vim
@@ -148,14 +148,14 @@ endfunction
function! s:get_tmux_option(option) abort
let cmd = 'tmux show-option -qvg '.a:option " try global scope
- let out = system(cmd)
+ let out = system(split(cmd))
let val = substitute(out, '\v(\s|\r|\n)', '', 'g')
if v:shell_error
call health#report_error('command failed: '.cmd."\n".out)
return 'error'
elseif empty(val)
let cmd = 'tmux show-option -qvgs '.a:option " try session scope
- let out = system(cmd)
+ let out = system(split(cmd))
let val = substitute(out, '\v(\s|\r|\n)', '', 'g')
if v:shell_error
call health#report_error('command failed: '.cmd."\n".out)
@@ -202,11 +202,11 @@ function! s:check_tmux() abort
" check default-terminal and $TERM
call health#report_info('$TERM: '.$TERM)
let cmd = 'tmux show-option -qvg default-terminal'
- let out = system(cmd)
+ let out = system(split(cmd))
let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g')
if empty(tmux_default_term)
let cmd = 'tmux show-option -qvgs default-terminal'
- let out = system(cmd)
+ let out = system(split(cmd))
let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g')
endif
@@ -225,7 +225,7 @@ function! s:check_tmux() abort
endif
" check for RGB capabilities
- let info = system('tmux server-info')
+ let info = system(['tmux', 'server-info'])
let has_tc = stridx(info, " Tc: (flag) true") != -1
let has_rgb = stridx(info, " RGB: (flag) true") != -1
if !has_tc && !has_rgb
@@ -242,7 +242,7 @@ function! s:check_terminal() abort
endif
call health#report_start('terminal')
let cmd = 'infocmp -L'
- let out = system(cmd)
+ let out = system(split(cmd))
let kbs_entry = matchstr(out, 'key_backspace=[^,[:space:]]*')
let kdch1_entry = matchstr(out, 'key_dc=[^,[:space:]]*')
diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim
index 8f0dbbab39..2f35179338 100644
--- a/runtime/autoload/health/provider.vim
+++ b/runtime/autoload/health/provider.vim
@@ -565,7 +565,7 @@ function! s:check_ruby() abort
\ ['Install Ruby and verify that `ruby` and `gem` commands work.'])
return
endif
- call health#report_info('Ruby: '. s:system('ruby -v'))
+ call health#report_info('Ruby: '. s:system(['ruby', '-v']))
let [host, err] = provider#ruby#Detect()
if empty(host)
@@ -588,11 +588,11 @@ function! s:check_ruby() abort
endif
let latest_gem = get(split(latest_gem, 'neovim (\|, \|)$' ), 0, 'not found')
- let current_gem_cmd = host .' --version'
+ let current_gem_cmd = [host, '--version']
let current_gem = s:system(current_gem_cmd)
if s:shell_error
- call health#report_error('Failed to run: '. current_gem_cmd,
- \ ['Report this issue with the output of: ', current_gem_cmd])
+ call health#report_error('Failed to run: '. join(current_gem_cmd),
+ \ ['Report this issue with the output of: ', join(current_gem_cmd)])
return
endif
@@ -619,7 +619,7 @@ function! s:check_node() abort
\ ['Install Node.js and verify that `node` and `npm` (or `yarn`) commands work.'])
return
endif
- let node_v = get(split(s:system('node -v'), "\n"), 0, '')
+ let node_v = get(split(s:system(['node', '-v']), "\n"), 0, '')
call health#report_info('Node.js: '. node_v)
if s:shell_error || s:version_cmp(node_v[1:], '6.0.0') < 0
call health#report_warn('Nvim node.js host does not support '.node_v)
@@ -660,8 +660,8 @@ function! s:check_node() abort
let current_npm_cmd = ['node', host, '--version']
let current_npm = s:system(current_npm_cmd)
if s:shell_error
- call health#report_error('Failed to run: '. string(current_npm_cmd),
- \ ['Report this issue with the output of: ', string(current_npm_cmd)])
+ call health#report_error('Failed to run: '. join(current_npm_cmd),
+ \ ['Report this issue with the output of: ', join(current_npm_cmd)])
return
endif
@@ -734,8 +734,8 @@ function! s:check_perl() abort
let current_cpan_cmd = [perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION']
let current_cpan = s:system(current_cpan_cmd)
if s:shell_error
- call health#report_error('Failed to run: '. string(current_cpan_cmd),
- \ ['Report this issue with the output of: ', string(current_cpan_cmd)])
+ call health#report_error('Failed to run: '. join(current_cpan_cmd),
+ \ ['Report this issue with the output of: ', join(current_cpan_cmd)])
return
endif
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index bb04376f57..4153c1c9d8 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -3543,24 +3543,25 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The
:if has("win32")
< *feature-list*
List of supported pseudo-feature names:
- acl |ACL| support
+ acl |ACL| support.
bsd BSD system (not macOS, use "mac" for that).
- iconv Can use |iconv()| for conversion.
- +shellslash Can use backslashes in filenames (Windows)
clipboard |clipboard| provider is available.
fname_case Case in file names matters (for Darwin and MS-Windows
this is not present).
+ iconv Can use |iconv()| for conversion.
+ linux Linux system.
mac MacOS system.
nvim This is Nvim.
python3 Legacy Vim |python3| interface. |has-python|
pythonx Legacy Vim |python_x| interface. |has-pythonx|
- ttyin input is a terminal (tty)
- ttyout output is a terminal (tty)
+ sun SunOS system.
+ ttyin input is a terminal (tty).
+ ttyout output is a terminal (tty).
unix Unix system.
*vim_starting* True during |startup|.
win32 Windows system (32 or 64 bit).
win64 Windows system (64 bit).
- wsl WSL (Windows Subsystem for Linux) system
+ wsl WSL (Windows Subsystem for Linux) system.
*has-patch*
3. Vim patch. For example the "patch123" feature means that
@@ -4347,6 +4348,9 @@ line({expr} [, {winid}]) *line()*
line("'t") line number of mark t
line("'" . marker) line number of mark marker
<
+ To jump to the last known position when opening a file see
+ |last-position-jump|.
+
Can also be used as a |method|: >
GetValue()->line()
@@ -4912,8 +4916,10 @@ min({expr}) Return the minimum value of all items in {expr}.
< *mkdir()* *E739*
mkdir({name} [, {path} [, {prot}]])
Create directory {name}.
+
If {path} is "p" then intermediate directories are created as
necessary. Otherwise it must be "".
+
If {prot} is given it is used to set the protection bits of
the new directory. The default is 0o755 (rwxr-xr-x: r/w for
the user, readable for others). Use 0o700 to make it
@@ -4922,6 +4928,7 @@ mkdir({name} [, {path} [, {prot}]])
{prot} is applied for all parts of {name}. Thus if you create
/tmp/foo/bar then /tmp/foo will be created with 0o700. Example: >
:call mkdir($HOME . "/tmp/foo/bar", "p", 0o700)
+
< This function is not available in the |sandbox|.
If you try to create an existing directory with {path} set to
@@ -5758,8 +5765,10 @@ remove({list}, {idx} [, {end}]) *remove()*
Example: >
:echo "last item: " . remove(mylist, -1)
:call remove(mylist, 0, 9)
+<
+ Use |delete()| to remove a file.
-< Can also be used as a |method|: >
+ Can also be used as a |method|: >
mylist->remove(idx)
remove({blob}, {idx} [, {end}])
@@ -5779,8 +5788,6 @@ remove({dict}, {key})
:echo "removed " . remove(dict, "one")
< If there is no {key} in {dict} this is an error.
- Use |delete()| to remove a file.
-
rename({from}, {to}) *rename()*
Rename the file by the name {from} to the name {to}. This
should also work to move files across file systems. The
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f2b014dde6..d6486073cf 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -676,7 +676,7 @@ similar to -1. >
:let otherblob = myblob[:] " make a copy of the Blob
If the first index is beyond the last byte of the Blob or the second byte is
-before the first byte, the result is an empty Blob. There is no error
+before the first index, the result is an empty Blob. There is no error
message.
If the second index is equal to or greater than the length of the Blob the
diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt
index 950028d9cc..fa1bc6f7da 100644
--- a/runtime/doc/message.txt
+++ b/runtime/doc/message.txt
@@ -27,8 +27,7 @@ depends on the 'shortmess' option.
Clear messages, keeping only the {count} most
recent ones.
-The number of remembered messages is fixed at 20 for the tiny version and 200
-for other versions.
+The number of remembered messages is fixed at 200.
*g<*
The "g<" command can be used to see the last page of previous command output.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 2984a68ea2..6e2bc228d0 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5462,7 +5462,7 @@ A jump table for the options with a short description can be found at |Q_op|.
flag meaning when present ~
f use "(3 of 5)" instead of "(file 3 of 5)"
i use "[noeol]" instead of "[Incomplete last line]"
- l use "999L, 888C" instead of "999 lines, 888 characters"
+ l use "999L, 888B" instead of "999 lines, 888 bytes"
m use "[+]" instead of "[Modified]"
n use "[New]" instead of "[New File]"
r use "[RO]" instead of "[readonly]"
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 3e9fb21039..61fa5971a4 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -96,7 +96,6 @@ CONFIG = {
'win_config.c',
'tabpage.c',
'ui.c',
- 'extmark.c',
],
# List of files/directories for doxygen to read, separated by blanks
'files': os.path.join(base_dir, 'src/nvim/api'),
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index f540f8f7ee..ddcfff0097 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -139,10 +139,10 @@ bool try_end(Error *err)
got_int = false;
} else if (msg_list != NULL && *msg_list != NULL) {
int should_free;
- char *msg = (char *)get_exception_string(*msg_list,
- ET_ERROR,
- NULL,
- &should_free);
+ char *msg = get_exception_string(*msg_list,
+ ET_ERROR,
+ NULL,
+ &should_free);
api_set_error(err, kErrorTypeException, "%s", msg);
free_global_msglist();
@@ -720,7 +720,6 @@ fail_and_free:
xfree(parsed_args.rhs);
xfree(parsed_args.orig_rhs);
XFREE_CLEAR(parsed_args.desc);
- return;
}
/// Collects `n` buffer lines into array `l`, optionally replacing newlines
@@ -990,18 +989,16 @@ Object copy_object(Object obj)
static void set_option_value_for(char *key, int numval, char *stringval, int opt_flags,
int opt_type, void *from, Error *err)
{
- win_T *save_curwin = NULL;
- tabpage_T *save_curtab = NULL;
+ switchwin_T switchwin;
aco_save_T aco;
try_start();
switch (opt_type)
{
case SREQ_WIN:
- if (switch_win_noblock(&save_curwin, &save_curtab, (win_T *)from,
- win_find_tabpage((win_T *)from), true)
+ if (switch_win_noblock(&switchwin, (win_T *)from, win_find_tabpage((win_T *)from), true)
== FAIL) {
- restore_win_noblock(save_curwin, save_curtab, true);
+ restore_win_noblock(&switchwin, true);
if (try_end(err)) {
return;
}
@@ -1011,7 +1008,7 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt
return;
}
set_option_value_err(key, numval, stringval, opt_flags, err);
- restore_win_noblock(save_curwin, save_curtab, true);
+ restore_win_noblock(&switchwin, true);
break;
case SREQ_BUF:
aucmd_prepbuf(&aco, (buf_T *)from);
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 907306da7b..9fd4de4bb2 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -455,17 +455,12 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
}
tabpage_T *tabpage = win_find_tabpage(win);
- win_T *save_curwin;
- tabpage_T *save_curtab;
-
try_start();
Object res = OBJECT_INIT;
- if (switch_win_noblock(&save_curwin, &save_curtab, win, tabpage, true) ==
- OK) {
+ WIN_EXECUTE(win, tabpage, {
Array args = ARRAY_DICT_INIT;
res = nlua_call_ref(fun, NULL, args, true, err);
- }
- restore_win_noblock(save_curwin, save_curtab, true);
+ });
try_end(err);
return res;
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 94ac389139..2e7f9c5136 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1069,8 +1069,6 @@ void ex_doautoall(exarg_T *eap)
do_modelines(0);
}
}
-
- check_cursor(); // just in case lines got deleted
}
/// Check *argp for <nomodeline>. When it is present return false, otherwise
@@ -1171,6 +1169,10 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
curbuf = buf;
aco->new_curwin_handle = curwin->handle;
set_bufref(&aco->new_curbuf, curbuf);
+
+ // disable the Visual area, the position may be invalid in another buffer
+ aco->save_VIsual_active = VIsual_active;
+ VIsual_active = false;
}
/// Cleanup after executing autocommands for a (hidden) buffer.
@@ -1267,6 +1269,12 @@ win_found:
check_cursor();
}
}
+
+ check_cursor(); // just in case lines got deleted
+ VIsual_active = aco->save_VIsual_active;
+ if (VIsual_active) {
+ check_pos(curbuf, &VIsual);
+ }
}
/// Execute autocommands for "event" and file name "fname".
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index ac12e2acf3..63c5abd4f8 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -14,6 +14,7 @@ typedef struct {
handle_T save_prevwin_handle; ///< ID of saved prevwin
bufref_T new_curbuf; ///< new curbuf
char_u *globaldir; ///< saved value of globaldir
+ bool save_VIsual_active; ///< saved VIsual_active
} aco_save_T;
typedef struct AutoCmd {
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index b6e35f3047..75ebf0084e 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -268,7 +268,7 @@ void do_debug(char_u *cmd)
DOCMD_VERBOSE|DOCMD_EXCRESET);
debug_break_level = n;
}
- lines_left = (int)(Rows - 1);
+ lines_left = Rows - 1;
}
xfree(cmdline);
@@ -277,7 +277,7 @@ void do_debug(char_u *cmd)
redraw_all_later(NOT_VALID);
need_wait_return = false;
msg_scroll = save_msg_scroll;
- lines_left = (int)(Rows - 1);
+ lines_left = Rows - 1;
State = save_State;
debug_mode = false;
did_emsg = save_did_emsg;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b8e9f41551..5d9326eb24 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6963,10 +6963,9 @@ win_T *find_tabwin(typval_T *wvp, typval_T *tvp)
/// @param off 1 for gettabwinvar()
void getwinvar(typval_T *argvars, typval_T *rettv, int off)
{
- win_T *win, *oldcurwin;
+ win_T *win;
dictitem_T *v;
tabpage_T *tp = NULL;
- tabpage_T *oldtabpage = NULL;
bool done = false;
if (off == 1) {
@@ -6986,8 +6985,8 @@ void getwinvar(typval_T *argvars, typval_T *rettv, int off)
// otherwise the window is not valid. Only do this when needed,
// autocommands get blocked.
bool need_switch_win = tp != curtab || win != curwin;
- if (!need_switch_win
- || switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) {
+ switchwin_T switchwin;
+ if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) {
if (*varname == '&') {
if (varname[1] == NUL) {
// get all window-local options in a dict
@@ -7015,7 +7014,7 @@ void getwinvar(typval_T *argvars, typval_T *rettv, int off)
if (need_switch_win) {
// restore previous notion of curwin
- restore_win(oldcurwin, oldtabpage, true);
+ restore_win(&switchwin, true);
}
}
emsg_off--;
@@ -7517,11 +7516,9 @@ void setwinvar(typval_T *argvars, typval_T *rettv, int off)
typval_T *varp = &argvars[off + 2];
if (win != NULL && varname != NULL && varp != NULL) {
- win_T *save_curwin;
- tabpage_T *save_curtab;
bool need_switch_win = tp != curtab || win != curwin;
- if (!need_switch_win
- || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) {
+ switchwin_T switchwin;
+ if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) {
if (*varname == '&') {
long numval;
bool error = false;
@@ -7543,7 +7540,7 @@ void setwinvar(typval_T *argvars, typval_T *rettv, int off)
}
}
if (need_switch_win) {
- restore_win(save_curwin, save_curtab, true);
+ restore_win(&switchwin, true);
}
}
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 29619f62e9..50030f2994 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2176,25 +2176,12 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *tp;
win_T *wp = win_id2wp_tp(argvars, &tp);
- win_T *save_curwin;
- tabpage_T *save_curtab;
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
if (wp != NULL && tp != NULL) {
- pos_T curpos = wp->w_cursor;
- if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) ==
- OK) {
- check_cursor();
- execute_common(argvars, rettv, fptr, 1);
- }
- restore_win_noblock(save_curwin, save_curtab, true);
-
- // Update the status line if the cursor moved.
- if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) {
- wp->w_redr_status = true;
- }
+ WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
}
}
@@ -4031,8 +4018,6 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- win_T *oldcurwin;
- tabpage_T *oldtabpage;
bool done = false;
rettv->v_type = VAR_STRING;
@@ -4046,7 +4031,8 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
win_T *const window = tp == curtab || tp->tp_firstwin == NULL
? firstwin
: tp->tp_firstwin;
- if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
+ switchwin_T switchwin;
+ if (switch_win(&switchwin, window, tp, true) == OK) {
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
@@ -4059,7 +4045,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// restore previous notion of curwin
- restore_win(oldcurwin, oldtabpage, true);
+ restore_win(&switchwin, true);
}
if (!done && argvars[2].v_type != VAR_UNKNOWN) {
@@ -4433,6 +4419,12 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#if defined(BSD) && !defined(__APPLE__)
"bsd",
#endif
+#ifdef __linux__
+ "linux",
+#endif
+#ifdef SUN_SYSTEM
+ "sun",
+#endif
#ifdef UNIX
"unix",
#endif
@@ -5881,18 +5873,16 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (argvars[1].v_type != VAR_UNKNOWN) {
tabpage_T *tp;
- win_T *save_curwin;
- tabpage_T *save_curtab;
// use window specified in the second argument
win_T *wp = win_id2wp_tp(&argvars[1], &tp);
if (wp != NULL && tp != NULL) {
- if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true)
- == OK) {
+ switchwin_T switchwin;
+ if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
check_cursor();
fp = var2fpos(&argvars[0], true, &fnum);
}
- restore_win_noblock(save_curwin, save_curtab, true);
+ restore_win_noblock(&switchwin, true);
}
} else {
// use current window
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index e6d63d08a7..1916fa7e44 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1366,7 +1366,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd,
ui_cursor_goto(Rows - 1, 0);
if (do_out) {
- if (u_save((line2), (linenr_T)(line2 + 1)) == FAIL) {
+ if (u_save(line2, (linenr_T)(line2 + 1)) == FAIL) {
xfree(cmd_buf);
goto error;
}
@@ -3055,7 +3055,7 @@ void ex_append(exarg_T *eap)
// it is the same as "start" -- Acevedo
if (!cmdmod.lockmarks) {
curbuf->b_op_start.lnum
- = (eap->line2 < curbuf->b_ml.ml_line_count) ? eap->line2 + 1 : curbuf->b_ml.ml_line_count;
+ = (eap->line2 < curbuf->b_ml.ml_line_count) ? eap->line2 + 1 : curbuf->b_ml.ml_line_count;
if (eap->cmdidx != CMD_append) {
curbuf->b_op_start.lnum--;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index b94fe47c17..d884838136 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -8139,6 +8139,7 @@ static void ex_put(exarg_T *eap)
eap->forceit = TRUE;
}
curwin->w_cursor.lnum = eap->line2;
+ check_cursor_col();
do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1,
PUT_LINE|PUT_CURSLINE);
}
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index b1c59a607c..851828afcf 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -599,7 +599,7 @@ static void catch_exception(except_T *excp)
{
excp->caught = caught_stack;
caught_stack = excp;
- set_vim_var_string(VV_EXCEPTION, (char *)excp->value, -1);
+ set_vim_var_string(VV_EXCEPTION, excp->value, -1);
if (*excp->throw_name != NUL) {
if (excp->throw_lnum != 0) {
vim_snprintf((char *)IObuff, IOSIZE, _("%s, line %" PRId64),
@@ -650,7 +650,7 @@ static void finish_exception(except_T *excp)
}
caught_stack = caught_stack->caught;
if (caught_stack != NULL) {
- set_vim_var_string(VV_EXCEPTION, (char *)caught_stack->value, -1);
+ set_vim_var_string(VV_EXCEPTION, caught_stack->value, -1);
if (*caught_stack->throw_name != NUL) {
if (caught_stack->throw_lnum != 0) {
vim_snprintf((char *)IObuff, IOSIZE,
@@ -733,7 +733,7 @@ static void report_pending(int action, int pending, void *value)
vim_snprintf((char *)IObuff, IOSIZE,
mesg, _("Exception"));
mesg = (char *)concat_str(IObuff, (char_u *)": %s");
- s = (char *)((except_T *)value)->value;
+ s = ((except_T *)value)->value;
} else if ((pending & CSTP_ERROR) && (pending & CSTP_INTERRUPT)) {
s = _("Error and interrupt");
} else if (pending & CSTP_ERROR) {
@@ -1620,7 +1620,7 @@ void ex_endtry(exarg_T *eap)
// the finally clause. The latter case need not be tested since then
// anything pending has already been discarded.
bool skip = did_emsg || got_int || current_exception
- || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
+ || !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
eap->errmsg = get_end_emsg(cstack);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 3bb5d37212..f81f49a174 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -311,7 +311,7 @@ static char_u *get_healthcheck_names(expand_T *xp, int idx)
healthchecks.last_gen = last_prompt_id;
}
return idx <
- (int)healthchecks.names.ga_len ? ((char_u **)(healthchecks.names.ga_data))[idx] : NULL;
+ healthchecks.names.ga_len ? ((char_u **)(healthchecks.names.ga_data))[idx] : NULL;
}
/// Transform healthcheck file path into it's name.
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index f6d37adf89..f28ee1bfcb 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -3863,7 +3863,7 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars)
*p++ = ' ';
}
if (shortmess(SHM_LINES)) {
- vim_snprintf((char *)p, IOSIZE - (p - IObuff), "%" PRId64 "L, %" PRId64 "C",
+ vim_snprintf((char *)p, IOSIZE - (p - IObuff), "%" PRId64 "L, %" PRId64 "B",
(int64_t)lnum, (int64_t)nchars);
} else {
vim_snprintf((char *)p, IOSIZE - (p - IObuff),
@@ -3871,7 +3871,7 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars)
(int64_t)lnum);
p += STRLEN(p);
vim_snprintf((char *)p, IOSIZE - (p - IObuff),
- NGETTEXT("%" PRId64 " character", "%" PRId64 " characters", nchars),
+ NGETTEXT("%" PRId64 " byte", "%" PRId64 " bytes", nchars),
(int64_t)nchars);
}
}
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index daef8db267..9ca01137cf 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -919,8 +919,8 @@ static int cs_find(exarg_T *eap)
/// Common code for cscope find, shared by cs_find() and ex_cstag().
-static bool cs_find_common(char *opt, char *pat, int forceit, int verbose,
- bool use_ll, char_u *cmdline)
+static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool use_ll,
+ char_u *cmdline)
{
char *cmd;
int *nummatches;
@@ -1594,7 +1594,6 @@ static char *cs_pathcomponents(char *path)
char *s = path + strlen(path) - 1;
for (int i = 0; i < p_cspc; i++) {
while (s > path && *--s != '/') {
- continue;
}
}
if ((s > path && *s == '/')) {
@@ -1813,7 +1812,6 @@ static int cs_read_prompt(size_t i)
static void sig_handler(int s)
{
// do nothing
- return;
}
#endif
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 5c4d7e3c91..cbfb8364f6 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -682,7 +682,7 @@ int nlua_call(lua_State *lstate)
typval_T vim_args[MAX_FUNC_ARGS + 1];
int i = 0; // also used for freeing the variables
for (; i < nargs; i++) {
- lua_pushvalue(lstate, (int)i+2);
+ lua_pushvalue(lstate, i+2);
if (!nlua_pop_typval(lstate, &vim_args[i])) {
api_set_error(&err, kErrorTypeException,
"error converting argument %d", i+1);
@@ -747,7 +747,7 @@ static int nlua_rpc(lua_State *lstate, bool request)
Array args = ARRAY_DICT_INIT;
for (int i = 0; i < nargs; i++) {
- lua_pushvalue(lstate, (int)i+3);
+ lua_pushvalue(lstate, i+3);
ADD(args, nlua_pop_Object(lstate, false, &err));
if (ERROR_SET(&err)) {
api_free_array(args);
diff --git a/src/nvim/message.c b/src/nvim/message.c
index e1e253cd2e..d963cba6cb 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -262,7 +262,6 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea
if (*s != NUL) {
msg_outtrans_attr((char_u *)s, attr);
}
- return;
}
@@ -329,7 +328,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
}
retval = msg_end();
- if (keep && retval && vim_strsize((char_u *)s) < (int)(Rows - cmdline_row - 1)
+ if (keep && retval && vim_strsize((char_u *)s) < (Rows - cmdline_row - 1)
* Columns + sc_col) {
set_keep_msg((char *)s, 0);
}
@@ -356,10 +355,10 @@ char_u *msg_strtrunc(char_u *s, int force)
len = vim_strsize(s);
if (msg_scrolled != 0) {
// Use all the columns.
- room = (int)(Rows - msg_row) * Columns - 1;
+ room = (Rows - msg_row) * Columns - 1;
} else {
// Use up to 'showcmd' column.
- room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1;
+ room = (Rows - msg_row - 1) * Columns + sc_col - 1;
}
if (len > room && room > 0) {
// may have up to 18 bytes per cell (6 per char, up to two
@@ -873,7 +872,7 @@ char_u *msg_may_trunc(bool force, char_u *s)
{
int room;
- room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
+ room = (Rows - cmdline_row - 1) * Columns + sc_col - 1;
if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
&& (int)STRLEN(s) - room > 0) {
int size = vim_strsize(s);
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 67ec19903f..27cc2b341c 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -346,10 +346,10 @@ void update_topline(win_T *wp)
*/
void update_topline_win(win_T *win)
{
- win_T *save_curwin;
- switch_win(&save_curwin, NULL, win, NULL, true);
+ switchwin_T switchwin;
+ switch_win(&switchwin, win, NULL, true);
update_topline(curwin);
- restore_win(save_curwin, NULL, true);
+ restore_win(&switchwin, true);
}
/*
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c597aed545..225c66aae1 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1030,7 +1030,7 @@ static int normal_execute(VimState *state, int key)
s->need_flushbuf = add_to_showcmd(s->c);
- while (normal_get_command_count(s)) { continue; }
+ while (normal_get_command_count(s)) { }
if (s->c == K_EVENT) {
// Save the count values so that ca.opcount and ca.count0 are exactly
@@ -3098,8 +3098,14 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock)
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
|| !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
clearopbeep(oap);
- } else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
- foldOpenCursor();
+ } else {
+ if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
+ foldOpenCursor();
+ }
+ // clear any search statistics
+ if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) {
+ clear_cmdline = true;
+ }
}
}
@@ -4093,7 +4099,7 @@ static void nv_colon(cmdarg_T *cap)
if (is_lua) {
cmd_result = map_execute_lua();
} else {
- // get a command line and execute it
+ // get a command line and execute it
cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
}
@@ -6328,7 +6334,7 @@ static void nv_g_cmd(cmdarg_T *cap)
curwin->w_set_curswant = true;
break;
- case 'M': {
+ case 'M':
oap->motion_type = kMTCharWise;
oap->inclusive = false;
i = linetabsize(get_cursor_line_ptr());
@@ -6338,8 +6344,7 @@ static void nv_g_cmd(cmdarg_T *cap)
coladvance((colnr_T)(i / 2));
}
curwin->w_set_curswant = true;
- }
- break;
+ break;
case '_':
/* "g_": to the last non-blank character in the line or <count> lines
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 11484eee57..b8b639265c 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -381,8 +381,8 @@ static void shift_block(oparg_T *oap, int amount)
}
}
for (; ascii_iswhite(*bd.textstart);) {
- // TODO: is passing bd.textstart for start of the line OK?
- incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (bd.start_vcol));
+ // TODO(fmoralesc): is passing bd.textstart for start of the line OK?
+ incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, bd.start_vcol);
total += incr;
bd.start_vcol += incr;
}
@@ -2789,8 +2789,6 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
curbuf->b_op_end.col = MAXCOL;
}
}
-
- return;
}
// Copy a block range into a register.
@@ -3472,6 +3470,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curwin->w_cursor.col -= first_byte_off;
}
} else {
+ linenr_T new_lnum = new_cursor.lnum;
+ size_t len;
+
// Insert at least one line. When y_type is kMTCharWise, break the first
// line in two.
for (cnt = 1; cnt <= count; cnt++) {
@@ -3488,6 +3489,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
STRCAT(newp, ptr);
// insert second line
ml_append(lnum, newp, (colnr_T)0, false);
+ new_lnum++;
xfree(newp);
oldp = ml_get(lnum);
@@ -3503,10 +3505,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
for (; i < y_size; i++) {
- if ((y_type != kMTCharWise || i < y_size - 1)
- && ml_append(lnum, y_array[i], (colnr_T)0, false)
- == FAIL) {
- goto error;
+ if ((y_type != kMTCharWise || i < y_size - 1)) {
+ if (ml_append(lnum, y_array[i], (colnr_T)0, false) == FAIL) {
+ goto error;
+ }
+ new_lnum++;
}
lnum++;
++nr_lines;
@@ -3556,6 +3559,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
extmark_splice(curbuf, (int)new_cursor.lnum-1, col + 1, 0, 0, 0,
(int)y_size+1, 0, totsize+2, kExtmarkUndo);
}
+
+ if (cnt == 1) {
+ new_lnum = lnum;
+ }
}
error:
@@ -3583,11 +3590,12 @@ error:
// Put the '] mark on the first byte of the last inserted character.
// Correct the length for change in indent.
- curbuf->b_op_end.lnum = lnum;
- col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
+ curbuf->b_op_end.lnum = new_lnum;
+ len = STRLEN(y_array[y_size - 1]);
+ col = (colnr_T)len - lendiff;
if (col > 1) {
curbuf->b_op_end.col = col - 1 - utf_head_off(y_array[y_size - 1],
- y_array[y_size - 1] + col - 1);
+ y_array[y_size - 1] + len - 1);
} else {
curbuf->b_op_end.col = 0;
}
@@ -3606,8 +3614,12 @@ error:
}
curwin->w_cursor.col = 0;
} else {
- curwin->w_cursor.lnum = lnum;
+ curwin->w_cursor.lnum = new_lnum;
curwin->w_cursor.col = col;
+ curbuf->b_op_end = curwin->w_cursor;
+ if (col > 1) {
+ curbuf->b_op_end.col = col - 1;
+ }
}
} else if (y_type == kMTLineWise) {
// put cursor on first non-blank in first inserted line
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 80dde2eda6..2c4c4819ea 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1781,7 +1781,7 @@ static char *illegal_char(char *errbuf, size_t errbuflen, int c)
if (errbuf == NULL) {
return "";
}
- vim_snprintf((char *)errbuf, errbuflen, _("E539: Illegal character <%s>"),
+ vim_snprintf(errbuf, errbuflen, _("E539: Illegal character <%s>"),
(char *)transchar(c));
return errbuf;
}
@@ -2284,12 +2284,12 @@ static char *set_string_option(const int opt_idx, const char *const value, const
*varp = s;
char *const saved_oldval = xstrdup(oldval);
- char *const saved_oldval_l = (oldval_l != NULL) ? xstrdup((char *)oldval_l) : 0;
- char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup((char *)oldval_g) : 0;
+ char *const saved_oldval_l = (oldval_l != NULL) ? xstrdup(oldval_l) : 0;
+ char *const saved_oldval_g = (oldval_g != NULL) ? xstrdup(oldval_g) : 0;
char *const saved_newval = xstrdup(s);
int value_checked = false;
- char *const r = did_set_string_option(opt_idx, (char_u **)varp, (int)true,
+ char *const r = did_set_string_option(opt_idx, (char_u **)varp, true,
(char_u *)oldval,
NULL, 0, opt_flags, &value_checked);
if (r == NULL) {
@@ -2777,7 +2777,7 @@ ambw_end:
if (!ascii_isdigit(*(s - 1))) {
if (errbuf != NULL) {
- vim_snprintf((char *)errbuf, errbuflen,
+ vim_snprintf(errbuf, errbuflen,
_("E526: Missing number after <%s>"),
transchar_byte(*(s - 1)));
errmsg = errbuf;
@@ -2968,7 +2968,7 @@ ambw_end:
}
} else {
if (errbuf != NULL) {
- vim_snprintf((char *)errbuf, errbuflen,
+ vim_snprintf(errbuf, errbuflen,
_("E535: Illegal character after <%c>"),
*--s);
errmsg = errbuf;
@@ -4429,7 +4429,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
// Don't change the value and return early if validation failed.
if (errmsg != NULL) {
- return (char *)errmsg;
+ return errmsg;
}
*pp = value;
@@ -4553,7 +4553,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
// Check the (new) bounds for Rows and Columns here.
if (p_lines < min_rows() && full_screen) {
if (errbuf != NULL) {
- vim_snprintf((char *)errbuf, errbuflen,
+ vim_snprintf(errbuf, errbuflen,
_("E593: Need at least %d lines"), min_rows());
errmsg = errbuf;
}
@@ -4561,7 +4561,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
if (p_columns < MIN_COLUMNS && full_screen) {
if (errbuf != NULL) {
- vim_snprintf((char *)errbuf, errbuflen,
+ vim_snprintf(errbuf, errbuflen,
_("E594: Need at least %d columns"), MIN_COLUMNS);
errmsg = errbuf;
}
@@ -4677,7 +4677,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
check_redraw(options[opt_idx].flags);
- return (char *)errmsg;
+ return errmsg;
}
/// Trigger the OptionSet autocommand.
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index da2ada791f..d7726409b5 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -291,7 +291,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
} else {
assert(Columns - pum_col - pum_scrollbar >= INT_MIN
&& Columns - pum_col - pum_scrollbar <= INT_MAX);
- pum_width = (int)(Columns - pum_col - pum_scrollbar);
+ pum_width = Columns - pum_col - pum_scrollbar;
}
if ((pum_width > max_width + pum_kind_width + pum_extra_width + 1)
@@ -352,12 +352,12 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
// not enough room, will use what we have
if (pum_rl) {
assert(Columns - 1 >= INT_MIN);
- pum_col = (int)(Columns - 1);
+ pum_col = Columns - 1;
} else {
pum_col = 0;
}
assert(Columns - 1 >= INT_MIN);
- pum_width = (int)(Columns - 1);
+ pum_width = Columns - 1;
} else {
if (max_width > p_pw) {
// truncate
@@ -369,7 +369,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
} else {
assert(Columns - max_width >= INT_MIN
&& Columns - max_width <= INT_MAX);
- pum_col = (int)(Columns - max_width);
+ pum_col = Columns - max_width;
}
pum_width = max_width - pum_scrollbar;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 56a658ec6d..7e7115b6af 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -6919,8 +6919,6 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
if (!grid->throttled) {
ui_call_grid_scroll(grid->handle, row, end, col, col+width, -line_count, 0);
}
-
- return;
}
/// delete lines on the screen and move lines up.
@@ -6971,8 +6969,6 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
if (!grid->throttled) {
ui_call_grid_scroll(grid->handle, row, end, col, col+width, line_count, 0);
}
-
- return;
}
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index a308df07d1..8b41781c98 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -1501,28 +1501,28 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict)
if (p == NULL) {
p = "NONE";
}
- tv_dict_add_str(retdict, S_LEN("linehl"), (char *)p);
+ tv_dict_add_str(retdict, S_LEN("linehl"), p);
}
if (sp->sn_text_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_text_hl - 1, false);
if (p == NULL) {
p = "NONE";
}
- tv_dict_add_str(retdict, S_LEN("texthl"), (char *)p);
+ tv_dict_add_str(retdict, S_LEN("texthl"), p);
}
if (sp->sn_cul_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_cul_hl - 1, false);
if (p == NULL) {
p = "NONE";
}
- tv_dict_add_str(retdict, S_LEN("culhl"), (char *)p);
+ tv_dict_add_str(retdict, S_LEN("culhl"), p);
}
if (sp->sn_num_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_num_hl - 1, false);
if (p == NULL) {
p = "NONE";
}
- tv_dict_add_str(retdict, S_LEN("numhl"), (char *)p);
+ tv_dict_add_str(retdict, S_LEN("numhl"), p);
}
}
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index ab26dddbe0..883f036fe1 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -63,6 +63,15 @@ func CheckUnix()
endif
endfunc
+" Command to check for not running on a BSD system.
+" TODO: using this checks should not be needed
+command CheckNotBSD call CheckNotBSD()
+func CheckNotBSD()
+ if has('bsd')
+ throw 'Skipped: does not work on BSD'
+ endif
+endfunc
+
" Command to check that making screendumps is supported.
" Caller must source screendump.vim
command CheckScreendump call CheckScreendump()
@@ -104,6 +113,14 @@ func CheckNotGui()
endif
endfunc
+" Command to check that test is not running as root
+command CheckNotRoot call CheckNotRoot()
+func CheckNotRoot()
+ if IsRoot()
+ throw 'Skipped: cannot run test as root'
+ endif
+endfunc
+
" Command to check that the current language is English
command CheckEnglish call CheckEnglish()
func CheckEnglish()
diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim
index f456ff4250..c2809844ac 100644
--- a/src/nvim/testdir/shared.vim
+++ b/src/nvim/testdir/shared.vim
@@ -343,6 +343,15 @@ func RunVimPiped(before, after, arguments, pipecmd)
return 1
endfunc
+func IsRoot()
+ if !has('unix')
+ return v:false
+ elseif $USER == 'root' || system('id -un') =~ '\<root\>'
+ return v:true
+ endif
+ return v:false
+endfunc
+
" Get all messages but drop the maintainer entry.
func GetMessages()
redir => result
diff --git a/src/nvim/testdir/test_alot_utf8.vim b/src/nvim/testdir/test_alot_utf8.vim
index 70f14320a6..77f5ede4c8 100644
--- a/src/nvim/testdir/test_alot_utf8.vim
+++ b/src/nvim/testdir/test_alot_utf8.vim
@@ -6,7 +6,6 @@
source test_charsearch_utf8.vim
source test_expr_utf8.vim
-source test_matchadd_conceal_utf8.vim
source test_mksession_utf8.vim
source test_regexp_utf8.vim
source test_source_utf8.vim
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 231ab2acf1..433410248b 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -2543,6 +2543,16 @@ func Test_close_autocmd_tab()
%bwipe!
endfunc
+func Test_Visual_doautoall_redraw()
+ call setline(1, ['a', 'b'])
+ new
+ wincmd p
+ call feedkeys("G\<C-V>", 'txn')
+ autocmd User Explode ++once redraw
+ doautoall User Explode
+ %bwipe!
+endfunc
+
func Test_autocmd_closes_window()
au BufNew,BufWinLeave * e %e
file yyy
diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim
index cc6154af69..faf37485cd 100644
--- a/src/nvim/testdir/test_cscope.vim
+++ b/src/nvim/testdir/test_cscope.vim
@@ -102,7 +102,7 @@ func Test_cscopeWithCscopeConnections()
for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c']
enew
let a = execute(cmd)
- call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+C')
+ call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+B')
call assert_equal('Xmemfile_test.c', @%)
endfor
@@ -112,7 +112,7 @@ func Test_cscopeWithCscopeConnections()
let a = execute(cmd)
let alines = split(a, '\n', 1)
call assert_equal('', alines[0])
- call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+C')
+ call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+B')
call assert_equal('(1 of 1): <<global>> #include <assert.h>', alines[2])
call assert_equal('#include <assert.h>', getline('.'))
endfor
diff --git a/src/nvim/testdir/test_execute_func.vim b/src/nvim/testdir/test_execute_func.vim
index 2cb6d73407..16cc20e9a7 100644
--- a/src/nvim/testdir/test_execute_func.vim
+++ b/src/nvim/testdir/test_execute_func.vim
@@ -147,3 +147,30 @@ func Test_win_execute_other_tab()
tabclose
unlet xyz
endfunc
+
+func Test_win_execute_visual_redraw()
+ call setline(1, ['a', 'b', 'c'])
+ new
+ wincmd p
+ " start Visual in current window, redraw in other window with fewer lines
+ call feedkeys("G\<C-V>", 'txn')
+ call win_execute(winnr('#')->win_getid(), 'redraw')
+ call feedkeys("\<Esc>", 'txn')
+ bwipe!
+ bwipe!
+
+ enew
+ new
+ call setline(1, ['a', 'b', 'c'])
+ let winid = win_getid()
+ wincmd p
+ " start Visual in current window, extend it in other window with more lines
+ call feedkeys("\<C-V>", 'txn')
+ call win_execute(winid, 'call feedkeys("G\<C-V>", ''txn'')')
+ redraw
+
+ bwipe!
+ bwipe!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_expand.vim b/src/nvim/testdir/test_expand.vim
new file mode 100644
index 0000000000..48dce25bb3
--- /dev/null
+++ b/src/nvim/testdir/test_expand.vim
@@ -0,0 +1,83 @@
+" Test for expanding file names
+
+func Test_with_directories()
+ call mkdir('Xdir1')
+ call mkdir('Xdir2')
+ call mkdir('Xdir3')
+ cd Xdir3
+ call mkdir('Xdir4')
+ cd ..
+
+ split Xdir1/file
+ call setline(1, ['a', 'b'])
+ w
+ w Xdir3/Xdir4/file
+ close
+
+ next Xdir?/*/file
+ call assert_equal('Xdir3/Xdir4/file', expand('%'))
+ if has('unix')
+ next! Xdir?/*/nofile
+ call assert_equal('Xdir?/*/nofile', expand('%'))
+ endif
+ " Edit another file, on MS-Windows the swap file would be in use and can't
+ " be deleted.
+ edit foo
+
+ call assert_equal(0, delete('Xdir1', 'rf'))
+ call assert_equal(0, delete('Xdir2', 'rf'))
+ call assert_equal(0, delete('Xdir3', 'rf'))
+endfunc
+
+func Test_with_tilde()
+ let dir = getcwd()
+ call mkdir('Xdir ~ dir')
+ call assert_true(isdirectory('Xdir ~ dir'))
+ cd Xdir\ ~\ dir
+ call assert_true(getcwd() =~ 'Xdir \~ dir')
+ call chdir(dir)
+ call delete('Xdir ~ dir', 'd')
+ call assert_false(isdirectory('Xdir ~ dir'))
+endfunc
+
+func Test_expand_tilde_filename()
+ split ~
+ call assert_equal('~', expand('%'))
+ call assert_notequal(expand('%:p'), expand('~/'))
+ call assert_match('\~', expand('%:p'))
+ bwipe!
+endfunc
+
+func Test_expandcmd()
+ let $FOO = 'Test'
+ call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y'))
+ unlet $FOO
+
+ new
+ edit Xfile1
+ call assert_equal('e Xfile1', expandcmd('e %'))
+ edit Xfile2
+ edit Xfile1
+ call assert_equal('e Xfile2', 'e #'->expandcmd())
+ edit Xfile2
+ edit Xfile3
+ edit Xfile4
+ let bnum = bufnr('Xfile2')
+ call assert_equal('e Xfile2', expandcmd('e #' . bnum))
+ call setline('.', 'Vim!@#')
+ call assert_equal('e Vim', expandcmd('e <cword>'))
+ call assert_equal('e Vim!@#', expandcmd('e <cWORD>'))
+ enew!
+ edit Xfile.java
+ call assert_equal('e Xfile.py', expandcmd('e %:r.py'))
+ call assert_equal('make abc.java', expandcmd('make abc.%:e'))
+ call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?'))
+ edit a1a2a3.rb
+ call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o'))
+
+ call assert_fails('call expandcmd("make <afile>")', 'E495:')
+ call assert_fails('call expandcmd("make <afile>")', 'E495:')
+ enew
+ call assert_fails('call expandcmd("make %")', 'E499:')
+ close
+endfunc
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 0edbeb420a..42facdd491 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1377,6 +1377,36 @@ func Test_func_exists_on_reload()
delfunc ExistingFunction
endfunc
+func Test_platform_name()
+ " The system matches at most only one name.
+ let names = ['amiga', 'beos', 'bsd', 'hpux', 'linux', 'mac', 'qnx', 'sun', 'vms', 'win32', 'win32unix']
+ call assert_inrange(0, 1, len(filter(copy(names), 'has(v:val)')))
+
+ " Is Unix?
+ call assert_equal(has('beos'), has('beos') && has('unix'))
+ call assert_equal(has('bsd'), has('bsd') && has('unix'))
+ call assert_equal(has('hpux'), has('hpux') && has('unix'))
+ call assert_equal(has('linux'), has('linux') && has('unix'))
+ call assert_equal(has('mac'), has('mac') && has('unix'))
+ call assert_equal(has('qnx'), has('qnx') && has('unix'))
+ call assert_equal(has('sun'), has('sun') && has('unix'))
+ call assert_equal(has('win32'), has('win32') && !has('unix'))
+ call assert_equal(has('win32unix'), has('win32unix') && has('unix'))
+
+ if has('unix') && executable('uname')
+ let uname = system('uname')
+ call assert_equal(uname =~? 'BeOS', has('beos'))
+ " GNU userland on BSD kernels (e.g., GNU/kFreeBSD) don't have BSD defined
+ call assert_equal(uname =~? '\%(GNU/k\w\+\)\@<!BSD\|DragonFly', has('bsd'))
+ call assert_equal(uname =~? 'HP-UX', has('hpux'))
+ call assert_equal(uname =~? 'Linux', has('linux'))
+ call assert_equal(uname =~? 'Darwin', has('mac'))
+ call assert_equal(uname =~? 'QNX', has('qnx'))
+ call assert_equal(uname =~? 'SunOS', has('sun'))
+ call assert_equal(uname =~? 'CYGWIN\|MSYS', has('win32unix'))
+ endif
+endfunc
+
sandbox function Fsandbox()
normal ix
endfunc
@@ -1519,24 +1549,31 @@ func Test_libcall_libcallnr()
let libc = 'msvcrt.dll'
elseif has('mac')
let libc = 'libSystem.B.dylib'
- elseif system('uname -s') =~ 'SunOS'
- " Set the path to libc.so according to the architecture.
- let test_bits = system('file ' . GetVimProg())
- let test_arch = system('uname -p')
- if test_bits =~ '64-bit' && test_arch =~ 'sparc'
- let libc = '/usr/lib/sparcv9/libc.so'
- elseif test_bits =~ '64-bit' && test_arch =~ 'i386'
- let libc = '/usr/lib/amd64/libc.so'
+ elseif executable('ldd')
+ let libc = matchstr(split(system('ldd ' . GetVimProg())), '/libc\.so\>')
+ endif
+ if get(l:, 'libc', '') ==# ''
+ " On Unix, libc.so can be in various places.
+ if has('linux')
+ " There is not documented but regarding the 1st argument of glibc's
+ " dlopen an empty string and nullptr are equivalent, so using an empty
+ " string for the 1st argument of libcall allows to call functions.
+ let libc = ''
+ elseif has('sun')
+ " Set the path to libc.so according to the architecture.
+ let test_bits = system('file ' . GetVimProg())
+ let test_arch = system('uname -p')
+ if test_bits =~ '64-bit' && test_arch =~ 'sparc'
+ let libc = '/usr/lib/sparcv9/libc.so'
+ elseif test_bits =~ '64-bit' && test_arch =~ 'i386'
+ let libc = '/usr/lib/amd64/libc.so'
+ else
+ let libc = '/usr/lib/libc.so'
+ endif
else
- let libc = '/usr/lib/libc.so'
+ " Unfortunately skip this test until a good way is found.
+ return
endif
- elseif system('uname -s') =~ 'OpenBSD'
- let libc = 'libc.so'
- else
- " On Unix, libc.so can be in various places.
- " Interestingly, using an empty string for the 1st argument of libcall
- " allows to call functions from libc which is not documented.
- let libc = ''
endif
if has('win32')
diff --git a/src/nvim/testdir/test_number.vim b/src/nvim/testdir/test_number.vim
index d737ebe9f0..dfbdc0bffd 100644
--- a/src/nvim/testdir/test_number.vim
+++ b/src/nvim/testdir/test_number.vim
@@ -284,10 +284,10 @@ func Test_relativenumber_colors()
" Default colors
call VerifyScreenDump(buf, 'Test_relnr_colors_1', {})
- call term_sendkeys(buf, ":hi LineNrAbove ctermfg=blue\<CR>")
+ call term_sendkeys(buf, ":hi LineNrAbove ctermfg=blue\<CR>:\<CR>")
call VerifyScreenDump(buf, 'Test_relnr_colors_2', {})
- call term_sendkeys(buf, ":hi LineNrBelow ctermfg=green\<CR>")
+ call term_sendkeys(buf, ":hi LineNrBelow ctermfg=green\<CR>:\<CR>")
call VerifyScreenDump(buf, 'Test_relnr_colors_3', {})
call term_sendkeys(buf, ":hi clear LineNrAbove\<CR>")
diff --git a/src/nvim/testdir/test_put.vim b/src/nvim/testdir/test_put.vim
index 440717eaa8..ed76709a56 100644
--- a/src/nvim/testdir/test_put.vim
+++ b/src/nvim/testdir/test_put.vim
@@ -1,5 +1,7 @@
" Tests for put commands, e.g. ":put", "p", "gp", "P", "gP", etc.
+source check.vim
+
func Test_put_block()
new
call feedkeys("i\<C-V>u2500\<CR>x\<ESC>", 'x')
@@ -112,6 +114,39 @@ func Test_put_p_indent_visual()
bwipe!
endfunc
+func Test_gp_with_count_leaves_cursor_at_end()
+ new
+ call setline(1, '<---->')
+ call setreg('@', "foo\nbar", 'c')
+ normal 1G3|3gp
+ call assert_equal([0, 4, 4, 0], getpos("."))
+ call assert_equal(['<--foo', 'barfoo', 'barfoo', 'bar-->'], getline(1, '$'))
+ call assert_equal([0, 4, 3, 0], getpos("']"))
+
+ bwipe!
+endfunc
+
+func Test_p_with_count_leaves_mark_at_end()
+ new
+ call setline(1, '<---->')
+ call setreg('@', "start\nend", 'c')
+ normal 1G3|3p
+ call assert_equal([0, 1, 4, 0], getpos("."))
+ call assert_equal(['<--start', 'endstart', 'endstart', 'end-->'], getline(1, '$'))
+ call assert_equal([0, 4, 3, 0], getpos("']"))
+
+ bwipe!
+endfunc
+
+func Test_put_above_first_line()
+ new
+ let @" = 'text'
+ silent! normal 0o00
+ 0put
+ call assert_equal('text', getline(1))
+ bwipe!
+endfunc
+
func Test_multibyte_op_end_mark()
new
call setline(1, 'тест')
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 6db679c5f9..f137ed5346 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1914,6 +1914,7 @@ func Test_switchbuf()
" If opening a file changes 'switchbuf', then the new value should be
" retained.
+ set modeline&vim
call writefile(["vim: switchbuf=split"], 'Xqftestfile1')
enew | only
set switchbuf&vim
diff --git a/src/nvim/testdir/test_rename.vim b/src/nvim/testdir/test_rename.vim
index 3887fcfabf..5359b84923 100644
--- a/src/nvim/testdir/test_rename.vim
+++ b/src/nvim/testdir/test_rename.vim
@@ -1,5 +1,7 @@
" Test rename()
+source shared.vim
+
func Test_rename_file_to_file()
call writefile(['foo'], 'Xrename1')
@@ -81,7 +83,7 @@ func Test_rename_copy()
call assert_equal(0, rename('Xrenamedir/Xrenamefile', 'Xrenamefile'))
- if !has('win32')
+ if !has('win32') && !IsRoot()
" On Windows, the source file is removed despite
" its directory being made not writable.
call assert_equal(['foo'], readfile('Xrenamedir/Xrenamefile'))
diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim
index f7f7467e91..d950626615 100644
--- a/src/nvim/testdir/test_search_stat.vim
+++ b/src/nvim/testdir/test_search_stat.vim
@@ -1,14 +1,15 @@
" Tests for search_stats, when "S" is not in 'shortmess'
-source screendump.vim
source check.vim
+source screendump.vim
func Test_search_stat()
new
set shortmess-=S
" Append 50 lines with text to search for, "foobar" appears 20 times
call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 10))
- call nvim_win_set_cursor(0, [1, 0])
+
+ call cursor(1, 1)
" searchcount() returns an empty dictionary when previous pattern was not set
call assert_equal({}, searchcount(#{pattern: ''}))
@@ -45,7 +46,6 @@ func Test_search_stat()
\ searchcount(#{pattern: 'fooooobar', maxcount: 1}))
" match at second line
- call cursor(1, 1)
let messages_before = execute('messages')
let @/ = 'fo*\(bar\?\)\?'
let g:a = execute(':unsilent :norm! n')
@@ -262,6 +262,34 @@ func Test_searchcount_fails()
call assert_fails('echo searchcount("boo!")', 'E715:')
endfunc
+func Test_searchcount_in_statusline()
+ CheckScreendump
+
+ let lines =<< trim END
+ set shortmess-=S
+ call append(0, 'this is something')
+ function TestSearchCount() abort
+ let search_count = searchcount()
+ if !empty(search_count)
+ return '[' . search_count.current . '/' . search_count.total . ']'
+ else
+ return ''
+ endif
+ endfunction
+ set hlsearch
+ set laststatus=2 statusline+=%{TestSearchCount()}
+ END
+ call writefile(lines, 'Xsearchstatusline')
+ let buf = RunVimInTerminal('-S Xsearchstatusline', #{rows: 10})
+ call TermWait(buf)
+ call term_sendkeys(buf, "/something")
+ call VerifyScreenDump(buf, 'Test_searchstat_4', {})
+
+ call term_sendkeys(buf, "\<Esc>")
+ call StopVimInTerminal(buf)
+ call delete('Xsearchstatusline')
+endfunc
+
func Test_search_stat_foldopen()
CheckScreendump
@@ -319,30 +347,29 @@ func! Test_search_stat_screendump()
call delete('Xsearchstat')
endfunc
-func Test_searchcount_in_statusline()
+func Test_search_stat_then_gd()
CheckScreendump
let lines =<< trim END
+ call setline(1, ['int cat;', 'int dog;', 'cat = dog;'])
set shortmess-=S
- call append(0, 'this is something')
- function TestSearchCount() abort
- let search_count = searchcount()
- if !empty(search_count)
- return '[' . search_count.current . '/' . search_count.total . ']'
- else
- return ''
- endif
- endfunction
set hlsearch
- set laststatus=2 statusline+=%{TestSearchCount()}
END
- call writefile(lines, 'Xsearchstatusline')
- let buf = RunVimInTerminal('-S Xsearchstatusline', #{rows: 10})
+ call writefile(lines, 'Xsearchstatgd')
+
+ let buf = RunVimInTerminal('-S Xsearchstatgd', #{rows: 10})
+ call term_sendkeys(buf, "/dog\<CR>")
call TermWait(buf)
- call term_sendkeys(buf, "/something")
- call VerifyScreenDump(buf, 'Test_searchstat_4', {})
+ call VerifyScreenDump(buf, 'Test_searchstatgd_1', {})
+
+ call term_sendkeys(buf, "G0gD")
+ call TermWait(buf)
+ call VerifyScreenDump(buf, 'Test_searchstatgd_2', {})
- call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
- call delete('Xsearchstatusline')
+ call delete('Xsearchstatgd')
endfunc
+
+
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_source_utf8.vim b/src/nvim/testdir/test_source_utf8.vim
index e93ea29dff..66fabe0442 100644
--- a/src/nvim/testdir/test_source_utf8.vim
+++ b/src/nvim/testdir/test_source_utf8.vim
@@ -1,4 +1,5 @@
" Test the :source! command
+source check.vim
func Test_source_utf8()
" check that sourcing a script with 0x80 as second byte works
@@ -31,24 +32,24 @@ endfunc
" Test for sourcing a file with CTRL-V's at the end of the line
func Test_source_ctrl_v()
- call writefile(['map __1 afirst',
- \ 'map __2 asecond',
- \ 'map __3 athird',
- \ 'map __4 afourth',
- \ 'map __5 afifth',
- \ "map __1 asd\<C-V>",
- \ "map __2 asd\<C-V>\<C-V>",
- \ "map __3 asd\<C-V>\<C-V>",
- \ "map __4 asd\<C-V>\<C-V>\<C-V>",
- \ "map __5 asd\<C-V>\<C-V>\<C-V>",
- \ ], 'Xtestfile')
+ call writefile(['map __1 afirst',
+ \ 'map __2 asecond',
+ \ 'map __3 athird',
+ \ 'map __4 afourth',
+ \ 'map __5 afifth',
+ \ "map __1 asd\<C-V>",
+ \ "map __2 asd\<C-V>\<C-V>",
+ \ "map __3 asd\<C-V>\<C-V>",
+ \ "map __4 asd\<C-V>\<C-V>\<C-V>",
+ \ "map __5 asd\<C-V>\<C-V>\<C-V>",
+ \ ], 'Xtestfile')
source Xtestfile
enew!
exe "normal __1\<Esc>\<Esc>__2\<Esc>__3\<Esc>\<Esc>__4\<Esc>__5\<Esc>"
exe "%s/\<C-J>/0/g"
call assert_equal(['sd',
- \ "map __2 asd\<Esc>secondsd\<Esc>sd0map __5 asd0fifth"],
- \ getline(1, 2))
+ \ "map __2 asd\<Esc>secondsd\<Esc>sd0map __5 asd0fifth"],
+ \ getline(1, 2))
enew!
call delete('Xtestfile')
diff --git a/src/nvim/testdir/test_swap.vim b/src/nvim/testdir/test_swap.vim
index b3018b2b0d..b180f27685 100644
--- a/src/nvim/testdir/test_swap.vim
+++ b/src/nvim/testdir/test_swap.vim
@@ -1,6 +1,7 @@
" Tests for the swap feature
source check.vim
+source shared.vim
func s:swapname()
return trim(execute('swapname'))
@@ -198,14 +199,17 @@ func Test_swapfile_delete()
quit
call assert_equal(fnamemodify(swapfile_name, ':t'), fnamemodify(s:swapname, ':t'))
- " Write the swapfile with a modified PID, now it will be automatically
- " deleted. Process one should never be Vim.
- let swapfile_bytes[24:27] = 0z01000000
- call writefile(swapfile_bytes, swapfile_name)
- let s:swapname = ''
- split XswapfileText
- quit
- call assert_equal('', s:swapname)
+ " This test won't work as root because root can successfully run kill(1, 0)
+ if !IsRoot()
+ " Write the swapfile with a modified PID, now it will be automatically
+ " deleted. Process one should never be Vim.
+ let swapfile_bytes[24:27] = 0z01000000
+ call writefile(swapfile_bytes, swapfile_name)
+ let s:swapname = ''
+ split XswapfileText
+ quit
+ call assert_equal('', s:swapname)
+ endif
" Now set the modified flag, the swap file will not be deleted
let swapfile_bytes[28 + 80 + 899] = 0x55
diff --git a/src/nvim/testdir/test_utf8_comparisons.vim b/src/nvim/testdir/test_utf8_comparisons.vim
index fdf9d80802..62947c6e6e 100644
--- a/src/nvim/testdir/test_utf8_comparisons.vim
+++ b/src/nvim/testdir/test_utf8_comparisons.vim
@@ -86,6 +86,9 @@ endfunc
" test that g~ap changes one paragraph only.
func Test_gap()
new
- call feedkeys("iabcd\n\ndefggg0g~ap", "tx")
+ " setup text
+ call feedkeys("iabcd\<cr>\<cr>defg", "tx")
+ " modify only first line
+ call feedkeys("gg0g~ap", "tx")
call assert_equal(["ABCD", "", "defg"], getline(1,3))
endfunc
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index aa7882d129..5ffbe82082 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -43,7 +43,7 @@ func Test_writefile_fails_gently()
endfunc
func Test_writefile_fails_conversion()
- if !has('iconv') || system('uname -s') =~ 'SunOS'
+ if !has('iconv') || has('sun')
return
endif
" Without a backup file the write won't happen if there is a conversion
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 5fec41f9a5..6e48df3734 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -315,7 +315,6 @@ static TermKeyResult tk_getkey(TermKey *tk, TermKeyKey *key, bool force)
return force ? termkey_getkey_force(tk, key) : termkey_getkey(tk, key);
}
-static void tinput_timer_cb(TimeWatcher *watcher, void *data);
static void tk_getkeys(TermInput *input, bool force)
{
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 5e2a81795a..71cca52773 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -2093,7 +2093,7 @@ void list_in_columns(char_u **items, int size, int current)
// The rightmost column doesn't need a separator.
// Sacrifice it to fit in one more column if possible.
- int ncol = (int)(Columns + 1) / width;
+ int ncol = (Columns + 1) / width;
int nrow = item_count / ncol + (item_count % ncol ? 1 : 0);
int cur_row = 1;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 8e44fd5014..6996a93928 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -577,18 +577,19 @@ static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize, int64_t Pren
void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err)
{
- win_T *win = find_window_by_handle(window, err), *save_curwin = curwin;
+ win_T *win = find_window_by_handle(window, err);
buf_T *buf = find_buffer_by_handle(buffer, err);
- tabpage_T *tab = win_find_tabpage(win), *save_curtab = curtab;
+ tabpage_T *tab = win_find_tabpage(win);
if (!win || !buf) {
return;
}
-
if (noautocmd) {
block_autocmds();
}
- if (switch_win_noblock(&save_curwin, &save_curtab, win, tab, false) == FAIL) {
+
+ switchwin_T switchwin;
+ if (switch_win_noblock(&switchwin, win, tab, false) == FAIL) {
api_set_error(err,
kErrorTypeException,
"Failed to switch to window %d",
@@ -608,7 +609,7 @@ void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err)
// So do it now.
validate_cursor();
- restore_win_noblock(save_curwin, save_curtab, false);
+ restore_win_noblock(&switchwin, false);
if (noautocmd) {
unblock_autocmds();
}
@@ -6631,20 +6632,27 @@ static win_T *get_snapshot_focus(int idx)
/// triggered, another tabpage access is limited.
///
/// @return FAIL if switching to "win" failed.
-int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp,
- bool no_display)
+int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display)
{
block_autocmds();
- return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
+ return switch_win_noblock(switchwin, win, tp, no_display);
}
// As switch_win() but without blocking autocommands.
-int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp,
- bool no_display)
+int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display)
{
- *save_curwin = curwin;
+ memset(switchwin, 0, sizeof(switchwin_T));
+ switchwin->sw_curwin = curwin;
+ if (win == curwin) {
+ switchwin->sw_same_win = true;
+ } else {
+ // Disable Visual selection, because redrawing may fail.
+ switchwin->sw_visual_active = VIsual_active;
+ VIsual_active = false;
+ }
+
if (tp != NULL) {
- *save_curtab = curtab;
+ switchwin->sw_curtab = curtab;
if (no_display) {
curtab->tp_firstwin = firstwin;
curtab->tp_lastwin = lastwin;
@@ -6666,28 +6674,33 @@ int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab, win_T *win,
// Restore current tabpage and window saved by switch_win(), if still valid.
// When "no_display" is true the display won't be affected, no redraw is
// triggered.
-void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
+void restore_win(switchwin_T *switchwin, bool no_display)
{
- restore_win_noblock(save_curwin, save_curtab, no_display);
+ restore_win_noblock(switchwin, no_display);
unblock_autocmds();
}
// As restore_win() but without unblocking autocommands.
-void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, bool no_display)
+void restore_win_noblock(switchwin_T *switchwin, bool no_display)
{
- if (save_curtab != NULL && valid_tabpage(save_curtab)) {
+ if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) {
if (no_display) {
curtab->tp_firstwin = firstwin;
curtab->tp_lastwin = lastwin;
- curtab = save_curtab;
+ curtab = switchwin->sw_curtab;
firstwin = curtab->tp_firstwin;
lastwin = curtab->tp_lastwin;
} else {
- goto_tabpage_tp(save_curtab, false, false);
+ goto_tabpage_tp(switchwin->sw_curtab, false, false);
}
}
- if (win_valid(save_curwin)) {
- curwin = save_curwin;
+
+ if (!switchwin->sw_same_win) {
+ VIsual_active = switchwin->sw_visual_active;
+ }
+
+ if (win_valid(switchwin->sw_curwin)) {
+ curwin = switchwin->sw_curwin;
curbuf = curwin->w_buffer;
}
// If called by win_execute() and executing the command changed the
diff --git a/src/nvim/window.h b/src/nvim/window.h
index 7e465a9f08..e2fd2c515d 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
+#include "nvim/mark.h"
// Values for file_name_in_line()
#define FNAME_MESS 1 // give error message
@@ -32,6 +33,38 @@
#define MIN_COLUMNS 12 // minimal columns for screen
#define MIN_LINES 2 // minimal lines for screen
+/// Structure used by switch_win() to pass values to restore_win()
+typedef struct {
+ win_T *sw_curwin;
+ tabpage_T *sw_curtab;
+ bool sw_same_win; ///< VIsual_active was not reset
+ bool sw_visual_active;
+} switchwin_T;
+
+/// Execute a block of code in the context of window `wp` in tabpage `tp`.
+/// Ensures the status line is redrawn and cursor position is valid if it is moved.
+#define WIN_EXECUTE(wp, tp, block) \
+ do { \
+ win_T *const wp_ = (wp); \
+ const pos_T curpos_ = wp_->w_cursor; \
+ switchwin_T switchwin_; \
+ if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \
+ check_cursor(); \
+ block; \
+ } \
+ restore_win_noblock(&switchwin_, true); \
+ /* Update the status line if the cursor moved. */ \
+ if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \
+ wp_->w_redr_status = true; \
+ } \
+ /* In case the command moved the cursor or changed the Visual area, */ \
+ /* check it is valid. */ \
+ check_cursor(); \
+ if (VIsual_active) { \
+ check_pos(curbuf, &VIsual); \
+ } \
+ } while (false)
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "window.h.generated.h"
#endif
diff --git a/test/functional/autocmd/focus_spec.lua b/test/functional/autocmd/focus_spec.lua
index 3f9a0ad09b..e3c9e1f9ee 100644
--- a/test/functional/autocmd/focus_spec.lua
+++ b/test/functional/autocmd/focus_spec.lua
@@ -56,7 +56,7 @@ describe('autoread TUI FocusGained/FocusLost', function()
line 3 |
line 4 |
{5:xtest-foo }|
- "xtest-foo" 4L, 28C |
+ "xtest-foo" 4L, 28B |
{3:-- TERMINAL --} |
]]}
end)
diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua
deleted file mode 100644
index cd3713eabe..0000000000
--- a/test/functional/legacy/expand_spec.lua
+++ /dev/null
@@ -1,129 +0,0 @@
--- Test for expanding file names
-
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local call = helpers.call
-local nvim = helpers.meths
-local clear = helpers.clear
-local source = helpers.source
-
-local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
-end
-
-describe('expand file name', function()
- after_each(function()
- helpers.rmdir('Xdir1')
- helpers.rmdir('Xdir2')
- helpers.rmdir('Xdir3')
- helpers.rmdir('Xdir4')
- end)
-
- before_each(function()
- clear()
-
- source([[
- func Test_with_directories()
- call mkdir('Xdir1')
- call mkdir('Xdir2')
- call mkdir('Xdir3')
- cd Xdir3
- call mkdir('Xdir4')
- cd ..
-
- split Xdir1/file
- call setline(1, ['a', 'b'])
- w
- w Xdir3/Xdir4/file
- close
-
- next Xdir?/*/file
- call assert_equal('Xdir3/Xdir4/file', expand('%'))
- if has('unix')
- next! Xdir?/*/nofile
- call assert_equal('Xdir?/*/nofile', expand('%'))
- endif
- " Edit another file, on MS-Windows the swap file would be in use and can't
- " be deleted
- edit foo
-
- call assert_equal(0, delete('Xdir1', 'rf'))
- call assert_equal(0, delete('Xdir2', 'rf'))
- call assert_equal(0, delete('Xdir3', 'rf'))
- endfunc
-
- func Test_with_tilde()
- let dir = getcwd()
- call mkdir('Xdir ~ dir')
- call assert_true(isdirectory('Xdir ~ dir'))
- cd Xdir\ ~\ dir
- call assert_true(getcwd() =~ 'Xdir \~ dir')
- exe 'cd ' . fnameescape(dir)
- call delete('Xdir ~ dir', 'd')
- call assert_false(isdirectory('Xdir ~ dir'))
- endfunc
-
- func Test_expand_tilde_filename()
- split ~
- call assert_equal('~', expand('%'))
- call assert_notequal(expand('%:p'), expand('~/'))
- call assert_match('\~', expand('%:p'))
- bwipe!
- endfunc
-
- func Test_expandcmd()
- let $FOO = 'Test'
- call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y'))
- unlet $FOO
-
- new
- edit Xfile1
- call assert_equal('e Xfile1', expandcmd('e %'))
- edit Xfile2
- edit Xfile1
- call assert_equal('e Xfile2', 'e #'->expandcmd())
- edit Xfile2
- edit Xfile3
- edit Xfile4
- let bnum = bufnr('Xfile2')
- call assert_equal('e Xfile2', expandcmd('e #' . bnum))
- call setline('.', 'Vim!@#')
- call assert_equal('e Vim', expandcmd('e <cword>'))
- call assert_equal('e Vim!@#', expandcmd('e <cWORD>'))
- enew!
- edit Xfile.java
- call assert_equal('e Xfile.py', expandcmd('e %:r.py'))
- call assert_equal('make abc.java', expandcmd('make abc.%:e'))
- call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?'))
- edit a1a2a3.rb
- call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o'))
-
- call assert_fails('call expandcmd("make <afile>")', 'E495:')
- call assert_fails('call expandcmd("make <afile>")', 'E495:')
- enew
- call assert_fails('call expandcmd("make %")', 'E499:')
- close
- endfunc
- ]])
- end)
-
- it('works with directories', function()
- call('Test_with_directories')
- expected_empty()
- end)
-
- it('works with tilde', function()
- call('Test_with_tilde')
- expected_empty()
- end)
-
- it('does not expand tilde if it is a filename', function()
- call('Test_expand_tilde_filename')
- expected_empty()
- end)
-
- it('works with expandcmd()', function()
- call('Test_expandcmd')
- expected_empty()
- end)
-end)
diff --git a/test/functional/legacy/search_stat_spec.lua b/test/functional/legacy/search_stat_spec.lua
new file mode 100644
index 0000000000..fdd46c0cb9
--- /dev/null
+++ b/test/functional/legacy/search_stat_spec.lua
@@ -0,0 +1,121 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, feed, exec, command = helpers.clear, helpers.feed, helpers.exec, helpers.command
+local poke_eventloop = helpers.poke_eventloop
+
+describe('search stat', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(30, 10)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [2] = {background = Screen.colors.Yellow}, -- Search
+ [3] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}, -- Folded
+ })
+ screen:attach()
+ end)
+
+ it('right spacing with silent mapping vim-patch:8.1.1970', function()
+ exec([[
+ set shortmess-=S
+ " Append 50 lines with text to search for, "foobar" appears 20 times
+ call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 20))
+ call setline(2, 'find this')
+ call setline(70, 'find this')
+ nnoremap n n
+ let @/ = 'find this'
+ call cursor(1,1)
+ norm n
+ ]])
+ screen:expect([[
+ foobar |
+ {2:^find this} |
+ fooooobar |
+ foba |
+ foobar |
+ foobar |
+ foo |
+ fooooobar |
+ foba |
+ /find this [1/2] |
+ ]])
+ command('nnoremap <silent> n n')
+ feed('gg0n')
+ screen:expect([[
+ foobar |
+ {2:^find this} |
+ fooooobar |
+ foba |
+ foobar |
+ foobar |
+ foo |
+ fooooobar |
+ foba |
+ [1/2] |
+ ]])
+ end)
+
+ it('when only match is in fold vim-patch:8.2.0840', function()
+ exec([[
+ set shortmess-=S
+ setl foldenable foldmethod=indent foldopen-=search
+ call append(0, ['if', "\tfoo", "\tfoo", 'endif'])
+ let @/ = 'foo'
+ call cursor(1,1)
+ norm n
+ ]])
+ screen:expect([[
+ if |
+ {3:^+-- 2 lines: foo·············}|
+ endif |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /foo [1/2] |
+ ]])
+ feed('n')
+ poke_eventloop()
+ screen:expect_unchanged()
+ feed('n')
+ poke_eventloop()
+ screen:expect_unchanged()
+ end)
+
+ it('is cleared by gd and gD vim-patch:8.2.3583', function()
+ exec([[
+ call setline(1, ['int cat;', 'int dog;', 'cat = dog;'])
+ set shortmess-=S
+ set hlsearch
+ ]])
+ feed('/dog<CR>')
+ screen:expect([[
+ int cat; |
+ int {2:^dog}; |
+ cat = {2:dog}; |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /dog [1/2] |
+ ]])
+ feed('G0gD')
+ screen:expect([[
+ int {2:^cat}; |
+ int dog; |
+ {2:cat} = dog; |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index ddcf7687f5..17f7a04db6 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2406,6 +2406,17 @@ describe('lua stdlib', function()
eq(buf1, meths.get_current_buf())
eq(buf2, val)
end)
+
+ it('does not cause ml_get errors with invalid visual selection', function()
+ -- Should be fixed by vim-patch:8.2.4028.
+ exec_lua [[
+ local a = vim.api
+ local t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
+ a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
+ a.nvim_feedkeys(t "G<C-V>", "txn", false)
+ a.nvim_buf_call(a.nvim_create_buf(false, true), function() vim.cmd "redraw" end)
+ ]]
+ end)
end)
describe('vim.api.nvim_win_call', function()
@@ -2434,6 +2445,75 @@ describe('lua stdlib', function()
eq(win1, meths.get_current_win())
eq(win2, val)
end)
+
+ it('does not cause ml_get errors with invalid visual selection', function()
+ -- Add lines to the current buffer and make another window looking into an empty buffer.
+ exec_lua [[
+ _G.a = vim.api
+ _G.t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end
+ _G.win_lines = a.nvim_get_current_win()
+ vim.cmd "new"
+ _G.win_empty = a.nvim_get_current_win()
+ a.nvim_set_current_win(win_lines)
+ a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"})
+ ]]
+
+ -- Start Visual in current window, redraw in other window with fewer lines.
+ -- Should be fixed by vim-patch:8.2.4018.
+ exec_lua [[
+ a.nvim_feedkeys(t "G<C-V>", "txn", false)
+ a.nvim_win_call(win_empty, function() vim.cmd "redraw" end)
+ ]]
+
+ -- Start Visual in current window, extend it in other window with more lines.
+ -- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected.
+ exec_lua [[
+ a.nvim_feedkeys(t "<Esc>gg", "txn", false)
+ a.nvim_set_current_win(win_empty)
+ a.nvim_feedkeys(t "gg<C-V>", "txn", false)
+ a.nvim_win_call(win_lines, function() a.nvim_feedkeys(t "G<C-V>", "txn", false) end)
+ vim.cmd "redraw"
+ ]]
+ end)
+
+ it('updates ruler if cursor moved', function()
+ -- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too!
+ local screen = Screen.new(30, 5)
+ screen:set_default_attr_ids {
+ [1] = {reverse = true},
+ [2] = {bold = true, reverse = true},
+ }
+ screen:attach()
+ exec_lua [[
+ _G.a = vim.api
+ vim.opt.ruler = true
+ local lines = {}
+ for i = 0, 499 do lines[#lines + 1] = tostring(i) end
+ a.nvim_buf_set_lines(0, 0, -1, true, lines)
+ a.nvim_win_set_cursor(0, {20, 0})
+ vim.cmd "split"
+ _G.win = a.nvim_get_current_win()
+ vim.cmd "wincmd w | redraw"
+ ]]
+ screen:expect [[
+ 19 |
+ {1:[No Name] [+] 20,1 3%}|
+ ^19 |
+ {2:[No Name] [+] 20,1 3%}|
+ |
+ ]]
+ exec_lua [[
+ a.nvim_win_call(win, function() a.nvim_win_set_cursor(0, {100, 0}) end)
+ vim.cmd "redraw"
+ ]]
+ screen:expect [[
+ 99 |
+ {1:[No Name] [+] 100,1 19%}|
+ ^19 |
+ {2:[No Name] [+] 20,1 3%}|
+ |
+ ]]
+ end)
end)
end)
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index 37de5d0ce6..f7c2dbdb43 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -230,3 +230,14 @@ describe('health.vim', function()
end)
end)
end)
+
+describe(':checkhealth provider', function()
+ it("works correctly with a wrongly configured 'shell'", function()
+ clear()
+ command([[set shell=echo\ WRONG!!!]])
+ command('let g:loaded_perl_provider = 0')
+ command('let g:loaded_python3_provider = 0')
+ command('checkhealth provider')
+ eq(nil, string.match(curbuf_contents(), 'WRONG!!!'))
+ end)
+end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index 11718a6e18..78f4c6ddd3 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -165,7 +165,7 @@ describe('input non-printable chars', function()
{1:~ }|
{1:~ }|
{1:~ }|
- "Xtest-overwrite" [noeol] 1L, 6C |
+ "Xtest-overwrite" [noeol] 1L, 6B |
]])
-- The timestamp is in second resolution, wait two seconds to be sure.
diff --git a/test/helpers.lua b/test/helpers.lua
index 87431e4342..522714c8be 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -815,7 +815,7 @@ end
function module.read_nvim_log(logfile, ci_rename)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local is_ci = module.isCI()
- local keep = is_ci and 999 or 10
+ local keep = is_ci and 100 or 10
local lines = module.read_file_list(logfile, -keep) or {}
local log = (('-'):rep(78)..'\n'
..string.format('$NVIM_LOG_FILE: %s\n', logfile)