Patch 9.0.0736
Problem:    Quickfix listing does not handle very long messages.
Solution:   Use a growarray instead of a fixed size buffer. (Yegappan
            Lakshmanan, closes #11357)
Files:      src/quickfix.c, src/testdir/test_quickfix.vim


*** ../vim-9.0.0735/src/quickfix.c      2022-08-29 20:45:11.344535306 +0100
--- src/quickfix.c      2022-10-13 11:47:57.445145504 +0100
***************
*** 176,183 ****
  static char_u *qf_pop_dir(struct dir_stack_T **);
  static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *);
  static void   qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int 
forceit, int newwin);
! static void   qf_fmt_text(char_u *text, char_u *buf, int bufsize);
! static void   qf_range_text(qfline_T *qfp, char_u *buf, int bufsize);
  static int    qf_win_pos_update(qf_info_T *qi, int old_qf_index);
  static win_T  *qf_find_win(qf_info_T *qi);
  static buf_T  *qf_find_buf(qf_info_T *qi);
--- 176,183 ----
  static char_u *qf_pop_dir(struct dir_stack_T **);
  static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *);
  static void   qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int 
forceit, int newwin);
! static void   qf_fmt_text(garray_T *gap, char_u *text);
! static void   qf_range_text(garray_T *gap, qfline_T *qfp);
  static int    qf_win_pos_update(qf_info_T *qi, int old_qf_index);
  static win_T  *qf_find_win(qf_info_T *qi);
  static buf_T  *qf_find_buf(qf_info_T *qi);
