diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 116 |
1 files changed, 96 insertions, 20 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 66cd0e09c6..0a83c3a586 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2818,7 +2818,7 @@ static int do_unlet_var(lval_T *const lp, char_u *const name_end, int forceit) /// @param[in] fonceit If true, do not complain if variable doesn’t exist. /// /// @return OK if it existed, FAIL otherwise. -int do_unlet(const char *const name, const size_t name_len, const int forceit) +int do_unlet(const char *const name, const size_t name_len, const bool forceit) FUNC_ATTR_NONNULL_ALL { const char *varname; @@ -5552,19 +5552,18 @@ void prepare_assert_error(garray_T *gap) } } -// Append "str" to "gap", escaping unprintable characters. +// Append "p[clen]" to "gap", escaping unprintable characters. // Changes NL to \n, CR to \r, etc. -static void ga_concat_esc(garray_T *gap, char_u *str) +static void ga_concat_esc(garray_T *gap, const char_u *p, int clen) + FUNC_ATTR_NONNULL_ALL { - char_u *p; char_u buf[NUMBUFLEN]; - if (str == NULL) { - ga_concat(gap, (char_u *)"NULL"); - return; - } - - for (p = str; *p != NUL; p++) { + if (clen > 1) { + memmove(buf, p, clen); + buf[clen] = NUL; + ga_concat(gap, buf); + } else { switch (*p) { case BS: ga_concat(gap, (char_u *)"\\b"); break; case ESC: ga_concat(gap, (char_u *)"\\e"); break; @@ -5585,6 +5584,41 @@ static void ga_concat_esc(garray_T *gap, char_u *str) } } +// Append "str" to "gap", escaping unprintable characters. +// Changes NL to \n, CR to \r, etc. +static void ga_concat_shorten_esc(garray_T *gap, const char_u *str) + FUNC_ATTR_NONNULL_ARG(1) +{ + char_u buf[NUMBUFLEN]; + + if (str == NULL) { + ga_concat(gap, (char_u *)"NULL"); + return; + } + + for (const char_u *p = str; *p != NUL; p++) { + int same_len = 1; + const char_u *s = p; + const int c = mb_ptr2char_adv(&s); + const int clen = s - p; + while (*s != NUL && c == utf_ptr2char(s)) { + same_len++; + s += clen; + } + if (same_len > 20) { + ga_concat(gap, (char_u *)"\\["); + ga_concat_esc(gap, p, clen); + ga_concat(gap, (char_u *)" occurs "); + vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len); + ga_concat(gap, buf); + ga_concat(gap, (char_u *)" times]"); + p = s - 1; + } else { + ga_concat_esc(gap, p, clen); + } + } +} + // Fill "gap" with information about an assert error. void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, @@ -5609,10 +5643,10 @@ void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, if (exp_str == NULL) { tofree = (char_u *)encode_tv2string(exp_tv, NULL); - ga_concat_esc(gap, tofree); + ga_concat_shorten_esc(gap, tofree); xfree(tofree); } else { - ga_concat_esc(gap, exp_str); + ga_concat_shorten_esc(gap, exp_str); } if (atype != ASSERT_NOTEQUAL) { @@ -5624,7 +5658,7 @@ void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, ga_concat(gap, (char_u *)" but got "); } tofree = (char_u *)encode_tv2string(got_tv, NULL); - ga_concat_esc(gap, tofree); + ga_concat_shorten_esc(gap, tofree); xfree(tofree); } } @@ -5674,6 +5708,9 @@ int assert_equalfile(typval_T *argvars) IObuff[0] = NUL; FILE *const fd1 = os_fopen(fname1, READBIN); + char line1[200]; + char line2[200]; + ptrdiff_t lineidx = 0; if (fd1 == NULL) { snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname1); } else { @@ -5682,6 +5719,7 @@ int assert_equalfile(typval_T *argvars) fclose(fd1); snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2); } else { + int64_t linecount = 1; for (int64_t count = 0; ; count++) { const int c1 = fgetc(fd1); const int c2 = fgetc(fd2); @@ -5693,10 +5731,24 @@ int assert_equalfile(typval_T *argvars) } else if (c2 == EOF) { STRCPY(IObuff, "second file is shorter"); break; - } else if (c1 != c2) { - snprintf((char *)IObuff, IOSIZE, - "difference at byte %" PRId64, count); - break; + } else { + line1[lineidx] = c1; + line2[lineidx] = c2; + lineidx++; + if (c1 != c2) { + snprintf((char *)IObuff, IOSIZE, + "difference at byte %" PRId64 ", line %" PRId64, + count, linecount); + break; + } + } + if (c1 == NL) { + linecount++; + lineidx = 0; + } else if (lineidx + 2 == (ptrdiff_t)sizeof(line1)) { + memmove(line1, line1 + 100, lineidx - 100); + memmove(line2, line2 + 100, lineidx - 100); + lineidx -= 100; } } fclose(fd1); @@ -5705,7 +5757,24 @@ int assert_equalfile(typval_T *argvars) } if (IObuff[0] != NUL) { prepare_assert_error(&ga); + if (argvars[2].v_type != VAR_UNKNOWN) { + char *const tofree = encode_tv2echo(&argvars[2], NULL); + ga_concat(&ga, (char_u *)tofree); + xfree(tofree); + ga_concat(&ga, (char_u *)": "); + } ga_concat(&ga, IObuff); + if (lineidx > 0) { + line1[lineidx] = NUL; + line2[lineidx] = NUL; + ga_concat(&ga, (char_u *)" after \""); + ga_concat(&ga, (char_u *)line1); + if (STRCMP(line1, line2) != 0) { + ga_concat(&ga, (char_u *)"\" vs \""); + ga_concat(&ga, (char_u *)line2); + } + ga_concat(&ga, (char_u *)"\""); + } assert_error(&ga); ga_clear(&ga); return 1; @@ -7143,6 +7212,16 @@ bool callback_from_typval(Callback *const callback, typval_T *const arg) func_ref(name); callback->data.funcref = vim_strsave(name); callback->type = kCallbackFuncref; + } else if (nlua_is_table_from_lua(arg)) { + char_u *name = nlua_register_table_as_callable(arg); + + if (name != NULL) { + func_ref(name); + callback->data.funcref = vim_strsave(name); + callback->type = kCallbackFuncref; + } else { + r = FAIL; + } } else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0) { callback->type = kCallbackNone; } else { @@ -8137,9 +8216,6 @@ void set_argv_var(char **argv, int argc) list_T *l = tv_list_alloc(argc); int i; - if (l == NULL) { - getout(1); - } tv_list_set_lock(l, VAR_FIXED); for (i = 0; i < argc; i++) { tv_list_append_string(l, (const char *const)argv[i], -1); |