diff options
author | Matthieu Coudron <mattator@gmail.com> | 2020-04-13 22:49:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-13 22:49:00 +0200 |
commit | 93b2cb7a3824f91ee24ddf57406d5682699f684b (patch) | |
tree | 4ea7bb4aca7520a26a749b0958046ba52b450d4f /src | |
parent | 13b4a6fd4fa67794e76892cb362121a33a756f58 (diff) | |
parent | cf223e7d78df5e8a63b84d423be55a29eefd8883 (diff) | |
download | rneovim-93b2cb7a3824f91ee24ddf57406d5682699f684b.tar.gz rneovim-93b2cb7a3824f91ee24ddf57406d5682699f684b.tar.bz2 rneovim-93b2cb7a3824f91ee24ddf57406d5682699f684b.zip |
Merge pull request #11997 from janlazo/vim-8.1.2389
[RDY]vim-patch:8.1.{1745,2147,2280,2282,},8.2.{41,134,365,366,381,387,389,397,398,406,415,457,464,473,474,507,544,549}
Diffstat (limited to 'src')
29 files changed, 534 insertions, 170 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 7578f0fbc5..b345dcaccd 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1402,7 +1402,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, uint64_t ns_id = src2ns(&src_id); - if (!(0 <= line && line < buf->b_ml.ml_line_count)) { + if (!(line < buf->b_ml.ml_line_count)) { // safety check, we can't add marks outside the range return src_id; } diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c2573cf942..24ba43676a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1750,6 +1750,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, false, curbuf); } if (aborting()) { // autocmds may abort script processing + xfree(ffname); return NULL; } if (buf == curbuf) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index dc20940166..12b13a1f08 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6328,6 +6328,10 @@ call_func( } if (error == ERROR_NONE && partial->pt_argc > 0) { for (argv_clear = 0; argv_clear < partial->pt_argc; argv_clear++) { + if (argv_clear + argcount_in >= MAX_FUNC_ARGS) { + error = ERROR_TOOMANY; + goto theend; + } tv_copy(&partial->pt_argv[argv_clear], &argv[argv_clear]); } for (int i = 0; i < argcount_in; i++) { @@ -6382,7 +6386,9 @@ call_func( error = ERROR_DELETED; } else if (fp != NULL) { if (argv_func != NULL) { - argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); + // postponed filling in the arguments, do it now + argcount = argv_func(argcount, argvars, argv_clear, + fp->uf_args.ga_len); } if (fp->uf_flags & FC_RANGE) { *doesrange = true; @@ -6430,10 +6436,9 @@ call_func( if (error == ERROR_NONE) ret = OK; - /* - * Report an error unless the argument evaluation or function call has been - * cancelled due to an aborting error, an interrupt, or an exception. - */ +theend: + // Report an error unless the argument evaluation or function call has been + // cancelled due to an aborting error, an interrupt, or an exception. if (!aborting()) { switch (error) { case ERROR_UNKNOWN: @@ -7130,6 +7135,10 @@ void common_function(typval_T *argvars, typval_T *rettv, list = argvars[arg_idx].vval.v_list; if (tv_list_len(list) == 0) { arg_idx = 0; + } else if (tv_list_len(list) > MAX_FUNC_ARGS) { + emsg_funcname((char *)e_toomanyarg, name); + xfree(name); + goto theend; } } } @@ -9527,7 +9536,8 @@ dictitem_T *find_var(const char *const name, const size_t name_len, return find_var_in_scoped_ht(name, name_len, no_autoload || htp != NULL); } -/// Find variable in hashtab +/// Find variable in hashtab. +/// When "varname" is empty returns curwin/curtab/etc vars dictionary. /// /// @param[in] ht Hashtab to find variable in. /// @param[in] htname Hashtab name (first character). diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 918823c311..7606d16f5d 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -187,7 +187,7 @@ extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1]; #undef LAST_MSGPACK_TYPE -typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, +typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip, int called_func_argcount); /// trans_function_name() flags diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8800e02295..21a6904674 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2807,11 +2807,12 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf != NULL && varname != NULL) { - // set curbuf to be our buf, temporarily - buf_T *const save_curbuf = curbuf; - curbuf = buf; - if (*varname == '&') { // buffer-local-option + buf_T *const save_curbuf = curbuf; + + // set curbuf to be our buf, temporarily + curbuf = buf; + if (varname[1] == NUL) { // get all buffer-local options in a dict dict_T *opts = get_winbuf_options(true); @@ -2824,19 +2825,21 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // buffer-local-option done = true; } + + // restore previous notion of curbuf + curbuf = save_curbuf; } else { // Look up the variable. // Let getbufvar({nr}, "") return the "b:" dictionary. - dictitem_T *const v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 'b', - varname, strlen(varname), false); + dictitem_T *const v = *varname == NUL + ? (dictitem_T *)&buf->b_bufvar + : find_var_in_ht(&buf->b_vars->dv_hashtab, 'b', + varname, strlen(varname), false); if (v != NULL) { tv_copy(&v->di_tv, rettv); done = true; } } - - // restore previous notion of curbuf - curbuf = save_curbuf; } emsg_off--; @@ -5648,8 +5651,11 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char grpbuf[NUMBUFLEN]; char patbuf[NUMBUFLEN]; + // group const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf); + // pattern const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); + // default priority int prio = 10; int id = -1; bool error = false; @@ -7821,10 +7827,9 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // reset notion of buffer aucmd_restbuf(&aco); } else { - buf_T *save_curbuf = curbuf; - const size_t varname_len = STRLEN(varname); char *const bufvarname = xmalloc(varname_len + 3); + buf_T *const save_curbuf = curbuf; curbuf = buf; memcpy(bufvarname, "b:", 2); memcpy(bufvarname + 2, varname, varname_len + 1); diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index e77b556024..38d111f2aa 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -789,7 +789,7 @@ bool decorations_redraw_start(buf_T *buf, int top_row, ExtmarkItem *item = map_ref(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id, false); if ((!(mark.id&MARKTREE_END_FLAG) && altpos.row < top_row - && !kv_size(item->virt_text)) + && item && !kv_size(item->virt_text)) || ((mark.id&MARKTREE_END_FLAG) && altpos.row >= top_row)) { goto next_mark; } @@ -854,7 +854,7 @@ int decorations_redraw_col(buf_T *buf, int col, DecorationRedrawState *state) if (endpos.row < mark.row || (endpos.row == mark.row && endpos.col <= mark.col)) { - if (!kv_size(item->virt_text)) { + if (item && !kv_size(item->virt_text)) { goto next_mark; } } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index e5845e0749..88e9390c65 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -407,11 +407,27 @@ readfile( if (newfile) { if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname, - FALSE, curbuf, eap)) - return aborting() ? FAIL : OK; + false, curbuf, eap)) { + int status = OK; + + if (aborting()) { + status = FAIL; + } + + // The BufReadCmd code usually uses ":read" to get the text and + // perhaps ":file" to change the buffer name. But we should + // consider this to work like ":edit", thus reset the + // BF_NOTEDITED flag. Then ":write" will work to overwrite the + // same file. + if (status == OK) { + curbuf->b_flags &= ~BF_NOTEDITED; + } + return status; + } } else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname, - FALSE, NULL, eap)) + false, NULL, eap)) { return aborting() ? FAIL : OK; + } curbuf->b_op_start = pos; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index be131f7e00..aca27e0208 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -615,7 +615,9 @@ static void normal_redraw_mode_message(NormalState *s) kmsg = keep_msg; keep_msg = NULL; - // showmode() will clear keep_msg, but we want to use it anyway + // Showmode() will clear keep_msg, but we want to use it anyway. + // First update w_topline. + setcursor(); update_screen(0); // now reset it, otherwise it's put in the history again keep_msg = kmsg; @@ -623,6 +625,7 @@ static void normal_redraw_mode_message(NormalState *s) xfree(kmsg); } setcursor(); + ui_cursor_shape(); // show different cursor shape ui_flush(); if (msg_scroll || emsg_on_display) { os_delay(1000L, true); // wait at least one second diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 5457400b76..a70224f98b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -261,7 +261,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount) sprintf((char *)IObuff, _("%" PRId64 " lines %sed %d times"), (int64_t)oap->line_count, s, amount); } - msg(IObuff); + msg_attr_keep(IObuff, 0, true, false); } /* diff --git a/src/nvim/option.c b/src/nvim/option.c index 43a4a9fdf9..86a7d9b3c2 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3668,7 +3668,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) } // first round: check for valid value, second round: assign values - for (round = 0; round <= set ? 1 : 0; round++) { + for (round = 0; round <= (set ? 1 : 0); round++) { if (round > 0) { // After checking that the value is valid: set defaults for (i = 0; i < entries; i++) { @@ -3843,11 +3843,12 @@ static char_u *did_set_spell_option(bool is_spellfile) * Return error message when failed, NULL when OK. */ static char_u *compile_cap_prog(synblock_T *synblock) + FUNC_ATTR_NONNULL_ALL { regprog_T *rp = synblock->b_cap_prog; char_u *re; - if (*synblock->b_p_spc == NUL) { + if (synblock->b_p_spc == NULL || *synblock->b_p_spc == NUL) { synblock->b_cap_prog = NULL; } else { // Prepend a ^ so that we only match at one column diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index c444326533..484168e798 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -5134,6 +5134,7 @@ theend: // Restore current working directory to "dirname_start" if they differ, taking // into account whether it is set locally or globally. static void restore_start_dir(char_u *dirname_start) + FUNC_ATTR_NONNULL_ALL { char_u *dirname_now = xmalloc(MAXPATHL); @@ -5251,8 +5252,29 @@ load_dummy_buffer ( // directory to "dirname_start" prior to returning, if autocmds or the // 'autochdir' option have changed it. static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start) + FUNC_ATTR_NONNULL_ALL { - if (curbuf != buf) { // safety check + // If any autocommand opened a window on the dummy buffer, close that + // window. If we can't close them all then give up. + while (buf->b_nwindows > 0) { + bool did_one = false; + + if (firstwin->w_next != NULL) { + for (win_T *wp = firstwin; wp != NULL; wp = wp->w_next) { + if (wp->w_buffer == buf) { + if (win_close(wp, false) == OK) { + did_one = true; + } + break; + } + } + } + if (!did_one) { + return; + } + } + + if (curbuf != buf && buf->b_nwindows == 0) { // safety check cleanup_T cs; // Reset the error/interrupt/exception state here so that aborting() diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 90dc8ab90f..5ad7ce9a16 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -6491,20 +6491,24 @@ typedef struct { static regsubmatch_T rsm; // can only be used when can_f_submatch is true -/// Put the submatches in "argv[0]" which is a list passed into call_func() by -/// vim_regsub_both(). -static int fill_submatch_list(int argc, typval_T *argv, int argcount) +/// Put the submatches in "argv[argskip]" which is a list passed into +/// call_func() by vim_regsub_both(). +static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, + int argskip, int argcount) + FUNC_ATTR_NONNULL_ALL { - if (argcount == 0) { - // called function doesn't take an argument - return 0; + typval_T *listarg = argv + argskip; + + if (argcount == argskip) { + // called function doesn't take a submatches argument + return argskip; } // Relies on sl_list to be the first item in staticList10_T. - tv_list_init_static10((staticList10_T *)argv->vval.v_list); + tv_list_init_static10((staticList10_T *)listarg->vval.v_list); // There are always 10 list items in staticList10_T. - listitem_T *li = tv_list_first(argv->vval.v_list); + listitem_T *li = tv_list_first(listarg->vval.v_list); for (int i = 0; i < 10; i++) { char_u *s = rsm.sm_match->startp[i]; if (s == NULL || rsm.sm_match->endp[i] == NULL) { @@ -6516,7 +6520,7 @@ static int fill_submatch_list(int argc, typval_T *argv, int argcount) TV_LIST_ITEM_TV(li)->vval.v_string = s; li = TV_LIST_ITEM_NEXT(argv->vval.v_list, li); } - return 1; + return argskip + 1; } static void clear_submatch_list(staticList10_T *sl) @@ -6679,10 +6683,15 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, // fill_submatch_list() was called. clear_submatch_list(&matchList); } - char buf[NUMBUFLEN]; - eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf); - if (eval_result != NULL) { - eval_result = vim_strsave(eval_result); + if (rettv.v_type == VAR_UNKNOWN) { + // something failed, no need to report another error + eval_result = NULL; + } else { + char buf[NUMBUFLEN]; + eval_result = (char_u *)tv_get_string_buf_chk(&rettv, buf); + if (eval_result != NULL) { + eval_result = vim_strsave(eval_result); + } } tv_clear(&rettv); } else { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 5e303b0a47..9c590efdbc 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2220,7 +2220,6 @@ win_line ( int tocol = MAXCOL; // end of inverting int fromcol_prev = -2; // start of inverting after cursor bool noinvcur = false; // don't invert the cursor - pos_T *top, *bot; int lnum_in_visual_area = false; pos_T pos; long v; @@ -2420,6 +2419,8 @@ win_line ( // handle Visual active in this window if (VIsual_active && wp->w_buffer == curwin->w_buffer) { + pos_T *top, *bot; + if (ltoreq(curwin->w_cursor, VIsual)) { // Visual is after curwin->w_cursor top = &curwin->w_cursor; @@ -3160,8 +3161,8 @@ win_line ( shl->endcol += (*mb_ptr2len)(line + shl->endcol); } - /* Loop to check if the match starts at the - * current position */ + // Loop to check if the match starts at the + // current position continue; } } @@ -5732,12 +5733,11 @@ static void end_search_hl(void) * Init for calling prepare_search_hl(). */ static void init_search_hl(win_T *wp) + FUNC_ATTR_NONNULL_ALL { - matchitem_T *cur; - - /* Setup for match and 'hlsearch' highlighting. Disable any previous - * match */ - cur = wp->w_match_head; + // Setup for match and 'hlsearch' highlighting. Disable any previous + // match + matchitem_T *cur = wp->w_match_head; while (cur != NULL) { cur->hl.rm = cur->match; if (cur->hlg_id == 0) @@ -5747,7 +5747,7 @@ static void init_search_hl(win_T *wp) cur->hl.buf = wp->w_buffer; cur->hl.lnum = 0; cur->hl.first_lnum = 0; - /* Set the time limit to 'redrawtime'. */ + // Set the time limit to 'redrawtime'. cur->hl.tm = profile_setlimit(p_rdt); cur = cur->next; } @@ -5763,18 +5763,16 @@ static void init_search_hl(win_T *wp) * Advance to the match in window "wp" line "lnum" or past it. */ static void prepare_search_hl(win_T *wp, linenr_T lnum) + FUNC_ATTR_NONNULL_ALL { - matchitem_T *cur; /* points to the match list */ - match_T *shl; /* points to search_hl or a match */ - int shl_flag; /* flag to indicate whether search_hl - has been processed or not */ - int n; - - /* - * When using a multi-line pattern, start searching at the top - * of the window or just after a closed fold. - * Do this both for search_hl and the match list. - */ + matchitem_T *cur; // points to the match list + match_T *shl; // points to search_hl or a match + bool shl_flag; // flag to indicate whether search_hl + // has been processed or not + + // When using a multi-line pattern, start searching at the top + // of the window or just after a closed fold. + // Do this both for search_hl and the match list. cur = wp->w_match_head; shl_flag = false; while (cur != NULL || shl_flag == false) { @@ -5801,7 +5799,7 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) } bool pos_inprogress = true; // mark that a position match search is // in progress - n = 0; + int n = 0; while (shl->first_lnum < lnum && (shl->rm.regprog != NULL || (cur != NULL && pos_inprogress))) { next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, @@ -5839,6 +5837,7 @@ next_search_hl ( colnr_T mincol, /* minimal column for a match */ matchitem_T *cur /* to retrieve match positions if any */ ) + FUNC_ATTR_NONNULL_ARG(2) { linenr_T l; colnr_T matchcol; @@ -5846,11 +5845,10 @@ next_search_hl ( int save_called_emsg = called_emsg; if (shl->lnum != 0) { - /* Check for three situations: - * 1. If the "lnum" is below a previous match, start a new search. - * 2. If the previous match includes "mincol", use it. - * 3. Continue after the previous match. - */ + // Check for three situations: + // 1. If the "lnum" is below a previous match, start a new search. + // 2. If the previous match includes "mincol", use it. + // 3. Continue after the previous match. l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum; if (lnum > l) shl->lnum = 0; @@ -5864,22 +5862,21 @@ next_search_hl ( */ called_emsg = FALSE; for (;; ) { - /* Stop searching after passing the time limit. */ + // Stop searching after passing the time limit. if (profile_passed_limit(shl->tm)) { shl->lnum = 0; /* no match found in time */ break; } - /* Three situations: - * 1. No useful previous match: search from start of line. - * 2. Not Vi compatible or empty match: continue at next character. - * Break the loop if this is beyond the end of the line. - * 3. Vi compatible searching: continue at end of previous match. - */ - if (shl->lnum == 0) + // Three situations: + // 1. No useful previous match: search from start of line. + // 2. Not Vi compatible or empty match: continue at next character. + // Break the loop if this is beyond the end of the line. + // 3. Vi compatible searching: continue at end of previous match. + if (shl->lnum == 0) { matchcol = 0; - else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL - || (shl->rm.endpos[0].lnum == 0 - && shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) { + } else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL + || (shl->rm.endpos[0].lnum == 0 + && shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) { char_u *ml; matchcol = shl->rm.startpos[0].col; @@ -5896,8 +5893,8 @@ next_search_hl ( shl->lnum = lnum; if (shl->rm.regprog != NULL) { - /* Remember whether shl->rm is using a copy of the regprog in - * cur->match. */ + // Remember whether shl->rm is using a copy of the regprog in + // cur->match. bool regprog_is_copy = (shl != &search_hl && cur != NULL && shl == &cur->hl @@ -5926,7 +5923,7 @@ next_search_hl ( nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol); } if (nmatched == 0) { - shl->lnum = 0; /* no match found */ + shl->lnum = 0; // no match found break; } if (shl->rm.startpos[0].lnum > 0 @@ -5934,7 +5931,7 @@ next_search_hl ( || nmatched > 1 || shl->rm.endpos[0].col > mincol) { shl->lnum += shl->rm.startpos[0].lnum; - break; /* useful match found */ + break; // useful match found } // Restore called_emsg for assert_fails(). @@ -5951,6 +5948,7 @@ next_search_hl_pos( posmatch_T *posmatch, // match positions colnr_T mincol // minimal column for a match ) + FUNC_ATTR_NONNULL_ALL { int i; int found = -1; diff --git a/src/nvim/search.c b/src/nvim/search.c index 7d00785c74..23086c629b 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1192,6 +1192,7 @@ int do_search( len = STRLEN(p) + off_len + 3; } + xfree(msgbuf); msgbuf = xmalloc(len); { memset(msgbuf, ' ', len); diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 6cb8d01f51..180073ade1 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2827,9 +2827,6 @@ void spell_suggest(int count) smsg(_("Sorry, only %" PRId64 " suggestions"), (int64_t)sug.su_ga.ga_len); } else { - XFREE_CLEAR(repl_from); - XFREE_CLEAR(repl_to); - // When 'rightleft' is set the list is drawn right-left. cmdmsg_rl = curwin->w_p_rl; if (cmdmsg_rl) @@ -2909,6 +2906,9 @@ void spell_suggest(int count) if (selected > 0 && selected <= sug.su_ga.ga_len && u_save_cursor() == OK) { // Save the from and to text for :spellrepall. + XFREE_CLEAR(repl_from); + XFREE_CLEAR(repl_to); + stp = &SUG(sug.su_ga, selected - 1); if (sug.su_badlen > stp->st_orglen) { // Replacing less than "su_badlen", append the remainder to @@ -5761,19 +5761,22 @@ cleanup_suggestions ( int maxscore, int keep // nr of suggestions to keep ) + FUNC_ATTR_NONNULL_ALL { suggest_T *stp = &SUG(*gap, 0); - // Sort the list. - qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare); + if (gap->ga_len > 0) { + // Sort the list. + qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare); - // Truncate the list to the number of suggestions that will be displayed. - if (gap->ga_len > keep) { - for (int i = keep; i < gap->ga_len; ++i) { - xfree(stp[i].st_word); + // Truncate the list to the number of suggestions that will be displayed. + if (gap->ga_len > keep) { + for (int i = keep; i < gap->ga_len; i++) { + xfree(stp[i].st_word); + } + gap->ga_len = keep; + return stp[keep - 1].st_score; } - gap->ga_len = keep; - return stp[keep - 1].st_score; } return maxscore; } diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 57bb43c846..ff07a00952 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2540,7 +2540,9 @@ parse_match( } p += 2; // skip ";\"" if (*p++ == TAB) { - while (ASCII_ISALPHA(*p)) { + // Accept ASCII alphabetic kind characters and any multi-byte + // character. + while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) { if (STRNCMP(p, "kind:", 5) == 0) { tagp->tagkind = p + 5; } else if (STRNCMP(p, "user_data:", 10) == 0) { @@ -2559,19 +2561,22 @@ parse_match( } if (pt == NULL) break; - p = pt + 1; + p = pt; + MB_PTR_ADV(p); } } } if (tagp->tagkind != NULL) { for (p = tagp->tagkind; - *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p) - ; + *p && *p != '\t' && *p != '\r' && *p != '\n'; + MB_PTR_ADV(p)) { + } tagp->tagkind_end = p; } if (tagp->user_data != NULL) { for (p = tagp->user_data; - *p && *p != '\t' && *p != '\r' && *p != '\n'; p++) { + *p && *p != '\t' && *p != '\r' && *p != '\n'; + MB_PTR_ADV(p)) { } tagp->user_data_end = p; } @@ -3181,7 +3186,8 @@ int get_tags(list_T *list, char_u *pat, char_u *buf_fname) if (tp.command_end != NULL) { for (char_u *p = tp.command_end + 3; - *p != NUL && *p != '\n' && *p != '\r'; p++) { + *p != NUL && *p != '\n' && *p != '\r'; + MB_PTR_ADV(p)) { if (p == tp.tagkind || (p + 5 == tp.tagkind && STRNCMP(p, "kind:", 5) == 0)) { // skip "kind:<kind>" and "<kind>" diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index e3547aea5b..954e5d875f 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1072,6 +1072,40 @@ func Test_Cmd_Autocmds() enew! endfunc +func s:ReadFile() + setl noswapfile nomodified + let filename = resolve(expand("<afile>:p")) + execute 'read' fnameescape(filename) + 1d_ + exe 'file' fnameescape(filename) + setl buftype=acwrite +endfunc + +func s:WriteFile() + let filename = resolve(expand("<afile>:p")) + setl buftype= + noautocmd execute 'write' fnameescape(filename) + setl buftype=acwrite + setl nomodified +endfunc + +func Test_BufReadCmd() + autocmd BufReadCmd *.test call s:ReadFile() + autocmd BufWriteCmd *.test call s:WriteFile() + + call writefile(['one', 'two', 'three'], 'Xcmd.test') + edit Xcmd.test + call assert_match('Xcmd.test" line 1 of 3', execute('file')) + normal! Gofour + write + call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test')) + + bwipe! + call delete('Xcmd.test') + au! BufReadCmd + au! BufWriteCmd +endfunc + func SetChangeMarks(start, end) exe a:start. 'mark [' exe a:end. 'mark ]' @@ -1786,3 +1820,46 @@ func Test_FileChangedShell_reload() bwipe! call delete('Xchanged') endfunc + +" Test for FileReadCmd autocmd +func Test_autocmd_FileReadCmd() + func ReadFileCmd() + call append(line('$'), "v:cmdarg = " .. v:cmdarg) + endfunc + augroup FileReadCmdTest + au! + au FileReadCmd Xtest call ReadFileCmd() + augroup END + + new + read ++bin Xtest + read ++nobin Xtest + read ++edit Xtest + read ++bad=keep Xtest + read ++bad=drop Xtest + read ++bad=- Xtest + read ++ff=unix Xtest + read ++ff=dos Xtest + read ++ff=mac Xtest + read ++enc=utf-8 Xtest + + call assert_equal(['', + \ 'v:cmdarg = ++bin', + \ 'v:cmdarg = ++nobin', + \ 'v:cmdarg = ++edit', + \ 'v:cmdarg = ++bad=keep', + \ 'v:cmdarg = ++bad=drop', + \ 'v:cmdarg = ++bad=-', + \ 'v:cmdarg = ++ff=unix', + \ 'v:cmdarg = ++ff=dos', + \ 'v:cmdarg = ++ff=mac', + \ 'v:cmdarg = ++enc=utf-8'], getline(1, '$')) + + close! + augroup FileReadCmdTest + au! + augroup END + delfunc ReadFileCmd +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index dd546dbf71..264d8b000f 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -475,6 +475,8 @@ func Test_funcref() let OneByRef = funcref('One') call assert_equal(2, OneByRef()) call assert_fails('echo funcref("{")', 'E475:') + let OneByRef = funcref("One", repeat(["foo"], 20)) + call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:') endfunc func Test_empty_concatenate() diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 9605348389..e4e48d2d35 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -79,6 +79,7 @@ let s:filename_checks = { \ 'bib': ['file.bib'], \ 'bindzone': ['named.root'], \ 'blank': ['file.bl'], + \ 'bsdl': ['file.bsdl'], \ 'bst': ['file.bst'], \ 'bzr': ['bzr_log.any'], \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c'], @@ -436,7 +437,7 @@ let s:filename_checks = { \ 'swiftgyb': ['file.swift.gyb'], \ 'sil': ['file.sil'], \ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf'], - \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.mount', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file'], + \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.mount', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file'], \ 'systemverilog': ['file.sv', 'file.svh'], \ 'tags': ['tags'], \ 'tak': ['file.tak'], @@ -480,7 +481,7 @@ let s:filename_checks = { \ 'verilog': ['file.v'], \ 'verilogams': ['file.va', 'file.vams'], \ 'vgrindefs': ['vgrindefs'], - \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123'], + \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho'], \ 'vim': ['file.vim', 'file.vba', '.exrc', '_exrc'], \ 'viminfo': ['.viminfo', '_viminfo'], \ 'vmasm': ['file.mar'], diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index b75b095841..bd5cb6ad19 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -666,6 +666,16 @@ func Test_getbufvar() call assert_equal('iso-8859-2', getbufvar(bufnr('%'), '&fenc')) close + " Get the b: dict. + let b:testvar = 'one' + new + let b:testvar = 'two' + let thebuf = bufnr() + wincmd w + call assert_equal('two', getbufvar(thebuf, 'testvar')) + call assert_equal('two', getbufvar(thebuf, '').testvar) + bwipe! + set fileformats& endfunc diff --git a/src/nvim/testdir/test_hardcopy.vim b/src/nvim/testdir/test_hardcopy.vim index ced13b107c..6125f9b993 100644 --- a/src/nvim/testdir/test_hardcopy.vim +++ b/src/nvim/testdir/test_hardcopy.vim @@ -1,39 +1,137 @@ " Test :hardcopy -func Test_printoptions_parsing() - " Only test that this doesn't throw an error. - set printoptions=left:5in,right:10pt,top:8mm,bottom:2pc - set printoptions=left:2in,top:30pt,right:16mm,bottom:3pc - set printoptions=header:3,syntax:y,number:7,wrap:n - set printoptions=duplex:short,collate:n,jobsplit:y,portrait:n - set printoptions=paper:10x14 - set printoptions=paper:A3 - set printoptions=paper:A4 - set printoptions=paper:A5 - set printoptions=paper:B4 - set printoptions=paper:B5 - set printoptions=paper:executive - set printoptions=paper:folio - set printoptions=paper:ledger - set printoptions=paper:legal - set printoptions=paper:letter - set printoptions=paper:quarto - set printoptions=paper:statement - set printoptions=paper:tabloid - set printoptions=formfeed:y - set printoptions= - set printoptions& +func Test_printoptions() + edit test_hardcopy.vim + syn on + + for opt in ['left:5in,right:10pt,top:8mm,bottom:2pc', + \ 'left:2in,top:30pt,right:16mm,bottom:3pc', + \ 'header:3,syntax:y,number:y,wrap:n', + \ 'header:3,syntax:n,number:y,wrap:y', + \ 'duplex:short,collate:n,jobsplit:y,portrait:n', + \ 'duplex:long,collate:y,jobsplit:n,portrait:y', + \ 'paper:10x14', + \ 'paper:A3', + \ 'paper:A4', + \ 'paper:A5', + \ 'paper:B4', + \ 'paper:B5', + \ 'paper:executive', + \ 'paper:folio', + \ 'paper:ledger', + \ 'paper:legal', + \ 'paper:letter', + \ 'paper:quarto', + \ 'paper:statement', + \ 'paper:tabloid', + \ 'formfeed:y', + \ ''] + exe 'set printoptions=' .. opt + if has('postscript') + hardcopy > Xhardcopy_printoptions + let lines = readfile('Xhardcopy_printoptions') + call assert_true(len(lines) > 20, opt) + call assert_true(lines[0] =~ 'PS-Adobe', opt) + call delete('Xhardcopy_printoptions') + endif + endfor call assert_fails('set printoptions=paper', 'E550:') call assert_fails('set printoptions=shredder:on', 'E551:') call assert_fails('set printoptions=left:no', 'E552:') + set printoptions& + bwipe endfunc -func Test_printmbfont_parsing() - " Only test that this doesn't throw an error. - set printmbfont=r:WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-Bold-Italic,c:yes,a:no - set printmbfont= +func Test_printmbfont() + " Print a small help page which contains tabs to cover code that expands tabs to spaces. + help help + syn on + + for opt in [':WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-Bold-Italic,c:yes,a:no', + \ ''] + exe 'set printmbfont=' .. opt + if has('postscript') + hardcopy > Xhardcopy_printmbfont + let lines = readfile('Xhardcopy_printmbfont') + call assert_true(len(lines) > 20, opt) + call assert_true(lines[0] =~ 'PS-Adobe', opt) + call delete('Xhardcopy_printmbfont') + endif + endfor set printmbfont& + bwipe +endfunc + +func Test_printexpr() + if !has('unix') + return + endif + + " Not a very useful printexpr value, but enough to test + " hardcopy with 'printexpr'. + function PrintFile(fname) + call writefile(['Test printexpr: ' .. v:cmdarg], + \ 'Xhardcopy_printexpr') + call delete(a:fname) + return 0 + endfunc + set printexpr=PrintFile(v:fname_in) + + help help + hardcopy dummy args + call assert_equal(['Test printexpr: dummy args'], + \ readfile('Xhardcopy_printexpr')) + call delete('Xhardcopy_printexpr') + + " Function return 1 to test print failure. + function PrintFails(fname) + call delete(a:fname) + return 1 + endfunc + set printexpr=PrintFails(v:fname_in) + call assert_fails('hardcopy', 'E365:') + + set printexpr& + bwipe +endfunc + +func Test_errors() + " FIXME: Windows fails differently than Unix. + if has('unix') + edit test_hardcopy.vim + call assert_fails('hardcopy >', 'E324:') + bwipe + endif +endfunc + +func Test_dark_background() + edit test_hardcopy.vim + syn on + + for bg in ['dark', 'light'] + exe 'set background=' .. bg + + if has('postscript') + hardcopy > Xhardcopy_dark_background + let lines = readfile('Xhardcopy_dark_background') + call assert_true(len(lines) > 20) + call assert_true(lines[0] =~ 'PS-Adobe') + call delete('Xhardcopy_dark_background') + endif + endfor + + set background& + bwipe +endfun + +func Test_empty_buffer() + " FIXME: Unclear why this fails on Windows. + if has('unix') + new + call assert_equal("\nNo text to be printed", execute('hardcopy')) + bwipe + endif endfunc func Test_printheader_parsing() @@ -46,22 +144,6 @@ func Test_printheader_parsing() set printheader& endfunc -" Test that :hardcopy produces a non-empty file. -" We don't check much of the contents. -func Test_with_syntax() - if has('postscript') - edit test_hardcopy.vim - set printoptions=syntax:y - syn on - hardcopy > Xhardcopy - let lines = readfile('Xhardcopy') - call assert_true(len(lines) > 20) - call assert_true(lines[0] =~ 'PS-Adobe') - call delete('Xhardcopy') - set printoptions& - endif -endfunc - func Test_fname_with_spaces() if !has('postscript') return @@ -86,4 +168,3 @@ func Test_illegal_byte() bwipe! call delete('Xpstest') endfunc - diff --git a/src/nvim/testdir/test_maparg.vim b/src/nvim/testdir/test_maparg.vim index 0b941d51ec..5f73bd80ad 100644 --- a/src/nvim/testdir/test_maparg.vim +++ b/src/nvim/testdir/test_maparg.vim @@ -41,6 +41,11 @@ function Test_maparg() map abc y<S-char-114>y call assert_equal("yRy", maparg('abc')) + omap { w + let d = maparg('{', 'o', 0, 1) + call assert_equal(['{', 'w', 'o'], [d.lhs, d.rhs, d.mode]) + ounmap { + map abc <Nop> call assert_equal("<Nop>", maparg('abc')) unmap abc @@ -62,3 +67,5 @@ function Test_range_map() execute "normal a\uf040\<Esc>" call assert_equal("abcd", getline(1)) endfunction + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index f14f292a92..82562339f6 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -390,3 +390,77 @@ func Test_motionforce_omap() delfunc Select delfunc GetCommand endfunc + +" Test for mapping errors +func Test_map_error() + call assert_fails('unmap', 'E474:') + call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:') + call assert_fails('unmap abc', 'E31:') + call assert_fails('unabbr abc', 'E24:') + call assert_equal('', maparg('')) + call assert_fails('echo maparg("abc", [])', 'E730:') + + " unique map + map ,w /[#&!]<CR> + call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:') + " unique buffer-local map + call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:') + unmap ,w + + " unique abbreviation + abbr SP special + call assert_fails("abbr <unique> SP special", 'E226:') + " unique buffer-local map + call assert_fails("abbr <buffer> <unique> SP special", 'E224:') + unabbr SP + + call assert_fails('mapclear abc', 'E474:') + call assert_fails('abclear abc', 'E474:') +endfunc + +" Test for <special> key mapping +func Test_map_special() + throw 'skipped: Nvim does not support cpoptions flag "<"' + new + let old_cpo = &cpo + set cpo+=< + imap <F12> Blue + call feedkeys("i\<F12>", "x") + call assert_equal("<F12>", getline(1)) + call feedkeys("ddi<F12>", "x") + call assert_equal("Blue", getline(1)) + iunmap <F12> + imap <special> <F12> Green + call feedkeys("ddi\<F12>", "x") + call assert_equal("Green", getline(1)) + call feedkeys("ddi<F12>", "x") + call assert_equal("<F12>", getline(1)) + iunmap <special> <F12> + let &cpo = old_cpo + %bwipe! +endfunc + +" Test for hasmapto() +func Test_hasmapto() + call assert_equal(0, hasmapto('/^\k\+ (')) + call assert_equal(0, hasmapto('/^\k\+ (', 'n')) + nmap ,f /^\k\+ (<CR> + call assert_equal(1, hasmapto('/^\k\+ (')) + call assert_equal(1, hasmapto('/^\k\+ (', 'n')) + call assert_equal(0, hasmapto('/^\k\+ (', 'v')) + + call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1)) +endfunc + +" Test for command-line completion of maps +func Test_mapcomplete() + call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>', + \ '<silent>', '<special>', '<unique>'], + \ getcompletion('', 'mapping')) + call assert_equal([], getcompletion(',d', 'mapping')) + + call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match("abbr! \x01", @:) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim index f3eb88abf0..4b0097617e 100644 --- a/src/nvim/testdir/test_profile.vim +++ b/src/nvim/testdir/test_profile.vim @@ -16,6 +16,7 @@ func Test_profile_func() while l:count > 0 let l:count = l:count - 1 endwhile + sleep 1m endfunc func! Foo3() endfunc @@ -51,7 +52,7 @@ func Test_profile_func() " - Unlike Foo3(), Foo2() should not be deleted since there is a check " for v:profiling. " - Bar() is not reported since it does not match "profile func Foo*". - call assert_equal(30, len(lines)) + call assert_equal(31, len(lines)) call assert_equal('FUNCTION Foo1()', lines[0]) call assert_match('Defined:.*Xprofile_func.vim:3', lines[1]) @@ -71,17 +72,18 @@ func Test_profile_func() call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[16]) call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[17]) call assert_match('^\s*101\s\+.*\sendwhile$', lines[18]) - call assert_equal('', lines[19]) - call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[20]) - call assert_equal('count total (s) self (s) function', lines[21]) - call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[22]) - call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[23]) - call assert_equal('', lines[24]) - call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[25]) - call assert_equal('count total (s) self (s) function', lines[26]) - call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[27]) - call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[28]) - call assert_equal('', lines[29]) + call assert_match('^\s*1\s\+.\+sleep 1m$', lines[19]) + call assert_equal('', lines[20]) + call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[21]) + call assert_equal('count total (s) self (s) function', lines[22]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[23]) + call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[24]) + call assert_equal('', lines[25]) + call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[26]) + call assert_equal('count total (s) self (s) function', lines[27]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[28]) + call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[29]) + call assert_equal('', lines[30]) call delete('Xprofile_func.vim') call delete('Xprofile_func.log') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 015f771435..35555ca9d3 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -3318,6 +3318,14 @@ func Test_lvimgrep_crash() enew | only endfunc +func Test_lvimgrep_crash2() + au BufNewFile x sfind + call assert_fails('lvimgrep x x', 'E480:') + call assert_fails('lvimgrep x x x', 'E480:') + + au! BufNewFile +endfunc + " Test for the position of the quickfix and location list window func Test_qfwin_pos() " Open two windows diff --git a/src/nvim/testdir/test_quotestar.vim b/src/nvim/testdir/test_quotestar.vim index ce5a9ee827..77a5153a81 100644 --- a/src/nvim/testdir/test_quotestar.vim +++ b/src/nvim/testdir/test_quotestar.vim @@ -108,7 +108,8 @@ func Do_test_quotestar_for_x11() call remote_send(name, ":gui -f\<CR>") endif " Wait for the server in the GUI to be up and answering requests. - call WaitForAssert({-> assert_match("1", remote_expr(name, "has('gui_running')", "", 1))}) + " On some systems and with valgrind this can be very slow. + call WaitForAssert({-> assert_match("1", remote_expr(name, "has('gui_running')", "", 1))}, 10000) call remote_send(name, ":let @* = 'maybe'\<CR>") call WaitForAssert({-> assert_equal("maybe", remote_expr(name, "@*", "", 2))}) diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index e94bd22cea..ff07d8eceb 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -613,6 +613,25 @@ func Test_sub_replace_10() call assert_equal('1aaa', substitute('123', '1\zs\|[23]', 'a', 'g')) endfunc +func SubReplacer(text, submatches) + return a:text .. a:submatches[0] .. a:text +endfunc +func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches) + return a:t3 .. a:submatches[0] .. a:t11 +endfunc + +func Test_substitute_partial() + call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g')) + + " 19 arguments plus one is just OK + let Replacer = function('SubReplacer20', repeat(['foo'], 19)) + call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g')) + + " 20 arguments plus one is too many + let Replacer = function('SubReplacer20', repeat(['foo'], 20)) + call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118') +endfunc + func Test_sub_cmd_9() new let input = ['1 aaa', '2 aaa', '3 aaa'] diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim index cb54ace695..d4ff42fd68 100644 --- a/src/nvim/testdir/test_taglist.vim +++ b/src/nvim/testdir/test_taglist.vim @@ -7,6 +7,7 @@ func Test_taglist() \ "BFoo\tXbar\t1", \ "BBar\tXbar\t2", \ "Kindly\tXbar\t3;\"\tv\tfile:", + \ "Lambda\tXbar\t3;\"\tλ\tfile:", \ "Command\tXbar\tcall cursor(3, 4)|;\"\td", \ ], 'Xtags') set tags=Xtags @@ -17,12 +18,16 @@ func Test_taglist() call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xfoo"), {i, v -> v.name})) call assert_equal(['BFoo', 'FFoo'], map(taglist("Foo", "Xbar"), {i, v -> v.name})) - let kind = taglist("Kindly") - call assert_equal(1, len(kind)) - call assert_equal('v', kind[0]['kind']) - call assert_equal('3', kind[0]['cmd']) - call assert_equal(1, kind[0]['static']) - call assert_equal('Xbar', kind[0]['filename']) + let kindly = taglist("Kindly") + call assert_equal(1, len(kindly)) + call assert_equal('v', kindly[0]['kind']) + call assert_equal('3', kindly[0]['cmd']) + call assert_equal(1, kindly[0]['static']) + call assert_equal('Xbar', kindly[0]['filename']) + + let lambda = taglist("Lambda") + call assert_equal(1, len(lambda)) + call assert_equal('λ', lambda[0]['kind']) let cmd = taglist("Command") call assert_equal(1, len(cmd)) diff --git a/src/nvim/window.c b/src/nvim/window.c index 9ec47f8e89..a89715ff79 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6544,10 +6544,12 @@ void restore_buffer(bufref_T *save_curbuf) /// @param[in] id a desired ID 'id' can be specified /// (greater than or equal to 1). -1 must be specified if no /// particular ID is desired +/// @param[in] conceal_char pointer to conceal replacement char /// @return ID of added match, -1 on failure. int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, int id, list_T *pos_list, const char *const conceal_char) + FUNC_ATTR_NONNULL_ARG(1, 2) { matchitem_T *cur; matchitem_T *prev; @@ -6584,7 +6586,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, return -1; } - /* Find available match ID. */ + // Find available match ID. while (id == -1) { cur = wp->w_match_head; while (cur != NULL && cur->id != wp->w_next_match_id) @@ -6594,7 +6596,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, wp->w_next_match_id++; } - /* Build new match. */ + // Build new match. m = xcalloc(1, sizeof(matchitem_T)); m->id = id; m->priority = prio; @@ -6702,9 +6704,9 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, rtype = VALID; } } - - /* Insert new match. The match list is in ascending order with regard to - * the match priorities. */ + + // Insert new match. The match list is in ascending order with regard to + // the match priorities. cur = wp->w_match_head; prev = cur; while (cur != NULL && prio >= cur->priority) { |