***************
*** 3286,3304 ****
        linenr_T        old_lnum)
  {
      linenr_T          i;
!     int                       len;
  
      // Update the screen before showing the message, unless the screen
      // scrolled up.
      if (!msg_scrolled)
        update_topline_redraw();
!     sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index,
            qf_get_curlist(qi)->qf_count,
            qf_ptr->qf_cleared ? _(" (line deleted)") : "",
            (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
      // Add the message, skipping leading whitespace and newlines.
!     len = (int)STRLEN(IObuff);
!     qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len);
  
      // Output the message.  Overwrite to avoid scrolling when the 'O'
      // flag is present in 'shortmess'; But when not jumping, print the
--- 3286,3305 ----
        linenr_T        old_lnum)
  {
      linenr_T          i;
!     garray_T          ga;
  
      // Update the screen before showing the message, unless the screen
      // scrolled up.
      if (!msg_scrolled)
        update_topline_redraw();
!     vim_snprintf((char *)IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index,
            qf_get_curlist(qi)->qf_count,
            qf_ptr->qf_cleared ? _(" (line deleted)") : "",
            (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
      // Add the message, skipping leading whitespace and newlines.
!     ga_init2(&ga, 1, 256);
!     ga_concat(&ga, IObuff);
!     qf_fmt_text(&ga, skipwhite(qf_ptr->qf_text));
  
      // Output the message.  Overwrite to avoid scrolling when the 'O'
      // flag is present in 'shortmess'; But when not jumping, print the
***************
*** 3308,3315 ****
        msg_scroll = TRUE;
      else if (!msg_scrolled && shortmess(SHM_OVERALL))
        msg_scroll = FALSE;
!     msg_attr_keep((char *)IObuff, 0, TRUE);
      msg_scroll = i;
  }
  
  /*
--- 3309,3317 ----
        msg_scroll = TRUE;
      else if (!msg_scrolled && shortmess(SHM_OVERALL))
        msg_scroll = FALSE;
!     msg_attr_keep((char *)ga.ga_data, 0, TRUE);
      msg_scroll = i;
+     ga_clear(&ga);
  }
  
  /*
***************
*** 3574,3579 ****
--- 3576,3582 ----
      char_u    *fname;
      buf_T     *buf;
      int               filter_entry;
+     garray_T  ga;
  
      fname = NULL;
      if (qfp->qf_module != NULL && *qfp->qf_module != NUL)
***************
*** 3614,3659 ****
  
      if (qfp->qf_lnum != 0)
        msg_puts_attr(":", qfSepAttr);
      if (qfp->qf_lnum == 0)
!       IObuff[0] = NUL;
      else
!       qf_range_text(qfp, IObuff, IOSIZE);
!     sprintf((char *)IObuff + STRLEN(IObuff), "%s",
!           (char *)qf_types(qfp->qf_type, qfp->qf_nr));
!     msg_puts_attr((char *)IObuff, qfLineAttr);
      msg_puts_attr(":", qfSepAttr);
      if (qfp->qf_pattern != NULL)
      {
!       qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
!       msg_puts((char *)IObuff);
        msg_puts_attr(":", qfSepAttr);
      }
      msg_puts(" ");
  
      {
-       char_u *tbuf = IObuff;
-       size_t  tbuflen = IOSIZE;
-       size_t  len = STRLEN(qfp->qf_text) + 3;
- 
-       if (len > IOSIZE)
-       {
-           tbuf = alloc(len);
-           if (tbuf != NULL)
-               tbuflen = len;
-           else
-               tbuf = IObuff;
-       }
- 
        // Remove newlines and leading whitespace from the text.  For an
        // unrecognized line keep the indent, the compiler may mark a word
        // with ^^^^.
!       qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
!                                   ? skipwhite(qfp->qf_text) : qfp->qf_text,
!                                   tbuf, (int)tbuflen);
!       msg_prt_line(tbuf, FALSE);
! 
!       if (tbuf != IObuff)
!           vim_free(tbuf);
      }
      out_flush();              // show one line at a time
  }
--- 3617,3649 ----
  
      if (qfp->qf_lnum != 0)
        msg_puts_attr(":", qfSepAttr);
+     ga_init2(&ga, 1, 256);
      if (qfp->qf_lnum == 0)
!       ga_append(&ga, NUL);
      else
!       qf_range_text(&ga, qfp);
!     ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr));
!     ga_append(&ga, NUL);
!     msg_puts_attr((char *)ga.ga_data, qfLineAttr);
!     ga_clear(&ga);
      msg_puts_attr(":", qfSepAttr);
      if (qfp->qf_pattern != NULL)
      {
!       qf_fmt_text(&ga, qfp->qf_pattern);
!       msg_puts((char *)ga.ga_data);
!       ga_clear(&ga);
        msg_puts_attr(":", qfSepAttr);
      }
      msg_puts(" ");
  
      {
        // Remove newlines and leading whitespace from the text.  For an
        // unrecognized line keep the indent, the compiler may mark a word
        // with ^^^^.
!       qf_fmt_text(&ga, (fname != NULL || qfp->qf_lnum != 0)
!                                   ? skipwhite(qfp->qf_text) : qfp->qf_text);
!       msg_prt_line((char_u *)ga.ga_data, FALSE);
!       ga_clear(&ga);
      }
      out_flush();              // show one line at a time
  }
***************
*** 3738,3774 ****
  
  /*
   * Remove newlines and leading whitespace from an error message.
!  * Put the result in "buf[bufsize]".
   */
      static void
! qf_fmt_text(char_u *text, char_u *buf, int bufsize)
  {
-     int               i;
      char_u    *p = text;
  
!     for (i = 0; *p != NUL && i < bufsize - 1; ++i)
      {
        if (*p == '\n')
        {
!           buf[i] = ' ';
            while (*++p != NUL)
                if (!VIM_ISWHITE(*p) && *p != '\n')
                    break;
        }
        else
!           buf[i] = *p++;
      }
!     buf[i] = NUL;
  }
  
  /*
!  * Range information from lnum, col, end_lnum, and end_col.
!  * Put the result in "buf[bufsize]".
   */
      static void
! qf_range_text(qfline_T *qfp, char_u *buf, int bufsize)
  {
      int len;
      vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum);
      len = (int)STRLEN(buf);
  
--- 3728,3767 ----
  
  /*
   * Remove newlines and leading whitespace from an error message.
!  * Add the result to the grow array "gap".
   */
      static void
! qf_fmt_text(garray_T *gap, char_u *text)
  {
      char_u    *p = text;
  
!     while (*p != NUL)
      {
        if (*p == '\n')
        {
!           ga_append(gap, ' ');
            while (*++p != NUL)
                if (!VIM_ISWHITE(*p) && *p != '\n')
                    break;
        }
        else
!           ga_append(gap, *p++);
      }
! 
!     ga_append(gap, NUL);
  }
  
  /*
!  * Add the range information from the lnum, col, end_lnum, and end_col values
!  * of a quickfix entry to the grow array "gap".
   */
      static void
! qf_range_text(garray_T *gap, qfline_T *qfp)
  {
+     char_u    *buf = IObuff;
+     int               bufsize = IOSIZE;
      int len;
+ 
      vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum);
      len = (int)STRLEN(buf);
  
***************
*** 3790,3795 ****
--- 3783,3790 ----
        }
      }
      buf[len] = NUL;
