diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 220 |
1 files changed, 183 insertions, 37 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 417a38e906..71d60d6b45 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -354,6 +354,7 @@ static struct vimvar { VV(VV_FCS_CHOICE, "fcs_choice", VAR_STRING, 0), VV(VV_BEVAL_BUFNR, "beval_bufnr", VAR_NUMBER, VV_RO), VV(VV_BEVAL_WINNR, "beval_winnr", VAR_NUMBER, VV_RO), + VV(VV_BEVAL_WINID, "beval_winid", VAR_NUMBER, VV_RO), VV(VV_BEVAL_LNUM, "beval_lnum", VAR_NUMBER, VV_RO), VV(VV_BEVAL_COL, "beval_col", VAR_NUMBER, VV_RO), VV(VV_BEVAL_TEXT, "beval_text", VAR_STRING, VV_RO), @@ -363,6 +364,7 @@ static struct vimvar { VV(VV_SWAPCOMMAND, "swapcommand", VAR_STRING, VV_RO), VV(VV_CHAR, "char", VAR_STRING, 0), VV(VV_MOUSE_WIN, "mouse_win", VAR_NUMBER, 0), + VV(VV_MOUSE_WINID, "mouse_winid", VAR_NUMBER, 0), VV(VV_MOUSE_LNUM, "mouse_lnum", VAR_NUMBER, 0), VV(VV_MOUSE_COL, "mouse_col", VAR_NUMBER, 0), VV(VV_OP, "operator", VAR_STRING, VV_RO), @@ -384,6 +386,15 @@ static struct vimvar { VV(VV_NULL, "null", VAR_SPECIAL, VV_RO), VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO), VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO), + VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO), + VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO), + VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO), + VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO), + VV(VV_TYPE_LIST, "t_list", VAR_NUMBER, VV_RO), + VV(VV_TYPE_DICT, "t_dict", VAR_NUMBER, VV_RO), + VV(VV_TYPE_FLOAT, "t_float", VAR_NUMBER, VV_RO), + VV(VV_TYPE_BOOL, "t_bool", VAR_NUMBER, VV_RO), + VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO), }; #undef VV @@ -397,7 +408,7 @@ static struct vimvar { #define vv_dict vv_di.di_tv.vval.v_dict #define vv_tv vv_di.di_tv -static dictitem_T vimvars_var; /* variable used for v: */ +static dictitem_T vimvars_var; // variable used for v: #define vimvarht vimvardict.dv_hashtab typedef struct { @@ -559,10 +570,19 @@ void eval_init(void) set_vim_var_list(VV_ERRORS, list_alloc()); set_vim_var_nr(VV_SEARCHFORWARD, 1L); set_vim_var_nr(VV_HLSEARCH, 1L); + set_vim_var_nr(VV_COUNT1, 1); + set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER); + set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING); + set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC); + set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST); + set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT); + set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT); + set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL); set_vim_var_special(VV_FALSE, kSpecialVarFalse); set_vim_var_special(VV_TRUE, kSpecialVarTrue); set_vim_var_special(VV_NULL, kSpecialVarNull); + set_vim_var_special(VV_EXITING, kSpecialVarNull); set_reg_var(0); // default for v:register is not 0 but '"' } @@ -2142,11 +2162,9 @@ get_lval ( if (lp->ll_tv->v_type == VAR_DICT) { if (len == -1) { - /* "[key]": get key from "var1" */ - key = get_tv_string(&var1); /* is number or string */ - if (*key == NUL) { - if (!quiet) - EMSG(_(e_emptykey)); + // "[key]": get key from "var1" + key = get_tv_string_chk(&var1); // is number or string + if (key == NULL) { clear_tv(&var1); return NULL; } @@ -4597,10 +4615,8 @@ eval_index ( dictitem_T *item; if (len == -1) { - key = get_tv_string(&var1); - if (*key == NUL) { - if (verbose) - EMSG(_(e_emptykey)); + key = get_tv_string_chk(&var1); + if (key == NULL) { clear_tv(&var1); return FAIL; } @@ -6584,10 +6600,8 @@ static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) } if (evaluate) { key = get_tv_string_buf_chk(&tvkey, buf); - if (key == NULL || *key == NUL) { - /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ - if (key != NULL) - EMSG(_(e_emptykey)); + if (key == NULL) { + // "key" is NULL when get_tv_string_buf_chk() gave an errmsg clear_tv(&tvkey); goto failret; } @@ -8009,7 +8023,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) int saved = RedrawingDisabled; RedrawingDisabled = 0; - ins_compl_check_keys(0); + ins_compl_check_keys(0, true); rettv->vval.v_number = compl_interrupted; RedrawingDisabled = saved; } @@ -9565,6 +9579,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) --allow_keys; vimvars[VV_MOUSE_WIN].vv_nr = 0; + vimvars[VV_MOUSE_WINID].vv_nr = 0; vimvars[VV_MOUSE_LNUM].vv_nr = 0; vimvars[VV_MOUSE_COL].vv_nr = 0; @@ -9607,6 +9622,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (wp = firstwin; wp != win; wp = wp->w_next) ++winnr; vimvars[VV_MOUSE_WIN].vv_nr = winnr; + vimvars[VV_MOUSE_WINID].vv_nr = wp->handle; vimvars[VV_MOUSE_LNUM].vv_nr = lnum; vimvars[VV_MOUSE_COL].vv_nr = col + 1; } @@ -10653,7 +10669,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!n) { if (STRNICMP(name, "patch", 5) == 0) { if (name[5] == '-' - && strlen(name) > 11 + && strlen(name) >= 11 && ascii_isdigit(name[6]) && ascii_isdigit(name[8]) && ascii_isdigit(name[10])) { @@ -10769,7 +10785,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (scope_number[kCdScopeTab] > 0) { tp = find_tabpage(scope_number[kCdScopeTab]); if (!tp) { - EMSG(_("5000: Cannot find tab number.")); + EMSG(_("E5000: Cannot find tab number.")); return; } } @@ -11454,6 +11470,9 @@ static void f_jobclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) process_close_err(proc); } else { process_close_streams(proc); + if (proc->type == kProcessTypePty) { + pty_process_close_master(&data->proc.pty); + } } } } @@ -11562,7 +11581,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; } -static char **tv_to_argv(typval_T *cmd_tv, char **cmd) +static char **tv_to_argv(typval_T *cmd_tv, char **cmd, bool *executable) { if (cmd_tv->v_type == VAR_STRING) { char *cmd_str = (char *)get_tv_string(cmd_tv); @@ -11580,7 +11599,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd) list_T *argl = cmd_tv->vval.v_list; int argc = argl->lv_len; if (!argc) { - EMSG(_("Argument vector must have at least one item")); + EMSG(_(e_invarg)); // List must have at least one item. return NULL; } @@ -11588,9 +11607,8 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd) const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv); if (!exe || !os_can_exe(exe, NULL, true)) { - // String is not executable - if (exe) { - EMSG2(e_jobexe, exe); + if (exe && executable) { + *executable = false; } return NULL; } @@ -11598,7 +11616,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd) if (cmd) { *cmd = (char *)exe; } - + // Build the argument vector int i = 0; char **argv = xcalloc(argc + 1, sizeof(char *)); @@ -11625,8 +11643,10 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - char **argv = tv_to_argv(&argvars[0], NULL); + bool executable = true; + char **argv = tv_to_argv(&argvars[0], NULL, &executable); if (!argv) { + rettv->vval.v_number = executable ? 0 : -1; return; // Did error message in tv_to_argv. } @@ -12192,9 +12212,16 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) p_cpo = (char_u *)""; rettv->vval.v_number = -1; - if (type == 3) { - /* return empty list when there are no matches */ + if (type == 3 || type == 4) { + // type 3: return empty list when there are no matches. + // type 4: return ["", -1, -1, -1] rettv_list_alloc(rettv); + if (type == 4) { + list_append_string(rettv->vval.v_list, (char_u *)"", 0); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + list_append_number(rettv->vval.v_list, (varnumber_T)-1); + } } else if (type == 2) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -12257,7 +12284,7 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) break; } xfree(tofree); - tofree = str = (char_u *) encode_tv2echo(&li->li_tv, NULL); + tofree = expr = str = (char_u *)encode_tv2echo(&li->li_tv, NULL); if (str == NULL) { break; } @@ -12285,7 +12312,19 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) } if (match) { - if (type == 3) { + if (type == 4) { + listitem_T *li1 = rettv->vval.v_list->lv_first; + listitem_T *li2 = li1->li_next; + listitem_T *li3 = li2->li_next; + listitem_T *li4 = li3->li_next; + int rd = (int)(regmatch.endp[0] - regmatch.startp[0]); + li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0], rd); + li3->li_tv.vval.v_number = (varnumber_T)(regmatch.startp[0] - expr); + li4->li_tv.vval.v_number = (varnumber_T)(regmatch.endp[0] - expr); + if (l != NULL) { + li2->li_tv.vval.v_number = (varnumber_T)idx; + } + } else if (type == 3) { int i; /* return list with matched string and submatches */ @@ -12320,6 +12359,11 @@ static void find_some_match(typval_T *argvars, typval_T *rettv, int type) vim_regfree(regmatch.regprog); } + if (type == 4 && l == NULL) { + // matchstrpos() without a list: drop the second item + listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first->li_next); + } + theend: xfree(tofree); p_cpo = save_cpo; @@ -12492,6 +12536,11 @@ static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) find_some_match(argvars, rettv, 2); } +/// "matchstrpos()" function +static void f_matchstrpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + find_some_match(argvars, rettv, 4); +} static void max_min(typval_T *argvars, typval_T *rettv, int domax) { @@ -15612,6 +15661,39 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "strgetchar()" function +static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char_u *str; + int len; + int error = false; + int charidx; + + rettv->vval.v_number = -1; + str = get_tv_string_chk(&argvars[0]); + if (str == NULL) { + return; + } + len = (int)STRLEN(str); + charidx = get_tv_number_chk(&argvars[1], &error); + if (error) { + return; + } + + { + int byteidx = 0; + + while (charidx >= 0 && byteidx < len) { + if (charidx == 0) { + rettv->vval.v_number = mb_ptr2char(str + byteidx); + break; + } + charidx--; + byteidx += mb_cptr2len(str + byteidx); + } + } +} + /* * "stridx()" function */ @@ -15712,6 +15794,64 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (varnumber_T) mb_string2cells(s); } +// "strcharpart()" function +static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + char_u *p; + int nchar; + int nbyte = 0; + int charlen; + int len = 0; + int slen; + int error = false; + + p = get_tv_string(&argvars[0]); + slen = (int)STRLEN(p); + + nchar = get_tv_number_chk(&argvars[1], &error); + if (!error) { + if (nchar > 0) { + while (nchar > 0 && nbyte < slen) { + nbyte += mb_cptr2len(p + nbyte); + nchar--; + } + } else { + nbyte = nchar; + } + } + if (argvars[2].v_type != VAR_UNKNOWN) { + charlen = get_tv_number(&argvars[2]); + while (charlen > 0 && nbyte + len < slen) { + int off = nbyte + len; + + if (off < 0) { + len += 1; + } else { + len += mb_cptr2len(p + off); + } + charlen--; + } + } else { + len = slen - nbyte; // default: all bytes that are available. + } + + // Only return the overlap between the specified part and the actual + // string. + if (nbyte < 0) { + len += nbyte; + nbyte = 0; + } else if (nbyte > slen) { + nbyte = slen; + } + if (len < 0) { + len = 0; + } else if (nbyte + len > slen) { + len = slen - nbyte; + } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strnsave(p + nbyte, len); +} + /* * "strpart()" function */ @@ -16096,7 +16236,7 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, } // get shell command to execute - char **argv = tv_to_argv(&argvars[0], NULL); + char **argv = tv_to_argv(&argvars[0], NULL, NULL); if (!argv) { xfree(input); return; // Already did emsg. @@ -16329,8 +16469,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) } char *cmd; - char **argv = tv_to_argv(&argvars[0], &cmd); + bool executable = true; + char **argv = tv_to_argv(&argvars[0], &cmd, &executable); if (!argv) { + rettv->vval.v_number = executable ? 0 : -1; return; // Did error message in tv_to_argv. } @@ -16701,17 +16843,17 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) int n = -1; switch (argvars[0].v_type) { - case VAR_NUMBER: n = 0; break; - case VAR_STRING: n = 1; break; - case VAR_FUNC: n = 2; break; - case VAR_LIST: n = 3; break; - case VAR_DICT: n = 4; break; - case VAR_FLOAT: n = 5; break; + case VAR_NUMBER: n = VAR_TYPE_NUMBER; break; + case VAR_STRING: n = VAR_TYPE_STRING; break; + case VAR_FUNC: n = VAR_TYPE_FUNC; break; + case VAR_LIST: n = VAR_TYPE_LIST; break; + case VAR_DICT: n = VAR_TYPE_DICT; break; + case VAR_FLOAT: n = VAR_TYPE_FLOAT; break; case VAR_SPECIAL: { switch (argvars[0].vval.v_special) { case kSpecialVarTrue: case kSpecialVarFalse: { - n = 6; + n = VAR_TYPE_BOOL; break; } case kSpecialVarNull: { @@ -17655,6 +17797,8 @@ void set_vcount(long count, long count1, int set_prevcount) /// @param[in] val Value to set to. void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) { + clear_tv(&vimvars[idx].vv_tv); + vimvars[idx].vv_type = VAR_NUMBER; vimvars[idx].vv_nr = val; } @@ -17664,6 +17808,8 @@ void set_vim_var_nr(const VimVarIndex idx, const varnumber_T val) /// @param[in] val Value to set to. void set_vim_var_special(const VimVarIndex idx, const SpecialVarValue val) { + clear_tv(&vimvars[idx].vv_tv); + vimvars[idx].vv_type = VAR_SPECIAL; vimvars[idx].vv_special = val; } |