diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/nvim/assert.h | 9 | ||||
-rw-r--r-- | src/nvim/eval.c | 29 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 15 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 135 | ||||
-rw-r--r-- | src/nvim/globals.h | 10 | ||||
-rw-r--r-- | src/nvim/message.c | 107 | ||||
-rw-r--r-- | src/nvim/misc2.c | 5 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/remote_ui.c | 12 | ||||
-rw-r--r-- | src/nvim/option.c | 19 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 3 | ||||
-rw-r--r-- | src/nvim/screen.c | 54 | ||||
-rw-r--r-- | src/nvim/syntax.c | 89 | ||||
-rw-r--r-- | src/nvim/syntax_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.in | 123 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.ok | 74 | ||||
-rw-r--r-- | src/nvim/testdir/test_menu.vim | 9 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 6 | ||||
-rw-r--r-- | src/nvim/ugrid.h | 2 | ||||
-rw-r--r-- | src/nvim/ui.c | 7 | ||||
-rw-r--r-- | src/nvim/ui.h | 3 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 11 | ||||
-rw-r--r-- | src/nvim/version.c | 21 |
24 files changed, 387 insertions, 363 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 6b2ce08d36..172643091a 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -231,7 +231,6 @@ endif() list(APPEND NVIM_LINK_LIBRARIES ${LIBUV_LIBRARIES} ${MSGPACK_LIBRARIES} - ${LUAJIT_LIBRARIES} ${LIBVTERM_LIBRARIES} ${LIBTERMKEY_LIBRARIES} ${UNIBILIUM_LIBRARIES} 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 712ee06b85..201a71facb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -18123,6 +18123,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) @@ -18147,7 +18166,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; } @@ -18169,9 +18192,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; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 415d6ee460..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. diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index df387f9a60..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". */ 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/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/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/syntax.c b/src/nvim/syntax.c index b04180ad1c..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 @@ -6169,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); @@ -6370,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]; } } } @@ -6456,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 { @@ -6520,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; @@ -6536,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)); } @@ -6552,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; + } } @@ -6601,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; } } @@ -6639,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; } @@ -6700,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); } @@ -6737,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); @@ -6851,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) @@ -6939,11 +6965,16 @@ 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; + 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.cterm_ae_attr != 0 || at_en.rgb_ae_attr != 0) { + || 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; } } @@ -7275,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 7195c7e632..90542a6a6c 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -32,7 +32,6 @@ SCRIPTS := \ test73.out \ test79.out \ test_listlbr.out \ - test_breakindent.out \ test_close_count.out \ test_marks.out \ @@ -41,6 +40,7 @@ SCRIPTS := \ NEW_TESTS = \ test_cursor_func.res \ test_help_tagjump.res \ + test_menu.res \ test_viml.res \ test_alot.res 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_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 202c5666a1..62bc81ba64 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -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 af8b3b3fde..3134b10108 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -69,6 +69,7 @@ static char *features[] = { // clang-format off static int included_patches[] = { + 1832, 1809, 1808, 1806, @@ -573,7 +574,7 @@ static int included_patches[] = { 1113, 1112, // 1111, - // 1110, + 1110, // 1109 NA // 1108, 1107, @@ -581,7 +582,7 @@ static int included_patches[] = { 1105, // 1104 NA // 1103 NA - // 1102, + 1102, 1101, // 1100 NA // 1099 NA @@ -622,11 +623,11 @@ static int included_patches[] = { // 1064, // 1063 NA // 1062 NA - // 1061, + 1061, // 1060 NA - // 1059, + 1059, // 1058, - // 1057, + 1057, // 1056, 1055, 1054, @@ -637,7 +638,7 @@ static int included_patches[] = { 1049, 1048, 1047, - // 1046, + 1046, // 1045 NA // 1044 NA // 1043 NA @@ -647,9 +648,9 @@ static int included_patches[] = { // 1039, // 1038 NA 1037, - // 1036, + 1036, 1035, - // 1034, + 1034, // 1033 NA 1032, // 1031 NA, @@ -665,8 +666,8 @@ static int included_patches[] = { // 1021 NA // 1020 NA // 1019 NA - // 1018, - // 1017, + 1018, + 1017, // 1016 NA 1015, // 1014 NA |