+ 
+     ga_concat_len(gap, buf, len);
  }
  
  /*
***************
*** 4597,4622 ****
        int             first_bufline,
        char_u          *qftf_str)
  {
-     int               len;
      buf_T     *errbuf;
  
      // If the 'quickfixtextfunc' function returned a non-empty custom string
      // for this entry, then use it.
      if (qftf_str != NULL && *qftf_str != NUL)
!       vim_strncpy(IObuff, qftf_str, IOSIZE - 1);
      else
      {
        if (qfp->qf_module != NULL)
!       {
!           vim_strncpy(IObuff, qfp->qf_module, IOSIZE - 1);
!           len = (int)STRLEN(IObuff);
!       }
        else if (qfp->qf_fnum != 0
                && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
                && errbuf->b_fname != NULL)
        {
            if (qfp->qf_type == 1)      // :helpgrep
!               vim_strncpy(IObuff, gettail(errbuf->b_fname), IOSIZE - 1);
            else
            {
                // Shorten the file name if not done already.
--- 4592,4616 ----
        int             first_bufline,
        char_u          *qftf_str)
  {
      buf_T     *errbuf;
+     garray_T  ga;
+ 
+     ga_init2(&ga, 1, 256);
  
      // If the 'quickfixtextfunc' function returned a non-empty custom string
      // for this entry, then use it.
      if (qftf_str != NULL && *qftf_str != NUL)
!       ga_concat(&ga, qftf_str);
      else
      {
        if (qfp->qf_module != NULL)
!           ga_concat(&ga, qfp->qf_module);
        else if (qfp->qf_fnum != 0
                && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
                && errbuf->b_fname != NULL)
        {
            if (qfp->qf_type == 1)      // :helpgrep
!               ga_concat(&ga, gettail(errbuf->b_fname));
            else
            {
                // Shorten the file name if not done already.
***************
*** 4629,4675 ****
                        mch_dirname(dirname, MAXPATHL);
                    shorten_buf_fname(errbuf, dirname, FALSE);
                }
!               vim_strncpy(IObuff, errbuf->b_fname, IOSIZE - 1);
            }
-           len = (int)STRLEN(IObuff);
        }
-       else
-           len = 0;
  
!       if (len < IOSIZE - 1)
!           IObuff[len++] = '|';
  
        if (qfp->qf_lnum > 0)
        {
!           qf_range_text(qfp, IObuff + len, IOSIZE - len);
!           len += (int)STRLEN(IObuff + len);
! 
!           vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s",
!                   (char *)qf_types(qfp->qf_type, qfp->qf_nr));
!           len += (int)STRLEN(IObuff + len);
        }
        else if (qfp->qf_pattern != NULL)
!       {
!           qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
!           len += (int)STRLEN(IObuff + len);
!       }
!       if (len < IOSIZE - 2)
!       {
!           IObuff[len++] = '|';
!           IObuff[len++] = ' ';
!       }
  
        // Remove newlines and leading whitespace from the text.
        // For an unrecognized line keep the indent, the compiler may
        // mark a word with ^^^^.
!       qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
!               IObuff + len, IOSIZE - len);
      }
  
!     if (ml_append_buf(buf, lnum, IObuff,
!               (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL)
        return FAIL;
  
      return OK;
  }
  
--- 4623,4657 ----
                        mch_dirname(dirname, MAXPATHL);
                    shorten_buf_fname(errbuf, dirname, FALSE);
                }
!               ga_concat(&ga, errbuf->b_fname);
            }
        }
  
!       ga_append(&ga, '|');
  
        if (qfp->qf_lnum > 0)
        {
!           qf_range_text(&ga, qfp);
!           ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr));
        }
        else if (qfp->qf_pattern != NULL)
!           qf_fmt_text(&ga, qfp->qf_pattern);
!       ga_append(&ga, '|');
!       ga_append(&ga, ' ');
  
        // Remove newlines and leading whitespace from the text.
        // For an unrecognized line keep the indent, the compiler may
        // mark a word with ^^^^.
!       qf_fmt_text(&ga, ga.ga_len > 3 ? skipwhite(qfp->qf_text) : 
qfp->qf_text);
      }
  
!     ga_append(&ga, NUL);
! 
!     if (ml_append_buf(buf, lnum, ga.ga_data, ga.ga_len + 1, FALSE) == FAIL)
        return FAIL;
  
+     ga_clear(&ga);
+ 
      return OK;
  }
  
*** ../vim-9.0.0735/src/testdir/test_quickfix.vim       2022-10-05 
21:45:23.775124283 +0100
--- src/testdir/test_quickfix.vim       2022-10-13 11:47:57.445145504 +0100
***************
*** 6334,6337 ****
--- 6334,6375 ----
    call setloclist(0, [], 'f')
  endfunc
  
+ " Test for a very long error line and a very long information line
+ func Test_very_long_error_line()
+   let msg = repeat('abcdefghijklmn', 146)
+   let emsg = 'Xlonglines.c:1:' . msg
+   call writefile([msg, emsg], 'Xerror', 'D')
+   cfile Xerror
+   cwindow
+   call assert_equal($'|| {msg}', getline(1))
+   call assert_equal($'Xlonglines.c|1| {msg}', getline(2))
+   cclose
+ 
+   let l = execute('clist!')->split("\n")
+   call assert_equal([$' 1: {msg}', $' 2 Xlonglines.c:1: {msg}'], l)
+ 
+   let l = execute('cc')->split("\n")
+   call assert_equal([$'(2 of 2): {msg}'], l)
+ 
+   call setqflist([], 'f')
+ endfunc
+ 
+ " In the quickfix window, spaces at the beginning of an informational line
+ " should not be removed but should be removed from an error line.
+ func Test_info_line_with_space()
+   cexpr ["a.c:20:12:         error: expected ';' before ':' token",
+         \ '   20 |     Afunc():', '', '      |            ^']
+   copen
+   call assert_equal(["a.c|20 col 12| error: expected ';' before ':' token",
+         \ '||    20 |     Afunc():', '|| ',
+         \ '||       |            ^'], getline(1, '$'))
+   cclose
+ 
+   let l = execute('clist!')->split("\n")
+   call assert_equal([" 1 a.c:20 col 12: error: expected ';' before ':' token",
+         \ ' 2:    20 |     Afunc():', ' 3:  ', ' 4:       |            ^'], l)
+ 
+   call setqflist([], 'f')
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.0735/src/version.c       2022-10-12 21:32:38.428890899 +0100
--- src/version.c       2022-10-13 11:49:13.088369085 +0100
***************
*** 701,702 ****
--- 701,704 ----
  {   /* Add new patch number below this line */
+ /**/
+     736,
  /**/

-- 
GUEST:        He's killed the best man!
SECOND GUEST: (holding a limp WOMAN) He's killed my auntie.
FATHER:       No, please!  This is supposed to be a happy occasion!  Let's
              not bicker and argue about who killed who ...
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221013105954.7F3281C5298%40moolenaar.net.

Raspunde prin e-mail lui