diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 168 |
1 files changed, 104 insertions, 64 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 327d0bf637..31175773f0 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3580,9 +3580,10 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate) type = TYPE_SEQUAL; break; case 'i': if (p[1] == 's') { - if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') + if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') { len = 5; - if (!vim_isIDc(p[len])) { + } + if (!isalnum(p[len]) && p[len] != '_') { type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL; type_is = TRUE; } @@ -7323,10 +7324,10 @@ static struct fst { { "setcharsearch", 1, 1, f_setcharsearch }, { "setcmdpos", 1, 1, f_setcmdpos }, { "setline", 2, 2, f_setline }, - { "setloclist", 2, 3, f_setloclist }, + { "setloclist", 2, 4, f_setloclist }, { "setmatches", 1, 1, f_setmatches }, { "setpos", 2, 2, f_setpos }, - { "setqflist", 1, 2, f_setqflist }, + { "setqflist", 1, 3, f_setqflist }, { "setreg", 2, 3, f_setreg }, { "settabvar", 3, 3, f_settabvar }, { "settabwinvar", 4, 4, f_settabwinvar }, @@ -10697,11 +10698,11 @@ getwinvar ( int off /* 1 for gettabwinvar() */ ) { - win_T *win, *oldcurwin; - char_u *varname; - dictitem_T *v; - tabpage_T *tp = NULL; - tabpage_T *oldtabpage = NULL; + win_T *win, *oldcurwin; + char_u *varname; + dictitem_T *v; + tabpage_T *tp = NULL; + tabpage_T *oldtabpage = NULL; bool done = false; if (off == 1) @@ -10716,12 +10717,16 @@ getwinvar ( rettv->vval.v_string = NULL; if (win != NULL && varname != NULL) { - /* Set curwin to be our win, temporarily. Also set the tabpage, - * otherwise the window is not valid. */ - if (switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK) { - if (*varname == '&') { /* window-local-option */ - if (get_option_tv(&varname, rettv, 1) == OK) + // Set curwin to be our win, temporarily. Also set the tabpage, + // otherwise the window is not valid. Only do this when needed, + // autocommands get blocked. + bool need_switch_win = tp != curtab || win != curwin; + if (!need_switch_win + || switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) { + if (*varname == '&') { // window-local-option + if (get_option_tv(&varname, rettv, 1) == OK) { done = true; + } } else { // Look up the variable. // Let getwinvar({nr}, "") return the "w:" dictionary. @@ -10733,8 +10738,10 @@ getwinvar ( } } - /* restore previous notion of curwin */ - restore_win(oldcurwin, oldtabpage, TRUE); + if (need_switch_win) { + // restore previous notion of curwin + restore_win(oldcurwin, oldtabpage, true); + } } if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) @@ -15208,14 +15215,26 @@ static void f_setline(typval_T *argvars, typval_T *rettv) appended_lines_mark(lcount, added); } - -/* - * Used by "setqflist()" and "setloclist()" functions - */ -static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv) +/// Create quickfix/location list from VimL values +/// +/// Used by `setqflist()` and `setloclist()` functions. Accepts invalid +/// list_arg, action_arg and title_arg arguments in which case errors out, +/// including VAR_UNKNOWN parameters. +/// +/// @param[in,out] wp Window to create location list for. May be NULL in +/// which case quickfix list will be created. +/// @param[in] list_arg Quickfix list contents. +/// @param[in] action_arg Action to perform: append to an existing list, +/// replace its content or create a new one. +/// @param[in] title_arg New list title. Defaults to caller function name. +/// @param[out] rettv Return value: 0 in case of success, -1 otherwise. +static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, + typval_T *title_arg, typval_T *rettv) + FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5) { char_u *act; int action = ' '; + char_u *title = NULL; rettv->vval.v_number = -1; @@ -15224,7 +15243,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, else { list_T *l = list_arg->vval.v_list; - if (action_arg->v_type == VAR_STRING) { + if (action_arg->v_type != VAR_UNKNOWN) { act = get_tv_string_chk(action_arg); if (act == NULL) return; /* type error; errmsg already given */ @@ -15232,9 +15251,20 @@ static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, action = *act; } - if (l != NULL && set_errorlist(wp, l, action, - (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK) + if (title_arg->v_type != VAR_UNKNOWN) { + title = get_tv_string_chk(title_arg); + if (!title) { + return; // type error; errmsg already given + } + } + + if (!title) { + title = (char_u*)(wp ? "setloclist()" : "setqflist()"); + } + + if (l && set_errorlist(wp, l, action, title) == OK) { rettv->vval.v_number = 0; + } } } @@ -15248,8 +15278,9 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = -1; win = find_win_by_nr(&argvars[0], NULL); - if (win != NULL) - set_qf_ll_list(win, &argvars[1], &argvars[2], rettv); + if (win != NULL) { + set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv); + } } /* @@ -15385,7 +15416,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv) */ static void f_setqflist(typval_T *argvars, typval_T *rettv) { - set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv); + set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv); } /* @@ -15559,26 +15590,32 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) varname = get_tv_string_chk(&argvars[off + 1]); varp = &argvars[off + 2]; - if (win != NULL && varname != NULL && varp != NULL - && switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK) { - if (*varname == '&') { - long numval; - char_u *strval; - int error = FALSE; - - ++varname; - numval = get_tv_number_chk(varp, &error); - strval = get_tv_string_buf_chk(varp, nbuf); - if (!error && strval != NULL) - set_option_value(varname, numval, strval, OPT_LOCAL); - } else { - winvarname = xmalloc(STRLEN(varname) + 3); - STRCPY(winvarname, "w:"); - STRCPY(winvarname + 2, varname); - set_var(winvarname, varp, TRUE); - xfree(winvarname); + if (win != NULL && varname != NULL && varp != NULL) { + bool need_switch_win = tp != curtab || win != curwin; + if (!need_switch_win + || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) { + if (*varname == '&') { + long numval; + char_u *strval; + int error = false; + + ++varname; + numval = get_tv_number_chk(varp, &error); + strval = get_tv_string_buf_chk(varp, nbuf); + if (!error && strval != NULL) { + set_option_value(varname, numval, strval, OPT_LOCAL); + } + } else { + winvarname = xmalloc(STRLEN(varname) + 3); + STRCPY(winvarname, "w:"); + STRCPY(winvarname + 2, varname); + set_var(winvarname, varp, true); + xfree(winvarname); + } + } + if (need_switch_win) { + restore_win(save_curwin, save_curtab, true); } - restore_win(save_curwin, save_curtab, TRUE); } } @@ -18091,23 +18128,23 @@ void set_vim_var_list(int idx, list_T *val) } /// Set Dictionary v: variable to "val". -void set_vim_var_dict(int idx, dict_T *val) FUNC_ATTR_NONNULL_ALL +void set_vim_var_dict(int idx, dict_T *val) { dict_unref(vimvars[idx].vv_dict); + vimvars[idx].vv_dict = val; - // Set readonly - int todo = (int)val->dv_hashtab.ht_used; - for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) { - if (HASHITEM_EMPTY(hi)) { - continue; + if (val != NULL) { + ++val->dv_refcount; + // Set readonly + size_t todo = val->dv_hashtab.ht_used; + for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) { + if (HASHITEM_EMPTY(hi)) { + continue; + } + --todo; + HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } - - --todo; - HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } - - vimvars[idx].vv_dict = val; - ++val->dv_refcount; } /* @@ -20913,14 +20950,18 @@ call_user_func ( save_sourcing_name = sourcing_name; save_sourcing_lnum = sourcing_lnum; sourcing_lnum = 1; - sourcing_name = xmalloc((save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name)) - + STRLEN(fp->uf_name) + 13); + // need space for function name + ("function " + 3) or "[number]" + size_t len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name)) + + STRLEN(fp->uf_name) + 20; + sourcing_name = xmalloc(len); { if (save_sourcing_name != NULL - && STRNCMP(save_sourcing_name, "function ", 9) == 0) - sprintf((char *)sourcing_name, "%s..", save_sourcing_name); - else + && STRNCMP(save_sourcing_name, "function ", 9) == 0) { + vim_snprintf((char *)sourcing_name, len, "%s[%zu]..", + save_sourcing_name, save_sourcing_lnum); + } else { STRCPY(sourcing_name, "function "); + } cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); if (p_verbose >= 12) { @@ -22186,7 +22227,6 @@ static void on_process_exit(Process *proc, int status, void *d) char msg[22]; snprintf(msg, sizeof msg, "\r\n[Process exited %d]", proc->status); terminal_close(data->term, msg); - apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, curbuf); } if (data->status_ptr) { |