aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c161
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) {