aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt10
-rw-r--r--src/nvim/assert.h9
-rw-r--r--src/nvim/eval.c78
-rw-r--r--src/nvim/ex_cmds.c44
-rw-r--r--src/nvim/ex_cmds2.c167
-rw-r--r--src/nvim/ex_docmd.c46
-rw-r--r--src/nvim/globals.h10
-rw-r--r--src/nvim/message.c107
-rw-r--r--src/nvim/misc2.c5
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.c12
-rw-r--r--src/nvim/normal.c26
-rw-r--r--src/nvim/ops.c19
-rw-r--r--src/nvim/option.c19
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/os/env.c117
-rw-r--r--src/nvim/os/fs.c4
-rw-r--r--src/nvim/quickfix.c3
-rw-r--r--src/nvim/screen.c54
-rw-r--r--src/nvim/shada.c2
-rw-r--r--src/nvim/spell.c70
-rw-r--r--src/nvim/syntax.c136
-rw-r--r--src/nvim/syntax_defs.h4
-rw-r--r--src/nvim/testdir/Makefile9
-rw-r--r--src/nvim/testdir/runtest.vim6
-rw-r--r--src/nvim/testdir/test1.in34
-rw-r--r--src/nvim/testdir/test10.in3
-rw-r--r--src/nvim/testdir/test10a.in1
-rw-r--r--src/nvim/testdir/test12.in1
-rw-r--r--src/nvim/testdir/test13.in1
-rw-r--r--src/nvim/testdir/test14.in1
-rw-r--r--src/nvim/testdir/test17.in1
-rw-r--r--src/nvim/testdir/test30.in1
-rw-r--r--src/nvim/testdir/test32.in1
-rw-r--r--src/nvim/testdir/test34.in1
-rw-r--r--src/nvim/testdir/test37.in2
-rw-r--r--src/nvim/testdir/test40.in1
-rw-r--r--src/nvim/testdir/test42.inbin2368 -> 2354 bytes
-rw-r--r--src/nvim/testdir/test47.in1
-rw-r--r--src/nvim/testdir/test48.in1
-rw-r--r--src/nvim/testdir/test49.in1
-rw-r--r--src/nvim/testdir/test50.in1
-rw-r--r--src/nvim/testdir/test52.in1
-rw-r--r--src/nvim/testdir/test53.in1
-rw-r--r--src/nvim/testdir/test55.in1
-rw-r--r--src/nvim/testdir/test64.in1
-rw-r--r--src/nvim/testdir/test68.in131
-rw-r--r--src/nvim/testdir/test68.ok77
-rw-r--r--src/nvim/testdir/test69.in2
-rw-r--r--src/nvim/testdir/test73.in1
-rw-r--r--src/nvim/testdir/test8.in3
-rw-r--r--src/nvim/testdir/test_breakindent.in123
-rw-r--r--src/nvim/testdir/test_breakindent.ok74
-rw-r--r--src/nvim/testdir/test_close_count.in156
-rw-r--r--src/nvim/testdir/test_close_count.ok23
-rw-r--r--src/nvim/testdir/test_help_tagjump.vim40
-rw-r--r--src/nvim/testdir/test_listlbr.in1
-rw-r--r--src/nvim/testdir/test_menu.vim9
-rw-r--r--src/nvim/tui/tui.c8
-rw-r--r--src/nvim/ugrid.h2
-rw-r--r--src/nvim/ui.c7
-rw-r--r--src/nvim/ui.h3
-rw-r--r--src/nvim/ui_bridge.c11
-rw-r--r--src/nvim/version.c60
64 files changed, 758 insertions, 995 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 0711642868..172643091a 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -1,4 +1,5 @@
include(CheckLibraryExists)
+include(CheckCCompilerFlag)
option(USE_GCOV "Enable gcov support" OFF)
@@ -230,7 +231,6 @@ endif()
list(APPEND NVIM_LINK_LIBRARIES
${LIBUV_LIBRARIES}
${MSGPACK_LIBRARIES}
- ${LUAJIT_LIBRARIES}
${LIBVTERM_LIBRARIES}
${LIBTERMKEY_LIBRARIES}
${UNIBILIUM_LIBRARIES}
@@ -258,8 +258,14 @@ install_helper(TARGETS nvim)
if(CLANG_ASAN_UBSAN)
message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.")
+ check_c_compiler_flag(-fno-sanitize-recover=all SANITIZE_RECOVER_ALL)
+ if(SANITIZE_RECOVER_ALL)
+ set(SANITIZE_RECOVER -fno-sanitize-recover=all) # Clang 3.6+
+ else()
+ set(SANITIZE_RECOVER -fno-sanitize-recover) # Clang 3.5-
+ endif()
set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "-DEXITFREE ")
- set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "-fno-sanitize-recover -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/.asan-blacklist")
+ set_property(TARGET nvim APPEND_STRING PROPERTY COMPILE_FLAGS "${SANITIZE_RECOVER} -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/.asan-blacklist")
set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=address -fsanitize=undefined ")
elseif(CLANG_MSAN)
message(STATUS "Enabling Clang memory sanitizer for nvim.")
diff --git a/src/nvim/assert.h b/src/nvim/assert.h
index 2c43777858..761636305e 100644
--- a/src/nvim/assert.h
+++ b/src/nvim/assert.h
@@ -65,9 +65,16 @@
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
# undef STATIC_ASSERT_PRAGMA_START
+
+#if __GNUC__ >= 6
# define STATIC_ASSERT_PRAGMA_START \
_Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-pedantic\"") \
+ _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
+#else
+# define STATIC_ASSERT_PRAGMA_START \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-pedantic\"")
+#endif
# undef STATIC_ASSERT_PRAGMA_END
# define STATIC_ASSERT_PRAGMA_END \
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6e9f89bbb5..96c008b0e0 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6877,6 +6877,7 @@ static struct fst {
{ "setbufvar", 3, 3, f_setbufvar },
{ "setcharsearch", 1, 1, f_setcharsearch },
{ "setcmdpos", 1, 1, f_setcmdpos },
+ { "setfperm", 2, 2, f_setfperm },
{ "setline", 2, 2, f_setline },
{ "setloclist", 2, 4, f_setloclist },
{ "setmatches", 1, 1, f_setmatches },
@@ -10684,6 +10685,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
"tablineat",
"tag_binary",
"tag_old_static",
+ "termguicolors",
"termresponse",
"textobjects",
"title",
@@ -14445,6 +14447,38 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = set_cmdline_pos(pos);
}
+
+/// "setfperm({fname}, {mode})" function
+static void f_setfperm(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = 0;
+
+ char_u *fname = get_tv_string_chk(&argvars[0]);
+ if (fname == NULL) {
+ return;
+ }
+
+ char_u modebuf[NUMBUFLEN];
+ char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf);
+ if (mode_str == NULL) {
+ return;
+ }
+ if (STRLEN(mode_str) != 9) {
+ EMSG2(_(e_invarg2), mode_str);
+ return;
+ }
+
+ int mask = 1;
+ int mode = 0;
+ for (int i = 8; i >= 0; i--) {
+ if (mode_str[i] != '-') {
+ mode |= mask;
+ }
+ mask = mask << 1;
+ }
+ rettv->vval.v_number = os_setperm(fname, mode) == OK;
+}
+
/*
* "setline()" function
*/
@@ -18122,6 +18156,25 @@ static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, in
return HI2DI(hi);
}
+// Get function call environment based on backtrace debug level
+static funccall_T *get_funccal(void)
+{
+ funccall_T *funccal = current_funccal;
+ if (debug_backtrace_level > 0) {
+ for (int i = 0; i < debug_backtrace_level; i++) {
+ funccall_T *temp_funccal = funccal->caller;
+ if (temp_funccal) {
+ funccal = temp_funccal;
+ } else {
+ // backtrace level overflow. reset to max
+ debug_backtrace_level = i;
+ }
+ }
+ }
+
+ return funccal;
+}
+
// Find the dict and hashtable used for a variable name. Set "varname" to the
// start of name without ':'.
static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
@@ -18146,7 +18199,11 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
return &compat_hashtab;
}
- *d = current_funccal ? &current_funccal->l_vars : &globvardict;
+ if (current_funccal == NULL) {
+ *d = &globvardict;
+ } else {
+ *d = &get_funccal()->l_vars; // l: variable
+ }
goto end;
}
@@ -18168,9 +18225,9 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
} else if (*name == 'v') { // v: variable
*d = &vimvardict;
} else if (*name == 'a' && current_funccal != NULL) { // function argument
- *d = &current_funccal->l_avars;
+ *d = &get_funccal()->l_avars;
} else if (*name == 'l' && current_funccal != NULL) { // local variable
- *d = &current_funccal->l_vars;
+ *d = &get_funccal()->l_vars;
} else if (*name == 's' // script variable
&& current_SID > 0 && current_SID <= ga_scripts.ga_len) {
*d = &SCRIPT_SV(current_SID)->sv_dict;
@@ -21700,6 +21757,18 @@ static void term_resize(uint16_t width, uint16_t height, void *d)
pty_process_resize(&data->proc.pty, width, height);
}
+static inline void term_delayed_free(void **argv)
+{
+ TerminalJobData *j = argv[0];
+ if (j->in.pending_reqs || j->out.pending_reqs || j->err.pending_reqs) {
+ queue_put(j->events, term_delayed_free, 1, j);
+ return;
+ }
+
+ terminal_destroy(j->term);
+ term_job_data_decref(j);
+}
+
static void term_close(void *d)
{
TerminalJobData *data = d;
@@ -21707,8 +21776,7 @@ static void term_close(void *d)
data->exited = true;
process_stop((Process *)&data->proc);
}
- terminal_destroy(data->term);
- term_job_data_decref(d);
+ queue_put(data->events, term_delayed_free, 1, data);
}
static void term_job_data_decref(TerminalJobData *data)
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index e8314e02e0..86f1a16216 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3816,16 +3816,17 @@ skip:
EMSG2(_(e_patnotf2), get_search_pat());
}
- if (do_ask && hasAnyFolding(curwin))
- /* Cursor position may require updating */
+ if (do_ask && hasAnyFolding(curwin)) {
+ // Cursor position may require updating
changed_window_setting();
+ }
- vim_regfree(regmatch.regprog);
+ vim_regfree(regmatch.regprog);
- // Restore the flag values, they can be used for ":&&".
- do_all = save_do_all;
- do_ask = save_do_ask;
- }
+ // Restore the flag values, they can be used for ":&&".
+ do_all = save_do_all;
+ do_ask = save_do_ask;
+}
/*
* Give message for number of substitutions.
@@ -4413,17 +4414,20 @@ int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_la
|| (arg[0] == '\\' && arg[1] == '{'))
*d++ = '\\';
- for (s = arg; *s; ++s) {
- /*
- * Replace "|" with "bar" and '"' with "quote" to match the name of
- * the tags for these commands.
- * Replace "*" with ".*" and "?" with "." to match command line
- * completion.
- * Insert a backslash before '~', '$' and '.' to avoid their
- * special meaning.
- */
- if (d - IObuff > IOSIZE - 10) /* getting too long!? */
+ // If tag starts with "('", skip the "(". Fixes CTRL-] on ('option'.
+ if (*arg == '(' && arg[1] == '\'') {
+ arg++;
+ }
+ for (s = arg; *s; s++) {
+ // Replace "|" with "bar" and '"' with "quote" to match the name of
+ // the tags for these commands.
+ // Replace "*" with ".*" and "?" with "." to match command line
+ // completion.
+ // Insert a backslash before '~', '$' and '.' to avoid their
+ // special meaning.
+ if (d - IObuff > IOSIZE - 10) { // getting too long!?
break;
+ }
switch (*s) {
case '|': STRCPY(d, "bar");
d += 3;
@@ -4484,6 +4488,12 @@ int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_la
*d++ = *s;
+ // If tag contains "({" or "([", tag terminates at the "(".
+ // This is for help on functions, e.g.: abs({expr}).
+ if (*s == '(' && (s[1] == '{' || s[1] =='[')) {
+ break;
+ }
+
/*
* If tag starts with ', toss everything after a second '. Fixes
* CTRL-] on 'option'. (would include the trailing '.').
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 12efddc205..5fe6209a0a 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -144,6 +144,10 @@ void do_debug(char_u *cmd)
#define CMD_FINISH 4
#define CMD_QUIT 5
#define CMD_INTERRUPT 6
+#define CMD_BACKTRACE 7
+#define CMD_FRAME 8
+#define CMD_UP 9
+#define CMD_DOWN 10
++RedrawingDisabled; /* don't redisplay the window */
@@ -185,6 +189,7 @@ void do_debug(char_u *cmd)
ignore_script = TRUE;
}
+ xfree(cmdline);
cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
if (typeahead_saved) {
@@ -194,6 +199,7 @@ void do_debug(char_u *cmd)
ex_normal_busy = save_ex_normal_busy;
cmdline_row = msg_row;
+ msg_starthere();
if (cmdline != NULL) {
/* If this is a debug command, set "last_cmd".
* If not, reset "last_cmd".
@@ -210,8 +216,15 @@ void do_debug(char_u *cmd)
case 's': last_cmd = CMD_STEP;
tail = "tep";
break;
- case 'f': last_cmd = CMD_FINISH;
- tail = "inish";
+ case 'f':
+ last_cmd = 0;
+ if (p[1] == 'r') {
+ last_cmd = CMD_FRAME;
+ tail = "rame";
+ } else {
+ last_cmd = CMD_FINISH;
+ tail = "inish";
+ }
break;
case 'q': last_cmd = CMD_QUIT;
tail = "uit";
@@ -219,6 +232,26 @@ void do_debug(char_u *cmd)
case 'i': last_cmd = CMD_INTERRUPT;
tail = "nterrupt";
break;
+ case 'b':
+ last_cmd = CMD_BACKTRACE;
+ if (p[1] == 't') {
+ tail = "t";
+ } else {
+ tail = "acktrace";
+ }
+ break;
+ case 'w':
+ last_cmd = CMD_BACKTRACE;
+ tail = "here";
+ break;
+ case 'u':
+ last_cmd = CMD_UP;
+ tail = "p";
+ break;
+ case 'd':
+ last_cmd = CMD_DOWN;
+ tail = "own";
+ break;
default: last_cmd = 0;
}
if (last_cmd != 0) {
@@ -228,8 +261,9 @@ void do_debug(char_u *cmd)
++p;
++tail;
}
- if (ASCII_ISALPHA(*p))
+ if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME) {
last_cmd = 0;
+ }
}
}
@@ -259,7 +293,28 @@ void do_debug(char_u *cmd)
/* Do not repeat ">interrupt" cmd, continue stepping. */
last_cmd = CMD_STEP;
break;
+ case CMD_BACKTRACE:
+ do_showbacktrace(cmd);
+ continue;
+ case CMD_FRAME:
+ if (*p == NUL) {
+ do_showbacktrace(cmd);
+ } else {
+ p = skipwhite(p);
+ do_setdebugtracelevel(p);
+ }
+ continue;
+ case CMD_UP:
+ debug_backtrace_level++;
+ do_checkbacktracelevel();
+ continue;
+ case CMD_DOWN:
+ debug_backtrace_level--;
+ do_checkbacktracelevel();
+ continue;
}
+ // Going out reset backtrace_level
+ debug_backtrace_level = 0;
break;
}
@@ -269,8 +324,6 @@ void do_debug(char_u *cmd)
(void)do_cmdline(cmdline, getexline, NULL,
DOCMD_VERBOSE|DOCMD_EXCRESET);
debug_break_level = n;
-
- xfree(cmdline);
}
lines_left = (int)(Rows - 1);
}
@@ -294,6 +347,78 @@ void do_debug(char_u *cmd)
debug_did_msg = TRUE;
}
+static int get_maxbacktrace_level(void)
+{
+ int maxbacktrace = 0;
+
+ if (sourcing_name != NULL) {
+ char *p = (char *)sourcing_name;
+ char *q;
+ while ((q = strstr(p, "..")) != NULL) {
+ p = q + 2;
+ maxbacktrace++;
+ }
+ }
+ return maxbacktrace;
+}
+
+static void do_setdebugtracelevel(char_u *arg)
+{
+ int level = atoi((char *)arg);
+ if (*arg == '+' || level < 0) {
+ debug_backtrace_level += level;
+ } else {
+ debug_backtrace_level = level;
+ }
+
+ do_checkbacktracelevel();
+}
+
+static void do_checkbacktracelevel(void)
+{
+ if (debug_backtrace_level < 0) {
+ debug_backtrace_level = 0;
+ MSG(_("frame is zero"));
+ } else {
+ int max = get_maxbacktrace_level();
+ if (debug_backtrace_level > max) {
+ debug_backtrace_level = max;
+ smsg(_("frame at highest level: %d"), max);
+ }
+ }
+}
+
+static void do_showbacktrace(char_u *cmd)
+{
+ if (sourcing_name != NULL) {
+ int i = 0;
+ int max = get_maxbacktrace_level();
+ char *cur = (char *)sourcing_name;
+ while (!got_int) {
+ char *next = strstr(cur, "..");
+ if (next != NULL) {
+ *next = NUL;
+ }
+ if (i == max - debug_backtrace_level) {
+ smsg("->%d %s", max - i, cur);
+ } else {
+ smsg(" %d %s", max - i, cur);
+ }
+ i++;
+ if (next == NULL) {
+ break;
+ }
+ *next = '.';
+ cur = next + 2;
+ }
+ }
+ if (sourcing_lnum != 0) {
+ smsg(_("line %" PRId64 ": %s"), (int64_t)sourcing_lnum, cmd);
+ } else {
+ smsg(_("cmd: %s"), cmd);
+ }
+}
+
/*
* ":debug".
*/
@@ -1241,16 +1366,18 @@ static void add_bufnum(int *bufnrs, int *bufnump, int nr)
*bufnump = *bufnump + 1;
}
-/*
- * Return TRUE if any buffer was changed and cannot be abandoned.
- * That changed buffer becomes the current buffer.
- */
-int
-check_changed_any (
- int hidden /* Only check hidden buffers */
-)
+/// Check if any buffer was changed and cannot be abandoned.
+/// That changed buffer becomes the current buffer.
+/// When "unload" is true the current buffer is unloaded instead of making it
+/// hidden. This is used for ":q!".
+///
+/// @param[in] hidden specifies whether to check only hidden buffers.
+/// @param[in] unload specifies whether to unload, instead of hide, the buffer.
+///
+/// @returns true if any buffer is changed and cannot be abandoned
+int check_changed_any(bool hidden, bool unload)
{
- int ret = FALSE;
+ bool ret = false;
int save;
int i;
int bufnum = 0;
@@ -1261,8 +1388,9 @@ check_changed_any (
++bufcount;
}
- if (bufcount == 0)
- return FALSE;
+ if (bufcount == 0) {
+ return false;
+ }
bufnrs = xmalloc(sizeof(*bufnrs) * bufcount);
@@ -1346,9 +1474,10 @@ check_changed_any (
}
buf_found:
- /* Open the changed buffer in the current window. */
- if (buf != curbuf)
- set_curbuf(buf, DOBUF_GOTO);
+ // Open the changed buffer in the current window.
+ if (buf != curbuf) {
+ set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
+ }
theend:
xfree(bufnrs);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 89c35a3c45..870284a0f7 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -5671,10 +5671,10 @@ static void ex_quit(exarg_T *eap)
exiting = TRUE;
if ((!P_HID(curbuf)
&& check_changed(curbuf, (p_awa ? CCGD_AW : 0)
- | (eap->forceit ? CCGD_FORCEIT : 0)
- | CCGD_EXCMD))
- || check_more(TRUE, eap->forceit) == FAIL
- || (only_one_window() && check_changed_any(eap->forceit))) {
+ | (eap->forceit ? CCGD_FORCEIT : 0)
+ | CCGD_EXCMD))
+ || check_more(true, eap->forceit) == FAIL
+ || (only_one_window() && check_changed_any(eap->forceit, true))) {
not_exiting();
} else {
// quit last window
@@ -5723,9 +5723,10 @@ static void ex_quit_all(exarg_T *eap)
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
return;
- exiting = TRUE;
- if (eap->forceit || !check_changed_any(FALSE))
+ exiting = true;
+ if (eap->forceit || !check_changed_any(false, false)) {
getout(0);
+ }
not_exiting();
}
@@ -6010,21 +6011,22 @@ static void ex_exit(exarg_T *eap)
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
return;
- /*
- * if more files or windows we won't exit
- */
- if (check_more(FALSE, eap->forceit) == OK && only_one_window())
- exiting = TRUE;
- if ( ((eap->cmdidx == CMD_wq
- || curbufIsChanged())
- && do_write(eap) == FAIL)
- || check_more(TRUE, eap->forceit) == FAIL
- || (only_one_window() && check_changed_any(eap->forceit))) {
+ // if more files or windows we won't exit
+ if (check_more(false, eap->forceit) == OK && only_one_window()) {
+ exiting = true;
+ }
+ if (((eap->cmdidx == CMD_wq
+ || curbufIsChanged())
+ && do_write(eap) == FAIL)
+ || check_more(true, eap->forceit) == FAIL
+ || (only_one_window() && check_changed_any(eap->forceit, false))) {
not_exiting();
} else {
- if (only_one_window()) /* quit last window, exit Vim */
+ if (only_one_window()) {
+ // quit last window, exit Vim
getout(0);
- /* Quit current window, may free the buffer. */
+ }
+ // Quit current window, may free the buffer.
win_close(curwin, !P_HID(curwin->w_buffer));
}
}
@@ -9497,12 +9499,14 @@ static void ex_folddo(exarg_T *eap)
static void ex_terminal(exarg_T *eap)
{
- // We will call termopen() with ['shell'] if not given a {cmd}.
- char *name = (char *)p_sh;
+ char *name = (char *)p_sh; // Default to 'shell' if {cmd} is not given.
+ bool mustfree = false;
char *lquote = "['";
char *rquote = "']";
+
if (*eap->arg != NUL) {
name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\");
+ mustfree = true;
lquote = rquote = "\"";
}
@@ -9512,7 +9516,7 @@ static void ex_terminal(exarg_T *eap)
eap->forceit==TRUE ? "!" : "", lquote, name, rquote);
do_cmdline_cmd(ex_cmd);
- if (name != (char *)p_sh) {
+ if (mustfree) {
xfree(name);
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 49d1de21d9..dafb75ca87 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -293,10 +293,11 @@ EXTERN int msg_no_more INIT(= FALSE); /* don't use more prompt, truncate
EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */
EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
-EXTERN int ex_nesting_level INIT(= 0); /* nesting level */
-EXTERN int debug_break_level INIT(= -1); /* break below this level */
-EXTERN int debug_did_msg INIT(= FALSE); /* did "debug mode" message */
-EXTERN int debug_tick INIT(= 0); /* breakpoint change count */
+EXTERN int ex_nesting_level INIT(= 0); // nesting level
+EXTERN int debug_break_level INIT(= -1); // break below this level
+EXTERN int debug_did_msg INIT(= false); // did "debug mode" message
+EXTERN int debug_tick INIT(= 0); // breakpoint change count
+EXTERN int debug_backtrace_level INIT(= 0); // breakpoint backtrace level
/* Values for "do_profiling". */
#define PROF_NONE 0 /* profiling not started */
@@ -503,6 +504,7 @@ EXTERN int cterm_normal_fg_bold INIT(= 0);
EXTERN int cterm_normal_bg_color INIT(= 0);
EXTERN RgbValue normal_fg INIT(= -1);
EXTERN RgbValue normal_bg INIT(= -1);
+EXTERN RgbValue normal_sp INIT(= -1);
EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */
EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 265f8c00c0..47f246fc76 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1508,51 +1508,44 @@ void msg_puts_attr(char_u *s, int attr)
msg_puts_attr_len(s, -1, attr);
}
-/*
- * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
- * When "maxlen" is -1 there is no maximum length.
- * When "maxlen" is >= 0 the message is not put in the history.
- */
+/// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes).
+/// When "maxlen" is -1 there is no maximum length.
+/// When "maxlen" is >= 0 the message is not put in the history.
static void msg_puts_attr_len(char_u *str, int maxlen, int attr)
{
- /*
- * If redirection is on, also write to the redirection file.
- */
+ // If redirection is on, also write to the redirection file.
redir_write(str, maxlen);
- /*
- * Don't print anything when using ":silent cmd".
- */
- if (msg_silent != 0)
+ // Don't print anything when using ":silent cmd".
+ if (msg_silent != 0) {
return;
+ }
- /* if MSG_HIST flag set, add message to history */
+ // if MSG_HIST flag set, add message to history
if ((attr & MSG_HIST) && maxlen < 0) {
add_msg_hist(str, -1, attr);
attr &= ~MSG_HIST;
}
- /*
- * When writing something to the screen after it has scrolled, requires a
- * wait-return prompt later. Needed when scrolling, resetting
- * need_wait_return after some prompt, and then outputting something
- * without scrolling
- */
- if (msg_scrolled != 0 && !msg_scrolled_ign)
- need_wait_return = TRUE;
- msg_didany = TRUE; /* remember that something was outputted */
+ // When writing something to the screen after it has scrolled, requires a
+ // wait-return prompt later. Needed when scrolling, resetting
+ // need_wait_return after some prompt, and then outputting something
+ // without scrolling
+ if (msg_scrolled != 0 && !msg_scrolled_ign) {
+ need_wait_return = true;
+ }
+ msg_didany = true; // remember that something was outputted
- /*
- * If there is no valid screen, use fprintf so we can see error messages.
- * If termcap is not active, we may be writing in an alternate console
- * window, cursor positioning may not work correctly (window size may be
- * different, e.g. for Win32 console) or we just don't know where the
- * cursor is.
- */
- if (msg_use_printf())
- msg_puts_printf(str, maxlen);
- else
- msg_puts_display(str, maxlen, attr, FALSE);
+ // If there is no valid screen, use fprintf so we can see error messages.
+ // If termcap is not active, we may be writing in an alternate console
+ // window, cursor positioning may not work correctly (window size may be
+ // different, e.g. for Win32 console) or we just don't know where the
+ // cursor is.
+ if (msg_use_printf()) {
+ msg_puts_printf((char *)str, maxlen);
+ } else {
+ msg_puts_display(str, maxlen, attr, false);
+ }
}
/*
@@ -1926,46 +1919,46 @@ int msg_use_printf(void)
return !embedded_mode && !ui_active();
}
-/*
- * Print a message when there is no valid screen.
- */
-static void msg_puts_printf(char_u *str, int maxlen)
+/// Print a message when there is no valid screen.
+static void msg_puts_printf(char *str, int maxlen)
{
- char_u *s = str;
- char_u buf[4];
- char_u *p;
+ char *s = str;
+ char buf[4];
+ char *p;
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) {
if (!(silent_mode && p_verbose == 0)) {
- /* NL --> CR NL translation (for Unix, not for "--version") */
- /* NL --> CR translation (for Mac) */
+ // NL --> CR NL translation (for Unix, not for "--version")
p = &buf[0];
- if (*s == '\n' && !info_message)
+ if (*s == '\n' && !info_message) {
*p++ = '\r';
+ }
*p++ = *s;
*p = '\0';
- if (info_message) /* informative message, not an error */
- mch_msg((char *)buf);
- else
- mch_errmsg((char *)buf);
+ if (info_message) {
+ mch_msg(buf);
+ } else {
+ mch_errmsg(buf);
+ }
}
- /* primitive way to compute the current column */
+ // primitive way to compute the current column
if (cmdmsg_rl) {
- if (*s == '\r' || *s == '\n')
+ if (*s == '\r' || *s == '\n') {
msg_col = Columns - 1;
- else
- --msg_col;
+ } else {
+ msg_col--;
+ }
} else {
- if (*s == '\r' || *s == '\n')
+ if (*s == '\r' || *s == '\n') {
msg_col = 0;
- else
- ++msg_col;
+ } else {
+ msg_col++;
+ }
}
- ++s;
+ s++;
}
- msg_didout = TRUE; /* assume that line is not empty */
-
+ msg_didout = true; // assume that line is not empty
}
/*
diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c
index 4b64de1be0..368f83cfb5 100644
--- a/src/nvim/misc2.c
+++ b/src/nvim/misc2.c
@@ -467,11 +467,12 @@ bool put_bytes(FILE *fd, uintmax_t number, size_t len)
}
/// Writes time_t to file "fd" in 8 bytes.
-void put_time(FILE *fd, time_t time_)
+/// @returns FAIL when the write failed.
+int put_time(FILE *fd, time_t time_)
{
uint8_t buf[8];
time_to_bytes(time_, buf);
- (void)fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd);
+ return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL;
}
/// Writes time_t to "buf[8]".
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c
index f0d92b52a0..6ffcffe2e1 100644
--- a/src/nvim/msgpack_rpc/remote_ui.c
+++ b/src/nvim/msgpack_rpc/remote_ui.c
@@ -96,6 +96,7 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
ui->visual_bell = remote_ui_visual_bell;
ui->update_fg = remote_ui_update_fg;
ui->update_bg = remote_ui_update_bg;
+ ui->update_sp = remote_ui_update_sp;
ui->flush = remote_ui_flush;
ui->suspend = remote_ui_suspend;
ui->set_title = remote_ui_set_title;
@@ -285,6 +286,10 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
PUT(hl, "background", INTEGER_OBJ(attrs.background));
}
+ if (attrs.special != -1) {
+ PUT(hl, "special", INTEGER_OBJ(attrs.special));
+ }
+
ADD(args, DICTIONARY_OBJ(hl));
push_call(ui, "highlight_set", args);
}
@@ -323,6 +328,13 @@ static void remote_ui_update_bg(UI *ui, int bg)
push_call(ui, "update_bg", args);
}
+static void remote_ui_update_sp(UI *ui, int sp)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(sp));
+ push_call(ui, "update_sp", args);
+}
+
static void remote_ui_flush(UI *ui)
{
UIData *data = ui->data;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index f5607f3676..382c4943ff 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -7648,19 +7648,25 @@ static void nv_halfpage(cmdarg_T *cap)
*/
static void nv_join(cmdarg_T *cap)
{
- if (VIsual_active) /* join the visual lines */
+ if (VIsual_active) { // join the visual lines
nv_operator(cap);
- else if (!checkclearop(cap->oap)) {
- if (cap->count0 <= 1)
- cap->count0 = 2; /* default for join is two lines! */
+ } else if (!checkclearop(cap->oap)) {
+ if (cap->count0 <= 1) {
+ cap->count0 = 2; // default for join is two lines!
+ }
if (curwin->w_cursor.lnum + cap->count0 - 1 >
- curbuf->b_ml.ml_line_count)
- clearopbeep(cap->oap); /* beyond last line */
- else {
- prep_redo(cap->oap->regname, cap->count0,
- NUL, cap->cmdchar, NUL, NUL, cap->nchar);
- do_join(cap->count0, cap->nchar == NUL, true, true, true);
+ curbuf->b_ml.ml_line_count) {
+ // can't join when on the last line
+ if (cap->count0 <= 2) {
+ clearopbeep(cap->oap);
+ return;
+ }
+ cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1;
}
+
+ prep_redo(cap->oap->regname, cap->count0,
+ NUL, cap->cmdchar, NUL, NUL, cap->nchar);
+ do_join(cap->count0, cap->nchar == NUL, true, true, true);
}
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index eda963ff77..adfd0424f0 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5372,11 +5372,10 @@ void cursor_pos_info(dict_T *dict)
}
}
- // Don't shorten this message, the user asked for it.
bom_count = bomb_size();
if (bom_count > 0) {
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
- _("(+%" PRId64 " for BOM)"), (int64_t)byte_count);
+ _("(+%" PRId64 " for BOM)"), (int64_t)bom_count);
}
if (dict == NULL) {
p = p_shm;
@@ -5387,20 +5386,18 @@ void cursor_pos_info(dict_T *dict)
}
if (dict != NULL) {
+ // Don't shorten this message, the user asked for it.
dict_add_nr_str(dict, "words", word_count, NULL);
dict_add_nr_str(dict, "chars", char_count, NULL);
dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL);
- if (l_VIsual_active) {
- dict_add_nr_str(dict, "visual_bytes", byte_count_cursor, NULL);
- dict_add_nr_str(dict, "visual_chars", char_count_cursor, NULL);
- dict_add_nr_str(dict, "visual_words", word_count_cursor, NULL);
- } else {
- dict_add_nr_str(dict, "cursor_bytes", byte_count_cursor, NULL);
- dict_add_nr_str(dict, "cursor_chars", char_count_cursor, NULL);
- dict_add_nr_str(dict, "cursor_words", word_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
+ byte_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
+ char_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words",
+ word_count_cursor, NULL);
}
- }
}
/// Check if the default register (used in an unnamed paste) should be a
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2f22c245dd..45ebb4fa4c 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1639,18 +1639,21 @@ do_set (
&& STRNCMP(s, newval, i) == 0
&& (!(flags & P_COMMA)
|| s[i] == ','
- || s[i] == NUL))
+ || s[i] == NUL)) {
break;
- /* Count backslashes. Only a comma with an
- * even number of backslashes before it is
- * recognized as a separator */
- if (s > origval && s[-1] == '\\')
- ++bs;
- else
+ }
+ // Count backslashes. Only a comma with an even number of
+ // backslashes or a single backslash preceded by a comma
+ // before it is recognized as a separator
+ if ((s > origval + 1 && s[-1] == '\\' && s[-2] != ',')
+ || (s == origval + 1 && s[-1] == '\\')) {
+ bs++;
+ } else {
bs = 0;
+ }
}
- /* do not add if already there */
+ // do not add if already there
if ((adding || prepending) && *s) {
prepending = FALSE;
adding = FALSE;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 87a9a7398c..904e97f8ca 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -619,6 +619,7 @@ EXTERN long p_titlelen; ///< 'titlelen'
EXTERN char_u *p_titleold; ///< 'titleold'
EXTERN char_u *p_titlestring; ///< 'titlestring'
EXTERN char_u *p_tsr; ///< 'thesaurus'
+EXTERN bool p_tgc; ///< 'termguicolors'
EXTERN int p_ttimeout; ///< 'ttimeout'
EXTERN long p_ttm; ///< 'ttimeoutlen'
EXTERN char_u *p_udir; ///< 'undodir'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index a743e8c605..218e34f595 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2383,6 +2383,14 @@ return {
defaults={if_true={vi=""}}
},
{
+ full_name='termguicolors', abbreviation='tgc',
+ type='bool', scope={'global'},
+ vi_def=false,
+ redraw={'everything'},
+ varname='p_tgc',
+ defaults={if_true={vi=false}}
+ },
+ {
full_name='terse',
type='bool', scope={'global'},
vi_def=true,
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 384a17004e..edc430410c 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -147,7 +147,7 @@ static char_u *homedir = NULL;
void init_homedir(void)
{
- /* In case we are called a second time (when 'encoding' changes). */
+ // In case we are called a second time (when 'encoding' changes).
xfree(homedir);
homedir = NULL;
@@ -176,16 +176,16 @@ void init_homedir(void)
if (var != NULL) {
#ifdef UNIX
- /*
- * Change to the directory and get the actual path. This resolves
- * links. Don't do it when we can't return.
- */
+ // Change to the directory and get the actual path. This resolves
+ // links. Don't do it when we can't return.
if (os_dirname(NameBuff, MAXPATHL) == OK
&& os_chdir((char *)NameBuff) == 0) {
- if (!os_chdir((char *)var) && os_dirname(IObuff, IOSIZE) == OK)
+ if (!os_chdir((char *)var) && os_dirname(IObuff, IOSIZE) == OK) {
var = IObuff;
- if (os_chdir((char *)NameBuff) != 0)
+ }
+ if (os_chdir((char *)NameBuff) != 0) {
EMSG(_(e_prev_dir));
+ }
}
#endif
homedir = vim_strsave(var);
@@ -239,29 +239,29 @@ void expand_env(char_u *src, char_u *dst, int dstlen)
/// "~/" is also expanded, using $HOME. For Unix "~user/" is expanded.
/// Skips over "\ ", "\~" and "\$" (not for Win32 though).
/// If anything fails no expansion is done and dst equals src.
-/// startstr recognize the start of a new name, for '~' expansion.
+/// prefix recognize the start of a new name, for '~' expansion.
/// @param srcp Input string e.g. "$HOME/vim.hlp"
/// @param dst Where to put the result
/// @param dstlen Maximum length of the result
/// @param esc Should we escape spaces in expanded variables?
/// @param one Should we expand more than one '~'?
-/// @param startstr Common prefix for paths, can be NULL
-void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
- char_u *startstr)
+/// @param prefix Common prefix for paths, can be NULL
+void expand_env_esc(char_u *restrict srcp,
+ char_u *restrict dst,
+ int dstlen,
+ bool esc,
+ bool one,
+ char_u *prefix)
{
- char_u *src;
char_u *tail;
- int c;
char_u *var;
bool copy_char;
bool mustfree; // var was allocated, need to free it later
bool at_start = true; // at start of a name
- int startstr_len = 0;
- if (startstr != NULL)
- startstr_len = (int)STRLEN(startstr);
+ int prefix_len = (prefix == NULL) ? 0 : (int)STRLEN(prefix);
- src = skipwhite(srcp);
+ char_u *src = skipwhite(srcp);
dstlen--; // leave one char space for "\,"
while (*src && dstlen > 0) {
// Skip over `=expr`.
@@ -281,6 +281,7 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
dstlen -= (int)len;
continue;
}
+
copy_char = true;
if ((*src == '$') || (*src == '~' && at_start)) {
mustfree = false;
@@ -290,14 +291,15 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
if (*src != '~') { // environment var
tail = src + 1;
var = dst;
- c = dstlen - 1;
+ int c = dstlen - 1;
#ifdef UNIX
// Unix has ${var-name} type environment vars
if (*tail == '{' && !vim_isIDc('{')) {
- tail++; /* ignore '{' */
- while (c-- > 0 && *tail && *tail != '}')
+ tail++; // ignore '{'
+ while (c-- > 0 && *tail != NUL && *tail != '}') {
*var++ = *tail++;
+ }
} else // NOLINT
#endif
{
@@ -321,7 +323,7 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
#if defined(UNIX)
}
#endif
- } else if ( src[1] == NUL /* home directory */
+ } else if (src[1] == NUL // home directory
|| vim_ispathsep(src[1])
|| vim_strchr((char_u *)" ,\t\n", src[1]) != NULL) {
var = homedir;
@@ -331,12 +333,13 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
// Copy ~user to dst[], so we can put a NUL after it.
tail = src;
var = dst;
- c = dstlen - 1;
- while ( c-- > 0
- && *tail
- && vim_isfilec(*tail)
- && !vim_ispathsep(*tail))
+ int c = dstlen - 1;
+ while (c-- > 0
+ && *tail
+ && vim_isfilec(*tail)
+ && !vim_ispathsep(*tail)) {
*var++ = *tail++;
+ }
*var = NUL;
// Use os_get_user_directory() to get the user directory.
// If this function fails, the shell is used to
@@ -344,8 +347,7 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
// does not support ~user (old versions of /bin/sh).
var = (char_u *)os_get_user_directory((char *)dst + 1);
mustfree = true;
- if (var == NULL)
- {
+ if (var == NULL) {
expand_T xpc;
ExpandInit(&xpc);
@@ -381,8 +383,9 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL) {
char_u *p = vim_strsave_escaped(var, (char_u *)" \t");
- if (mustfree)
+ if (mustfree) {
xfree(var);
+ }
var = p;
mustfree = true;
}
@@ -391,7 +394,7 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
&& (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen)) {
STRCPY(dst, var);
dstlen -= (int)STRLEN(var);
- c = (int)STRLEN(var);
+ int c = (int)STRLEN(var);
// if var[] ends in a path separator and tail[] starts
// with it, skip a character
if (*var != NUL && after_pathsep((char *)dst, (char *)dst + c)
@@ -404,8 +407,9 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
src = tail;
copy_char = false;
}
- if (mustfree)
+ if (mustfree) {
xfree(var);
+ }
}
if (copy_char) { // copy at least one char
@@ -422,9 +426,10 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
*dst++ = *src++;
--dstlen;
- if (startstr != NULL && src - startstr_len >= srcp
- && STRNCMP(src - startstr_len, startstr, startstr_len) == 0)
+ if (prefix != NULL && src - prefix_len >= srcp
+ && STRNCMP(src - prefix_len, prefix, prefix_len) == 0) {
at_start = true;
+ }
}
}
*dst = NUL;
@@ -451,17 +456,37 @@ static char *vim_version_dir(const char *vimdir)
return NULL;
}
-/// If the string between "p" and "pend" ends in "name/", return "pend" minus
-/// the length of "name/". Otherwise return "pend".
-static char *remove_tail(char *p, char *pend, char *name)
+/// If `dirname + "/"` precedes `pend` in the path, return the pointer to
+/// `dirname + "/" + pend`. Otherwise return `pend`.
+///
+/// Examples (path = /usr/local/share/nvim/runtime/doc/help.txt):
+///
+/// pend = help.txt
+/// dirname = doc
+/// -> doc/help.txt
+///
+/// pend = doc/help.txt
+/// dirname = runtime
+/// -> runtime/doc/help.txt
+///
+/// pend = runtime/doc/help.txt
+/// dirname = vim74
+/// -> runtime/doc/help.txt
+///
+/// @param path Path to a file
+/// @param pend A suffix of the path
+/// @param dirname The immediate path fragment before the pend
+/// @return The new pend including dirname or just pend
+static char *remove_tail(char *path, char *pend, char *dirname)
{
- size_t len = STRLEN(name) + 1;
- char *newend = pend - len;
+ size_t len = STRLEN(dirname);
+ char *new_tail = pend - len - 1;
- if (newend >= p
- && fnamencmp((char_u *)newend, (char_u *)name, len - 1) == 0
- && (newend == p || after_pathsep(p, newend)))
- return newend;
+ if (new_tail >= path
+ && fnamencmp((char_u *)new_tail, (char_u *)dirname, len) == 0
+ && (new_tail == path || after_pathsep(path, new_tail))) {
+ return new_tail;
+ }
return pend;
}
@@ -745,9 +770,10 @@ void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, bool one)
/// @param src Input file name
char_u * home_replace_save(buf_T *buf, char_u *src) FUNC_ATTR_NONNULL_RET
{
- size_t len = 3; /* space for "~/" and trailing NUL */
- if (src != NULL) /* just in case */
+ size_t len = 3; // space for "~/" and trailing NUL
+ if (src != NULL) { // just in case
len += STRLEN(src);
+ }
char_u *dst = xmalloc(len);
home_replace(buf, src, dst, (int)len, true);
return dst;
@@ -783,8 +809,7 @@ char_u *get_env_name(expand_T *xp, int idx)
STRLCPY(name, envname, ENVNAMELEN);
xfree(envname);
return name;
- } else {
- return NULL;
}
+ return NULL;
}
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 49a74cf0d1..143a7160b0 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -111,8 +111,8 @@ int os_nodetype(const char *name)
#endif
uv_stat_t statbuf;
- if (os_stat(name, &statbuf) == 0) {
- return NODE_NORMAL;
+ if (0 != os_stat(name, &statbuf)) {
+ return NODE_NORMAL; // File doesn't exist.
}
#ifndef WIN32
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 17cb8a86aa..151b9d3790 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -160,9 +160,6 @@ qf_init (
{
qf_info_T *qi = &ql_info;
- if (efile == NULL)
- return FAIL;
-
if (wp != NULL) {
qi = ll_get_or_alloc_list(wp);
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 10b5b6bba4..34eef83164 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -3385,11 +3385,9 @@ win_line (
&& lcs_nbsp)
|| (c == ' ' && lcs_space && ptr - line <= trailcol))) {
c = (c == ' ') ? lcs_space : lcs_nbsp;
- if (area_attr == 0 && search_attr == 0) {
- n_attr = 1;
- extra_attr = hl_attr(HLF_8);
- saved_attr2 = char_attr; // save current attr
- }
+ n_attr = 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; // save current attr
mb_c = c;
if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = true;
@@ -3402,11 +3400,9 @@ win_line (
if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') {
c = lcs_trail;
- if (!attr_pri) {
- n_attr = 1;
- extra_attr = hl_attr(HLF_8);
- saved_attr2 = char_attr; /* save current attr */
- }
+ n_attr = 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; // save current attr
mb_c = c;
if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = TRUE;
@@ -3554,11 +3550,9 @@ win_line (
c = ' ';
}
lcs_eol_one = -1;
- --ptr; /* put it back at the NUL */
- if (!attr_pri) {
- extra_attr = hl_attr(HLF_AT);
- n_attr = 1;
- }
+ ptr--; // put it back at the NUL
+ extra_attr = hl_attr(HLF_AT);
+ n_attr = 1;
mb_c = c;
if (enc_utf8 && (*mb_char2len)(c) > 1) {
mb_utf8 = TRUE;
@@ -3587,12 +3581,10 @@ win_line (
n_extra = byte2cells(c) - 1;
c = *p_extra++;
}
- if (!attr_pri) {
- n_attr = n_extra + 1;
- extra_attr = hl_attr(HLF_8);
- saved_attr2 = char_attr; /* save current attr */
- }
- mb_utf8 = FALSE; /* don't draw as UTF-8 */
+ n_attr = n_extra + 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; // save current attr
+ mb_utf8 = false; // don't draw as UTF-8
} else if (VIsual_active
&& (VIsual_mode == Ctrl_V
|| VIsual_mode == 'v')
@@ -3702,11 +3694,10 @@ win_line (
did_wcol = true;
}
- /* Don't override visual selection highlighting. */
- if (n_attr > 0
- && draw_state == WL_LINE
- && !attr_pri)
- char_attr = extra_attr;
+ // Don't override visual selection highlighting.
+ if (n_attr > 0 && draw_state == WL_LINE) {
+ char_attr = hl_combine_attr(char_attr, extra_attr);
+ }
/*
* Handle the case where we are in column 0 but not on the first
@@ -3734,13 +3725,12 @@ win_line (
mb_utf8 = TRUE;
u8cc[0] = 0;
c = 0xc0;
- } else
- mb_utf8 = FALSE; /* don't draw as UTF-8 */
- if (!attr_pri) {
- saved_attr3 = char_attr; /* save current attr */
- char_attr = hl_attr(HLF_AT); /* later copied to char_attr */
- n_attr3 = 1;
+ } else {
+ mb_utf8 = false; // don't draw as UTF-8
}
+ saved_attr3 = char_attr; // save current attr
+ char_attr = hl_attr(HLF_AT); // later copied to char_attr
+ n_attr3 = 1;
}
/*
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 3192be1b3c..51c8597d53 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -46,7 +46,7 @@
#ifdef HAVE_BE64TOH
# define _BSD_SOURCE 1
# define _DEFAULT_SOURCE 1
-# include <endian.h>
+# include ENDIAN_INCLUDE_FILE
#endif
// Note: when using bufset hash pointers are intentionally casted to uintptr_t
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 0acaa9ae2b..84906a3548 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -45,6 +45,9 @@
// Use SPELL_PRINTTREE for debugging: dump the word tree after adding a word.
// Only use it for small word lists!
+// Use SPELL_COMPRESS_ALLWAYS for debugging: compress the word tree after
+// adding a word. Only use it for small word lists!
+
// Use DEBUG_TRIEWALK to print the changes made in suggest_trie_walk() for a
// specific word.
@@ -156,6 +159,8 @@
//
// sectionID == SN_NOSPLITSUGS: nothing
//
+// sectionID == SN_NOCOMPOUNDSUGS: nothing
+//
// sectionID == SN_WORDS: <word> ...
// <word> N bytes NUL terminated common word
//
@@ -482,7 +487,7 @@ struct slang_S {
regprog_T **sl_prefprog; // table with regprogs for prefixes
garray_T sl_rep; // list of fromto_T entries from REP lines
- short sl_rep_first[256]; // indexes where byte first appears, -1 if
+ int16_t sl_rep_first[256]; // indexes where byte first appears, -1 if
// there is none
garray_T sl_sal; // list of salitem_T entries from SAL lines
salfirst_T sl_sal_first[256]; // indexes where byte first appears, -1 if
@@ -494,8 +499,9 @@ struct slang_S {
// "sl_sal_first" maps chars, when has_mbyte
// "sl_sal" is a list of wide char lists.
garray_T sl_repsal; // list of fromto_T entries from REPSAL lines
- short sl_repsal_first[256]; // sl_rep_first for REPSAL lines
- bool sl_nosplitsugs; // don't suggest splitting a word
+ int16_t sl_repsal_first[256]; // sl_rep_first for REPSAL lines
+ bool sl_nosplitsugs; // don't suggest splitting a word
+ bool sl_nocompoundsugs; // don't suggest compounding
// Info from the .sug file. Loaded on demand.
time_t sl_sugtime; // timestamp for .sug file
@@ -558,6 +564,7 @@ typedef struct langp_S {
#define SN_WORDS 13 // common words
#define SN_NOSPLITSUGS 14 // don't split word for suggestions
#define SN_INFO 15 // info section
+#define SN_NOCOMPOUNDSUGS 16 // don't compound for suggestions
#define SN_END 255 // end of sections
#define SNF_REQUIRED 1 // <sectionflags>: required section
@@ -948,6 +955,7 @@ typedef struct spellinfo_S {
char_u *si_sofoto; // SOFOTO text
int si_nosugfile; // NOSUGFILE item found
int si_nosplitsugs; // NOSPLITSUGS item found
+ int si_nocompoundsugs; // NOCOMPOUNDSUGS item found
int si_followup; // soundsalike: ?
int si_collapse; // soundsalike: ?
hashtab_T si_commonwords; // hashtable for common words
@@ -2666,7 +2674,11 @@ spell_load_file (
break;
case SN_NOSPLITSUGS:
- lp->sl_nosplitsugs = true; // <timestamp>
+ lp->sl_nosplitsugs = true;
+ break;
+
+ case SN_NOCOMPOUNDSUGS:
+ lp->sl_nocompoundsugs = true;
break;
case SN_COMPOUND:
@@ -2868,7 +2880,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp)
// Read REP or REPSAL items section from "fd": <repcount> <rep> ...
// Return SP_*ERROR flags.
-static int read_rep_section(FILE *fd, garray_T *gap, short *first)
+static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first)
{
int cnt;
fromto_T *ftp;
@@ -4266,9 +4278,9 @@ static void spell_print_node(wordnode_T *node, int depth)
PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0);
PRINTSOME(line2, depth, " ", 0, 0);
PRINTSOME(line3, depth, " ", 0, 0);
- msg(line1);
- msg(line2);
- msg(line3);
+ msg((char_u *)line1);
+ msg((char_u *)line2);
+ msg((char_u *)line3);
} else {
node->wn_u1.index = TRUE;
@@ -4289,9 +4301,9 @@ static void spell_print_node(wordnode_T *node, int depth)
PRINTSOME(line3, depth, " ", 0, 0);
if (node->wn_byte == NUL) {
- msg(line1);
- msg(line2);
- msg(line3);
+ msg((char_u *)line1);
+ msg((char_u *)line2);
+ msg((char_u *)line3);
}
// do the children
@@ -4633,6 +4645,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
spin->si_nosplitsugs = true;
+ } else if (is_aff_rule(items, itemcnt, "NOCOMPOUNDSUGS", 1)) {
+ spin->si_nocompoundsugs = true;
} else if (is_aff_rule(items, itemcnt, "NOSUGFILE", 1)) {
spin->si_nosugfile = true;
} else if (is_aff_rule(items, itemcnt, "PFXPOSTPONE", 1)) {
@@ -6289,7 +6303,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
node = *prev;
}
#ifdef SPELL_PRINTTREE
- smsg("Added \"%s\"", word);
+ smsg((char_u *)"Added \"%s\"", word);
spell_print_tree(root->wn_sibling);
#endif
@@ -6312,8 +6326,8 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int
// 3. When compressed before, added "compress_added" words
// (si_compress_cnt == 1) and the number of free nodes drops below the
// maximum word length.
-#ifndef SPELL_PRINTTREE
- if (spin->si_compress_cnt == 1
+#ifndef SPELL_COMPRESS_ALLWAYS
+ if (spin->si_compress_cnt == 1 // NOLINT(readability/braces)
? spin->si_free_count < MAXWLEN
: spin->si_blocks_cnt >= compress_start)
#endif
@@ -6857,6 +6871,15 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
put_bytes(fd, 0, 4); // <sectionlen>
}
+ // SN_NOCOMPUNDSUGS: nothing
+ // This is used to notify that no suggestions with compounds are to be
+ // made.
+ if (spin->si_nocompoundsugs) {
+ putc(SN_NOCOMPOUNDSUGS, fd); // <sectionID>
+ putc(0, fd); // <sectionflags>
+ put_bytes(fd, 0, 4); // <sectionlen>
+ }
+
// SN_COMPOUND: compound info.
// We don't mark it required, when not supported all compound words will
// be bad words.
@@ -9771,6 +9794,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// be possible to compound another (short) word.
try_compound = false;
if (!soundfold
+ && !slang->sl_nocompoundsugs
&& slang->sl_compprog != NULL
&& ((unsigned)flags >> 24) != 0
&& sp->ts_twordlen - sp->ts_splitoff
@@ -9791,21 +9815,21 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// For NOBREAK we never try splitting, it won't make any word
// valid.
- if (slang->sl_nobreak)
+ if (slang->sl_nobreak && !slang->sl_nocompoundsugs) {
try_compound = true;
-
- // If we could add a compound word, and it's also possible to
- // split at this point, do the split first and set
- // TSF_DIDSPLIT to avoid doing it again.
- else if (!fword_ends
- && try_compound
- && (sp->ts_flags & TSF_DIDSPLIT) == 0) {
+ } else if (!fword_ends
+ && try_compound
+ && (sp->ts_flags & TSF_DIDSPLIT) == 0) {
+ // If we could add a compound word, and it's also possible to
+ // split at this point, do the split first and set
+ // TSF_DIDSPLIT to avoid doing it again.
try_compound = false;
sp->ts_flags |= TSF_DIDSPLIT;
--sp->ts_curi; // do the same NUL again
compflags[sp->ts_complen] = NUL;
- } else
+ } else {
sp->ts_flags &= ~TSF_DIDSPLIT;
+ }
if (try_split || try_compound) {
if (!try_compound && (!fword_ends || !goodword_ends)) {
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 41af7af55c..1f9dbd8228 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -62,8 +62,10 @@ struct hl_group {
int sg_gui; // "gui=" highlighting attributes
RgbValue sg_rgb_fg; // RGB foreground color
RgbValue sg_rgb_bg; // RGB background color
+ RgbValue sg_rgb_sp; // RGB special color
uint8_t *sg_rgb_fg_name; // RGB foreground color name
uint8_t *sg_rgb_bg_name; // RGB background color name
+ uint8_t *sg_rgb_sp_name; // RGB special color name
};
#define SG_CTERM 2 // cterm has been set
@@ -2615,33 +2617,37 @@ find_endpos (
IF_SYN_TIME(&spp_skip->sp_time));
spp_skip->sp_prog = regmatch.regprog;
if (r && regmatch.startpos[0].col <= best_regmatch.startpos[0].col) {
- /* Add offset to skip pattern match */
+ // Add offset to skip pattern match
syn_add_end_off(&pos, &regmatch, spp_skip, SPO_ME_OFF, 1);
- /* If the skip pattern goes on to the next line, there is no
- * match with an end pattern in this line. */
- if (pos.lnum > startpos->lnum)
+ // If the skip pattern goes on to the next line, there is no
+ // match with an end pattern in this line.
+ if (pos.lnum > startpos->lnum) {
break;
+ }
- line = ml_get_buf(syn_buf, startpos->lnum, FALSE);
+ line = ml_get_buf(syn_buf, startpos->lnum, false);
+ int line_len = (int)STRLEN(line);
- /* take care of an empty match or negative offset */
- if (pos.col <= matchcol)
- ++matchcol;
- else if (pos.col <= regmatch.endpos[0].col)
+ // take care of an empty match or negative offset
+ if (pos.col <= matchcol) {
+ matchcol++;
+ } else if (pos.col <= regmatch.endpos[0].col) {
matchcol = pos.col;
- else
- /* Be careful not to jump over the NUL at the end-of-line */
+ } else {
+ // Be careful not to jump over the NUL at the end-of-line
for (matchcol = regmatch.endpos[0].col;
- line[matchcol] != NUL && matchcol < pos.col;
- ++matchcol)
- ;
+ matchcol < line_len && matchcol < pos.col;
+ matchcol++) {
+ }
+ }
- /* if the skip pattern includes end-of-line, break here */
- if (line[matchcol] == NUL)
+ // if the skip pattern includes end-of-line, break here
+ if (matchcol >= line_len) {
break;
+ }
- continue; /* start with first end pattern again */
+ continue; // start with first end pattern again
}
}
@@ -5004,6 +5010,10 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
curwin->w_s->b_syn_sync_maxlines = 0;
}
} else if (STRCMP(key, "LINECONT") == 0) {
+ if (*next_arg == NUL) { // missing pattern
+ illegal = true;
+ break;
+ }
if (curwin->w_s->b_syn_linecont_pat != NULL) {
EMSG(_("E403: syntax sync: line continuations pattern specified twice"));
finished = TRUE;
@@ -6161,12 +6171,11 @@ do_highlight (
break;
}
- /*
- * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or
- * "guibg").
- */
- while (*linep && !ascii_iswhite(*linep) && *linep != '=')
- ++linep;
+ // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg",
+ // "guibg" or "guisp").
+ while (*linep && !ascii_iswhite(*linep) && *linep != '=') {
+ linep++;
+ }
xfree(key);
key = vim_strnsave_up(key_start, (int)(linep - key_start));
linep = skipwhite(linep);
@@ -6362,18 +6371,14 @@ do_highlight (
} else
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
}
- color &= 7; /* truncate to 8 colors */
- } else if (t_colors == 16 || t_colors == 88 || t_colors == 256) {
- switch (t_colors) {
- case 16:
- color = color_numbers_8[i];
- break;
- case 88:
- color = color_numbers_88[i];
- break;
- case 256:
- color = color_numbers_256[i];
- break;
+ color &= 7; // truncate to 8 colors
+ } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) {
+ if (t_colors == 88) {
+ color = color_numbers_88[i];
+ } else if (t_colors >= 256) {
+ color = color_numbers_256[i];
+ } else {
+ color = color_numbers_8[i];
}
}
}
@@ -6448,7 +6453,23 @@ do_highlight (
normal_bg = HL_TABLE()[idx].sg_rgb_bg;
}
} else if (STRCMP(key, "GUISP") == 0) {
- // Ignored for now
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+
+ xfree(HL_TABLE()[idx].sg_rgb_sp_name);
+ if (STRCMP(arg, "NONE") != 0) {
+ HL_TABLE()[idx].sg_rgb_sp_name = (uint8_t *)xstrdup((char *)arg);
+ HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg);
+ } else {
+ HL_TABLE()[idx].sg_rgb_sp_name = NULL;
+ HL_TABLE()[idx].sg_rgb_sp = -1;
+ }
+ }
+
+ if (is_normal_group) {
+ normal_sp = HL_TABLE()[idx].sg_rgb_sp;
+ }
} else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) {
// Ignored for now
} else {
@@ -6512,6 +6533,7 @@ void restore_cterm_colors(void)
{
normal_fg = -1;
normal_bg = -1;
+ normal_sp = -1;
cterm_normal_fg_color = 0;
cterm_normal_fg_bold = 0;
cterm_normal_bg_color = 0;
@@ -6528,6 +6550,7 @@ static int hl_has_settings(int idx, int check_link)
|| HL_TABLE()[idx].sg_cterm_bg != 0
|| HL_TABLE()[idx].sg_rgb_fg_name != NULL
|| HL_TABLE()[idx].sg_rgb_bg_name != NULL
+ || HL_TABLE()[idx].sg_rgb_sp_name != NULL
|| (check_link && (HL_TABLE()[idx].sg_set & SG_LINK));
}
@@ -6544,14 +6567,18 @@ static void highlight_clear(int idx)
HL_TABLE()[idx].sg_gui = 0;
HL_TABLE()[idx].sg_rgb_fg = -1;
HL_TABLE()[idx].sg_rgb_bg = -1;
+ HL_TABLE()[idx].sg_rgb_sp = -1;
xfree(HL_TABLE()[idx].sg_rgb_fg_name);
HL_TABLE()[idx].sg_rgb_fg_name = NULL;
xfree(HL_TABLE()[idx].sg_rgb_bg_name);
HL_TABLE()[idx].sg_rgb_bg_name = NULL;
- /* Clear the script ID only when there is no link, since that is not
- * cleared. */
- if (HL_TABLE()[idx].sg_link == 0)
+ xfree(HL_TABLE()[idx].sg_rgb_sp_name);
+ HL_TABLE()[idx].sg_rgb_sp_name = NULL;
+ // Clear the script ID only when there is no link, since that is not
+ // cleared.
+ if (HL_TABLE()[idx].sg_link == 0) {
HL_TABLE()[idx].sg_scriptID = 0;
+ }
}
@@ -6593,7 +6620,8 @@ int get_attr_entry(attrentry_T *aep)
&& aep->cterm_bg_color == taep->cterm_bg_color
&& aep->rgb_ae_attr == taep->rgb_ae_attr
&& aep->rgb_fg_color == taep->rgb_fg_color
- && aep->rgb_bg_color == taep->rgb_bg_color) {
+ && aep->rgb_bg_color == taep->rgb_bg_color
+ && aep->rgb_sp_color == taep->rgb_sp_color) {
return i + ATTR_OFF;
}
}
@@ -6631,6 +6659,7 @@ int get_attr_entry(attrentry_T *aep)
taep->rgb_ae_attr = aep->rgb_ae_attr;
taep->rgb_fg_color = aep->rgb_fg_color;
taep->rgb_bg_color = aep->rgb_bg_color;
+ taep->rgb_sp_color = aep->rgb_sp_color;
return table->ga_len - 1 + ATTR_OFF;
}
@@ -6692,6 +6721,10 @@ int hl_combine_attr(int char_attr, int prim_attr)
if (spell_aep->rgb_bg_color >= 0) {
new_en.rgb_bg_color = spell_aep->rgb_bg_color;
}
+
+ if (spell_aep->rgb_sp_color >= 0) {
+ new_en.rgb_sp_color = spell_aep->rgb_sp_color;
+ }
}
return get_attr_entry(&new_en);
}
@@ -6729,7 +6762,7 @@ static void highlight_list_one(int id)
didh = highlight_list_arg(id, didh, LIST_STRING,
0, sgp->sg_rgb_bg_name, "guibg");
didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, NULL, "guisp");
+ 0, sgp->sg_rgb_sp_name, "guisp");
if (sgp->sg_link && !got_int) {
(void)syn_list_header(didh, 9999, id);
@@ -6843,8 +6876,9 @@ highlight_color (
if (modec == 'g') {
if (fg)
return HL_TABLE()[id - 1].sg_rgb_fg_name;
- if (sp)
- return NULL;
+ if (sp) {
+ return HL_TABLE()[id - 1].sg_rgb_sp_name;
+ }
return HL_TABLE()[id - 1].sg_rgb_bg_name;
}
if (font || sp)
@@ -6931,7 +6965,17 @@ set_hl_attr (
// before setting attr_entry->{f,g}g_color to a other than -1
at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
- sgp->sg_attr = get_attr_entry(&at_en);
+ at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
+
+ if (at_en.cterm_fg_color != 0 || at_en.cterm_bg_color != 0
+ || at_en.rgb_fg_color != -1 || at_en.rgb_bg_color != -1
+ || at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0
+ || at_en.rgb_ae_attr != 0) {
+ sgp->sg_attr = get_attr_entry(&at_en);
+ } else {
+ // If all the fields are cleared, clear the attr field back to default value
+ sgp->sg_attr = 0;
+ }
}
/*
@@ -7262,6 +7306,10 @@ int highlight_changed(void)
hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg;
}
+ if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) {
+ hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp;
+ }
+
highlight_ga.ga_len = hlcnt + i + 1;
set_hl_attr(hlcnt + i); /* At long last we can apply */
highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1);
diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h
index 67cf672ef2..8d207e6286 100644
--- a/src/nvim/syntax_defs.h
+++ b/src/nvim/syntax_defs.h
@@ -69,8 +69,8 @@ struct syn_state {
// Structure shared between syntax.c, screen.c
typedef struct attr_entry {
- short rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
- RgbValue rgb_fg_color, rgb_bg_color;
+ int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
+ RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
int cterm_fg_color, cterm_bg_color;
} attrentry_T;
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 82c7cd4de9..2fba6dd563 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -28,20 +28,19 @@ SCRIPTS := \
test53.out \
test55.out \
test64.out \
- test68.out \
test69.out \
test73.out \
test79.out \
test_listlbr.out \
- test_breakindent.out \
- test_close_count.out \
test_marks.out \
# Tests using runtest.vim.vim.
# Keep test_alot*.res as the last one, sort the others.
NEW_TESTS = \
- test_viml.res \
test_cursor_func.res \
+ test_help_tagjump.res \
+ test_menu.res \
+ test_viml.res \
test_alot.res
SCRIPTS_GUI := test16.out
@@ -98,7 +97,7 @@ test1.out: $(VIMPROG)
$(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) test1.out
RM_ON_RUN := test.out X* viminfo
-RM_ON_START := tiny.vim small.vim mbyte.vim test.ok
+RM_ON_START := test.ok
RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(VIMPROG) -u unix.vim -U NONE -i viminfo --noplugin -s dotest.in
clean:
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 6601dcf52f..2712fb9371 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -20,9 +20,6 @@
" If cleanup after each Test_ function is needed, define a TearDown function.
" It will be called after each Test_ function.
-" Without the +eval feature we can't run these tests, bail out.
-so small.vim
-
" Check that the screen size is at least 24 x 80 characters.
if &lines < 24 || &columns < 80
let error = 'Screen size too small! Tests require at least 24 lines with 80 characters'
@@ -68,7 +65,8 @@ function /^Test_
redir END
let tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g'))
-for test in tests
+" Execute the tests in alphabetical order.
+for test in sort(tests)
if exists("*SetUp")
call SetUp()
endif
diff --git a/src/nvim/testdir/test1.in b/src/nvim/testdir/test1.in
index 85ff1b4db2..272500cd25 100644
--- a/src/nvim/testdir/test1.in
+++ b/src/nvim/testdir/test1.in
@@ -1,20 +1,5 @@
-
First a simple test to check if the test script works.
-If Vim was not compiled with the +eval feature, the small.vim script will be
-set to copy the test.ok file to test.out, so that it looks like the test
-succeeded. Otherwise an empty small.vim is written. small.vim is sourced by
-tests that require the +eval feature or other features that are missing in the
-small version.
-
-If Vim was not compiled with the +windows feature, the tiny.vim script will be
-set like small.vim above. tiny.vim is sourced by tests that require the
-+windows feature or other features that are missing in the tiny version.
-
-If Vim was not compiled with the +multi_byte feature, the mbyte.vim script will
-be set like small.vim above. mbyte.vim is sourced by tests that require the
-+multi_byte feature.
-
STARTTEST
:" If columns or lines are too small, create wrongtermsize.
:" (Some tests will fail. When columns and/or lines are small)
@@ -23,25 +8,6 @@ STARTTEST
:" Write a single line to test.out to check if testing works at all.
:%d
athis is a test:w! test.out
-:" Create small.vim and tiny.vim empty, create mbyte.vim to skip the test.
-0D:w! small.vim
-:w! tiny.vim
-ae! test.ok
-w! test.out
-qa!
-:w! mbyte.vim
-:"
-:" If +multi_byte feature supported, make mbyte.vim empty.
-:if has("multi_byte") | sp another | w! mbyte.vim | q | endif
-:"
-:" If +eval feature supported quit here, leaving tiny.vim and small.vim empty.
-:" Otherwise write small.vim to skip the test.
-:if 1 | q! | endif
-:w! small.vim
-:" If +windows feature not supported :sp will fail and tiny.vim will be
-:" written to skip the test.
-:sp another
-:wq! tiny.vim
:qa!
ENDTEST
diff --git a/src/nvim/testdir/test10.in b/src/nvim/testdir/test10.in
index 769d690acb..2178cf41ce 100644
--- a/src/nvim/testdir/test10.in
+++ b/src/nvim/testdir/test10.in
@@ -1,9 +1,6 @@
Test for 'errorformat'. This will fail if the quickfix feature was disabled.
STARTTEST
-:so small.vim
-:" Also test a BOM is ignored.
-:so mbyte.vim
:7/start of errorfile/,/end of errorfile/w! Xerrorfile1
:7/start of errorfile/,/end of errorfile/-1w! Xerrorfile2
:/start of testfile/,/end of testfile/w! Xtestfile
diff --git a/src/nvim/testdir/test10a.in b/src/nvim/testdir/test10a.in
index 19e8652fe5..99a5a03db8 100644
--- a/src/nvim/testdir/test10a.in
+++ b/src/nvim/testdir/test10a.in
@@ -1,7 +1,6 @@
Test for 'errorformat'.
STARTTEST
-:so small.vim
:/start of errorfile/,/end of errorfile/w! Xerrorfile
:/start of testfile/,/end of testfile/w! Xtestfile
:cf Xerrorfile
diff --git a/src/nvim/testdir/test12.in b/src/nvim/testdir/test12.in
index be3169a625..0c0623e5d4 100644
--- a/src/nvim/testdir/test12.in
+++ b/src/nvim/testdir/test12.in
@@ -4,7 +4,6 @@ Tests for 'directory' option.
- "dir", in directory relative to current dir
STARTTEST
-:so small.vim
:set dir=.,~
:/start of testfile/,/end of testfile/w! Xtest1
:" do an ls of the current dir to find the swap file (should not be there)
diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in
index 6713f80e88..fa9ba312b7 100644
--- a/src/nvim/testdir/test13.in
+++ b/src/nvim/testdir/test13.in
@@ -11,7 +11,6 @@ Also test changing buffers in a BufDel autocommand. If this goes wrong there
are ml_line errors and/or a Crash.
STARTTEST
-:so small.vim
:/^start of testfile/,/^end of testfile/w! Xtestje1
:/^start of testfile/,/^end of testfile/w! Xtestje2
:/^start of testfile/,/^end of testfile/w! Xtestje3
diff --git a/src/nvim/testdir/test14.in b/src/nvim/testdir/test14.in
index 6ebec99af6..bef2e45431 100644
--- a/src/nvim/testdir/test14.in
+++ b/src/nvim/testdir/test14.in
@@ -5,7 +5,6 @@ Also test "[m", "]m", "[M" and "]M"
Also test search()
STARTTEST
-:so small.vim
/Start cursor here
vaBiBD:?Bug?,/Piece/-2w! test.out
/^- Bug
diff --git a/src/nvim/testdir/test17.in b/src/nvim/testdir/test17.in
index a8c81b832d..83abe17770 100644
--- a/src/nvim/testdir/test17.in
+++ b/src/nvim/testdir/test17.in
@@ -3,7 +3,6 @@ Tests for:
- ":checkpath!" with various 'include' settings.
STARTTEST
-:so small.vim
:set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,}
:function! DeleteDirectory(dir)
: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32")
diff --git a/src/nvim/testdir/test30.in b/src/nvim/testdir/test30.in
index 2a89eac73d..56d5d5c6c2 100644
--- a/src/nvim/testdir/test30.in
+++ b/src/nvim/testdir/test30.in
@@ -3,7 +3,6 @@ Test for a lot of variations of the 'fileformats' option
Note: This test will fail if "cat" is not available.
STARTTEST
-:so small.vim
:" first write three test files, one in each format
:set fileformat=unix
:set fileformats=
diff --git a/src/nvim/testdir/test32.in b/src/nvim/testdir/test32.in
index 1a73c862d1..76bd9be889 100644
--- a/src/nvim/testdir/test32.in
+++ b/src/nvim/testdir/test32.in
@@ -21,7 +21,6 @@ Test for insert expansion
* t-expansion
STARTTEST
-:so small.vim
:se backspace=""
:se cpt=.,w ff=unix | $-2,$w!Xtestfile | set ff&
:se cot=
diff --git a/src/nvim/testdir/test34.in b/src/nvim/testdir/test34.in
index 71ee5f63b2..4cb7e9494a 100644
--- a/src/nvim/testdir/test34.in
+++ b/src/nvim/testdir/test34.in
@@ -4,7 +4,6 @@ Also test that a builtin function cannot be replaced.
Also test for regression when calling arbitrary expression.
STARTTEST
-:so small.vim
:function Table(title, ...)
: let ret = a:title
: let idx = 1
diff --git a/src/nvim/testdir/test37.in b/src/nvim/testdir/test37.in
index 8ca1125793..156bf74a10 100644
--- a/src/nvim/testdir/test37.in
+++ b/src/nvim/testdir/test37.in
@@ -1,6 +1,6 @@
Test for 'scrollbind'. <eralston@computer.org> Do not add a line below!
STARTTEST
-:so small.vim
+:
:set noscrollbind
:set scrollopt=ver,jump
:set scrolloff=2
diff --git a/src/nvim/testdir/test40.in b/src/nvim/testdir/test40.in
index ced4572fb8..b0285709e5 100644
--- a/src/nvim/testdir/test40.in
+++ b/src/nvim/testdir/test40.in
@@ -1,7 +1,6 @@
Test for "*Cmd" autocommands
STARTTEST
-:so small.vim
:set wildchar=^E
:/^start/,$w! Xxx " write lines below to Xxx
:au BufReadCmd XtestA 0r Xxx|$del
diff --git a/src/nvim/testdir/test42.in b/src/nvim/testdir/test42.in
index c35569a76c..0ea0198d12 100644
--- a/src/nvim/testdir/test42.in
+++ b/src/nvim/testdir/test42.in
Binary files differ
diff --git a/src/nvim/testdir/test47.in b/src/nvim/testdir/test47.in
index f15eaf0f8f..c95c6a6850 100644
--- a/src/nvim/testdir/test47.in
+++ b/src/nvim/testdir/test47.in
@@ -3,7 +3,6 @@ Tests for vertical splits and filler lines in diff mode
Also tests restoration of saved options by :diffoff.
STARTTEST
-:so small.vim
:" Disable the title to avoid xterm keeping the wrong one.
:set notitle noicon
/^1
diff --git a/src/nvim/testdir/test48.in b/src/nvim/testdir/test48.in
index 998e1bba00..1df5a3c46a 100644
--- a/src/nvim/testdir/test48.in
+++ b/src/nvim/testdir/test48.in
@@ -1,7 +1,6 @@
This is a test of 'virtualedit'.
STARTTEST
-:so small.vim
:set noswf
:set ve=all
j-dgg
diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in
index d95052e14c..435e62765b 100644
--- a/src/nvim/testdir/test49.in
+++ b/src/nvim/testdir/test49.in
@@ -4,7 +4,6 @@ If after adding a new test, the test output doesn't appear properly in
test49.failed, try to add one or more "G"s at the line ending in "test.out"
STARTTEST
-:so small.vim
:se nomore
:lang mess C
:so test49.vim
diff --git a/src/nvim/testdir/test50.in b/src/nvim/testdir/test50.in
index 0cbf4bf6d6..392177b808 100644
--- a/src/nvim/testdir/test50.in
+++ b/src/nvim/testdir/test50.in
@@ -2,7 +2,6 @@ Test for shortpathname ':8' extension.
Only for use on Win32 systems!
STARTTEST
-:so small.vim
:fun! TestIt(file, bits, expected)
let res=fnamemodify(a:file,a:bits)
if a:expected == ''
diff --git a/src/nvim/testdir/test52.in b/src/nvim/testdir/test52.in
index 206b65a1f9..fa75129193 100644
--- a/src/nvim/testdir/test52.in
+++ b/src/nvim/testdir/test52.in
@@ -1,7 +1,6 @@
Tests for reading and writing files with conversion for Win32.
STARTTEST
-:so mbyte.vim
:" make this a dummy test for non-Win32 systems
:if !has("win32") | e! test.ok | wq! test.out | endif
:"
diff --git a/src/nvim/testdir/test53.in b/src/nvim/testdir/test53.in
index 7c35b2e853..f3778c5192 100644
--- a/src/nvim/testdir/test53.in
+++ b/src/nvim/testdir/test53.in
@@ -7,7 +7,6 @@ Also test match() and matchstr()
Also test the gn command and repeating it.
STARTTEST
-:so small.vim
/^start:/
da"
0va'a'rx
diff --git a/src/nvim/testdir/test55.in b/src/nvim/testdir/test55.in
index 9e3c1168cc..9a55eac6f6 100644
--- a/src/nvim/testdir/test55.in
+++ b/src/nvim/testdir/test55.in
@@ -1,7 +1,6 @@
Tests for List and Dictionary types. vim: set ft=vim :
STARTTEST
-:so small.vim
:fun Test(...)
:lang C
:" Creating List directly with different types
diff --git a/src/nvim/testdir/test64.in b/src/nvim/testdir/test64.in
index fd19d3af32..c4585ecbce 100644
--- a/src/nvim/testdir/test64.in
+++ b/src/nvim/testdir/test64.in
@@ -5,7 +5,6 @@ A pattern that gives the expected result produces OK, so that we know it was
actually tried.
STARTTEST
-:so small.vim
:" tl is a List of Lists with:
:" regexp engine
:" regexp pattern
diff --git a/src/nvim/testdir/test68.in b/src/nvim/testdir/test68.in
deleted file mode 100644
index ca54e942b5..0000000000
--- a/src/nvim/testdir/test68.in
+++ /dev/null
@@ -1,131 +0,0 @@
-Test for text formatting.
-
-Results of test68:
-
-STARTTEST
-:so small.vim
-/^{/+1
-:set noai tw=2 fo=t
-gRa b
-ENDTEST
-
-{
-
-
-}
-
-STARTTEST
-/^{/+1
-:set ai tw=2 fo=tw
-gqgqjjllab
-ENDTEST
-
-{
-a b
-
-a
-}
-
-STARTTEST
-/^{/+1
-:set tw=3 fo=t
-gqgqo
-a 
-ENDTEST
-
-{
-a 
-}
-
-STARTTEST
-/^{/+1
-:set tw=2 fo=tcq1 comments=:#
-gqgqjgqgqo
-a b
-#a b
-ENDTEST
-
-{
-a b
-#a b
-}
-
-STARTTEST
-/^{/+1
-:set tw=5 fo=tcn comments=:#
-A bjA b
-ENDTEST
-
-{
- 1 a
-# 1 a
-}
-
-STARTTEST
-/^{/+3
-:set tw=5 fo=t2a si
-i A_
-ENDTEST
-
-{
-
- x a
- b
- c
-
-}
-
-STARTTEST
-/^{/+1
-:set tw=5 fo=qn comments=:#
-gwap
-ENDTEST
-
-{
-# 1 a b
-}
-
-STARTTEST
-/^{/+1
-:set tw=5 fo=q2 comments=:#
-gwap
-ENDTEST
-
-{
-# x
-# a b
-}
-
-STARTTEST
-/^{/+2
-:set tw& fo=a
-I^^
-ENDTEST
-
-{
- 1aa
- 2bb
-}
-
-STARTTEST
-/mno pqr/
-:setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/
-A vwx yz
-ENDTEST
-
-/* abc def ghi jkl
- * mno pqr stu
- */
-
-STARTTEST
-/^#/
-:setl tw=12 fo=tqnc comments=:#
-A foobar
-ENDTEST
-
-# 1 xxxxx
-
-STARTTEST
-:g/^STARTTEST/.,/^ENDTEST/d
-:1;/^Results/,$wq! test.out
-ENDTEST
diff --git a/src/nvim/testdir/test68.ok b/src/nvim/testdir/test68.ok
deleted file mode 100644
index b3726a0a27..0000000000
--- a/src/nvim/testdir/test68.ok
+++ /dev/null
@@ -1,77 +0,0 @@
-Results of test68:
-
-
-{
-a
-b
-}
-
-
-{
-a
-b
-
-a
-b
-}
-
-
-{
-a
-
-
-a
-
-}
-
-
-{
-a b
-#a b
-
-a b
-#a b
-}
-
-
-{
- 1 a
- b
-# 1 a
-# b
-}
-
-
-{
-
- x a
- b_
- c
-
-}
-
-
-{
-# 1 a
-# b
-}
-
-
-{
-# x a
-# b
-}
-
-
-{ 1aa ^^2bb }
-
-
-/* abc def ghi jkl
- * mno pqr stu
- * vwx yz
- */
-
-
-# 1 xxxxx
-# foobar
-
diff --git a/src/nvim/testdir/test69.in b/src/nvim/testdir/test69.in
index f583947dfb..39b360fc81 100644
--- a/src/nvim/testdir/test69.in
+++ b/src/nvim/testdir/test69.in
@@ -4,7 +4,7 @@ And test "ra" on multi-byte characters.
Also test byteidx() and byteidxcomp()
STARTTEST
-:so mbyte.vim
+:
ENDTEST
Results of test69:
diff --git a/src/nvim/testdir/test73.in b/src/nvim/testdir/test73.in
index c525e51d28..7d6c7287a5 100644
--- a/src/nvim/testdir/test73.in
+++ b/src/nvim/testdir/test73.in
@@ -1,7 +1,6 @@
Tests for find completion.
STARTTEST
-:so small.vim
:set wildmode=full
:" Do all test in a separate window to avoid E211 when we recursively
:" delete the Xfind directory during cleanup
diff --git a/src/nvim/testdir/test8.in b/src/nvim/testdir/test8.in
index 41e6262e92..a5e6034782 100644
--- a/src/nvim/testdir/test8.in
+++ b/src/nvim/testdir/test8.in
@@ -2,7 +2,6 @@ Test for BufWritePre autocommand that deletes or unloads the buffer.
Test for BufUnload autocommand that unloads all other buffers.
STARTTEST
-:so small.vim
:au BufWritePre Xxx1 bunload
:au BufWritePre Xxx2 bwipe
/^start of
@@ -35,8 +34,6 @@ endfunc
:set shada='100
:au BufUnload * call CloseAll()
:au VimLeave * call WriteToOut()
-:e small.vim
-:sp mbyte.vim
:q
:qa!
ENDTEST
diff --git a/src/nvim/testdir/test_breakindent.in b/src/nvim/testdir/test_breakindent.in
deleted file mode 100644
index 5a8e580c4a..0000000000
--- a/src/nvim/testdir/test_breakindent.in
+++ /dev/null
@@ -1,123 +0,0 @@
-Test for breakindent
-
-STARTTEST
-:so small.vim
-:if !exists("+breakindent") | e! test.ok | w! test.out | qa! | endif
-:set wildchar=^E
-:10new|:vsp|:vert resize 20
-:put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"
-:set ts=4 sw=4 sts=4 breakindent
-:fu! ScreenChar(line, width)
-: let c=''
-: for i in range(1,a:width)
-: let c.=nr2char(screenchar(a:line, i))
-: endfor
-: let c.="\n"
-: for i in range(1,a:width)
-: let c.=nr2char(screenchar(a:line+1, i))
-: endfor
-: let c.="\n"
-: for i in range(1,a:width)
-: let c.=nr2char(screenchar(a:line+2, i))
-: endfor
-: return c
-:endfu
-:fu DoRecordScreen()
-: wincmd l
-: $put =printf(\"\n%s\", g:test)
-: $put =g:line1
-: wincmd p
-:endfu
-:set briopt=min:0
-:let g:test="Test 1: Simple breakindent"
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test="Test 2: Simple breakindent + sbr=>>"
-:set sbr=>>
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test ="Test 3: Simple breakindent + briopt:sbr"
-:set briopt=sbr,min:0 sbr=++
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test ="Test 4: Simple breakindent + min width: 18"
-:set sbr= briopt=min:18
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test =" Test 5: Simple breakindent + shift by 2"
-:set briopt=shift:2,min:0
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test=" Test 6: Simple breakindent + shift by -1"
-:set briopt=shift:-1,min:0
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"
-:set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4
-:let line1=ScreenChar(line('.'),10)
-:call DoRecordScreen()
-:let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"
-:set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi
-:let line1=ScreenChar(line('.'),10)
-:call DoRecordScreen()
-:let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"
-:set briopt-=sbr
-:let line1=ScreenChar(line('.'),10)
-:call DoRecordScreen()
-:let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"
-:set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0
-:let line1=ScreenChar(line('.'),10)
-:call DoRecordScreen()
-:wincmd p
-:let g:test="\n Test 11: strdisplaywidth when breakindent is on"
-:set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4
-:let text=getline(2) "skip leading tab when calculating text width
-:let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3 " text wraps 3 times
-:$put =g:test
-:$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)
-:let g:str="\t\t\t\t\t{"
-:let g:test=" Test 12: breakindent + long indent"
-:wincmd p
-:set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4
-:$put =g:str
-zt:let line1=ScreenChar(1,10)
-:wincmd p
-:call DoRecordScreen()
-:"
-:" Test, that the string " a\tb\tc\td\te" is correctly
-:" displayed in a 20 column wide window (see bug report
-:" https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ
-:only
-:vert 20new
-:set all& breakindent briopt=min:10
-:call setline(1, [" a\tb\tc\td\te", " z y x w v"])
-:/^\s*a
-fbgjyl:let line1 = @0
-:?^\s*z
-fygjyl:let line2 = @0
-:quit!
-:$put ='Test 13: breakindent with wrapping Tab'
-:$put =line1
-:$put =line2
-:"
-:let g:test="Test 14: breakindent + visual blockwise delete #1"
-:set all& breakindent shada+=nX-test-breakindent.shada
-:30vnew
-:normal! 3a1234567890
-:normal! a abcde
-:exec "normal! 0\<C-V>tex"
-:let line1=ScreenChar(line('.'),8)
-:call DoRecordScreen()
-:"
-:let g:test="Test 15: breakindent + visual blockwise delete #2"
-:%d
-:normal! 4a1234567890
-:exec "normal! >>\<C-V>3f0x"
-:let line1=ScreenChar(line('.'),20)
-:call DoRecordScreen()
-:quit!
-:"
-:%w! test.out
-:qa!
-ENDTEST
-dummy text
diff --git a/src/nvim/testdir/test_breakindent.ok b/src/nvim/testdir/test_breakindent.ok
deleted file mode 100644
index 995bd5f29c..0000000000
--- a/src/nvim/testdir/test_breakindent.ok
+++ /dev/null
@@ -1,74 +0,0 @@
-
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
-
-Test 1: Simple breakindent
- abcd
- qrst
- GHIJ
-
-Test 2: Simple breakindent + sbr=>>
- abcd
- >>qr
- >>EF
-
-Test 3: Simple breakindent + briopt:sbr
- abcd
-++ qrst
-++ GHIJ
-
-Test 4: Simple breakindent + min width: 18
- abcd
- qrstuv
- IJKLMN
-
- Test 5: Simple breakindent + shift by 2
- abcd
- qr
- EF
-
- Test 6: Simple breakindent + shift by -1
- abcd
- qrstu
- HIJKL
-
- Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr
- 2 ab
- ? m
- ? x
-
- Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr
- 2 ^Iabcd
- # opq
- # BCD
-
- Test 9: breakindent + shift by +1 + 'nu' + sbr=# list
- 2 ^Iabcd
- #op
- #AB
-
- Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n
- 2 ab
-~ mn
-~ yz
-
- Test 11: strdisplaywidth when breakindent is on
-strdisplaywidth: 46 == calculated: 64
- {
-
- Test 12: breakindent + long indent
-56
-
-~
-Test 13: breakindent with wrapping Tab
-d
-w
-
-Test 14: breakindent + visual blockwise delete #1
-e
-~
-~
-
-Test 15: breakindent + visual blockwise delete #2
- 1234567890
-~
-~
diff --git a/src/nvim/testdir/test_close_count.in b/src/nvim/testdir/test_close_count.in
deleted file mode 100644
index 58dfb425ce..0000000000
--- a/src/nvim/testdir/test_close_count.in
+++ /dev/null
@@ -1,156 +0,0 @@
-Tests for :[count]close! and :[count]hide vim: set ft=vim :
-
-STARTTEST
-:let tests = []
-:so tiny.vim
-:for i in range(5)
-:new
-:endfor
-:4wincmd w
-:close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:$close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-:2close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-:new
-:new
-:2wincmd w
-:-1close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:2wincmd w
-:+1close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:e! test.out
-:call append(0, map(copy(tests), 'join(v:val, " ")'))
-:w
-:only!
-:b1
-ENDTEST
-
-STARTTEST
-:let tests = []
-:so tiny.vim
-:for i in range(5)
-:new
-:endfor
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:4wincmd w
-:.hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:$hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-:2hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-:new
-:new
-:3wincmd w
-:-hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:2wincmd w
-:+hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:e! test.out
-:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
-Go
-:w
-:only!
-:b1
-ENDTEST
-
-STARTTEST
-:let tests = []
-:so tiny.vim
-:set hidden
-:for i in range(5)
-:new
-:endfor
-:1wincmd w
-:$ hide
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:$-1 close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-:.+close!
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:e! test.out
-:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
-Go
-:w
-:only!
-:b1
-ENDTEST
-
-STARTTEST
-:let tests = []
-:so tiny.vim
-:set hidden
-:for i in range(5)
-:new
-:endfor
-:4wincmd w
-c
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-1c
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-9c
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:1wincmd w
-2c
-:let buffers = []
-:windo call add(buffers, bufnr('%'))
-:call add(tests, buffers)
-:only!
-:e! test.out
-:call append(line('$'), map(copy(tests), 'join(v:val, " ")'))
-:w
-:qa!
-ENDTEST
-
-
diff --git a/src/nvim/testdir/test_close_count.ok b/src/nvim/testdir/test_close_count.ok
deleted file mode 100644
index 1cee870487..0000000000
--- a/src/nvim/testdir/test_close_count.ok
+++ /dev/null
@@ -1,23 +0,0 @@
-6 5 4 2 1
-5 4 2 1
-5 4 2
-5 2
-7 5 2
-7 5
-
-13 12 11 10 9 1
-13 12 11 9 1
-12 11 9 1
-12 11 9
-12 9
-15 12 9
-15 12
-
-20 19 18 17 16
-20 19 18 16
-20 18 16
-
-25 24 23 21 1
-24 23 21 1
-24 23 21
-24 21
diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim
new file mode 100644
index 0000000000..9f9207d27d
--- /dev/null
+++ b/src/nvim/testdir/test_help_tagjump.vim
@@ -0,0 +1,40 @@
+" Tests for :help! {subject}
+
+func SetUp()
+ " v:progpath is …/build/bin/nvim and we need …/build/runtime
+ " to be added to &rtp
+ let builddir = fnamemodify(exepath(v:progpath), ':h:h')
+ let s:rtp = &rtp
+ let &rtp .= printf(',%s/runtime', builddir)
+endfunc
+
+func TearDown()
+ let &rtp = s:rtp
+endfunc
+
+func Test_help_tagjump()
+ help
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ '\*help.txt\*')
+ helpclose
+
+ exec "help! ('textwidth'"
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ "\\*'textwidth'\\*")
+ helpclose
+
+ exec "help! ('buflisted'),"
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ "\\*'buflisted'\\*")
+ helpclose
+
+ exec "help! abs({expr})"
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ '\*abs()\*')
+ helpclose
+
+ exec "help! arglistid([{winnr})"
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ '\*arglistid()\*')
+ helpclose
+endfunc
diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in
index 6084711786..b5bac080ee 100644
--- a/src/nvim/testdir/test_listlbr.in
+++ b/src/nvim/testdir/test_listlbr.in
@@ -1,7 +1,6 @@
Test for linebreak and list option (non-utf8)
STARTTEST
-:so small.vim
:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif
:set wildchar=^E
:10new|:vsp|:vert resize 20
diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim
new file mode 100644
index 0000000000..be559467c8
--- /dev/null
+++ b/src/nvim/testdir/test_menu.vim
@@ -0,0 +1,9 @@
+" Test that the system menu can be loaded.
+
+func Test_load_menu()
+ try
+ source $VIMRUNTIME/menu.vim
+ catch
+ call assert_false(1, 'error while loading menus: ' . v:exception)
+ endtry
+endfunc
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index e1c0407b27..62bc81ba64 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -81,7 +81,7 @@ UI *tui_start(void)
{
UI *ui = xcalloc(1, sizeof(UI));
ui->stop = tui_stop;
- ui->rgb = os_getenv("NVIM_TUI_ENABLE_TRUE_COLOR") != NULL;
+ ui->rgb = p_tgc;
ui->resize = tui_resize;
ui->clear = tui_clear;
ui->eol_clear = tui_eol_clear;
@@ -100,6 +100,7 @@ UI *tui_start(void)
ui->visual_bell = tui_visual_bell;
ui->update_fg = tui_update_fg;
ui->update_bg = tui_update_bg;
+ ui->update_sp = tui_update_sp;
ui->flush = tui_flush;
ui->suspend = tui_suspend;
ui->set_title = tui_set_title;
@@ -573,6 +574,11 @@ static void tui_update_bg(UI *ui, int bg)
((TUIData *)ui->data)->grid.bg = bg;
}
+static void tui_update_sp(UI *ui, int sp)
+{
+ // Do nothing; 'special' color is for GUI only
+}
+
static void tui_flush(UI *ui)
{
TUIData *data = ui->data;
diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h
index df51e1fced..ad6d96a168 100644
--- a/src/nvim/ugrid.h
+++ b/src/nvim/ugrid.h
@@ -21,7 +21,7 @@ struct ugrid {
UCell **cells;
};
-#define EMPTY_ATTRS ((HlAttrs){false, false, false, false, false, -1, -1})
+#define EMPTY_ATTRS ((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
#define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \
do { \
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index d32969f149..05322a6f64 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -155,6 +155,7 @@ void ui_resize(int new_width, int new_height)
UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1));
UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1));
+ UI_CALL(update_sp, (ui->rgb ? normal_sp : -1));
sr.top = 0;
sr.bot = height - 1;
@@ -388,7 +389,7 @@ static void parse_control_character(uint8_t c)
static void set_highlight_args(int attr_code)
{
- HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 };
+ HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1, -1 };
HlAttrs cterm_attrs = rgb_attrs;
if (attr_code == HL_NORMAL) {
@@ -425,6 +426,10 @@ static void set_highlight_args(int attr_code)
rgb_attrs.background = aep->rgb_bg_color;
}
+ if (aep->rgb_sp_color != normal_sp) {
+ rgb_attrs.special = aep->rgb_sp_color;
+ }
+
if (cterm_normal_fg_color != aep->cterm_fg_color) {
cterm_attrs.foreground = aep->cterm_fg_color - 1;
}
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 4c051fcfbf..5934d2fee9 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -7,7 +7,7 @@
typedef struct {
bool bold, underline, undercurl, italic, reverse;
- int foreground, background;
+ int foreground, background, special;
} HlAttrs;
typedef struct ui_t UI;
@@ -35,6 +35,7 @@ struct ui_t {
void (*flush)(UI *ui);
void (*update_fg)(UI *ui, int fg);
void (*update_bg)(UI *ui, int bg);
+ void (*update_sp)(UI *ui, int sp);
void (*suspend)(UI *ui);
void (*set_title)(UI *ui, char *title);
void (*set_icon)(UI *ui, char *icon);
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 359fffe3bf..fd9d4671e3 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -49,6 +49,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
rv->bridge.visual_bell = ui_bridge_visual_bell;
rv->bridge.update_fg = ui_bridge_update_fg;
rv->bridge.update_bg = ui_bridge_update_bg;
+ rv->bridge.update_sp = ui_bridge_update_sp;
rv->bridge.flush = ui_bridge_flush;
rv->bridge.suspend = ui_bridge_suspend;
rv->bridge.set_title = ui_bridge_set_title;
@@ -305,6 +306,16 @@ static void ui_bridge_update_bg_event(void **argv)
ui->update_bg(ui, PTR2INT(argv[1]));
}
+static void ui_bridge_update_sp(UI *b, int sp)
+{
+ UI_CALL(b, update_sp, 2, b, INT2PTR(sp));
+}
+static void ui_bridge_update_sp_event(void **argv)
+{
+ UI *ui = UI(argv[0]);
+ ui->update_sp(ui, PTR2INT(argv[1]));
+}
+
static void ui_bridge_flush(UI *b)
{
UI_CALL(b, flush, 1, b);
diff --git a/src/nvim/version.c b/src/nvim/version.c
index d7e75ee26e..c19e1b01c2 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -69,9 +69,15 @@ static char *features[] = {
// clang-format off
static int included_patches[] = {
+ 1832,
+ 1809,
+ 1808,
+ 1806,
+ 1799,
1757,
1755,
1753,
+ 1728,
1654,
1652,
1643,
@@ -107,10 +113,10 @@ static int included_patches[] = {
1574,
// 1573,
// 1572 NA
- // 1571,
+ 1571,
1570,
1569,
- // 1568,
+ 1568,
// 1567,
// 1566 NA
// 1565,
@@ -157,15 +163,15 @@ static int included_patches[] = {
// 1524 NA
// 1523 NA
// 1522 NA
- // 1521,
+ 1521,
// 1520 NA
// 1519 NA
// 1518 NA
// 1517 NA
- // 1516,
+ 1516,
// 1515 NA
// 1514 NA
- // 1513,
+ 1513,
// 1512 NA
1511,
// 1510 NA
@@ -419,7 +425,7 @@ static int included_patches[] = {
// 1262 NA
// 1261 NA
// 1260 NA
- // 1259,
+ 1259,
// 1258 NA
// 1257 NA
// 1256 NA
@@ -568,7 +574,7 @@ static int included_patches[] = {
1113,
1112,
// 1111,
- // 1110,
+ 1110,
// 1109 NA
// 1108,
1107,
@@ -576,7 +582,7 @@ static int included_patches[] = {
1105,
// 1104 NA
// 1103 NA
- // 1102,
+ 1102,
1101,
// 1100 NA
// 1099 NA
@@ -607,32 +613,32 @@ static int included_patches[] = {
// 1074 NA,
// 1073,
1072,
- // 1071,
+ 1071,
// 1070 NA
// 1069 NA
// 1068,
// 1067 NA
// 1066 NA
1065,
- // 1064,
+ 1064,
// 1063 NA
// 1062 NA
- // 1061,
+ 1061,
// 1060 NA
- // 1059,
+ 1059,
// 1058,
- // 1057,
+ 1057,
// 1056,
1055,
- // 1054,
- // 1053,
- // 1052,
+ 1054,
+ 1053,
+ 1052,
// 1051,
- // 1050,
- // 1049,
- // 1048,
- // 1047,
- // 1046,
+ 1050,
+ 1049,
+ 1048,
+ 1047,
+ 1046,
// 1045 NA
// 1044 NA
// 1043 NA
@@ -641,10 +647,10 @@ static int included_patches[] = {
// 1040 NA
// 1039,
// 1038 NA
- // 1037,
- // 1036,
+ 1037,
+ 1036,
1035,
- // 1034,
+ 1034,
// 1033 NA
1032,
// 1031 NA,
@@ -660,8 +666,8 @@ static int included_patches[] = {
// 1021 NA
// 1020 NA
// 1019 NA
- // 1018,
- // 1017,
+ 1018,
+ 1017,
// 1016 NA
1015,
// 1014 NA
@@ -807,7 +813,7 @@ static int included_patches[] = {
// 874 NA
// 873 NA
// 872 NA
- // 871,
+ 871,
870,
// 869 NA
868,