diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 161 |
1 files changed, 91 insertions, 70 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9553c7a7ed..5323e17158 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4740,13 +4740,14 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) ++name; break; - /* Special key, e.g.: "\<C-W>" */ - case '<': extra = trans_special(&p, name, TRUE); + // Special key, e.g.: "\<C-W>" + case '<': + extra = trans_special((const char_u **) &p, STRLEN(p), name, true); if (extra != 0) { name += extra; break; } - /* FALLTHROUGH */ + // FALLTHROUGH default: MB_COPY_CHAR(p, name); break; @@ -6665,6 +6666,7 @@ static struct fst { { "argv", 0, 1, f_argv }, { "asin", 1, 1, f_asin }, // WJMc { "assert_equal", 2, 3, f_assert_equal }, + { "assert_exception", 1, 2, f_assert_exception }, { "assert_false", 1, 2, f_assert_false }, { "assert_true", 1, 2, f_assert_true }, { "atan", 1, 1, f_atan }, @@ -7627,6 +7629,26 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv) } } +/// "assert_exception(string[, msg])" function +static void f_assert_exception(typval_T *argvars, typval_T *rettv) +{ + garray_T ga; + + char *error = (char *)get_tv_string_chk(&argvars[0]); + if (vimvars[VV_EXCEPTION].vv_str == NULL) { + prepare_assert_error(&ga); + ga_concat(&ga, (char_u *)"v:exception is not set"); + assert_error(&ga); + ga_clear(&ga); + } else if (strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL) { + prepare_assert_error(&ga); + fill_assert_error(&ga, &argvars[1], NULL, &argvars[0], + &vimvars[VV_EXCEPTION].vv_tv); + assert_error(&ga); + ga_clear(&ga); + } +} + // Common for assert_true() and assert_false(). static void assert_bool(typval_T *argvars, bool is_true) { @@ -9798,7 +9820,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv) static void f_getcwd(typval_T *argvars, typval_T *rettv) { // Possible scope of working directory to return. - CdScope scope = kCdScopeWindow; + CdScope scope = MIN_CD_SCOPE; // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. @@ -9817,7 +9839,8 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) rettv->vval.v_string = NULL; // Pre-conditions and scope extraction together - for (int i = 0; i < kCdScopeGlobal; i++) { + for (int i = MIN_CD_SCOPE; i < MAX_CD_SCOPE; i++) { + // If there is no argument there are no more scopes after it, break out. if (argvars[i].v_type == VAR_UNKNOWN) { break; } @@ -9828,34 +9851,17 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) scope_number[i] = argvars[i].vval.v_number; // The scope is the current iteration step. scope = i; - - if (scope_number[i] < -1) { - EMSG(_(e_invarg)); - return; - } - } - - // Allocate and initialize the string to return. - cwd = xmalloc(MAXPATHL); - - // Get the scope and numbers from the arguments - for (int i = 0; i < MAX_CD_SCOPE; i++) { - // If there is no argument there are no more scopes after it, break out. - if (argvars[i].v_type == VAR_UNKNOWN) { - break; - } - scope_number[i] = argvars[i].vval.v_number; - // The scope is the current iteration step. - scope = i; // It is an error for the scope number to be less than `-1`. if (scope_number[i] < -1) { EMSG(_(e_invarg)); - goto end; + return; } } - // If the deepest scope number is `-1` advance the scope. + // Normalize scope, the number of the new scope will be 0. if (scope_number[scope] < 0) { + // Arguments to `getcwd` always end at second-highest scope, so scope will + // always be <= `MAX_CD_SCOPE`. scope++; } @@ -9866,7 +9872,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) tp = find_tabpage(scope_number[kCdScopeTab]); if (!tp) { EMSG(_("E5000: Cannot find tab number.")); - goto end; + return; } } @@ -9876,25 +9882,29 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) } else if (scope_number[kCdScopeWindow] >= 0) { if (!tp) { EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); - goto end; + return; } if (scope_number[kCdScopeWindow] > 0) { win = find_win_by_nr(&argvars[0], curtab); if (!win) { EMSG(_("E5002: Cannot find window number.")); - goto end; + return; } } } + cwd = xmalloc(MAXPATHL); + switch (scope) { case kCdScopeWindow: + assert(win); from = win->w_localdir; if (from) { break; } case kCdScopeTab: // FALLTHROUGH + assert(tp); from = tp->localdir; if (from) { break; @@ -9904,7 +9914,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) if (globaldir) { from = globaldir; } else { - // Copy the OS path directly into output string and jump to the end. + // We have to copy the OS path directly into output string. if (os_dirname(cwd, MAXPATHL) == FAIL) { EMSG(_("E41: Could not display path.")); goto end; @@ -9921,7 +9931,6 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv) #ifdef BACKSLASH_IN_FILENAME slash_adjust(rettv->vval.v_string); #endif - end: xfree(cwd); } @@ -10173,6 +10182,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { + update_curswant(); list_append_number(l, curwin->w_curswant == MAXCOL ? (varnumber_T)MAXCOL : (varnumber_T)curwin->w_curswant + 1); @@ -10756,7 +10766,7 @@ static void f_has_key(typval_T *argvars, typval_T *rettv) static void f_haslocaldir(typval_T *argvars, typval_T *rettv) { // Possible scope of working directory to return. - CdScope scope = kCdScopeWindow; + CdScope scope = MIN_CD_SCOPE; // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. @@ -10772,7 +10782,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = 0; // Pre-conditions and scope extraction together - for (int i = 0; i < kCdScopeGlobal; i++) { + for (int i = MIN_CD_SCOPE; i < MAX_CD_SCOPE; i++) { if (argvars[i].v_type == VAR_UNKNOWN) { break; } @@ -10789,9 +10799,11 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) } } - // It the deepest scope number is `-1` advance the scope by one. + // Normalize scope, the number of the new scope will be 0. if (scope_number[scope] < 0) { - ++scope; + // Arguments to `haslocaldir` always end at second-highest scope, so scope + // will always be <= `MAX_CD_SCOPE`. + scope++; } // Find the tabpage by number @@ -10825,13 +10837,16 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) switch (scope) { case kCdScopeWindow: + assert(win); rettv->vval.v_number = win->w_localdir ? 1 : 0; break; case kCdScopeTab: + assert(tp); rettv->vval.v_number = tp->localdir ? 1 : 0; break; case kCdScopeGlobal: - assert(0); + // The global scope never has a local directory + rettv->vval.v_number = 0; break; } } @@ -10866,21 +10881,22 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv) */ static void f_histadd(typval_T *argvars, typval_T *rettv) { - int histype; + HistoryType histype; char_u *str; char_u buf[NUMBUFLEN]; - rettv->vval.v_number = FALSE; - if (check_restricted() || check_secure()) + rettv->vval.v_number = false; + if (check_restricted() || check_secure()) { return; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - histype = str != NULL ? get_histtype(str) : -1; - if (histype >= 0) { + } + str = get_tv_string_chk(&argvars[0]); // NULL on type error + histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; + if (histype != HIST_INVALID) { str = get_tv_string_buf(&argvars[1], buf); if (*str != NUL) { init_history(); - add_to_history(histype, str, FALSE, NUL); - rettv->vval.v_number = TRUE; + add_to_history(histype, str, false, NUL); + rettv->vval.v_number = true; return; } } @@ -10895,20 +10911,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) char_u buf[NUMBUFLEN]; char_u *str; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - if (str == NULL) + str = get_tv_string_chk(&argvars[0]); // NULL on type error + if (str == NULL) { n = 0; - else if (argvars[1].v_type == VAR_UNKNOWN) - /* only one argument: clear entire history */ - n = clr_history(get_histtype(str)); - else if (argvars[1].v_type == VAR_NUMBER) - /* index given: remove that entry */ - n = del_history_idx(get_histtype(str), - (int)get_tv_number(&argvars[1])); - else - /* string given: remove all matching entries */ - n = del_history_entry(get_histtype(str), - get_tv_string_buf(&argvars[1], buf)); + } else if (argvars[1].v_type == VAR_UNKNOWN) { + // only one argument: clear entire history + n = clr_history(get_histtype(str, STRLEN(str), false)); + } else if (argvars[1].v_type == VAR_NUMBER) { + // index given: remove that entry + n = del_history_idx(get_histtype(str, STRLEN(str), false), + (int) get_tv_number(&argvars[1])); + } else { + // string given: remove all matching entries + n = del_history_entry(get_histtype(str, STRLEN(str), false), + get_tv_string_buf(&argvars[1], buf)); + } rettv->vval.v_number = n; } @@ -10917,20 +10934,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) */ static void f_histget(typval_T *argvars, typval_T *rettv) { - int type; + HistoryType type; int idx; char_u *str; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - if (str == NULL) + str = get_tv_string_chk(&argvars[0]); // NULL on type error + if (str == NULL) { rettv->vval.v_string = NULL; - else { - type = get_histtype(str); - if (argvars[1].v_type == VAR_UNKNOWN) + } else { + type = get_histtype(str, STRLEN(str), false); + if (argvars[1].v_type == VAR_UNKNOWN) { idx = get_history_idx(type); - else + } else { idx = (int)get_tv_number_chk(&argvars[1], NULL); - /* -1 on type error */ + } + // -1 on type error rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); } rettv->v_type = VAR_STRING; @@ -10945,11 +10963,13 @@ static void f_histnr(typval_T *argvars, typval_T *rettv) char_u *history = get_tv_string_chk(&argvars[0]); - i = history == NULL ? HIST_CMD - 1 : get_histtype(history); - if (i >= HIST_CMD && i < HIST_COUNT) + i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), + false); + if (i != HIST_INVALID) { i = get_history_idx(i); - else + } else { i = -1; + } rettv->vval.v_number = i; } @@ -12086,8 +12106,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) mode = get_map_mode(&which, 0); - keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); - rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, + CPO_TO_CPO_FLAGS); + rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local); xfree(keys_buf); if (!get_dict) { |