aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt6
-rw-r--r--src/nvim/api/private/dispatch.c2
-rw-r--r--src/nvim/api/ui.c7
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/api/vim.c14
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/buffer_updates.c5
-rw-r--r--src/nvim/channel.c1
-rw-r--r--src/nvim/charset.c4
-rw-r--r--src/nvim/eval.c71
-rw-r--r--src/nvim/ex_cmds.lua4
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/ex_getln.c9
-rw-r--r--src/nvim/fold.c16
-rw-r--r--src/nvim/globals.h8
-rw-r--r--src/nvim/mark.c49
-rw-r--r--src/nvim/mbyte.c48
-rw-r--r--src/nvim/misc1.c3
-rw-r--r--src/nvim/move.c9
-rw-r--r--src/nvim/msgpack_rpc/channel.c18
-rw-r--r--src/nvim/msgpack_rpc/helpers.c3
-rw-r--r--src/nvim/option.c7
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/os/users.c2
-rw-r--r--src/nvim/os/win_defs.h1
-rw-r--r--src/nvim/path.c17
-rw-r--r--src/nvim/po/CMakeLists.txt2
-rw-r--r--src/nvim/regexp.c23
-rw-r--r--src/nvim/regexp_nfa.c11
-rw-r--r--src/nvim/screen.c6
-rw-r--r--src/nvim/search.c88
-rw-r--r--src/nvim/tag.c11
-rw-r--r--src/nvim/terminal.c18
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_cmdline.vim4
-rw-r--r--src/nvim/testdir/test_fold.vim57
-rw-r--r--src/nvim/testdir/test_functions.vim415
-rw-r--r--src/nvim/testdir/test_listlbr_utf8.vim15
-rw-r--r--src/nvim/testdir/test_mapping.vim27
-rw-r--r--src/nvim/testdir/test_marks.vim44
-rw-r--r--src/nvim/testdir/test_normal.vim56
-rw-r--r--src/nvim/testdir/test_options.vim7
-rw-r--r--src/nvim/testdir/test_python2.vim24
-rw-r--r--src/nvim/testdir/test_python3.vim24
-rw-r--r--src/nvim/testdir/test_quotestar.vim17
-rw-r--r--src/nvim/testdir/test_regexp_utf8.vim82
-rw-r--r--src/nvim/testdir/test_scroll_opt.vim36
-rw-r--r--src/nvim/testdir/test_smartindent.vim27
-rw-r--r--src/nvim/testdir/test_startup.vim11
-rw-r--r--src/nvim/testdir/test_syntax.vim59
-rw-r--r--src/nvim/tui/tui.c6
-rw-r--r--src/nvim/ui.c16
-rw-r--r--src/nvim/ui.h1
-rw-r--r--src/nvim/ui_bridge.c25
-rw-r--r--src/nvim/undo.c6
-rw-r--r--src/nvim/version.c120
57 files changed, 1260 insertions, 292 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 2d803792c8..65c3c6bbb9 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -457,6 +457,8 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/Qt5Widgets.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libiconv-2.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/
)
add_dependencies(nvim_runtime_deps external_blobs)
@@ -484,7 +486,9 @@ set_property(
APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB "
)
-if(LUAJIT_FOUND)
+if(NOT LUAJIT_FOUND)
+ message(STATUS "luajit not found, skipping nvim-test (unit tests) target")
+else()
set(NVIM_TEST_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUAJIT_LIBRARIES})
add_library(
nvim-test
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index f8eebcdb10..5207a57b88 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -29,6 +29,8 @@ static void msgpack_rpc_add_method_handler(String method,
map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
}
+/// @param name API method name
+/// @param name_len name size (includes terminating NUL)
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
size_t name_len)
{
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 4cd2657561..b6e0b9a566 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -97,6 +97,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->set_icon = remote_ui_set_icon;
ui->option_set = remote_ui_option_set;
ui->event = remote_ui_event;
+ ui->inspect = remote_ui_inspect;
memset(ui->ui_ext, 0, sizeof(ui->ui_ext));
@@ -275,3 +276,9 @@ static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
}
push_call(ui, name, my_args);
}
+
+static void remote_ui_inspect(UI *ui, Dictionary *info)
+{
+ UIData *data = ui->data;
+ PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id));
+}
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 96d494460b..3ef16a7ac3 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -62,7 +62,7 @@ void set_title(String title)
void set_icon(String icon)
FUNC_API_SINCE(3);
void option_set(String name, Object value)
- FUNC_API_SINCE(4);
+ FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL;
void popupmenu_show(Array items, Integer selected, Integer row, Integer col)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index f587948cf0..b3ae52602b 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -16,6 +16,7 @@
#include "nvim/api/private/dispatch.h"
#include "nvim/api/buffer.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
@@ -1163,6 +1164,11 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data,
name.size);
+ if (handler.fn == msgpack_rpc_handle_missing_method) {
+ api_set_error(&nested_error, kErrorTypeException, "Invalid method: %s",
+ name.size > 0 ? name.data : "<empty>");
+ break;
+ }
Object result = handler.fn(channel_id, args, &nested_error);
if (ERROR_SET(&nested_error)) {
// error handled after loop
@@ -1747,6 +1753,14 @@ Dictionary nvim__stats(void)
/// Gets a list of dictionaries representing attached UIs.
///
/// @return Array of UI dictionaries
+///
+/// Each dictionary has the following keys:
+/// - "height" requested height of the UI
+/// - "width" requested width of the UI
+/// - "rgb" whether the UI uses rgb colors (false implies cterm colors)
+/// - "ext_..." Requested UI extensions, see |ui-options|
+/// - "chan" Channel id of remote UI (not present for TUI)
+///
Array nvim_list_uis(void)
FUNC_API_SINCE(4)
{
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index af77a9891b..838f267dcd 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -575,7 +575,7 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)
/* Change directories when the 'acd' option is set. */
do_autochdir();
- // disable live updates for the current buffer
+ // disable buffer updates for the current buffer
buf_updates_unregister_all(buf);
/*
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c
index 4774b969c4..157f80e55a 100644
--- a/src/nvim/buffer_updates.c
+++ b/src/nvim/buffer_updates.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include "nvim/buffer_updates.h"
#include "nvim/memline.h"
#include "nvim/api/private/helpers.h"
@@ -199,7 +202,7 @@ void buf_updates_send_changes(buf_T *buf,
// change notifications are so frequent that many dead channels will be
// cleared up quickly.
if (badchannelid != 0) {
- ELOG("Disabling live updates for dead channel %llu", badchannelid);
+ ELOG("Disabling buffer updates for dead channel %llu", badchannelid);
buf_updates_unregister(buf, badchannelid);
}
}
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 64d743891b..6ad64bbb85 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -602,6 +602,7 @@ static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf,
// process_channel_event will modify the read buffer(convert NULs into NLs)
if (chan->term) {
terminal_receive(chan->term, ptr, count);
+ terminal_flush_output(chan->term);
}
rbuffer_consumed(buf, count);
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 7d5f80c531..4f70bcc41a 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1018,7 +1018,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
// needs a break here
if (wp->w_p_lbr
&& vim_isbreak(c)
- && !vim_isbreak(s[1])
+ && !vim_isbreak((int)s[1])
&& wp->w_p_wrap
&& (wp->w_width != 0)) {
// Count all characters from first non-blank after a blank up to next
@@ -1042,7 +1042,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
c = *s;
if (!(c != NUL
- && (vim_isbreak(c) || col2 == col || !vim_isbreak(*ps)))) {
+ && (vim_isbreak(c) || col2 == col || !vim_isbreak((int)(*ps))))) {
break;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index ffea88aa83..9c29f18c0c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6742,36 +6742,39 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
char_u *tofree;
if (opt_msg_tv->v_type != VAR_UNKNOWN) {
- tofree = (char_u *) encode_tv2string(opt_msg_tv, NULL);
+ tofree = (char_u *)encode_tv2echo(opt_msg_tv, NULL);
ga_concat(gap, tofree);
xfree(tofree);
+ ga_concat(gap, (char_u *)": ");
+ }
+
+ if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
+ ga_concat(gap, (char_u *)"Pattern ");
+ } else if (atype == ASSERT_NOTEQUAL) {
+ ga_concat(gap, (char_u *)"Expected not equal to ");
} else {
- if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
- ga_concat(gap, (char_u *)"Pattern ");
- } else if (atype == ASSERT_NOTEQUAL) {
- ga_concat(gap, (char_u *)"Expected not equal to ");
- } else {
- ga_concat(gap, (char_u *)"Expected ");
- }
- if (exp_str == NULL) {
- tofree = (char_u *)encode_tv2string(exp_tv, NULL);
- ga_concat_esc(gap, tofree);
- xfree(tofree);
+ ga_concat(gap, (char_u *)"Expected ");
+ }
+
+ if (exp_str == NULL) {
+ tofree = (char_u *)encode_tv2string(exp_tv, NULL);
+ ga_concat_esc(gap, tofree);
+ xfree(tofree);
+ } else {
+ ga_concat_esc(gap, exp_str);
+ }
+
+ if (atype != ASSERT_NOTEQUAL) {
+ if (atype == ASSERT_MATCH) {
+ ga_concat(gap, (char_u *)" does not match ");
+ } else if (atype == ASSERT_NOTMATCH) {
+ ga_concat(gap, (char_u *)" does match ");
} else {
- ga_concat_esc(gap, exp_str);
- }
- if (atype != ASSERT_NOTEQUAL) {
- if (atype == ASSERT_MATCH) {
- ga_concat(gap, (char_u *)" does not match ");
- } else if (atype == ASSERT_NOTMATCH) {
- ga_concat(gap, (char_u *)" does match ");
- } else {
- ga_concat(gap, (char_u *)" but got ");
- }
- tofree = (char_u *)encode_tv2string(got_tv, NULL);
- ga_concat_esc(gap, tofree);
- xfree(tofree);
+ ga_concat(gap, (char_u *)" but got ");
}
+ tofree = (char_u *)encode_tv2string(got_tv, NULL);
+ ga_concat_esc(gap, tofree);
+ xfree(tofree);
}
}
@@ -14806,18 +14809,14 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
pos.col = 0;
}
if (name[0] == '.' && name[1] == NUL) {
- // set cursor
- if (fnum == curbuf->b_fnum) {
- curwin->w_cursor = pos;
- if (curswant >= 0) {
- curwin->w_curswant = curswant - 1;
- curwin->w_set_curswant = false;
- }
- check_cursor();
- rettv->vval.v_number = 0;
- } else {
- EMSG(_(e_invarg));
+ // set cursor; "fnum" is ignored
+ curwin->w_cursor = pos;
+ if (curswant >= 0) {
+ curwin->w_curswant = curswant - 1;
+ curwin->w_set_curswant = false;
}
+ check_cursor();
+ rettv->vval.v_number = 0;
} else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) {
// set mark
if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) {
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index ce02808ad3..c87e3d4c66 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -698,7 +698,7 @@ return {
},
{
command='delfunction',
- flags=bit.bor(NEEDARG, WORD1, CMDWIN),
+ flags=bit.bor(BANG, NEEDARG, WORD1, CMDWIN),
addr_type=ADDR_LINES,
func='ex_delfunction',
},
@@ -3082,7 +3082,7 @@ return {
},
{
command='windo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
addr_type=ADDR_WINDOWS,
func='ex_listdo',
},
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 52b810085c..e1efd5710d 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -8104,6 +8104,7 @@ static void ex_normal(exarg_T *eap)
if (eap->addr_count != 0) {
curwin->w_cursor.lnum = eap->line1++;
curwin->w_cursor.col = 0;
+ check_cursor_moved(curwin);
}
exec_normal_cmd(
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 96388a2a9d..2c828be083 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -295,10 +295,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
redir_off = true; // don't redirect the typed command
if (!cmd_silent) {
- s->i = msg_scrolled;
- msg_scrolled = 0; // avoid wait_return message
gotocmdline(true);
- msg_scrolled += s->i;
redrawcmdprompt(); // draw prompt or indent
set_cmdspos();
}
@@ -349,7 +346,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
// redraw the statusline for statuslines that display the current mode
// using the mode() function.
- if (KeyTyped) {
+ if (KeyTyped && msg_scrolled == 0) {
curwin->w_redr_status = true;
redraw_statuslines();
}
@@ -629,6 +626,7 @@ static int command_line_execute(VimState *state, int key)
// Entered command line, move it up
cmdline_row--;
redrawcmd();
+ wild_menu_showing = 0;
} else if (save_p_ls != -1) {
// restore 'laststatus' and 'winminheight'
p_ls = save_p_ls;
@@ -639,12 +637,13 @@ static int command_line_execute(VimState *state, int key)
restore_cmdline(&s->save_ccline);
redrawcmd();
save_p_ls = -1;
+ wild_menu_showing = 0;
} else {
win_redraw_last_status(topframe);
+ wild_menu_showing = 0; // must be before redraw_statuslines #8385
redraw_statuslines();
}
KeyTyped = skt;
- wild_menu_showing = 0;
if (ccline.input_fn) {
RedrawingDisabled = old_RedrawingDisabled;
}
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index b8ace511e8..52ed2fe3dc 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2464,27 +2464,27 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level,
flp->lnum - 1 - fp->fd_top);
if (lvl < level) {
- /* End of fold found, update the length when it got shorter. */
+ // End of fold found, update the length when it got shorter.
if (fp->fd_len != flp->lnum - fp->fd_top) {
- if (fp->fd_top + fp->fd_len > bot + 1) {
- /* fold continued below bot */
+ if (fp->fd_top + fp->fd_len - 1 > bot) {
+ // fold continued below bot
if (getlevel == foldlevelMarker
|| getlevel == foldlevelExpr
|| getlevel == foldlevelSyntax) {
- /* marker method: truncate the fold and make sure the
- * previously included lines are processed again */
+ // marker method: truncate the fold and make sure the
+ // previously included lines are processed again
bot = fp->fd_top + fp->fd_len - 1;
fp->fd_len = flp->lnum - fp->fd_top;
} else {
- /* indent or expr method: split fold to create a new one
- * below bot */
+ // indent or expr method: split fold to create a new one
+ // below bot
i = (int)(fp - (fold_T *)gap->ga_data);
foldSplit(gap, i, flp->lnum, bot);
fp = (fold_T *)gap->ga_data + i;
}
} else
fp->fd_len = flp->lnum - fp->fd_top;
- fold_changed = TRUE;
+ fold_changed = true;
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 4aa0ef7def..2860817f79 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -745,11 +745,9 @@ EXTERN int State INIT(= NORMAL); /* This is the current state of the
EXTERN bool finish_op INIT(= false); // true while an operator is pending
EXTERN long opcount INIT(= 0); // count for pending operator
-/*
- * ex mode (Q) state
- */
-EXTERN int exmode_active INIT(= 0); /* zero, EXMODE_NORMAL or EXMODE_VIM */
-EXTERN int ex_no_reprint INIT(= FALSE); /* no need to print after z or p */
+// Ex Mode (Q) state
+EXTERN int exmode_active INIT(= 0); // zero, EXMODE_NORMAL or EXMODE_VIM
+EXTERN int ex_no_reprint INIT(= false); // no need to print after z or p
EXTERN int Recording INIT(= FALSE); /* TRUE when recording into a reg. */
EXTERN int Exec_reg INIT(= FALSE); /* TRUE when executing a register */
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 3cd26a5bf7..bcd9cf2090 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -106,39 +106,41 @@ int setmark_pos(int c, pos_T *pos, int fnum)
return OK;
}
+ // Can't set a mark in a non-existant buffer.
+ buf_T *buf = buflist_findnr(fnum);
+ if (buf == NULL) {
+ return FAIL;
+ }
+
if (c == '"') {
- RESET_FMARK(&curbuf->b_last_cursor, *pos, curbuf->b_fnum);
+ RESET_FMARK(&buf->b_last_cursor, *pos, buf->b_fnum);
return OK;
}
/* Allow setting '[ and '] for an autocommand that simulates reading a
* file. */
if (c == '[') {
- curbuf->b_op_start = *pos;
+ buf->b_op_start = *pos;
return OK;
}
if (c == ']') {
- curbuf->b_op_end = *pos;
+ buf->b_op_end = *pos;
return OK;
}
if (c == '<' || c == '>') {
- if (c == '<')
- curbuf->b_visual.vi_start = *pos;
- else
- curbuf->b_visual.vi_end = *pos;
- if (curbuf->b_visual.vi_mode == NUL)
- /* Visual_mode has not yet been set, use a sane default. */
- curbuf->b_visual.vi_mode = 'v';
+ if (c == '<') {
+ buf->b_visual.vi_start = *pos;
+ } else {
+ buf->b_visual.vi_end = *pos;
+ }
+ if (buf->b_visual.vi_mode == NUL) {
+ // Visual_mode has not yet been set, use a sane default.
+ buf->b_visual.vi_mode = 'v';
+ }
return OK;
}
- buf_T *buf = buflist_findnr(fnum);
- // Can't set a mark in a non-existant buffer.
- if (buf == NULL) {
- return FAIL;
- }
-
if (ASCII_ISLOWER(c)) {
i = c - 'a';
RESET_FMARK(buf->b_namedm + i, *pos, fnum);
@@ -358,13 +360,14 @@ pos_T *getmark_buf_fnum(buf_T *buf, int c, int changefile, int *fnum)
} else if (c == '<' || c == '>') { /* start/end of visual area */
startp = &buf->b_visual.vi_start;
endp = &buf->b_visual.vi_end;
- if ((c == '<') == lt(*startp, *endp))
+ if (((c == '<') == lt(*startp, *endp) || endp->lnum == 0)
+ && startp->lnum != 0) {
posp = startp;
- else
+ } else {
posp = endp;
- /*
- * For Visual line mode, set mark at begin or end of line
- */
+ }
+
+ // For Visual line mode, set mark at begin or end of line
if (buf->b_visual.vi_mode == 'V') {
pos_copy = *posp;
posp = &pos_copy;
@@ -647,8 +650,8 @@ void do_marks(exarg_T *eap)
show_one_mark(-1, arg, NULL, NULL, false);
}
-static void
-show_one_mark (
+static void
+show_one_mark(
int c,
char_u *arg,
pos_T *p,
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index a52ab9f5d3..05e326104b 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -37,6 +37,8 @@
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
+#include "nvim/eval.h"
+#include "nvim/path.h"
#include "nvim/iconv.h"
#include "nvim/mbyte.h"
#include "nvim/charset.h"
@@ -72,6 +74,9 @@ struct interval {
# include "unicode_tables.generated.h"
#endif
+char_u e_loadlib[] = "E370: Could not load library %s";
+char_u e_loadfunc[] = "E448: Could not load library function %s";
+
// To speed up BYTELEN(); keep a lookup table to quickly get the length in
// bytes of a UTF-8 character from the first byte of a UTF-8 string. Bytes
// which are illegal when used as the first byte have a 1. The NUL byte has
@@ -2038,9 +2043,10 @@ void * my_iconv_open(char_u *to, char_u *from)
return (void *)-1; /* detected a broken iconv() previously */
#ifdef DYNAMIC_ICONV
- /* Check if the iconv.dll can be found. */
- if (!iconv_enabled(true))
+ // Check if the iconv.dll can be found.
+ if (!iconv_enabled(true)) {
return (void *)-1;
+ }
#endif
fd = iconv_open((char *)enc_skip(to), (char *)enc_skip(from));
@@ -2162,7 +2168,7 @@ static HINSTANCE hMsvcrtDLL = 0;
# ifndef DYNAMIC_ICONV_DLL
# define DYNAMIC_ICONV_DLL "iconv.dll"
-# define DYNAMIC_ICONV_DLL_ALT "libiconv.dll"
+# define DYNAMIC_ICONV_DLL_ALT "libiconv-2.dll"
# endif
# ifndef DYNAMIC_MSVCRT_DLL
# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
@@ -2208,6 +2214,35 @@ static void * get_iconv_import_func(HINSTANCE hInst,
return NULL;
}
+// Load library "name".
+HINSTANCE vimLoadLib(char *name)
+{
+ HINSTANCE dll = NULL;
+
+ // NOTE: Do not use mch_dirname() and mch_chdir() here, they may call
+ // vimLoadLib() recursively, which causes a stack overflow.
+ WCHAR old_dirw[MAXPATHL];
+
+ // Path to exe dir.
+ char *buf = xstrdup((char *)get_vim_var_str(VV_PROGPATH));
+ // ptrdiff_t len = ;
+ // assert(len > 0);
+ buf[path_tail_with_sep(buf) - buf] = '\0';
+
+ if (GetCurrentDirectoryW(MAXPATHL, old_dirw) != 0) {
+ // Change directory to where the executable is, both to make
+ // sure we find a .dll there and to avoid looking for a .dll
+ // in the current directory.
+ SetCurrentDirectory((LPCSTR)buf);
+ // TODO(justinmk): use uv_dlopen instead. see os_libcall
+ dll = LoadLibrary(name);
+ SetCurrentDirectoryW(old_dirw);
+ }
+
+ return dll;
+}
+
+
/*
* Try opening the iconv.dll and return TRUE if iconv() can be used.
*/
@@ -2255,10 +2290,13 @@ bool iconv_enabled(bool verbose)
void iconv_end(void)
{
- if (hIconvDLL != 0)
+ if (hIconvDLL != 0) {
+ // TODO(justinmk): use uv_dlclose instead.
FreeLibrary(hIconvDLL);
- if (hMsvcrtDLL != 0)
+ }
+ if (hMsvcrtDLL != 0) {
FreeLibrary(hMsvcrtDLL);
+ }
hIconvDLL = 0;
hMsvcrtDLL = 0;
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 6c5c47b91f..70733e5564 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -107,7 +107,8 @@ open_line (
char_u *p;
char_u saved_char = NUL; // init for GCC
pos_T *pos;
- bool do_si = (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin);
+ bool do_si = (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin
+ && *curbuf->b_p_inde == NUL);
bool no_si = false; // reset did_si afterwards
int first_char = NUL; // init for GCC
int vreplace_mode;
diff --git a/src/nvim/move.c b/src/nvim/move.c
index cb13a9e207..41859a489f 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -132,11 +132,9 @@ void update_topline(void)
bool check_botline = false;
long save_so = p_so;
- if (!screen_valid(true))
- return;
-
- // If the window height is zero, just use the cursor line.
- if (curwin->w_height == 0) {
+ // If there is no valid screen and when the window height is zero just use
+ // the cursor line.
+ if (!screen_valid(true) || curwin->w_height == 0) {
curwin->w_topline = curwin->w_cursor.lnum;
curwin->w_botline = curwin->w_topline;
curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
@@ -1979,6 +1977,7 @@ void halfpage(bool flag, linenr_T Prenum)
int n = curwin->w_p_scr <= curwin->w_height ? (int)curwin->w_p_scr
: curwin->w_height;
+ update_topline();
validate_botline();
int room = curwin->w_empty_rows + curwin->w_filler_rows;
if (flag) {
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 26b84b7cc7..6d0c270a51 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -312,24 +312,30 @@ static void handle_request(Channel *channel, msgpack_object *request)
api_clear_error(&error);
return;
}
+
// Retrieve the request handler
MsgpackRpcRequestHandler handler;
+ Array args = ARRAY_DICT_INIT;
msgpack_object *method = msgpack_rpc_method(request);
if (method) {
handler = msgpack_rpc_get_handler_for(method->via.bin.ptr,
method->via.bin.size);
+ if (handler.fn == msgpack_rpc_handle_missing_method) {
+ String m = method->via.bin.size > 0
+ ? cbuf_to_string(method->via.bin.ptr, method->via.bin.size)
+ : cstr_to_string("<empty>");
+ ADD(args, STRING_OBJ(m));
+ handler.async = true;
+ } else if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) {
+ handler.fn = msgpack_rpc_handle_invalid_arguments;
+ handler.async = true;
+ }
} else {
handler.fn = msgpack_rpc_handle_missing_method;
handler.async = true;
}
- Array args = ARRAY_DICT_INIT;
- if (!msgpack_rpc_to_array(msgpack_rpc_args(request), &args)) {
- handler.fn = msgpack_rpc_handle_invalid_arguments;
- handler.async = true;
- }
-
RequestEvent *evdata = xmalloc(sizeof(RequestEvent));
evdata->channel = channel;
evdata->handler = handler;
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index fecae11d45..e18c4472b5 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -493,7 +493,8 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id,
Array args,
Error *error)
{
- api_set_error(error, kErrorTypeException, "Invalid method name");
+ api_set_error(error, kErrorTypeException, "Invalid method: %s",
+ args.size > 0 ? args.items[0].data.string.data : "?");
return NIL;
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 88c458b597..26fc164c6c 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -939,11 +939,8 @@ void set_init_2(bool headless)
{
int idx;
- /*
- * 'scroll' defaults to half the window height. Note that this default is
- * wrong when the window height changes.
- */
- set_number_default("scroll", Rows / 2);
+ // 'scroll' defaults to half the window height. The stored default is zero,
+ // which results in the actual value computed from the window height.
idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
set_option_default(idx, OPT_LOCAL, p_cp);
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index f1f559fff0..47c9f5aa78 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1922,7 +1922,7 @@ return {
no_mkrc=true,
vi_def=true,
pv_name='p_scroll',
- defaults={if_true={vi=12}}
+ defaults={if_true={vi=0}}
},
{
full_name='scrollback', abbreviation='scbk',
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index 82bb918f70..7c48ac6e5e 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -76,7 +76,7 @@ char *os_get_user_directory(const char *name)
{
#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
struct passwd *pw;
- if (name == NULL) {
+ if (name == NULL || *name == NUL) {
return NULL;
}
pw = getpwnam(name); // NOLINT(runtime/threadsafe_fn)
diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h
index db93f016bf..356094baa1 100644
--- a/src/nvim/os/win_defs.h
+++ b/src/nvim/os/win_defs.h
@@ -59,7 +59,6 @@
#define BACKSLASH_IN_FILENAME
#ifdef _MSC_VER
-typedef SSIZE_T ssize_t;
typedef int mode_t;
#endif
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 4f3f7c0661..61cfaea84a 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -1097,17 +1097,18 @@ static bool has_env_var(char_u *p)
}
#ifdef SPECIAL_WILDCHAR
-/*
- * Return TRUE if "p" contains a special wildcard character.
- * Allowing for escaping.
- */
+
+// Return TRUE if "p" contains a special wildcard character, one that Vim
+// cannot expand, requires using a shell.
static bool has_special_wildchar(char_u *p)
{
for (; *p; mb_ptr_adv(p)) {
- if (*p == '\\' && p[1] != NUL)
- ++p;
- else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL)
+ // Allow for escaping
+ if (*p == '\\' && p[1] != NUL) {
+ p++;
+ } else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL) {
return true;
+ }
}
return false;
}
@@ -2033,7 +2034,7 @@ int expand_wildcards(int num_pat, char_u **pat, int *num_files, char_u ***files,
break;
}
if (match_file_list(p_wig, (*files)[i], ffname)) {
- // remove this matching files from the list
+ // remove this matching file from the list
xfree((*files)[i]);
for (j = i; j + 1 < *num_files; j++) {
(*files)[j] = (*files)[j + 1];
diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt
index 94cc63baea..a7b910f0eb 100644
--- a/src/nvim/po/CMakeLists.txt
+++ b/src/nvim/po/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(Gettext)
+find_package(Gettext REQUIRED)
find_program(XGETTEXT_PRG xgettext)
find_program(ICONV_PRG iconv)
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index e4de43b49e..c4af7d9e4a 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -479,6 +479,8 @@ static char_u *regprop(char_u *);
#endif
static char_u e_missingbracket[] = N_("E769: Missing ] after %s[");
+static char_u e_reverse_range[] = N_("E944: Reverse range in character class");
+static char_u e_large_class[] = N_("E945: Range too large in character class");
static char_u e_unmatchedpp[] = N_("E53: Unmatched %s%%(");
static char_u e_unmatchedp[] = N_("E54: Unmatched %s(");
static char_u e_unmatchedpar[] = N_("E55: Unmatched %s)");
@@ -2232,15 +2234,18 @@ collection:
if (endc == '\\' && !reg_cpo_lit)
endc = coll_get_char();
- if (startc > endc)
- EMSG_RET_NULL(_(e_invrange));
+ if (startc > endc) {
+ EMSG_RET_NULL(_(e_reverse_range));
+ }
if (has_mbyte && ((*mb_char2len)(startc) > 1
|| (*mb_char2len)(endc) > 1)) {
- /* Limit to a range of 256 chars */
- if (endc > startc + 256)
- EMSG_RET_NULL(_(e_invrange));
- while (++startc <= endc)
+ // Limit to a range of 256 chars
+ if (endc > startc + 256) {
+ EMSG_RET_NULL(_(e_large_class));
+ }
+ while (++startc <= endc) {
regmbc(startc);
+ }
} else {
while (++startc <= endc)
regc(startc);
@@ -2328,21 +2333,21 @@ collection:
regc('\t');
break;
case CLASS_CNTRL:
- for (cu = 1; cu <= 255; cu++) {
+ for (cu = 1; cu <= 127; cu++) {
if (iscntrl(cu)) {
regmbc(cu);
}
}
break;
case CLASS_DIGIT:
- for (cu = 1; cu <= 255; cu++) {
+ for (cu = 1; cu <= 127; cu++) {
if (ascii_isdigit(cu)) {
regmbc(cu);
}
}
break;
case CLASS_GRAPH:
- for (cu = 1; cu <= 255; cu++) {
+ for (cu = 1; cu <= 127; cu++) {
if (isgraph(cu)) {
regmbc(cu);
}
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 98fae858f6..334539b228 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -1711,8 +1711,9 @@ collection:
if (emit_range) {
endc = startc;
startc = oldstartc;
- if (startc > endc)
- EMSG_RET_FAIL(_(e_invrange));
+ if (startc > endc) {
+ EMSG_RET_FAIL(_(e_reverse_range));
+ }
if (endc > startc + 2) {
/* Emit a range instead of the sequence of
@@ -4358,16 +4359,18 @@ static int check_char_class(int class, int c)
return OK;
break;
case NFA_CLASS_CNTRL:
- if (c >= 1 && c <= 255 && iscntrl(c))
+ if (c >= 1 && c <= 127 && iscntrl(c)) {
return OK;
+ }
break;
case NFA_CLASS_DIGIT:
if (ascii_isdigit(c))
return OK;
break;
case NFA_CLASS_GRAPH:
- if (c >= 1 && c <= 255 && isgraph(c))
+ if (c >= 1 && c <= 127 && isgraph(c)) {
return OK;
+ }
break;
case NFA_CLASS_LOWER:
if (mb_islower(c) && c != 170 && c != 186) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index f15afa619f..b0bf3a7d5f 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -3454,7 +3454,8 @@ win_line (
}
// Found last space before word: check for line break.
- if (wp->w_p_lbr && c0 == c && vim_isbreak(c) && !vim_isbreak(*ptr)) {
+ if (wp->w_p_lbr && c0 == c && vim_isbreak(c)
+ && !vim_isbreak((int)(*ptr))) {
int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1) : 0;
char_u *p = ptr - (mb_off + 1);
// TODO: is passing p for start of the line OK?
@@ -4060,7 +4061,8 @@ win_line (
* Also highlight the 'colorcolumn' if it is different than
* 'cursorcolumn' */
vcol_save_attr = -1;
- if (draw_state == WL_LINE && !lnum_in_visual_area) {
+ if (draw_state == WL_LINE && !lnum_in_visual_area
+ && search_attr == 0 && area_attr == 0) {
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
&& lnum != wp->w_cursor.lnum) {
vcol_save_attr = char_attr;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 84782497a0..14a7d41300 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -130,8 +130,8 @@ typedef struct SearchedFile {
*
* returns FAIL if failed, OK otherwise.
*/
-int
-search_regcomp (
+int
+search_regcomp(
char_u *pat,
int pat_save,
int pat_use,
@@ -2121,9 +2121,9 @@ static int check_linecomment(char_u *line)
* Show the match only if it is visible on the screen.
* If there isn't a match, then beep.
*/
-void
-showmatch (
- int c /* char to show match for */
+void
+showmatch(
+ int c // char to show match for
)
{
pos_T *lpos, save_cursor;
@@ -2377,8 +2377,14 @@ findpar (
++curr;
curwin->w_cursor.lnum = curr;
if (curr == curbuf->b_ml.ml_line_count && what != '}') {
- if ((curwin->w_cursor.col = (colnr_T)STRLEN(ml_get(curr))) != 0) {
- --curwin->w_cursor.col;
+ char_u *line = ml_get(curr);
+
+ // Put the cursor on the last character in the last line and make the
+ // motion inclusive.
+ if ((curwin->w_cursor.col = (colnr_T)STRLEN(line)) != 0) {
+ curwin->w_cursor.col--;
+ curwin->w_cursor.col -=
+ (*mb_head_off)(line, line + curwin->w_cursor.col);
*pincl = true;
}
} else
@@ -2483,8 +2489,8 @@ static int cls(void)
* Returns FAIL if the cursor was already at the end of the file.
* If eol is TRUE, last word stops at end of line (for operators).
*/
-int
-fwd_word (
+int
+fwd_word(
long count,
int bigword, /* "W", "E" or "B" */
int eol
@@ -2666,8 +2672,8 @@ finished:
*
* Returns FAIL if start of the file was reached.
*/
-int
-bckend_word (
+int
+bckend_word(
long count,
int bigword, /* TRUE for "B" */
int eol /* TRUE: stop at end of line. */
@@ -2756,8 +2762,8 @@ static void find_first_blank(pos_T *posp)
/*
* Skip count/2 sentences and count/2 separating white spaces.
*/
-static void
-findsent_forward (
+static void
+findsent_forward(
long count,
int at_start_sent /* cursor is at start of sentence */
)
@@ -2776,8 +2782,8 @@ findsent_forward (
* Find word under cursor, cursor at end.
* Used while an operator is pending, and in Visual mode.
*/
-int
-current_word (
+int
+current_word(
oparg_T *oap,
long count,
int include, /* TRUE: include word and white space */
@@ -3084,8 +3090,8 @@ extend:
* Find block under the cursor, cursor at end.
* "what" and "other" are two matching parenthesis/brace/etc.
*/
-int
-current_block (
+int
+current_block(
oparg_T *oap,
long count,
int include, /* TRUE == include white space */
@@ -3282,8 +3288,8 @@ static int in_html_tag(int end_tag)
/*
* Find tag block under the cursor, cursor at end.
*/
-int
-current_tagblock (
+int
+current_tagblock(
oparg_T *oap,
long count_arg,
int include /* TRUE == include white space */
@@ -3465,8 +3471,8 @@ theend:
return retval;
}
-int
-current_par (
+int
+current_par(
oparg_T *oap,
long count,
int include, /* TRUE == include white space */
@@ -3632,8 +3638,8 @@ extend:
* as a quote.
* Returns column number of "quotechar" or -1 when not found.
*/
-static int
-find_next_quote (
+static int
+find_next_quote(
char_u *line,
int col,
int quotechar,
@@ -3664,8 +3670,8 @@ find_next_quote (
* as a quote.
* Return the found column or zero.
*/
-static int
-find_prev_quote (
+static int
+find_prev_quote(
char_u *line,
int col_start,
int quotechar,
@@ -3694,8 +3700,8 @@ find_prev_quote (
* Find quote under the cursor, cursor at end.
* Returns TRUE if found, else FALSE.
*/
-int
-current_quote (
+int
+current_quote(
oparg_T *oap,
long count,
int include, /* TRUE == include quote char */
@@ -3920,8 +3926,8 @@ current_quote (
* Find next search match under cursor, cursor at end.
* Used while an operator is pending, and in Visual mode.
*/
-int
-current_search (
+int
+current_search(
long count,
int forward /* move forward or backwards */
)
@@ -4116,19 +4122,19 @@ int linewhite(linenr_T lnum)
* Find identifiers or defines in included files.
* If p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase.
*/
-void
-find_pattern_in_path (
- char_u *ptr, /* pointer to search pattern */
- int dir, /* direction of expansion */
- size_t len, /* length of search pattern */
- int whole, /* match whole words only */
- int skip_comments, /* don't match inside comments */
- int type, /* Type of search; are we looking for a type?
- a macro? */
+void
+find_pattern_in_path(
+ char_u *ptr, // pointer to search pattern
+ int dir, // direction of expansion
+ size_t len, // length of search pattern
+ int whole, // match whole words only
+ int skip_comments, // don't match inside comments
+ int type, // Type of search; are we looking for a type?
+ // a macro?
long count,
- int action, /* What to do when we find it */
- linenr_T start_lnum, /* first line to start searching */
- linenr_T end_lnum /* last line for searching */
+ int action, // What to do when we find it
+ linenr_T start_lnum, // first line to start searching
+ linenr_T end_lnum // last line for searching
)
{
SearchedFile *files; /* Stack of included files */
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index ba2727f0d7..d7bdf97c48 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2404,11 +2404,14 @@ jumpto_tag (
}
}
- /* If it was a CTRL-W CTRL-] command split window now. For ":tab tag"
- * open a new tab page. */
+ // If it was a CTRL-W CTRL-] command split window now. For ":tab tag"
+ // open a new tab page.
if (postponed_split || cmdmod.tab != 0) {
- (void)win_split(postponed_split > 0 ? postponed_split : 0,
- postponed_split_flags);
+ if (win_split(postponed_split > 0 ? postponed_split : 0,
+ postponed_split_flags) == FAIL) {
+ RedrawingDisabled--;
+ goto erret;
+ }
RESET_BINDING(curwin);
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index c29f0b3927..c2370de0f8 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -528,6 +528,13 @@ void terminal_send(Terminal *term, char *data, size_t size)
term->opts.write_cb(data, size, term->opts.data);
}
+void terminal_flush_output(Terminal *term)
+{
+ size_t len = vterm_output_read(term->vt, term->textbuf,
+ sizeof(term->textbuf));
+ terminal_send(term, term->textbuf, len);
+}
+
void terminal_send_key(Terminal *term, int c)
{
VTermModifier mod = VTERM_MOD_NONE;
@@ -545,9 +552,7 @@ void terminal_send_key(Terminal *term, int c)
vterm_keyboard_unichar(term->vt, (uint32_t)c, mod);
}
- size_t len = vterm_output_read(term->vt, term->textbuf,
- sizeof(term->textbuf));
- terminal_send(term, term->textbuf, (size_t)len);
+ terminal_flush_output(term);
}
void terminal_receive(Terminal *term, char *data, size_t len)
@@ -982,7 +987,7 @@ static bool send_mouse_event(Terminal *term, int c)
mouse_action(term, button, row, col, drag, 0);
size_t len = vterm_output_read(term->vt, term->textbuf,
- sizeof(term->textbuf));
+ sizeof(term->textbuf));
terminal_send(term, term->textbuf, (size_t)len);
return false;
}
@@ -1234,8 +1239,9 @@ static void refresh_screen(Terminal *term, buf_T *buf)
int change_start = row_to_linenr(term, term->invalid_start);
int change_end = change_start + changed;
- // Note: don't send nvim_buf_lines_event event for a :terminal buffer
- changed_lines(change_start, 0, change_end, added, false);
+ changed_lines(change_start, 0, change_end, added,
+ // Don't send nvim_buf_lines_event for :terminal buffer.
+ false);
term->invalid_start = INT_MAX;
term->invalid_end = -1;
}
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index c1ede08c31..a161f14bc8 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -88,6 +88,8 @@ NEW_TESTS ?= \
test_options.res \
test_profile.res \
test_put.res \
+ test_python2.res \
+ test_python3.res \
test_quickfix.res \
test_quotestar.res \
test_recover.res \
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index b4baf7a8d7..c4b4a43ad4 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -27,6 +27,7 @@ source test_popup.vim
source test_put.vim
source test_recover.vim
source test_regexp_utf8.vim
+source test_scroll_opt.vim
source test_source_utf8.vim
source test_sha256.vim
source test_statusline.vim
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index be68e9ff9d..8139f00f0e 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -64,6 +64,10 @@ func Test_highlight_completion()
hi Aardig ctermfg=green
call feedkeys(":hi \<Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"hi Aardig', getreg(':'))
+ call feedkeys(":hi default \<Tab>\<Home>\"\<CR>", 'xt')
+ call assert_equal('"hi default Aardig', getreg(':'))
+ call feedkeys(":hi clear Aa\<Tab>\<Home>\"\<CR>", 'xt')
+ call assert_equal('"hi clear Aardig', getreg(':'))
call feedkeys(":hi li\<S-Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"hi link', getreg(':'))
call feedkeys(":hi d\<S-Tab>\<Home>\"\<CR>", 'xt')
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 7c6d38d7ec..0c2ec08af3 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -9,8 +9,8 @@ func! Test_address_fold()
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
\ 'after fold 1', 'after fold 2', 'after fold 3'])
setl fen fdm=marker
- " The next ccommands should all copy the same part of the buffer,
- " regardless of the adressing type, since the part to be copied
+ " The next commands should all copy the same part of the buffer,
+ " regardless of the addressing type, since the part to be copied
" is folded away
:1y
call assert_equal(['int FuncName() {/*{{{*/', '1', '2', '3', '4', '5', '}/*}}}*/'], getreg(0,1,1))
@@ -381,3 +381,56 @@ func Test_foldopen_exception()
endtry
call assert_match('E492:', a)
endfunc
+
+func Test_folddoopen_folddoclosed()
+ new
+ call setline(1, range(1, 9))
+ set foldmethod=manual
+ 1,3 fold
+ 6,8 fold
+
+ " Test without range.
+ folddoopen s/$/o/
+ folddoclosed s/$/c/
+ call assert_equal(['1c', '2c', '3c',
+ \ '4o', '5o',
+ \ '6c', '7c', '8c',
+ \ '9o'], getline(1, '$'))
+
+ " Test with range.
+ call setline(1, range(1, 9))
+ 1,8 folddoopen s/$/o/
+ 4,$ folddoclosed s/$/c/
+ call assert_equal(['1', '2', '3',
+ \ '4o', '5o',
+ \ '6c', '7c', '8c',
+ \ '9'], getline(1, '$'))
+
+ set foldmethod&
+ bw!
+endfunc
+
+func Test_fold_error()
+ new
+ call setline(1, [1, 2])
+
+ for fm in ['indent', 'expr', 'syntax', 'diff']
+ exe 'set foldmethod=' . fm
+ call assert_fails('norm zf', 'E350:')
+ call assert_fails('norm zd', 'E351:')
+ call assert_fails('norm zE', 'E352:')
+ endfor
+
+ set foldmethod=manual
+ call assert_fails('norm zd', 'E490:')
+ call assert_fails('norm zo', 'E490:')
+ call assert_fails('3fold', 'E16:')
+
+ set foldmethod=marker
+ set nomodifiable
+ call assert_fails('1,2fold', 'E21:')
+
+ set modifiable&
+ set foldmethod&
+ bw!
+endfunc
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 398e9ab331..8a82493ab6 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1,5 +1,101 @@
" Tests for various functions.
+" Must be done first, since the alternate buffer must be unset.
+func Test_00_bufexists()
+ call assert_equal(0, bufexists('does_not_exist'))
+ call assert_equal(1, bufexists(bufnr('%')))
+ call assert_equal(0, bufexists(0))
+ new Xfoo
+ let bn = bufnr('%')
+ call assert_equal(1, bufexists(bn))
+ call assert_equal(1, bufexists('Xfoo'))
+ call assert_equal(1, bufexists(getcwd() . '/Xfoo'))
+ call assert_equal(1, bufexists(0))
+ bw
+ call assert_equal(0, bufexists(bn))
+ call assert_equal(0, bufexists('Xfoo'))
+endfunc
+
+func Test_empty()
+ call assert_equal(1, empty(''))
+ call assert_equal(0, empty('a'))
+
+ call assert_equal(1, empty(0))
+ call assert_equal(1, empty(-0))
+ call assert_equal(0, empty(1))
+ call assert_equal(0, empty(-1))
+
+ call assert_equal(1, empty(0.0))
+ call assert_equal(1, empty(-0.0))
+ call assert_equal(0, empty(1.0))
+ call assert_equal(0, empty(-1.0))
+ call assert_equal(0, empty(1.0/0.0))
+ call assert_equal(0, empty(0.0/0.0))
+
+ call assert_equal(1, empty([]))
+ call assert_equal(0, empty(['a']))
+
+ call assert_equal(1, empty({}))
+ call assert_equal(0, empty({'a':1}))
+
+ call assert_equal(1, empty(v:null))
+ " call assert_equal(1, empty(v:none))
+ call assert_equal(1, empty(v:false))
+ call assert_equal(0, empty(v:true))
+
+ if has('channel')
+ call assert_equal(1, empty(test_null_channel()))
+ endif
+ if has('job')
+ call assert_equal(1, empty(test_null_job()))
+ endif
+
+ call assert_equal(0, empty(function('Test_empty')))
+endfunc
+
+func Test_len()
+ call assert_equal(1, len(0))
+ call assert_equal(2, len(12))
+
+ call assert_equal(0, len(''))
+ call assert_equal(2, len('ab'))
+
+ call assert_equal(0, len([]))
+ call assert_equal(2, len([2, 1]))
+
+ call assert_equal(0, len({}))
+ call assert_equal(2, len({'a': 1, 'b': 2}))
+
+ " call assert_fails('call len(v:none)', 'E701:')
+ call assert_fails('call len({-> 0})', 'E701:')
+endfunc
+
+func Test_max()
+ call assert_equal(0, max([]))
+ call assert_equal(2, max([2]))
+ call assert_equal(2, max([1, 2]))
+ call assert_equal(2, max([1, 2, v:null]))
+
+ call assert_equal(0, max({}))
+ call assert_equal(2, max({'a':1, 'b':2}))
+
+ call assert_fails('call max(1)', 'E712:')
+ " call assert_fails('call max(v:none)', 'E712:')
+endfunc
+
+func Test_min()
+ call assert_equal(0, min([]))
+ call assert_equal(2, min([2]))
+ call assert_equal(1, min([1, 2]))
+ call assert_equal(0, min([1, 2, v:null]))
+
+ call assert_equal(0, min({}))
+ call assert_equal(1, min({'a':1, 'b':2}))
+
+ call assert_fails('call min(1)', 'E712:')
+ " call assert_fails('call min(v:none)', 'E712:')
+endfunc
+
func Test_str2nr()
call assert_equal(0, str2nr(''))
call assert_equal(1, str2nr('1'))
@@ -15,6 +111,77 @@ func Test_str2nr()
call assert_equal(123456789, str2nr('123456789'))
call assert_equal(-123456789, str2nr('-123456789'))
+
+ call assert_equal(5, str2nr('101', 2))
+ call assert_equal(5, str2nr('0b101', 2))
+ call assert_equal(5, str2nr('0B101', 2))
+ call assert_equal(-5, str2nr('-101', 2))
+ call assert_equal(-5, str2nr('-0b101', 2))
+ call assert_equal(-5, str2nr('-0B101', 2))
+
+ call assert_equal(65, str2nr('101', 8))
+ call assert_equal(65, str2nr('0101', 8))
+ call assert_equal(-65, str2nr('-101', 8))
+ call assert_equal(-65, str2nr('-0101', 8))
+
+ call assert_equal(11259375, str2nr('abcdef', 16))
+ call assert_equal(11259375, str2nr('ABCDEF', 16))
+ call assert_equal(-11259375, str2nr('-ABCDEF', 16))
+ call assert_equal(11259375, str2nr('0xabcdef', 16))
+ call assert_equal(11259375, str2nr('0Xabcdef', 16))
+ call assert_equal(11259375, str2nr('0XABCDEF', 16))
+ call assert_equal(-11259375, str2nr('-0xABCDEF', 16))
+
+ call assert_equal(0, str2nr('0x10'))
+ call assert_equal(0, str2nr('0b10'))
+ call assert_equal(1, str2nr('12', 2))
+ call assert_equal(1, str2nr('18', 8))
+ call assert_equal(1, str2nr('1g', 16))
+
+ call assert_equal(0, str2nr(v:null))
+ " call assert_equal(0, str2nr(v:none))
+
+ call assert_fails('call str2nr([])', 'E730:')
+ call assert_fails('call str2nr({->2})', 'E729:')
+ call assert_fails('call str2nr(1.2)', 'E806:')
+ call assert_fails('call str2nr(10, [])', 'E474:')
+endfunc
+
+func Test_strftime()
+ if !exists('*strftime')
+ return
+ endif
+ " Format of strftime() depends on system. We assume
+ " that basic formats tested here are available and
+ " identical on all systems which support strftime().
+ "
+ " The 2nd parameter of strftime() is a local time, so the output day
+ " of strftime() can be 17 or 18, depending on timezone.
+ call assert_match('^2017-01-1[78]$', strftime('%Y-%m-%d', 1484695512))
+ "
+ call assert_match('^\d\d\d\d-\(0\d\|1[012]\)-\([012]\d\|3[01]\) \([01]\d\|2[0-3]\):[0-5]\d:\([0-5]\d\|60\)$', strftime('%Y-%m-%d %H:%M:%S'))
+
+ call assert_fails('call strftime([])', 'E730:')
+ call assert_fails('call strftime("%Y", [])', 'E745:')
+endfunc
+
+func Test_simplify()
+ call assert_equal('', simplify(''))
+ call assert_equal('/', simplify('/'))
+ call assert_equal('/', simplify('/.'))
+ call assert_equal('/', simplify('/..'))
+ call assert_equal('/...', simplify('/...'))
+ call assert_equal('./dir/file', simplify('./dir/file'))
+ call assert_equal('./dir/file', simplify('.///dir//file'))
+ call assert_equal('./dir/file', simplify('./dir/./file'))
+ call assert_equal('./file', simplify('./dir/../file'))
+ call assert_equal('../dir/file', simplify('dir/../../dir/file'))
+ call assert_equal('./file', simplify('dir/.././file'))
+
+ call assert_fails('call simplify({->0})', 'E729:')
+ call assert_fails('call simplify([])', 'E730:')
+ call assert_fails('call simplify({})', 'E731:')
+ call assert_fails('call simplify(1.2)', 'E806:')
endfunc
func Test_setbufvar_options()
@@ -48,6 +215,19 @@ func Test_setbufvar_options()
bwipe!
endfunc
+func Test_strpart()
+ call assert_equal('de', strpart('abcdefg', 3, 2))
+ call assert_equal('ab', strpart('abcdefg', -2, 4))
+ call assert_equal('abcdefg', strpart('abcdefg', -2))
+ call assert_equal('fg', strpart('abcdefg', 5, 4))
+ call assert_equal('defg', strpart('abcdefg', 3))
+
+ if has('multi_byte')
+ call assert_equal('lép', strpart('éléphant', 2, 4))
+ call assert_equal('léphant', strpart('éléphant', 2))
+ endif
+endfunc
+
func Test_tolower()
call assert_equal("", tolower(""))
@@ -188,7 +368,7 @@ func Test_toupper()
call assert_equal("YÝŶŸẎỲỶỸ", toupper("YÝŶŸẎỲỶỸ"))
call assert_equal("ZŹŻŽƵẐẔ", toupper("ZŹŻŽƵẐẔ"))
- call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ"))
+ call assert_equal("Ⱥ Ⱦ", toupper("ⱥ ⱦ"))
endfunc
" Tests for the mode() function
@@ -353,3 +533,236 @@ func Test_getbufvar()
set fileformats&
endfunc
+
+func Test_last_buffer_nr()
+ call assert_equal(bufnr('$'), last_buffer_nr())
+endfunc
+
+func Test_stridx()
+ call assert_equal(-1, stridx('', 'l'))
+ call assert_equal(0, stridx('', ''))
+ call assert_equal(0, stridx('hello', ''))
+ call assert_equal(-1, stridx('hello', 'L'))
+ call assert_equal(2, stridx('hello', 'l', -1))
+ call assert_equal(2, stridx('hello', 'l', 0))
+ call assert_equal(2, stridx('hello', 'l', 1))
+ call assert_equal(3, stridx('hello', 'l', 3))
+ call assert_equal(-1, stridx('hello', 'l', 4))
+ call assert_equal(-1, stridx('hello', 'l', 10))
+ call assert_equal(2, stridx('hello', 'll'))
+ call assert_equal(-1, stridx('hello', 'hello world'))
+endfunc
+
+func Test_strridx()
+ call assert_equal(-1, strridx('', 'l'))
+ call assert_equal(0, strridx('', ''))
+ call assert_equal(5, strridx('hello', ''))
+ call assert_equal(-1, strridx('hello', 'L'))
+ call assert_equal(3, strridx('hello', 'l'))
+ call assert_equal(3, strridx('hello', 'l', 10))
+ call assert_equal(3, strridx('hello', 'l', 3))
+ call assert_equal(2, strridx('hello', 'l', 2))
+ call assert_equal(-1, strridx('hello', 'l', 1))
+ call assert_equal(-1, strridx('hello', 'l', 0))
+ call assert_equal(-1, strridx('hello', 'l', -1))
+ call assert_equal(2, strridx('hello', 'll'))
+ call assert_equal(-1, strridx('hello', 'hello world'))
+endfunc
+
+func Test_matchend()
+ call assert_equal(7, matchend('testing', 'ing'))
+ call assert_equal(7, matchend('testing', 'ing', 2))
+ call assert_equal(-1, matchend('testing', 'ing', 5))
+endfunc
+
+func Test_nextnonblank_prevnonblank()
+ new
+insert
+This
+
+
+is
+
+a
+Test
+.
+ call assert_equal(0, nextnonblank(-1))
+ call assert_equal(0, nextnonblank(0))
+ call assert_equal(1, nextnonblank(1))
+ call assert_equal(4, nextnonblank(2))
+ call assert_equal(4, nextnonblank(3))
+ call assert_equal(4, nextnonblank(4))
+ call assert_equal(6, nextnonblank(5))
+ call assert_equal(6, nextnonblank(6))
+ call assert_equal(7, nextnonblank(7))
+ call assert_equal(0, nextnonblank(8))
+
+ call assert_equal(0, prevnonblank(-1))
+ call assert_equal(0, prevnonblank(0))
+ call assert_equal(1, prevnonblank(1))
+ call assert_equal(1, prevnonblank(2))
+ call assert_equal(1, prevnonblank(3))
+ call assert_equal(4, prevnonblank(4))
+ call assert_equal(4, prevnonblank(5))
+ call assert_equal(6, prevnonblank(6))
+ call assert_equal(7, prevnonblank(7))
+ call assert_equal(0, prevnonblank(8))
+ bw!
+endfunc
+
+func Test_byte2line_line2byte()
+ new
+ call setline(1, ['a', 'bc', 'd'])
+
+ set fileformat=unix
+ call assert_equal([-1, -1, 1, 1, 2, 2, 2, 3, 3, -1],
+ \ map(range(-1, 8), 'byte2line(v:val)'))
+ call assert_equal([-1, -1, 1, 3, 6, 8, -1],
+ \ map(range(-1, 5), 'line2byte(v:val)'))
+
+ set fileformat=mac
+ call assert_equal([-1, -1, 1, 1, 2, 2, 2, 3, 3, -1],
+ \ map(range(-1, 8), 'byte2line(v:val)'))
+ call assert_equal([-1, -1, 1, 3, 6, 8, -1],
+ \ map(range(-1, 5), 'line2byte(v:val)'))
+
+ set fileformat=dos
+ call assert_equal([-1, -1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, -1],
+ \ map(range(-1, 11), 'byte2line(v:val)'))
+ call assert_equal([-1, -1, 1, 4, 8, 11, -1],
+ \ map(range(-1, 5), 'line2byte(v:val)'))
+
+ set fileformat&
+ bw!
+endfunc
+
+func Test_count()
+ let l = ['a', 'a', 'A', 'b']
+ call assert_equal(2, count(l, 'a'))
+ call assert_equal(1, count(l, 'A'))
+ call assert_equal(1, count(l, 'b'))
+ call assert_equal(0, count(l, 'B'))
+
+ call assert_equal(2, count(l, 'a', 0))
+ call assert_equal(1, count(l, 'A', 0))
+ call assert_equal(1, count(l, 'b', 0))
+ call assert_equal(0, count(l, 'B', 0))
+
+ call assert_equal(3, count(l, 'a', 1))
+ call assert_equal(3, count(l, 'A', 1))
+ call assert_equal(1, count(l, 'b', 1))
+ call assert_equal(1, count(l, 'B', 1))
+ call assert_equal(0, count(l, 'c', 1))
+
+ call assert_equal(1, count(l, 'a', 0, 1))
+ call assert_equal(2, count(l, 'a', 1, 1))
+ call assert_fails('call count(l, "a", 0, 10)', 'E684:')
+
+ let d = {1: 'a', 2: 'a', 3: 'A', 4: 'b'}
+ call assert_equal(2, count(d, 'a'))
+ call assert_equal(1, count(d, 'A'))
+ call assert_equal(1, count(d, 'b'))
+ call assert_equal(0, count(d, 'B'))
+
+ call assert_equal(2, count(d, 'a', 0))
+ call assert_equal(1, count(d, 'A', 0))
+ call assert_equal(1, count(d, 'b', 0))
+ call assert_equal(0, count(d, 'B', 0))
+
+ call assert_equal(3, count(d, 'a', 1))
+ call assert_equal(3, count(d, 'A', 1))
+ call assert_equal(1, count(d, 'b', 1))
+ call assert_equal(1, count(d, 'B', 1))
+ call assert_equal(0, count(d, 'c', 1))
+
+ call assert_fails('call count(d, "a", 0, 1)', 'E474:')
+ call assert_fails('call count("a", "a")', 'E712:')
+endfunc
+
+func Test_changenr()
+ new Xchangenr
+ call assert_equal(0, changenr())
+ norm ifoo
+ call assert_equal(1, changenr())
+ set undolevels=10
+ norm Sbar
+ call assert_equal(2, changenr())
+ undo
+ call assert_equal(1, changenr())
+ redo
+ call assert_equal(2, changenr())
+ bw!
+ set undolevels&
+endfunc
+
+func Test_filewritable()
+ new Xfilewritable
+ write!
+ call assert_equal(1, filewritable('Xfilewritable'))
+
+ call assert_notequal(0, setfperm('Xfilewritable', 'r--r-----'))
+ call assert_equal(0, filewritable('Xfilewritable'))
+
+ call assert_notequal(0, setfperm('Xfilewritable', 'rw-r-----'))
+ call assert_equal(1, filewritable('Xfilewritable'))
+
+ call assert_equal(0, filewritable('doesnotexist'))
+
+ call delete('Xfilewritable')
+ bw!
+endfunc
+
+func Test_hostname()
+ let hostname_vim = hostname()
+ if has('unix')
+ let hostname_system = systemlist('uname -n')[0]
+ call assert_equal(hostname_vim, hostname_system)
+ endif
+endfunc
+
+func Test_getpid()
+ " getpid() always returns the same value within a vim instance.
+ call assert_equal(getpid(), getpid())
+ if has('unix')
+ call assert_equal(systemlist('echo $PPID')[0], string(getpid()))
+ endif
+endfunc
+
+func Test_hlexists()
+ call assert_equal(0, hlexists('does_not_exist'))
+ " call assert_equal(0, hlexists('Number'))
+ call assert_equal(0, highlight_exists('does_not_exist'))
+ " call assert_equal(0, highlight_exists('Number'))
+ syntax on
+ call assert_equal(0, hlexists('does_not_exist'))
+ " call assert_equal(1, hlexists('Number'))
+ call assert_equal(0, highlight_exists('does_not_exist'))
+ " call assert_equal(1, highlight_exists('Number'))
+ syntax off
+endfunc
+
+func Test_col()
+ new
+ call setline(1, 'abcdef')
+ norm gg4|mx6|mY2|
+ call assert_equal(2, col('.'))
+ call assert_equal(7, col('$'))
+ call assert_equal(4, col("'x"))
+ call assert_equal(6, col("'Y"))
+ call assert_equal(2, col([1, 2]))
+ call assert_equal(7, col([1, '$']))
+
+ call assert_equal(0, col(''))
+ call assert_equal(0, col('x'))
+ call assert_equal(0, col([2, '$']))
+ call assert_equal(0, col([1, 100]))
+ call assert_equal(0, col([1]))
+ bw!
+endfunc
+
+func Test_balloon_show()
+ if has('balloon_eval')
+ " This won't do anything but must not crash either.
+ call balloon_show('hi!')
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_listlbr_utf8.vim b/src/nvim/testdir/test_listlbr_utf8.vim
index 56a4cc9b31..b648a3361b 100644
--- a/src/nvim/testdir/test_listlbr_utf8.vim
+++ b/src/nvim/testdir/test_listlbr_utf8.vim
@@ -194,6 +194,21 @@ func Test_multibyte_sign_and_colorcolumn()
call s:close_windows()
endfunc
+func Test_colorcolumn_priority()
+ call s:test_windows('setl cc=4 cuc hls')
+ call setline(1, ["xxyy", ""])
+ norm! gg
+ exe "normal! /xxyy\<CR>"
+ norm! G
+ redraw!
+ let line_attr = s:screen_attr(1, [1, &cc])
+ " Search wins over CursorColumn
+ call assert_equal(line_attr[1], line_attr[0])
+ " Search wins over Colorcolumn
+ call assert_equal(line_attr[2], line_attr[3])
+ call s:close_windows('setl hls&vim')
+endfunc
+
func Test_illegal_byte_and_breakat()
call s:test_windows("setl sbr= brk+=<")
vert resize 18
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index f5e4c4b90c..0a198763bb 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -160,3 +160,30 @@ func Test_map_meta_quotes()
set nomodified
iunmap <M-">
endfunc
+
+func Test_map_timeout()
+ nnoremap aaaa :let got_aaaa = 1<CR>
+ nnoremap bb :let got_bb = 1<CR>
+ nmap b aaa
+ new
+ func ExitInsert(timer)
+ let g:line = getline(1)
+ call feedkeys("\<Esc>", "t")
+ endfunc
+ set timeout timeoutlen=200
+ call timer_start(300, 'ExitInsert')
+ " After the 'b' Vim waits for another character to see if it matches 'bb'.
+ " When it times out it is expanded to "aaa", but there is no wait for
+ " "aaaa". Can't check that reliably though.
+ call feedkeys("b", "xt!")
+ call assert_equal("aa", g:line)
+ call assert_false(exists('got_aaa'))
+ call assert_false(exists('got_bb'))
+
+ bwipe!
+ nunmap aaaa
+ nunmap bb
+ nunmap b
+ set timeoutlen&
+ delfunc ExitInsert
+endfunc
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index d00b1ddc88..18a0c71aab 100644
--- a/src/nvim/testdir/test_marks.vim
+++ b/src/nvim/testdir/test_marks.vim
@@ -24,3 +24,47 @@ function! Test_Incr_Marks()
call assert_equal("XXX 123 123", getline(3))
enew!
endfunction
+
+func Test_setpos()
+ new one
+ let onebuf = bufnr('%')
+ let onewin = win_getid()
+ call setline(1, ['aaa', 'bbb', 'ccc'])
+ new two
+ let twobuf = bufnr('%')
+ let twowin = win_getid()
+ call setline(1, ['aaa', 'bbb', 'ccc'])
+
+ " for the cursor the buffer number is ignored
+ call setpos(".", [0, 2, 1, 0])
+ call assert_equal([0, 2, 1, 0], getpos("."))
+ call setpos(".", [onebuf, 3, 3, 0])
+ call assert_equal([0, 3, 3, 0], getpos("."))
+
+ call setpos("''", [0, 1, 3, 0])
+ call assert_equal([0, 1, 3, 0], getpos("''"))
+ call setpos("''", [onebuf, 2, 2, 0])
+ call assert_equal([0, 2, 2, 0], getpos("''"))
+
+ " buffer-local marks
+ for mark in ["'a", "'\"", "'[", "']", "'<", "'>"]
+ call win_gotoid(twowin)
+ call setpos(mark, [0, 2, 1, 0])
+ call assert_equal([0, 2, 1, 0], getpos(mark), "for mark " . mark)
+ call setpos(mark, [onebuf, 1, 3, 0])
+ call win_gotoid(onewin)
+ call assert_equal([0, 1, 3, 0], getpos(mark), "for mark " . mark)
+ endfor
+
+ " global marks
+ call win_gotoid(twowin)
+ call setpos("'N", [0, 2, 1, 0])
+ call assert_equal([twobuf, 2, 1, 0], getpos("'N"))
+ call setpos("'N", [onebuf, 1, 3, 0])
+ call assert_equal([onebuf, 1, 3, 0], getpos("'N"))
+
+ call win_gotoid(onewin)
+ bwipe!
+ call win_gotoid(twowin)
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 1d15c7f83d..27ac084ef0 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -2314,28 +2314,36 @@ func! Test_normal53_digraph()
bw!
endfunc
-func! Test_normal54_Ctrl_bsl()
- new
- call setline(1, 'abcdefghijklmn')
- exe "norm! df\<c-\>\<c-n>"
- call assert_equal(['abcdefghijklmn'], getline(1,'$'))
- exe "norm! df\<c-\>\<c-g>"
- call assert_equal(['abcdefghijklmn'], getline(1,'$'))
- exe "norm! df\<c-\>m"
- call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+func Test_normal54_Ctrl_bsl()
+ new
+ call setline(1, 'abcdefghijklmn')
+ exe "norm! df\<c-\>\<c-n>"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+ exe "norm! df\<c-\>\<c-g>"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+ exe "norm! df\<c-\>m"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
if !has("multi_byte")
return
endif
- call setline(2, 'abcdefghijklmnāf')
- norm! 2gg0
- exe "norm! df\<Char-0x101>"
- call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
- norm! 1gg0
- exe "norm! df\<esc>"
- call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
+ call setline(2, 'abcdefghijklmnāf')
+ norm! 2gg0
+ exe "norm! df\<Char-0x101>"
+ call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
+ norm! 1gg0
+ exe "norm! df\<esc>"
+ call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
- " clean up
- bw!
+ " clean up
+ bw!
+endfunc
+
+func Test_normal_large_count()
+ " This may fail with 32bit long, how do we detect that?
+ new
+ normal o
+ normal 6666666666dL
+ bwipe!
endfunc
" Test for the gr (virtual replace) command
@@ -2379,3 +2387,15 @@ func Test_changelist()
%bwipe!
let &ul = save_ul
endfunc
+
+func Test_delete_until_paragraph()
+ if !has('multi_byte')
+ return
+ endif
+ new
+ normal grádv}
+ call assert_equal('á', getline(1))
+ normal grád}
+ call assert_equal('', getline(1))
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index eb42e35bd3..5ae8528ee9 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -22,6 +22,13 @@ function! Test_whichwrap()
set whichwrap&
endfunction
+function! Test_isfname()
+ " This used to cause Vim to access uninitialized memory.
+ set isfname=
+ call assert_equal("~X", expand("~X"))
+ set isfname&
+endfunction
+
function! Test_options()
let caught = 'ok'
try
diff --git a/src/nvim/testdir/test_python2.vim b/src/nvim/testdir/test_python2.vim
new file mode 100644
index 0000000000..fb98c1eda7
--- /dev/null
+++ b/src/nvim/testdir/test_python2.vim
@@ -0,0 +1,24 @@
+" Test for python 2 commands.
+" TODO: move tests from test87.in here.
+
+if !has('python')
+ finish
+endif
+
+func Test_pydo()
+ " Check deleting lines does not trigger ml_get error.
+ py import vim
+ new
+ call setline(1, ['one', 'two', 'three'])
+ pydo vim.command("%d_")
+ bwipe!
+
+ " Check switching to another buffer does not trigger ml_get error.
+ new
+ let wincount = winnr('$')
+ call setline(1, ['one', 'two', 'three'])
+ pydo vim.command("new")
+ call assert_equal(wincount + 1, winnr('$'))
+ bwipe!
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_python3.vim b/src/nvim/testdir/test_python3.vim
new file mode 100644
index 0000000000..bb241dacb1
--- /dev/null
+++ b/src/nvim/testdir/test_python3.vim
@@ -0,0 +1,24 @@
+" Test for python 2 commands.
+" TODO: move tests from test88.in here.
+
+if !has('python3')
+ finish
+endif
+
+func Test_py3do()
+ " Check deleting lines does not trigger an ml_get error.
+ py3 import vim
+ new
+ call setline(1, ['one', 'two', 'three'])
+ py3do vim.command("%d_")
+ bwipe!
+
+ " Check switching to another buffer does not trigger an ml_get error.
+ new
+ let wincount = winnr('$')
+ call setline(1, ['one', 'two', 'three'])
+ py3do vim.command("new")
+ call assert_equal(wincount + 1, winnr('$'))
+ bwipe!
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_quotestar.vim b/src/nvim/testdir/test_quotestar.vim
index d0dd04f91d..37e3a10ed1 100644
--- a/src/nvim/testdir/test_quotestar.vim
+++ b/src/nvim/testdir/test_quotestar.vim
@@ -39,6 +39,15 @@ func Do_test_quotestar_for_x11()
if cmd == ''
return 'GetVimCommand() failed'
endif
+ try
+ call remote_send('xxx', '')
+ catch
+ if v:exception =~ 'E240:'
+ " No connection to the X server, give up.
+ return
+ endif
+ " ignore other errors
+ endtry
let name = 'XVIMCLIPBOARD'
let cmd .= ' --servername ' . name
@@ -109,8 +118,12 @@ func Test_quotestar()
if has('macunix')
let skipped = Do_test_quotestar_for_macunix()
- elseif !empty("$DISPLAY")
- let skipped = Do_test_quotestar_for_x11()
+ elseif has('x11')
+ if empty($DISPLAY)
+ let skipped = "Test can only run when $DISPLAY is set."
+ else
+ let skipped = Do_test_quotestar_for_x11()
+ endif
else
let skipped = "Test is not implemented yet for this platform."
endif
diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim
index a2f4286d4f..97638e9aac 100644
--- a/src/nvim/testdir/test_regexp_utf8.vim
+++ b/src/nvim/testdir/test_regexp_utf8.vim
@@ -35,12 +35,21 @@ func s:classes_test()
set isprint=@,161-255
call assert_equal('Motörhead', matchstr('Motörhead', '[[:print:]]\+'))
+ let alnumchars = ''
let alphachars = ''
+ let backspacechar = ''
+ let blankchars = ''
+ let cntrlchars = ''
+ let digitchars = ''
+ let escapechar = ''
+ let graphchars = ''
let lowerchars = ''
- let upperchars = ''
- let alnumchars = ''
let printchars = ''
let punctchars = ''
+ let returnchar = ''
+ let spacechars = ''
+ let tabchar = ''
+ let upperchars = ''
let xdigitchars = ''
let i = 1
while i <= 255
@@ -48,21 +57,48 @@ func s:classes_test()
if c =~ '[[:alpha:]]'
let alphachars .= c
endif
- if c =~ '[[:lower:]]'
- let lowerchars .= c
- endif
- if c =~ '[[:upper:]]'
- let upperchars .= c
- endif
if c =~ '[[:alnum:]]'
let alnumchars .= c
endif
+ if c =~ '[[:backspace:]]'
+ let backspacechar .= c
+ endif
+ if c =~ '[[:blank:]]'
+ let blankchars .= c
+ endif
+ if c =~ '[[:cntrl:]]'
+ let cntrlchars .= c
+ endif
+ if c =~ '[[:digit:]]'
+ let digitchars .= c
+ endif
+ if c =~ '[[:escape:]]'
+ let escapechar .= c
+ endif
+ if c =~ '[[:graph:]]'
+ let graphchars .= c
+ endif
+ if c =~ '[[:lower:]]'
+ let lowerchars .= c
+ endif
if c =~ '[[:print:]]'
let printchars .= c
endif
if c =~ '[[:punct:]]'
let punctchars .= c
endif
+ if c =~ '[[:return:]]'
+ let returnchar .= c
+ endif
+ if c =~ '[[:space:]]'
+ let spacechars .= c
+ endif
+ if c =~ '[[:tab:]]'
+ let tabchar .= c
+ endif
+ if c =~ '[[:upper:]]'
+ let upperchars .= c
+ endif
if c =~ '[[:xdigit:]]'
let xdigitchars .= c
endif
@@ -70,11 +106,20 @@ func s:classes_test()
endwhile
call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alphachars)
- call assert_equal('abcdefghijklmnopqrstuvwxyzµßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ', lowerchars)
- call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ', upperchars)
call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars)
+ call assert_equal("\b", backspacechar)
+ call assert_equal("\t ", blankchars)
+ call assert_equal("\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0b\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f\x7f", cntrlchars)
+ call assert_equal("0123456789", digitchars)
+ call assert_equal("\<Esc>", escapechar)
+ call assert_equal('!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', graphchars)
+ call assert_equal('abcdefghijklmnopqrstuvwxyzµßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ', lowerchars)
call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', printchars)
call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars)
+ call assert_equal('ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ', upperchars)
+ call assert_equal("\r", returnchar)
+ call assert_equal("\t\n\x0b\f\r ", spacechars)
+ call assert_equal("\t", tabchar)
call assert_equal('0123456789ABCDEFabcdef', xdigitchars)
endfunc
@@ -121,3 +166,20 @@ func Test_eow_with_optional()
call assert_equal(expected, actual)
endfor
endfunc
+
+func Test_reversed_range()
+ for re in range(0, 2)
+ exe 'set re=' . re
+ call assert_fails('call match("abc def", "[c-a]")', 'E944:')
+ endfor
+ set re=0
+endfunc
+
+func Test_large_class()
+ set re=1
+ call assert_fails('call match("abc def", "[\u3000-\u4000]")', 'E945:')
+ set re=2
+ call assert_equal(0, 'abc def' =~# '[\u3000-\u4000]')
+ call assert_equal(1, "\u3042" =~# '[\u3000-\u4000]')
+ set re=0
+endfunc
diff --git a/src/nvim/testdir/test_scroll_opt.vim b/src/nvim/testdir/test_scroll_opt.vim
new file mode 100644
index 0000000000..77920eb8b0
--- /dev/null
+++ b/src/nvim/testdir/test_scroll_opt.vim
@@ -0,0 +1,36 @@
+" Test for reset 'scroll'
+"
+
+func Test_reset_scroll()
+ let scr = &l:scroll
+
+ setlocal scroll=1
+ setlocal scroll&
+ call assert_equal(scr, &l:scroll)
+
+ setlocal scroll=1
+ setlocal scroll=0
+ call assert_equal(scr, &l:scroll)
+
+ try
+ execute 'setlocal scroll=' . (winheight(0) + 1)
+ " not reached
+ call assert_false(1)
+ catch
+ call assert_exception('E49:')
+ endtry
+
+ split
+
+ let scr = &l:scroll
+
+ setlocal scroll=1
+ setlocal scroll&
+ call assert_equal(scr, &l:scroll)
+
+ setlocal scroll=1
+ setlocal scroll=0
+ call assert_equal(scr, &l:scroll)
+
+ quit!
+endfunc
diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim
index d00eac9798..9e93a55eb0 100644
--- a/src/nvim/testdir/test_smartindent.vim
+++ b/src/nvim/testdir/test_smartindent.vim
@@ -1,3 +1,4 @@
+" Tests for smartindent
" Tests for not doing smart indenting when it isn't set.
function! Test_nosmartindent()
@@ -12,3 +13,29 @@ function! Test_nosmartindent()
call assert_equal(" #test", getline(1))
enew! | close
endfunction
+
+function MyIndent()
+endfunction
+
+" When 'indentexpr' is set, setting 'si' has no effect.
+function Test_smartindent_has_no_effect()
+ new
+ exe "normal! i\<Tab>one\<Esc>"
+ set noautoindent
+ set smartindent
+ set indentexpr=
+ exe "normal! Gotwo\<Esc>"
+ call assert_equal("\ttwo", getline("$"))
+
+ set indentexpr=MyIndent
+ exe "normal! Gothree\<Esc>"
+ call assert_equal("three", getline("$"))
+
+ delfunction! MyIndent
+ set autoindent&
+ set smartindent&
+ set indentexpr&
+ bwipe!
+endfunction
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 11e26d03aa..495c561991 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -240,3 +240,14 @@ func Test_progpath()
" Only expect "vim" to appear in v:progname.
call assert_match('vim\c', v:progname)
endfunc
+
+func Test_silent_ex_mode()
+ if !has('unix') || has('gui_running')
+ " can't get output of Vim.
+ return
+ endif
+
+ " This caused an ml_get error.
+ let out = system(GetVimCommand() . '-u NONE -es -c''set verbose=1|h|exe "%norm\<c-y>\<c-d>"'' -c cq')
+ call assert_notmatch('E315:', out)
+endfunc
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index 8465fe7d45..ebdfc250aa 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -301,11 +301,19 @@ func Test_syntax_arg_skipped()
syn clear
endfunc
-
-func Test_invalid_arg()
+
+func Test_syntax_invalid_arg()
call assert_fails('syntax case asdf', 'E390:')
- call assert_fails('syntax conceal asdf', 'E390:')
+ if has('conceal')
+ call assert_fails('syntax conceal asdf', 'E390:')
+ endif
call assert_fails('syntax spell asdf', 'E390:')
+ call assert_fails('syntax clear @ABCD', 'E391:')
+ call assert_fails('syntax include @Xxx', 'E397:')
+ call assert_fails('syntax region X start="{"', 'E399:')
+ call assert_fails('syntax sync x', 'E404:')
+ call assert_fails('syntax keyword Abc a[', 'E789:')
+ call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
endfunc
func Test_syn_sync()
@@ -346,6 +354,50 @@ func Test_invalid_name()
hi clear @Wrong
endfunc
+func Test_ownsyntax()
+ new Xfoo
+ call setline(1, '#define FOO')
+ syntax on
+ set filetype=c
+ ownsyntax perl
+ call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
+ call assert_equal('c', b:current_syntax)
+ call assert_equal('perl', w:current_syntax)
+
+ " A new split window should have the original syntax.
+ split
+ call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
+ call assert_equal('c', b:current_syntax)
+ call assert_equal(0, exists('w:current_syntax'))
+
+ wincmd x
+ call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
+
+ syntax off
+ set filetype&
+ %bw!
+endfunc
+
+func Test_ownsyntax_completion()
+ call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"ownsyntax java javacc javascript', @:)
+endfunc
+
+func Test_highlight_invalid_arg()
+ if has('gui_running')
+ call assert_fails('hi XXX guifg=xxx', 'E254:')
+ endif
+ call assert_fails('hi DoesNotExist', 'E411:')
+ call assert_fails('hi link', 'E412:')
+ call assert_fails('hi link a', 'E412:')
+ call assert_fails('hi link a b c', 'E413:')
+ call assert_fails('hi XXX =', 'E415:')
+ call assert_fails('hi XXX cterm', 'E416:')
+ call assert_fails('hi XXX cterm=', 'E417:')
+ call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
+ call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
+ call assert_fails('hi XXX xxx=White', 'E423:')
+endfunc
func Test_conceal()
if !has('conceal')
@@ -382,3 +434,4 @@ func Test_conceal()
set conceallevel&
bw!
endfunc
+
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 65957626cb..25c39587f4 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -405,6 +405,10 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
{
got_winch = true;
UI *ui = data;
+ if (tui_is_stopped(ui)) {
+ return;
+ }
+
update_size(ui);
ui_schedule_refresh();
}
@@ -845,7 +849,7 @@ CursorShape tui_cursor_decode_shape(const char *shape_str)
static cursorentry_T decode_cursor_entry(Dictionary args)
{
- cursorentry_T r;
+ cursorentry_T r = shape_table[0];
for (size_t i = 0; i < args.size; i++) {
char *key = args.items[i].key.data;
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 42366fdb76..21dd6ec0dd 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -535,14 +535,18 @@ Array ui_array(void)
{
Array all_uis = ARRAY_DICT_INIT;
for (size_t i = 0; i < ui_count; i++) {
- Dictionary dic = ARRAY_DICT_INIT;
- PUT(dic, "width", INTEGER_OBJ(uis[i]->width));
- PUT(dic, "height", INTEGER_OBJ(uis[i]->height));
- PUT(dic, "rgb", BOOLEAN_OBJ(uis[i]->rgb));
+ UI *ui = uis[i];
+ Dictionary info = ARRAY_DICT_INIT;
+ PUT(info, "width", INTEGER_OBJ(ui->width));
+ PUT(info, "height", INTEGER_OBJ(ui->height));
+ PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb));
for (UIExtension j = 0; j < kUIExtCount; j++) {
- PUT(dic, ui_ext_names[j], BOOLEAN_OBJ(uis[i]->ui_ext[j]));
+ PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j]));
+ }
+ if (ui->inspect) {
+ ui->inspect(ui, &info);
}
- ADD(all_uis, DICTIONARY_OBJ(dic));
+ ADD(all_uis, DICTIONARY_OBJ(info));
}
return all_uis;
}
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 48896a6a3f..6b04e9c67a 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -36,6 +36,7 @@ struct ui_t {
#endif
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
void (*stop)(UI *ui);
+ void (*inspect)(UI *ui, Dictionary *info);
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index a8bbeea035..56db124a46 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -163,3 +163,28 @@ static void ui_bridge_suspend_event(void **argv)
UI *ui = UI(argv[0]);
ui->suspend(ui);
}
+
+static void ui_bridge_option_set(UI *ui, String name, Object value)
+{
+ String copy_name = copy_string(name);
+ Object *copy_value = xmalloc(sizeof(Object));
+ *copy_value = copy_object(value);
+ UI_BRIDGE_CALL(ui, option_set, 4, ui, copy_name.data,
+ INT2PTR(copy_name.size), copy_value);
+ // TODO(bfredl): when/if TUI/bridge teardown is refactored to use events, the
+ // commit that introduced this special case can be reverted.
+ // For now this is needed for nvim_list_uis().
+ if (strequal(name.data, "termguicolors")) {
+ ui->rgb = value.data.boolean;
+ }
+}
+static void ui_bridge_option_set_event(void **argv)
+{
+ UI *ui = UI(argv[0]);
+ String name = (String){ .data = argv[1], .size = (size_t)argv[2] };
+ Object value = *(Object *)argv[3];
+ ui->option_set(ui, name, value);
+ api_free_string(name);
+ api_free_object(value);
+ xfree(argv[3]);
+}
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 44bcefb332..8b290edd1f 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1698,9 +1698,9 @@ bool u_undo_and_forget(int count)
count = 1;
}
undo_undoes = true;
- // don't send a nvim_buf_lines_event for this undo is part of 'inccommand'
- // playing with buffer contents
- u_doit(count, true, false);
+ u_doit(count, true,
+ // Don't send nvim_buf_lines_event for u_undo_and_forget().
+ false);
if (curbuf->b_u_curhead == NULL) {
// nothing was undone.
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 17f89a25d2..be160e678e 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -145,7 +145,7 @@ static const int included_patches[] = {
// 1497,
// 1496,
// 1495,
- // 1494,
+ 1494,
1493,
// 1492,
// 1491,
@@ -167,7 +167,7 @@ static const int included_patches[] = {
1475,
// 1474,
// 1473,
- // 1472,
+ 1472,
// 1471,
// 1470,
// 1469,
@@ -328,7 +328,7 @@ static const int included_patches[] = {
// 1314,
// 1313,
// 1312,
- // 1311,
+ 1311,
// 1310,
// 1309,
// 1308,
@@ -405,9 +405,9 @@ static const int included_patches[] = {
// 1237,
// 1236,
// 1235,
- // 1234,
+ 1234,
// 1233,
- // 1232,
+ 1232,
// 1231,
1230,
1229,
@@ -442,13 +442,13 @@ static const int included_patches[] = {
1200,
// 1199,
// 1198,
- // 1197,
+ 1197,
// 1196,
// 1195,
// 1194,
// 1193,
// 1192,
- // 1191,
+ 1191,
// 1190,
1189,
1188,
@@ -458,8 +458,8 @@ static const int included_patches[] = {
// 1184,
// 1183,
// 1182,
- // 1181,
- // 1180,
+ 1181,
+ 1180,
// 1179,
// 1178,
// 1177,
@@ -489,7 +489,7 @@ static const int included_patches[] = {
// 1153,
// 1152,
// 1151,
- // 1150,
+ 1150,
// 1149,
// 1148,
// 1147,
@@ -498,7 +498,7 @@ static const int included_patches[] = {
// 1144,
// 1143,
// 1142,
- // 1141,
+ 1141,
// 1140,
// 1139,
// 1138,
@@ -518,7 +518,7 @@ static const int included_patches[] = {
// 1124,
// 1123,
// 1122,
- // 1121,
+ 1121,
// 1120,
// 1119,
// 1118,
@@ -714,7 +714,7 @@ static const int included_patches[] = {
// 928,
// 927,
// 926,
- // 925,
+ 925,
// 924,
// 923,
// 922,
@@ -758,7 +758,7 @@ static const int included_patches[] = {
// 884,
// 883,
// 882,
- // 881,
+ 881,
// 880,
// 879,
// 878,
@@ -1077,11 +1077,11 @@ static const int included_patches[] = {
565,
564,
// 563,
- // 562,
+ 562,
561,
// 560,
- // 559,
- // 558,
+ 559,
+ 558,
// 557,
// 556,
555,
@@ -1120,30 +1120,30 @@ static const int included_patches[] = {
// 522,
// 521,
// 520,
- // 519,
+ 519,
518,
517,
- // 516,
- // 515,
+ 516,
+ 515,
// 514,
513,
// 512,
- // 511,
+ 511,
// 510,
// 509,
// 508,
- // 507,
+ 507,
// 506,
- // 505,
+ 505,
// 504,
- // 503,
+ 503,
502,
// 501,
500,
499,
498,
- // 497,
- // 496,
+ 497,
+ 496,
495,
// 494,
// 493,
@@ -1175,36 +1175,36 @@ static const int included_patches[] = {
// 467,
// 466,
465,
- // 464,
- // 463,
+ 464,
+ 463,
// 462,
461,
- // 460,
+ 460,
459,
458,
457,
- // 456,
+ 456,
// 455,
- // 454,
+ 454,
453,
// 452,
// 451,
- // 450,
+ 450,
// 449,
448,
- // 447,
+ 447,
446,
// 445,
444,
443,
442,
- // 441,
+ 441,
440,
439,
- // 438,
+ 438,
437,
// 436,
- // 435,
+ 435,
434,
433,
// 432,
@@ -1220,23 +1220,23 @@ static const int included_patches[] = {
// 422,
421,
420,
- // 419,
+ 419,
// 418,
417,
- // 416,
- // 415,
+ 416,
+ 415,
// 414,
// 413,
// 412,
// 411,
// 410,
- // 409,
+ 409,
408,
407,
406,
405,
404,
- // 403,
+ 403,
402,
// 401,
400,
@@ -1255,20 +1255,20 @@ static const int included_patches[] = {
387,
// 386,
385,
- // 384,
- // 383,
- // 382,
+ 384,
+ 383,
+ 382,
381,
380,
379,
378,
377,
376,
- // 375,
+ 375,
374,
// 373,
// 372,
- // 371,
+ 371,
// 370,
// 369,
// 368,
@@ -1277,27 +1277,27 @@ static const int included_patches[] = {
// 365,
364,
// 363,
- // 362,
+ 362,
// 361,
360,
359,
358,
357,
- // 356,
+ 356,
// 355,
- // 354,
+ 354,
353,
352,
351,
// 350,
// 349,
- // 348,
+ 348,
347,
// 346,
345,
344,
343,
- // 342,
+ 342,
341,
// 340,
339,
@@ -1307,10 +1307,10 @@ static const int included_patches[] = {
335,
334,
333,
- // 332,
+ 332,
331,
330,
- // 329,
+ 329,
328,
327,
326,
@@ -1318,16 +1318,16 @@ static const int included_patches[] = {
324,
323,
322,
- // 321,
+ 321,
320,
319,
- // 318,
- // 317,
+ 318,
+ 317,
316,
315,
314,
- // 313,
- // 312,
+ 313,
+ 312,
311,
310,
309,
@@ -1335,7 +1335,7 @@ static const int included_patches[] = {
307,
306,
305,
- // 304,
+ 304,
// 303,
302,
301,
@@ -1378,7 +1378,7 @@ static const int included_patches[] = {
// 264,
263,
262,
- // 261,
+ 261,
260,
259,
258,