diff options
Diffstat (limited to 'src/nvim/eval.c')
| -rw-r--r-- | src/nvim/eval.c | 101 | 
1 files changed, 85 insertions, 16 deletions
| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index e1f9fe0253..0a83c3a586 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -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; | 
