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.