To: vim_dev@googlegroups.com Subject: Patch 8.0.1782 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1782 Problem: No simple way to label quickfix entries. Solution: Add the "module" item, to be used instead of the file name for display purposes. (Martin Szamotulski, closes #1757) Files: runtime/doc/eval.txt, runtime/doc/quickfix.txt, src/alloc.h, src/quickfix.c, src/testdir/test_quickfix.vim *** ../vim-8.0.1781/runtime/doc/eval.txt 2018-04-28 16:56:20.792322716 +0200 --- runtime/doc/eval.txt 2018-05-01 14:44:41.069164006 +0200 *************** *** 4721,4726 **** --- 4737,4743 ---- list item is a dictionary with these entries: bufnr number of buffer that has the file name, use bufname() to get the name + module module name lnum line number in the buffer (first line is 1) col column number (first column is 1) vcol |TRUE|: "col" is visual column *************** *** 7186,7191 **** --- 7222,7229 ---- buffer filename name of a file; only used when "bufnr" is not present or it is invalid. + module name of a module; if given it will be used in + quickfix error window instead of the filename. lnum line number in the file pattern search pattern used to locate the error col column number *** ../vim-8.0.1781/runtime/doc/quickfix.txt 2017-12-18 19:48:34.805669514 +0100 --- runtime/doc/quickfix.txt 2018-05-01 14:47:25.436146945 +0200 *************** *** 1135,1140 **** --- 1220,1226 ---- Basic items %f file name (finds a string) + %o module name (finds a string) %l line number (finds a number) %c column number (finds a number representing character column of the error, (1 == 1 character column)) *************** *** 1179,1184 **** --- 1265,1275 ---- output. Like the output of the "grep" shell command. When the pattern is present the line number will not be used. + The "%o" conversion specifies the module name in quickfix entry. If present + it will be used in quickfix error window instead of the filename. The module + name is used only for displaying purposes, the file name is used when jumping + to the file. + Changing directory The following uppercase conversion characters specify the type of special *** ../vim-8.0.1781/src/alloc.h 2016-08-29 22:42:14.000000000 +0200 --- src/alloc.h 2018-05-01 14:44:41.069164006 +0200 *************** *** 15,20 **** --- 15,21 ---- aid_qf_dirname_start, aid_qf_dirname_now, aid_qf_namebuf, + aid_qf_module, aid_qf_errmsg, aid_qf_pattern, aid_last *** ../vim-8.0.1781/src/quickfix.c 2018-05-01 14:30:32.250507112 +0200 --- src/quickfix.c 2018-05-01 14:51:51.150461918 +0200 *************** *** 33,38 **** --- 33,39 ---- int qf_fnum; /* file number for the line */ int qf_col; /* column where the error occurred */ int qf_nr; /* error number */ + char_u *qf_module; /* module name for this error */ char_u *qf_pattern; /* search pattern for the error */ char_u *qf_text; /* description of the error */ char_u qf_viscol; /* set to TRUE if qf_col is screen column */ *************** *** 101,107 **** static qf_info_T ql_info; /* global quickfix list */ static int_u last_qf_id = 0; /* Last used quickfix list id */ ! #define FMT_PATTERNS 10 /* maximum number of % recognized */ /* * Structure used to hold the info of one part of 'errorformat' --- 102,108 ---- static qf_info_T ql_info; /* global quickfix list */ static int_u last_qf_id = 0; /* Last used quickfix list id */ ! #define FMT_PATTERNS 11 /* maximum number of % recognized */ /* * Structure used to hold the info of one part of 'errorformat' *************** *** 135,141 **** static int qf_init_ext(qf_info_T *qi, int qf_idx, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc); static void qf_new_list(qf_info_T *qi, char_u *qf_title); ! static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid); static void qf_free(qf_info_T *qi, int idx); static char_u *qf_types(int, int); static int qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *, char_u *); --- 136,143 ---- static int qf_init_ext(qf_info_T *qi, int qf_idx, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc); static void qf_new_list(qf_info_T *qi, char_u *qf_title); ! static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid); ! static qf_info_T *ll_new_list(void); static void qf_free(qf_info_T *qi, int idx); static char_u *qf_types(int, int); static int qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *, char_u *); *************** *** 221,227 **** {'r', ".*"}, {'p', "[- .]*"}, {'v', "\\d\\+"}, ! {'s', ".\\+"} }; /* --- 223,230 ---- {'r', ".*"}, {'p', "[- .]*"}, {'v', "\\d\\+"}, ! {'s', ".\\+"}, ! {'o', ".\\+"} }; /* *************** *** 809,814 **** --- 812,818 ---- typedef struct { char_u *namebuf; + char_u *module; char_u *errmsg; int errmsglen; long lnum; *************** *** 868,873 **** --- 872,878 ---- if (qfl->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) continue; fields->namebuf[0] = NUL; + fields->module[0] = NUL; fields->pattern[0] = NUL; if (!qfl->qf_multiscan) fields->errmsg[0] = NUL; *************** *** 1008,1013 **** --- 1013,1027 ---- fields->pattern[len + 4] = '$'; fields->pattern[len + 5] = NUL; } + if ((i = (int)fmt_ptr->addr[10]) > 0) /* %o */ + { + if (regmatch.startp[i] == NULL) + continue; + len = (int)(regmatch.endp[i] - regmatch.startp[i]); + if (len > CMDBUFFSIZE) + len = CMDBUFFSIZE; + STRNCAT(fields->module, regmatch.startp[i], len); + } break; } } *************** *** 1181,1191 **** convert_setup(&state.vc, enc, p_enc); #endif fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf); fields.errmsglen = CMDBUFFSIZE + 1; fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); if (fields.namebuf == NULL || fields.errmsg == NULL ! || fields.pattern == NULL) goto qf_init_end; if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) --- 1195,1206 ---- convert_setup(&state.vc, enc, p_enc); #endif fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf); + fields.module = alloc_id(CMDBUFFSIZE + 1, aid_qf_module); fields.errmsglen = CMDBUFFSIZE + 1; fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); if (fields.namebuf == NULL || fields.errmsg == NULL ! || fields.pattern == NULL || fields.module == NULL) goto qf_init_end; if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) *************** *** 1282,1287 **** --- 1297,1303 ---- ? fields.namebuf : ((qfl->qf_currfile != NULL && fields.valid) ? qfl->qf_currfile : (char_u *)NULL), + fields.module, 0, fields.errmsg, fields.lnum, *************** *** 1327,1332 **** --- 1343,1349 ---- if (state.fd != NULL) fclose(state.fd); vim_free(fields.namebuf); + vim_free(fields.module); vim_free(fields.errmsg); vim_free(fields.pattern); vim_free(state.growbuf); *************** *** 1444,1449 **** --- 1461,1467 ---- int qf_idx, /* list index */ char_u *dir, /* optional directory name */ char_u *fname, /* file name or NULL */ + char_u *module, /* module name or NULL */ int bufnum, /* buffer number or zero */ char_u *mesg, /* message */ long lnum, /* line number */ *************** *** 1486,1491 **** --- 1504,1518 ---- vim_free(qfp); return FAIL; } + if (module == NULL || *module == NUL) + qfp->qf_module = NULL; + else if ((qfp->qf_module = vim_strsave(module)) == NULL) + { + vim_free(qfp->qf_text); + vim_free(qfp->qf_pattern); + vim_free(qfp); + return FAIL; + } qfp->qf_nr = nr; if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */ type = 0; *************** *** 1635,1640 **** --- 1662,1668 ---- to->w_llist->qf_curlist, NULL, NULL, + from_qfp->qf_module, 0, from_qfp->qf_text, from_qfp->qf_lnum, *************** *** 2765,2782 **** break; fname = NULL; ! if (qfp->qf_fnum != 0 ! && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) ! { ! fname = buf->b_fname; ! if (qfp->qf_type == 1) /* :helpgrep */ ! fname = gettail(fname); } - if (fname == NULL) - sprintf((char *)IObuff, "%2d", i); - else - vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", - i, (char *)fname); msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index ? HL_ATTR(HLF_QFL) : qfFileAttr); --- 2793,2814 ---- break; fname = NULL; ! if (qfp->qf_module != NULL && *qfp->qf_module != NUL) ! vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char *)qfp->qf_module); ! else { ! if (qfp->qf_fnum != 0 ! && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) ! { ! fname = buf->b_fname; ! if (qfp->qf_type == 1) /* :helpgrep */ ! fname = gettail(fname); ! } ! if (fname == NULL) ! sprintf((char *)IObuff, "%2d", i); ! else ! vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", ! i, (char *)fname); } msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index ? HL_ATTR(HLF_QFL) : qfFileAttr); *************** *** 2957,2965 **** qfpnext = qfp->qf_next; if (!stop) { vim_free(qfp->qf_text); - stop = (qfp == qfpnext); vim_free(qfp->qf_pattern); vim_free(qfp); if (stop) /* Somehow qf_count may have an incorrect value, set it to 1 --- 2989,2998 ---- qfpnext = qfp->qf_next; if (!stop) { + vim_free(qfp->qf_module); vim_free(qfp->qf_text); vim_free(qfp->qf_pattern); + stop = (qfp == qfpnext); vim_free(qfp); if (stop) /* Somehow qf_count may have an incorrect value, set it to 1 *************** *** 3562,3568 **** } while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) { ! if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { --- 3595,3606 ---- } while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) { ! if (qfp->qf_module != NULL) ! { ! STRCPY(IObuff, qfp->qf_module); ! len = (int)STRLEN(IObuff); ! } ! else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { *************** *** 4367,4372 **** --- 4405,4411 ---- qi->qf_curlist, NULL, /* dir */ fname, + NULL, duplicate_name ? 0 : buf->b_fnum, ml_get_buf(buf, regmatch->startpos[0].lnum + lnum, FALSE), *************** *** 4934,4939 **** --- 4973,4980 ---- || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL + || dict_add_nr_str(dict, "module", 0L, + qfp->qf_module == NULL ? (char_u *)"" : qfp->qf_module) == FAIL || dict_add_nr_str(dict, "pattern", 0L, qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL || dict_add_nr_str(dict, "text", 0L, *************** *** 5312,5318 **** { listitem_T *li; dict_T *d; ! char_u *filename, *pattern, *text, *type; int bufnum; long lnum; int col, nr; --- 5353,5359 ---- { listitem_T *li; dict_T *d; ! char_u *filename, *module, *pattern, *text, *type; int bufnum; long lnum; int col, nr; *************** *** 5347,5352 **** --- 5388,5394 ---- continue; filename = get_dict_string(d, (char_u *)"filename", TRUE); + module = get_dict_string(d, (char_u *)"module", TRUE); bufnum = (int)get_dict_number(d, (char_u *)"bufnr"); lnum = (int)get_dict_number(d, (char_u *)"lnum"); col = (int)get_dict_number(d, (char_u *)"col"); *************** *** 5383,5388 **** --- 5425,5431 ---- qf_idx, NULL, /* dir */ filename, + module, bufnum, text, lnum, *************** *** 5394,5399 **** --- 5437,5443 ---- valid); vim_free(filename); + vim_free(module); vim_free(pattern); vim_free(text); vim_free(type); *************** *** 6040,6045 **** --- 6084,6090 ---- qi->qf_curlist, NULL, /* dir */ fname, + NULL, 0, line, lnum, *************** *** 6104,6110 **** /* Skip files for a different language. */ if (lang != NULL && STRNICMP(lang, fnames[fi] ! + STRLEN(fnames[fi]) - 3, 2) != 0 && !(STRNICMP(lang, "en", 2) == 0 && STRNICMP("txt", fnames[fi] + STRLEN(fnames[fi]) - 3, 3) == 0)) --- 6149,6155 ---- /* Skip files for a different language. */ if (lang != NULL && STRNICMP(lang, fnames[fi] ! + STRLEN(fnames[fi]) - 3, 2) != 0 && !(STRNICMP(lang, "en", 2) == 0 && STRNICMP("txt", fnames[fi] + STRLEN(fnames[fi]) - 3, 3) == 0)) *** ../vim-8.0.1781/src/testdir/test_quickfix.vim 2018-05-01 14:30:32.246507139 +0200 --- src/testdir/test_quickfix.vim 2018-05-01 14:44:41.069164006 +0200 *************** *** 138,143 **** --- 138,153 ---- \ ' 4:40 col 20 x 44: Other', \ ' 5:50 col 25 55: one'], l) + " Test for module names, one needs to explicitly set `'valid':v:true` so + call g:Xsetlist([ + \ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true}, + \ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true}, + \ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}]) + let l = split(execute('Xlist', ""), "\n") + call assert_equal([' 1 Data.Text:10 col 5 warning 11: ModuleWarning', + \ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning', + \ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l) + " Error cases call assert_fails('Xlist abc', 'E488:') endfunc *************** *** 1142,1147 **** --- 1152,1172 ---- call assert_equal(1, l[4].valid) call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) + " Test for %o + set efm=%f(%o):%l\ %m + cgetexpr ['Xtestfile(Language.PureScript.Types):20 Error'] + call writefile(['Line1'], 'Xtestfile') + let l = getqflist() + call assert_equal(1, len(l), string(l)) + call assert_equal('Language.PureScript.Types', l[0].module) + copen + call assert_equal('Language.PureScript.Types|20| Error', getline(1)) + call feedkeys("\", 'xn') + call assert_equal('Xtestfile', expand('%:t')) + cclose + bd + call delete("Xtestfile") + " The following sequence of commands used to crash Vim set efm=%W%m cgetexpr ['msg1'] *** ../vim-8.0.1781/src/version.c 2018-05-01 14:30:32.250507112 +0200 --- src/version.c 2018-05-01 15:00:06.607133174 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 1782, /**/ -- FIRST GUARD: Ah! Now ... we're not allowed to ... SIR LAUNCELOT runs him through, grabs his spear and stabs the other guard who collapses in a heap. Hiccoughs quietly. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///