aboutsummaryrefslogtreecommitdiff
path: root/src/nvim
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim')
-rw-r--r--src/nvim/CMakeLists.txt6
-rw-r--r--src/nvim/eval.c14
-rw-r--r--src/nvim/ex_cmds.c39
-rw-r--r--src/nvim/ex_docmd.c55
-rw-r--r--src/nvim/ex_getln.c7
-rw-r--r--src/nvim/getchar.c12
-rw-r--r--src/nvim/main.c6
-rw-r--r--src/nvim/mbyte.c12
-rw-r--r--src/nvim/mbyte.h4
-rw-r--r--src/nvim/normal.c19
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/os/env.c4
-rw-r--r--src/nvim/os/fs.c4
-rw-r--r--src/nvim/testdir/test_alot.vim3
-rw-r--r--src/nvim/testdir/test_cmdline.vim10
-rw-r--r--src/nvim/testdir/test_ex_z.vim78
-rw-r--r--src/nvim/testdir/test_functions.vim8
-rw-r--r--src/nvim/testdir/test_goto.vim21
-rw-r--r--src/nvim/testdir/test_hardcopy.vim11
-rw-r--r--src/nvim/testdir/test_normal.vim56
20 files changed, 284 insertions, 87 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 2e44f2a030..15eb824d38 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -394,12 +394,6 @@ endif()
set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUA_PREFERRED_LIBRARIES})
-if(CMAKE_VERSION VERSION_LESS "2.8.8")
- # Use include_directories() because INCLUDE_DIRECTORIES target property
- # is not supported
- include_directories(${LUA_PREFERRED_INCLUDE_DIRS})
-endif()
-
# Don't use jemalloc in the unit test library.
if(JEMALLOC_FOUND)
list(APPEND NVIM_EXEC_LINK_LIBRARIES ${JEMALLOC_LIBRARIES})
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d8d785395c..5505f5f102 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -17838,11 +17838,14 @@ pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,
pos.col = 0;
if (name[1] == '0') { /* "w0": first visible line */
update_topline();
- pos.lnum = curwin->w_topline;
+ // In silent Ex mode topline is zero, but that's not a valid line
+ // number; use one instead.
+ pos.lnum = curwin->w_topline > 0 ? curwin->w_topline : 1;
return &pos;
} else if (name[1] == '$') { /* "w$": last visible line */
validate_botline();
- pos.lnum = curwin->w_botline - 1;
+ // In silent Ex mode botline is zero, return zero then.
+ pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
return &pos;
}
} else if (name[0] == '$') { /* last column or line */
@@ -19528,6 +19531,13 @@ void ex_execute(exarg_T *eap)
}
if (ret != FAIL && ga.ga_data != NULL) {
+ if (eap->cmdidx == CMD_echomsg || eap->cmdidx == CMD_echoerr) {
+ // Mark the already saved text as finishing the line, so that what
+ // follows is displayed on a new line when scrolling back at the
+ // more prompt.
+ msg_sb_eol();
+ }
+
if (eap->cmdidx == CMD_echomsg) {
MSG_ATTR(ga.ga_data, echo_attr);
ui_flush();
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 98eda8dcb8..d58d006dd0 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1306,10 +1306,10 @@ filterend:
* Call a shell to execute a command.
* When "cmd" is NULL start an interactive shell.
*/
-void
-do_shell (
+void
+do_shell(
char_u *cmd,
- int flags /* may be SHELL_DOOUT when output is redirected */
+ int flags // may be SHELL_DOOUT when output is redirected
)
{
int save_nwr;
@@ -1789,14 +1789,14 @@ theend:
* May set eap->forceit if a dialog says it's OK to overwrite.
* Return OK if it's OK, FAIL if it is not.
*/
-int
-check_overwrite (
+int
+check_overwrite(
exarg_T *eap,
buf_T *buf,
- char_u *fname, /* file name to be used (can differ from
- buf->ffname) */
- char_u *ffname, /* full path version of fname */
- int other /* writing under other name */
+ char_u *fname, // file name to be used (can differ from
+ // buf->ffname)
+ char_u *ffname, // full path version of fname
+ int other // writing under other name
)
{
/*
@@ -2823,7 +2823,7 @@ void ex_change(exarg_T *eap)
void ex_z(exarg_T *eap)
{
char_u *x;
- int bigness;
+ int64_t bigness;
char_u *kind;
int minus = 0;
linenr_T start, end, curs, i;
@@ -2856,10 +2856,17 @@ void ex_z(exarg_T *eap)
EMSG(_("E144: non-numeric argument to :z"));
return;
}
- bigness = atoi((char *)x);
+ bigness = atol((char *)x);
+
+ // bigness could be < 0 if atol(x) overflows.
+ if (bigness > 2 * curbuf->b_ml.ml_line_count || bigness < 0) {
+ bigness = 2 * curbuf->b_ml.ml_line_count;
+ }
+
p_window = bigness;
- if (*kind == '=')
+ if (*kind == '=') {
bigness += 2;
+ }
}
/* the number of '-' and '+' multiplies the distance */
@@ -4587,11 +4594,11 @@ char_u *check_help_lang(char_u *arg)
* Assumption is made that the matched_string passed has already been found to
* match some string for which help is requested. webb.
*/
-int
-help_heuristic (
+int
+help_heuristic(
char_u *matched_string,
- int offset, /* offset for match */
- int wrong_case /* no matching case */
+ int offset, // offset for match
+ int wrong_case // no matching case
)
{
int num_letters;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 2f41080a41..f0e4883fdd 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2315,11 +2315,11 @@ doend:
* Check for an Ex command with optional tail.
* If there is a match advance "pp" to the argument and return TRUE.
*/
-int
-checkforcmd (
- char_u **pp, /* start of command */
- char *cmd, /* name of command */
- int len /* required length */
+int
+checkforcmd(
+ char_u **pp, // start of command
+ char *cmd, // name of command
+ int len // required length
)
{
int i;
@@ -4080,6 +4080,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lgrep
&& eap->cmdidx != CMD_grepadd
&& eap->cmdidx != CMD_lgrepadd
+ && eap->cmdidx != CMD_hardcopy
&& !(eap->argt & NOSPC)
) {
char_u *l;
@@ -4702,9 +4703,9 @@ char_u *check_nextcmd(char_u *p)
* return FAIL and give error message if 'message' TRUE
* return OK otherwise
*/
-static int
-check_more (
- int message, /* when FALSE check only, no messages */
+static int
+check_more(
+ int message, // when FALSE check only, no messages
int forceit
)
{
@@ -5371,8 +5372,8 @@ static size_t add_cmd_modifier(char_u *buf, char *mod_str, bool *multi_mods)
* Returns the length of the replacement, which has been added to "buf".
* Returns -1 if there was no match, and only the "<" has been copied.
*/
-static size_t
-uc_check_code (
+static size_t
+uc_check_code(
char_u *code,
size_t len,
char_u *buf,
@@ -6033,10 +6034,11 @@ static void ex_cquit(exarg_T *eap)
static void ex_quit_all(exarg_T *eap)
{
if (cmdwin_type != 0) {
- if (eap->forceit)
- cmdwin_result = K_XF1; /* ex_window() takes care of this */
- else
+ if (eap->forceit) {
+ cmdwin_result = K_XF1; // open_cmdwin() takes care of this
+ } else {
cmdwin_result = K_XF2;
+ }
return;
}
@@ -6103,8 +6105,8 @@ static void ex_pclose(exarg_T *eap)
* Close window "win" and take care of handling closing the last window for a
* modified buffer.
*/
-static void
-ex_win_close (
+static void
+ex_win_close(
int forceit,
win_T *win,
tabpage_T *tp /* NULL or the tab page "win" is in */
@@ -6520,8 +6522,8 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum
* Add file "fname" to argument list "al".
* "fname" must have been allocated and "al" must have been checked for room.
*/
-void
-alist_add (
+void
+alist_add(
alist_T *al,
char_u *fname,
int set_fnum /* 1: set buffer number; 2: re-use curbuf */
@@ -6868,8 +6870,8 @@ static void ex_edit(exarg_T *eap)
/*
* ":edit <file>" command and alikes.
*/
-void
-do_exedit (
+void
+do_exedit(
exarg_T *eap,
win_T *old_curwin /* curwin before doing a split or NULL */
)
@@ -8611,7 +8613,8 @@ eval_vars (
default:
// should not happen
*errormsg = (char_u *)"";
- return NULL;
+ result = (char_u *)""; // avoid gcc warning
+ break;
}
resultlen = STRLEN(result); /* length of new string */
@@ -8758,8 +8761,8 @@ char_u *expand_sfile(char_u *arg)
* Write openfile commands for the current buffers to an .exrc file.
* Return FAIL on error, OK otherwise.
*/
-static int
-makeopens (
+static int
+makeopens(
FILE *fd,
char_u *dirnow /* Current directory name */
)
@@ -9205,8 +9208,8 @@ static int ses_do_win(win_T *wp)
* Write commands to "fd" to restore the view of a window.
* Caller must make sure 'scrolloff' is zero.
*/
-static int
-put_view (
+static int
+put_view(
FILE *fd,
win_T *wp,
int add_edit, /* add ":edit" command to view */
@@ -9400,8 +9403,8 @@ put_view (
* Write an argument list to the session file.
* Returns FAIL if writing fails.
*/
-static int
-ses_arglist (
+static int
+ses_arglist(
FILE *fd,
char *cmd,
garray_T *gap,
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 9b1dcfcafb..774007c66e 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -861,7 +861,7 @@ static int command_line_execute(VimState *state, int key)
if (s->c == cedit_key || s->c == K_CMDWIN) {
if (ex_normal_busy == 0 && got_int == false) {
// Open a window to edit the command line (and history).
- s->c = ex_window();
+ s->c = open_cmdwin();
s->some_key_typed = true;
}
} else {
@@ -1444,7 +1444,7 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s);
case K_IGNORE:
- // Ignore mouse event or ex_window() result.
+ // Ignore mouse event or open_cmdwin() result.
return command_line_not_changed(s);
@@ -6001,7 +6001,7 @@ int cmd_gchar(int offset)
* Ctrl_C if it is to be abandoned
* K_IGNORE if editing continues
*/
-static int ex_window(void)
+static int open_cmdwin(void)
{
struct cmdline_info save_ccline;
bufref_T old_curbuf;
@@ -6034,6 +6034,7 @@ static int ex_window(void)
block_autocmds();
/* don't use a new tab page */
cmdmod.tab = 0;
+ cmdmod.noswapfile = 1;
/* Create a window for the command-line buffer. */
if (win_split((int)p_cwh, WSP_BOT) == FAIL) {
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 1c0464b575..a77c467fe5 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -835,7 +835,7 @@ static void init_typebuf(void)
typebuf.tb_noremap = noremapbuf_init;
typebuf.tb_buflen = TYPELEN_INIT;
typebuf.tb_len = 0;
- typebuf.tb_off = 0;
+ typebuf.tb_off = MAXMAPLEN + 4;
typebuf.tb_change_cnt = 1;
}
}
@@ -879,9 +879,15 @@ int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
// Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
typebuf.tb_off -= addlen;
memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
+ } else if (typebuf.tb_len == 0
+ && typebuf.tb_buflen >= addlen + 3 * (MAXMAPLEN + 4)) {
+ // Buffer is empty and string fits in the existing buffer.
+ // Leave some space before and after, if possible.
+ typebuf.tb_off = (typebuf.tb_buflen - addlen - 3 * (MAXMAPLEN + 4)) / 2;
+ memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
} else {
// Need to allocate a new buffer.
- // In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
+ // In typebuf.tb_buf there must always be room for 3 * (MAXMAPLEN + 4)
// characters. We add some extra room to avoid having to allocate too
// often.
newoff = MAXMAPLEN + 4;
@@ -1145,7 +1151,7 @@ void alloc_typebuf(void)
typebuf.tb_buf = xmalloc(TYPELEN_INIT);
typebuf.tb_noremap = xmalloc(TYPELEN_INIT);
typebuf.tb_buflen = TYPELEN_INIT;
- typebuf.tb_off = 0;
+ typebuf.tb_off = MAXMAPLEN + 4; // can insert without realloc
typebuf.tb_len = 0;
typebuf.tb_maplen = 0;
typebuf.tb_silent = 0;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ea43b93b30..6aed84aba5 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -1410,6 +1410,12 @@ static void read_stdin(void)
int save_msg_didany = msg_didany;
set_buflisted(true);
(void)open_buffer(true, NULL, 0); // create memfile and read file
+ if (BUFEMPTY() && curbuf->b_next != NULL) {
+ // stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561
+ do_cmdline_cmd("silent! bnext");
+ // Delete the empty stdin buffer.
+ do_cmdline_cmd("bwipeout 1");
+ }
no_wait_return = false;
msg_didany = save_msg_didany;
TIME_MSG("reading stdin");
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index a8781ffbb8..ea538fb4fc 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1328,7 +1328,7 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1,
#endif
/// Reassigns `strw` to a new, allocated pointer to a UTF16 string.
-int utf8_to_utf16(const char *str, WCHAR **strw)
+int utf8_to_utf16(const char *str, wchar_t **strw)
FUNC_ATTR_NONNULL_ALL
{
ssize_t wchar_len = 0;
@@ -1344,7 +1344,7 @@ int utf8_to_utf16(const char *str, WCHAR **strw)
return GetLastError();
}
- ssize_t buf_sz = wchar_len * sizeof(WCHAR);
+ ssize_t buf_sz = wchar_len * sizeof(wchar_t);
if (buf_sz == 0) {
*strw = NULL;
@@ -1358,19 +1358,19 @@ int utf8_to_utf16(const char *str, WCHAR **strw)
0,
str,
-1,
- (WCHAR *)pos,
+ (wchar_t *)pos,
wchar_len);
assert(r == wchar_len);
if (r != wchar_len) {
EMSG2("MultiByteToWideChar failed: %d", r);
}
- *strw = (WCHAR *)pos;
+ *strw = (wchar_t *)pos;
return 0;
}
/// Reassigns `str` to a new, allocated pointer to a UTF8 string.
-int utf16_to_utf8(const WCHAR *strw, char **str)
+int utf16_to_utf8(const wchar_t *strw, char **str)
FUNC_ATTR_NONNULL_ALL
{
// Compute the space required to store the string as UTF-8.
@@ -2201,7 +2201,7 @@ HINSTANCE vimLoadLib(char *name)
// NOTE: Do not use mch_dirname() and mch_chdir() here, they may call
// vimLoadLib() recursively, which causes a stack overflow.
- WCHAR old_dirw[MAXPATHL];
+ wchar_t old_dirw[MAXPATHL];
// Path to exe dir.
char *buf = xstrdup((char *)get_vim_var_str(VV_PROGPATH));
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index dd8e44b3f9..99aadcacad 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -7,8 +7,8 @@
#include "nvim/iconv.h"
#include "nvim/func_attr.h"
-#include "nvim/os/os_defs.h" // For WCHAR, indirect
-#include "nvim/types.h" // for char_u
+#include "nvim/os/os_defs.h" // For indirect
+#include "nvim/types.h" // for char_u
/*
* Return byte length of character that starts with byte "b".
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index b959ea08f3..a649777ddd 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -3769,14 +3769,17 @@ find_decl (
t = false; /* match after start is failure too */
if (thisblock && t != false) {
- pos_T *pos;
-
- /* Check that the block the match is in doesn't end before the
- * position where we started the search from. */
- if ((pos = findmatchlimit(NULL, '}', FM_FORWARD,
- (int)(old_pos.lnum - curwin->w_cursor.lnum + 1))) != NULL
- && pos->lnum < old_pos.lnum)
+ const int64_t maxtravel = old_pos.lnum - curwin->w_cursor.lnum + 1;
+ const pos_T *pos = findmatchlimit(NULL, '}', FM_FORWARD, maxtravel);
+
+ // Check that the block the match is in doesn't end before the
+ // position where we started the search from.
+ if (pos != NULL && pos->lnum < old_pos.lnum) {
+ // There can't be a useful match before the end of this block.
+ // Skip to the end
+ curwin->w_cursor = *pos;
continue;
+ }
}
if (t == false) {
@@ -6895,7 +6898,7 @@ static void nv_g_cmd(cmdarg_T *cap)
else
show_utf8();
break;
-
+ // "g<": show scrollback text
case '<':
show_sb_text();
break;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 0851e6cc5f..68b0a525f1 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -5811,7 +5811,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_ml = p_ml;
buf->b_p_ml_nobin = p_ml_nobin;
buf->b_p_inf = p_inf;
- buf->b_p_swf = p_swf;
+ buf->b_p_swf = cmdmod.noswapfile ? false : p_swf;
buf->b_p_cpt = vim_strsave(p_cpt);
buf->b_p_cfu = vim_strsave(p_cfu);
buf->b_p_ofu = vim_strsave(p_ofu);
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 25c4cc4f92..0df857352b 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -56,7 +56,7 @@ int os_setenv(const char *name, const char *value, int overwrite)
char *envbuf = xmalloc(envbuflen);
snprintf(envbuf, envbuflen, "%s=%s", name, value);
- WCHAR *p;
+ wchar_t *p;
utf8_to_utf16(envbuf, &p);
xfree(envbuf);
if (p == NULL) {
@@ -146,7 +146,7 @@ void os_get_hostname(char *hostname, size_t size)
xstrlcpy(hostname, vutsname.nodename, size);
}
#elif defined(WIN32)
- WCHAR host_utf16[MAX_COMPUTERNAME_LENGTH + 1];
+ wchar_t host_utf16[MAX_COMPUTERNAME_LENGTH + 1];
DWORD host_wsize = sizeof(host_utf16) / sizeof(host_utf16[0]);
if (GetComputerNameW(host_utf16, &host_wsize) == 0) {
*hostname = '\0';
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 5412c5daae..cf00fd4f82 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -1052,7 +1052,7 @@ char *os_resolve_shortcut(const char *fname)
hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
&IID_IShellLinkW, (void **)&pslw);
if (hr == S_OK) {
- WCHAR *p;
+ wchar_t *p;
const int conversion_result = utf8_to_utf16(fname, &p);
if (conversion_result != 0) {
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
@@ -1080,7 +1080,7 @@ char *os_resolve_shortcut(const char *fname)
# endif
// Get the path to the link target.
- ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR));
+ ZeroMemory(wsz, MAX_PATH * sizeof(wchar_t));
hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0);
if (hr == S_OK && wsz[0] != NUL) {
const int conversion_result = utf16_to_utf8(wsz, &rfname);
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index c4b4a43ad4..71f3ad1bc0 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -5,6 +5,7 @@ source test_assign.vim
source test_changedtick.vim
source test_cursor_func.vim
source test_ex_undo.vim
+source test_ex_z.vim
source test_execute_func.vim
source test_expr.vim
source test_feedkeys.vim
@@ -19,8 +20,8 @@ source test_jumps.vim
source test_fileformat.vim
source test_filetype.vim
source test_lambda.vim
-source test_menu.vim
source test_mapping.vim
+source test_menu.vim
source test_messages.vim
source test_partial.vim
source test_popup.vim
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index a998bd90f1..5a43838218 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -430,4 +430,14 @@ func Test_getcmdtype()
cunmap <F6>
endfunc
+func Test_verbosefile()
+ set verbosefile=Xlog
+ echomsg 'foo'
+ echomsg 'bar'
+ set verbosefile=
+ let log = readfile('Xlog')
+ call assert_match("foo\nbar", join(log, "\n"))
+ call delete('Xlog')
+endfunc
+
set cpo&
diff --git a/src/nvim/testdir/test_ex_z.vim b/src/nvim/testdir/test_ex_z.vim
new file mode 100644
index 0000000000..608a36c490
--- /dev/null
+++ b/src/nvim/testdir/test_ex_z.vim
@@ -0,0 +1,78 @@
+" Test :z
+
+func Test_z()
+ call setline(1, range(1, 100))
+
+ let a = execute('20z3')
+ call assert_equal("\n20\n21\n22", a)
+ call assert_equal(22, line('.'))
+ " 'window' should be set to the {count} value.
+ call assert_equal(3, &window)
+
+ " If there is only one window, then twice the amount of 'scroll' is used.
+ set scroll=2
+ let a = execute('20z')
+ call assert_equal("\n20\n21\n22\n23", a)
+ call assert_equal(23, line('.'))
+
+ let a = execute('20z+3')
+ " FIXME: I would expect the same result as '20z3' but it
+ " gives "\n21\n22\n23" instead. Bug in Vim or in ":help :z"?
+ "call assert_equal("\n20\n21\n22", a)
+ "call assert_equal(22, line('.'))
+
+ let a = execute('20z-3')
+ call assert_equal("\n18\n19\n20", a)
+ call assert_equal(20, line('.'))
+
+ let a = execute('20z=3')
+ call assert_match("^\n18\n19\n-\\+\n20\n-\\+\n21\n22$", a)
+ call assert_equal(20, line('.'))
+
+ let a = execute('20z^3')
+ call assert_equal("\n14\n15\n16\n17", a)
+ call assert_equal(17, line('.'))
+
+ let a = execute('20z.3')
+ call assert_equal("\n19\n20\n21", a)
+ call assert_equal(21, line('.'))
+
+ let a = execute('20z#3')
+ call assert_equal("\n 20 20\n 21 21\n 22 22", a)
+ call assert_equal(22, line('.'))
+
+ let a = execute('20z#-3')
+ call assert_equal("\n 18 18\n 19 19\n 20 20", a)
+ call assert_equal(20, line('.'))
+
+ let a = execute('20z#=3')
+ call assert_match("^\n 18 18\n 19 19\n-\\+\n 20 20\n-\\+\n 21 21\n 22 22$", a)
+ call assert_equal(20, line('.'))
+
+ " Test with {count} bigger than the number of lines in buffer.
+ let a = execute('20z1000')
+ call assert_match("^\n20\n21\n.*\n99\n100$", a)
+ call assert_equal(100, line('.'))
+
+ let a = execute('20z-1000')
+ call assert_match("^\n1\n2\n.*\n19\n20$", a)
+ call assert_equal(20, line('.'))
+
+ let a = execute('20z=1000')
+ call assert_match("^\n1\n.*\n-\\+\n20\n-\\\+\n.*\n100$", a)
+ call assert_equal(20, line('.'))
+
+ call assert_fails('20z=a', 'E144:')
+
+ set window& scroll&
+ bw!
+endfunc
+
+func Test_z_bug()
+ " This used to access invalid memory as a result of an integer overflow
+ " and freeze vim.
+ normal ox
+ normal Heat
+ z777777776666666
+ ')
+endfunc
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 8847653498..3028f72fec 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -373,15 +373,18 @@ endfunc
" Tests for the mode() function
let current_modes = ''
-func! Save_mode()
+func Save_mode()
let g:current_modes = mode(0) . '-' . mode(1)
return ''
endfunc
-func! Test_mode()
+func Test_mode()
new
call append(0, ["Blue Ball Black", "Brown Band Bowl", ""])
+ " Only complete from the current buffer.
+ set complete=.
+
inoremap <F2> <C-R>=Save_mode()<CR>
normal! 3G
@@ -490,6 +493,7 @@ func! Test_mode()
bwipe!
iunmap <F2>
+ set complete&
endfunc
func Test_getbufvar()
diff --git a/src/nvim/testdir/test_goto.vim b/src/nvim/testdir/test_goto.vim
index 2573401707..ea67fe7386 100644
--- a/src/nvim/testdir/test_goto.vim
+++ b/src/nvim/testdir/test_goto.vim
@@ -288,3 +288,24 @@ func Test_cursorline_keep_col()
set nocursorline
endfunc
+func Test_gd_local_block()
+ let lines = [
+ \ ' int main()',
+ \ '{',
+ \ ' char *a = "NOT NULL";',
+ \ ' if(a)',
+ \ ' {',
+ \ ' char *b = a;',
+ \ ' printf("%s\n", b);',
+ \ ' }',
+ \ ' else',
+ \ ' {',
+ \ ' char *b = "NULL";',
+ \ ' return b;',
+ \ ' }',
+ \ '',
+ \ ' return 0;',
+ \ '}',
+ \ ]
+ call XTest_goto_decl('1gd', lines, 11, 11)
+endfunc
diff --git a/src/nvim/testdir/test_hardcopy.vim b/src/nvim/testdir/test_hardcopy.vim
index 7aea704e86..f630556bef 100644
--- a/src/nvim/testdir/test_hardcopy.vim
+++ b/src/nvim/testdir/test_hardcopy.vim
@@ -61,3 +61,14 @@ func Test_with_syntax()
set printoptions&
endif
endfunc
+
+func Test_fname_with_spaces()
+ if has('postscript')
+ split t\ e\ s\ t.txt
+ call setline(1, ['just', 'some', 'text'])
+ hardcopy > %.ps
+ call assert_true(filereadable('t e s t.txt.ps'))
+ call delete('t e s t.txt.ps')
+ bwipe!
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 27ac084ef0..c638920dd3 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -847,7 +847,7 @@ func! Test_normal18_z_fold()
norm! j
call assert_equal('52', getline('.'))
- " zA on a opened fold when foldenale is not set
+ " zA on a opened fold when foldenable is not set
50
set nofoldenable
norm! zA
@@ -909,7 +909,7 @@ func! Test_normal18_z_fold()
norm! j
call assert_equal('55', getline('.'))
- " 2) do not close fold under curser
+ " 2) do not close fold under cursor
51
set nofoldenable
norm! zx
@@ -1829,18 +1829,60 @@ fun! Test_normal34_g_cmd3()
if !has("multi_byte")
return
endif
+
" Test for g8
new
- call append(0, 'abcdefghijklmnopqrstuvwxyzäüö')
- let a=execute(':norm! 1gg$g8')
- call assert_equal('c3 b6 ', a[1:])
+ let a=execute(':norm! 1G0g8')
+ call assert_equal("\nNUL", a)
+
+ call setline(1, 'abcdefghijklmnopqrstuvwxyzäüö')
+ let a=execute(':norm! 1G$g8')
+ call assert_equal("\nc3 b6 ", a)
+
+ call setline(1, "a\u0302")
+ let a=execute(':norm! 1G0g8')
+ call assert_equal("\n61 + cc 82 ", a)
- " Test for gp gP
- call append(1, range(1,10))
" clean up
bw!
endfunc
+func Test_normal_8g8()
+ if !has("multi_byte")
+ return
+ endif
+ new
+
+ " Test 8g8 which finds invalid utf8 at or after the cursor.
+
+ " With invalid byte.
+ call setline(1, "___\xff___")
+ norm! 1G08g8g
+ call assert_equal([0, 1, 4, 0, 1], getcurpos())
+
+ " With invalid byte before the cursor.
+ call setline(1, "___\xff___")
+ norm! 1G$h8g8g
+ call assert_equal([0, 1, 6, 0, 9], getcurpos())
+
+ " With truncated sequence.
+ call setline(1, "___\xE2\x82___")
+ norm! 1G08g8g
+ call assert_equal([0, 1, 4, 0, 1], getcurpos())
+
+ " With overlong sequence.
+ call setline(1, "___\xF0\x82\x82\xAC___")
+ norm! 1G08g8g
+ call assert_equal([0, 1, 4, 0, 1], getcurpos())
+
+ " With valid utf8.
+ call setline(1, "café")
+ norm! 1G08g8
+ call assert_equal([0, 1, 1, 0, 1], getcurpos())
+
+ bw!
+endfunc
+
fun! Test_normal35_g_cmd4()
" Test for g<
" Cannot capture its output,