diff options
Diffstat (limited to 'src')
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 ? ¤t_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 = ¤t_funccal->l_avars; + *d = &get_funccal()->l_avars; } else if (*name == 'l' && current_funccal != NULL) { // local variable - *d = ¤t_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, ®match, 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 Binary files differindex c35569a76c..0ea0198d12 100644 --- a/src/nvim/testdir/test42.in +++ b/src/nvim/testdir/test42.in 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, |