Skip to content

Commit 2225ebb

Browse files
committed
patch 8.0.1754: ex_helpgrep() is too long
Problem: ex_helpgrep() is too long. Solution: Refactor the function. (Yegappan Lakshmanan, closes #2766)
1 parent 1c17ffa commit 2225ebb

File tree

3 files changed

+219
-136
lines changed

3 files changed

+219
-136
lines changed

src/quickfix.c

Lines changed: 211 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -5942,32 +5942,227 @@ ex_cexpr(exarg_T *eap)
59425942
#endif
59435943

59445944
/*
5945-
* ":helpgrep {pattern}"
5945+
* Get the location list for ":lhelpgrep"
59465946
*/
5947-
void
5948-
ex_helpgrep(exarg_T *eap)
5947+
static qf_info_T *
5948+
hgr_get_ll(int *new_ll)
5949+
{
5950+
win_T *wp;
5951+
qf_info_T *qi;
5952+
5953+
/* If the current window is a help window, then use it */
5954+
if (bt_help(curwin->w_buffer))
5955+
wp = curwin;
5956+
else
5957+
/* Find an existing help window */
5958+
FOR_ALL_WINDOWS(wp)
5959+
if (bt_help(wp->w_buffer))
5960+
break;
5961+
5962+
if (wp == NULL) /* Help window not found */
5963+
qi = NULL;
5964+
else
5965+
qi = wp->w_llist;
5966+
5967+
if (qi == NULL)
5968+
{
5969+
/* Allocate a new location list for help text matches */
5970+
if ((qi = ll_new_list()) == NULL)
5971+
return NULL;
5972+
*new_ll = TRUE;
5973+
}
5974+
5975+
return qi;
5976+
}
5977+
5978+
/*
5979+
* Search for a pattern in a help file.
5980+
*/
5981+
static void
5982+
hgr_search_file(
5983+
qf_info_T *qi,
5984+
char_u *fname,
5985+
#ifdef FEAT_MBYTE
5986+
vimconv_T *p_vc,
5987+
#endif
5988+
regmatch_T *p_regmatch)
5989+
{
5990+
FILE *fd;
5991+
long lnum;
5992+
5993+
fd = mch_fopen((char *)fname, "r");
5994+
if (fd == NULL)
5995+
return;
5996+
5997+
lnum = 1;
5998+
while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
5999+
{
6000+
char_u *line = IObuff;
6001+
#ifdef FEAT_MBYTE
6002+
/* Convert a line if 'encoding' is not utf-8 and
6003+
* the line contains a non-ASCII character. */
6004+
if (p_vc->vc_type != CONV_NONE
6005+
&& has_non_ascii(IObuff))
6006+
{
6007+
line = string_convert(p_vc, IObuff, NULL);
6008+
if (line == NULL)
6009+
line = IObuff;
6010+
}
6011+
#endif
6012+
6013+
if (vim_regexec(p_regmatch, line, (colnr_T)0))
6014+
{
6015+
int l = (int)STRLEN(line);
6016+
6017+
/* remove trailing CR, LF, spaces, etc. */
6018+
while (l > 0 && line[l - 1] <= ' ')
6019+
line[--l] = NUL;
6020+
6021+
if (qf_add_entry(qi,
6022+
qi->qf_curlist,
6023+
NULL, /* dir */
6024+
fname,
6025+
0,
6026+
line,
6027+
lnum,
6028+
(int)(p_regmatch->startp[0] - line)
6029+
+ 1, /* col */
6030+
FALSE, /* vis_col */
6031+
NULL, /* search pattern */
6032+
0, /* nr */
6033+
1, /* type */
6034+
TRUE /* valid */
6035+
) == FAIL)
6036+
{
6037+
got_int = TRUE;
6038+
#ifdef FEAT_MBYTE
6039+
if (line != IObuff)
6040+
vim_free(line);
6041+
#endif
6042+
break;
6043+
}
6044+
}
6045+
#ifdef FEAT_MBYTE
6046+
if (line != IObuff)
6047+
vim_free(line);
6048+
#endif
6049+
++lnum;
6050+
line_breakcheck();
6051+
}
6052+
fclose(fd);
6053+
}
6054+
6055+
/*
6056+
* Search for a pattern in all the help files in the doc directory under
6057+
* the given directory.
6058+
*/
6059+
static void
6060+
hgr_search_files_in_dir(
6061+
qf_info_T *qi,
6062+
char_u *dirname,
6063+
regmatch_T *p_regmatch
6064+
#ifdef FEAT_MBYTE
6065+
, vimconv_T *p_vc
6066+
#endif
6067+
#ifdef FEAT_MULTI_LANG
6068+
, char_u *lang
6069+
#endif
6070+
)
59496071
{
5950-
regmatch_T regmatch;
5951-
char_u *save_cpo;
5952-
char_u *p;
59536072
int fcount;
59546073
char_u **fnames;
5955-
FILE *fd;
59566074
int fi;
5957-
long lnum;
6075+
6076+
/* Find all "*.txt" and "*.??x" files in the "doc" directory. */
6077+
add_pathsep(dirname);
6078+
STRCAT(dirname, "doc/*.\\(txt\\|??x\\)");
6079+
if (gen_expand_wildcards(1, &dirname, &fcount,
6080+
&fnames, EW_FILE|EW_SILENT) == OK
6081+
&& fcount > 0)
6082+
{
6083+
for (fi = 0; fi < fcount && !got_int; ++fi)
6084+
{
6085+
#ifdef FEAT_MULTI_LANG
6086+
/* Skip files for a different language. */
6087+
if (lang != NULL
6088+
&& STRNICMP(lang, fnames[fi]
6089+
+ STRLEN(fnames[fi]) - 3, 2) != 0
6090+
&& !(STRNICMP(lang, "en", 2) == 0
6091+
&& STRNICMP("txt", fnames[fi]
6092+
+ STRLEN(fnames[fi]) - 3, 3) == 0))
6093+
continue;
6094+
#endif
6095+
6096+
hgr_search_file(qi, fnames[fi],
6097+
#ifdef FEAT_MBYTE
6098+
p_vc,
6099+
#endif
6100+
p_regmatch);
6101+
}
6102+
FreeWild(fcount, fnames);
6103+
}
6104+
}
6105+
6106+
/*
6107+
* Search for a pattern in all the help files in the 'runtimepath'.
6108+
*/
6109+
static void
6110+
hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg)
6111+
{
6112+
char_u *p;
59586113
#ifdef FEAT_MULTI_LANG
59596114
char_u *lang;
59606115
#endif
5961-
qf_info_T *qi = &ql_info;
5962-
int new_qi = FALSE;
5963-
win_T *wp;
5964-
char_u *au_name = NULL;
6116+
6117+
#ifdef FEAT_MBYTE
6118+
vimconv_T vc;
6119+
6120+
/* Help files are in utf-8 or latin1, convert lines when 'encoding'
6121+
* differs. */
6122+
vc.vc_type = CONV_NONE;
6123+
if (!enc_utf8)
6124+
convert_setup(&vc, (char_u *)"utf-8", p_enc);
6125+
#endif
59656126

59666127
#ifdef FEAT_MULTI_LANG
59676128
/* Check for a specified language */
5968-
lang = check_help_lang(eap->arg);
6129+
lang = check_help_lang(arg);
59696130
#endif
59706131

6132+
/* Go through all directories in 'runtimepath' */
6133+
p = p_rtp;
6134+
while (*p != NUL && !got_int)
6135+
{
6136+
copy_option_part(&p, NameBuff, MAXPATHL, ",");
6137+
6138+
hgr_search_files_in_dir(qi, NameBuff, p_regmatch
6139+
#ifdef FEAT_MBYTE
6140+
, &vc
6141+
#endif
6142+
#ifdef FEAT_MULTI_LANG
6143+
, lang
6144+
#endif
6145+
);
6146+
}
6147+
6148+
#ifdef FEAT_MBYTE
6149+
if (vc.vc_type != CONV_NONE)
6150+
convert_setup(&vc, NULL, NULL);
6151+
#endif
6152+
}
6153+
6154+
/*
6155+
* ":helpgrep {pattern}"
6156+
*/
6157+
void
6158+
ex_helpgrep(exarg_T *eap)
6159+
{
6160+
regmatch_T regmatch;
6161+
char_u *save_cpo;
6162+
qf_info_T *qi = &ql_info;
6163+
int new_qi = FALSE;
6164+
char_u *au_name = NULL;
6165+
59716166
switch (eap->cmdidx)
59726167
{
59736168
case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break;
@@ -5989,141 +6184,21 @@ ex_helpgrep(exarg_T *eap)
59896184

59906185
if (eap->cmdidx == CMD_lhelpgrep)
59916186
{
5992-
/* If the current window is a help window, then use it */
5993-
if (bt_help(curwin->w_buffer))
5994-
wp = curwin;
5995-
else
5996-
/* Find an existing help window */
5997-
FOR_ALL_WINDOWS(wp)
5998-
if (bt_help(wp->w_buffer))
5999-
break;
6000-
6001-
if (wp == NULL) /* Help window not found */
6002-
qi = NULL;
6003-
else
6004-
qi = wp->w_llist;
6005-
6187+
qi = hgr_get_ll(&new_qi);
60066188
if (qi == NULL)
6007-
{
6008-
/* Allocate a new location list for help text matches */
6009-
if ((qi = ll_new_list()) == NULL)
6010-
return;
6011-
new_qi = TRUE;
6012-
}
6189+
return;
60136190
}
60146191

60156192
regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
60166193
regmatch.rm_ic = FALSE;
60176194
if (regmatch.regprog != NULL)
60186195
{
6019-
#ifdef FEAT_MBYTE
6020-
vimconv_T vc;
6021-
6022-
/* Help files are in utf-8 or latin1, convert lines when 'encoding'
6023-
* differs. */
6024-
vc.vc_type = CONV_NONE;
6025-
if (!enc_utf8)
6026-
convert_setup(&vc, (char_u *)"utf-8", p_enc);
6027-
#endif
6028-
60296196
/* create a new quickfix list */
60306197
qf_new_list(qi, *eap->cmdlinep);
60316198

6032-
/* Go through all directories in 'runtimepath' */
6033-
p = p_rtp;
6034-
while (*p != NUL && !got_int)
6035-
{
6036-
copy_option_part(&p, NameBuff, MAXPATHL, ",");
6037-
6038-
/* Find all "*.txt" and "*.??x" files in the "doc" directory. */
6039-
add_pathsep(NameBuff);
6040-
STRCAT(NameBuff, "doc/*.\\(txt\\|??x\\)");
6041-
if (gen_expand_wildcards(1, &NameBuff, &fcount,
6042-
&fnames, EW_FILE|EW_SILENT) == OK
6043-
&& fcount > 0)
6044-
{
6045-
for (fi = 0; fi < fcount && !got_int; ++fi)
6046-
{
6047-
#ifdef FEAT_MULTI_LANG
6048-
/* Skip files for a different language. */
6049-
if (lang != NULL
6050-
&& STRNICMP(lang, fnames[fi]
6051-
+ STRLEN(fnames[fi]) - 3, 2) != 0
6052-
&& !(STRNICMP(lang, "en", 2) == 0
6053-
&& STRNICMP("txt", fnames[fi]
6054-
+ STRLEN(fnames[fi]) - 3, 3) == 0))
6055-
continue;
6056-
#endif
6057-
fd = mch_fopen((char *)fnames[fi], "r");
6058-
if (fd != NULL)
6059-
{
6060-
lnum = 1;
6061-
while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
6062-
{
6063-
char_u *line = IObuff;
6064-
#ifdef FEAT_MBYTE
6065-
/* Convert a line if 'encoding' is not utf-8 and
6066-
* the line contains a non-ASCII character. */
6067-
if (vc.vc_type != CONV_NONE
6068-
&& has_non_ascii(IObuff))
6069-
{
6070-
line = string_convert(&vc, IObuff, NULL);
6071-
if (line == NULL)
6072-
line = IObuff;
6073-
}
6074-
#endif
6075-
6076-
if (vim_regexec(&regmatch, line, (colnr_T)0))
6077-
{
6078-
int l = (int)STRLEN(line);
6079-
6080-
/* remove trailing CR, LF, spaces, etc. */
6081-
while (l > 0 && line[l - 1] <= ' ')
6082-
line[--l] = NUL;
6083-
6084-
if (qf_add_entry(qi,
6085-
qi->qf_curlist,
6086-
NULL, /* dir */
6087-
fnames[fi],
6088-
0,
6089-
line,
6090-
lnum,
6091-
(int)(regmatch.startp[0] - line)
6092-
+ 1, /* col */
6093-
FALSE, /* vis_col */
6094-
NULL, /* search pattern */
6095-
0, /* nr */
6096-
1, /* type */
6097-
TRUE /* valid */
6098-
) == FAIL)
6099-
{
6100-
got_int = TRUE;
6101-
#ifdef FEAT_MBYTE
6102-
if (line != IObuff)
6103-
vim_free(line);
6104-
#endif
6105-
break;
6106-
}
6107-
}
6108-
#ifdef FEAT_MBYTE
6109-
if (line != IObuff)
6110-
vim_free(line);
6111-
#endif
6112-
++lnum;
6113-
line_breakcheck();
6114-
}
6115-
fclose(fd);
6116-
}
6117-
}
6118-
FreeWild(fcount, fnames);
6119-
}
6120-
}
6199+
hgr_search_in_rtp(qi, &regmatch, eap->arg);
61216200

61226201
vim_regfree(regmatch.regprog);
6123-
#ifdef FEAT_MBYTE
6124-
if (vc.vc_type != CONV_NONE)
6125-
convert_setup(&vc, NULL, NULL);
6126-
#endif
61276202

61286203
qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
61296204
qi->qf_lists[qi->qf_curlist].qf_ptr =

src/testdir/test_quickfix.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,6 +2302,12 @@ func XvimgrepTests(cchar)
23022302
call assert_equal('Xtestfile2', bufname(''))
23032303
call assert_equal('Editor:Emacs EmAcS', l[0].text)
23042304

2305+
" Test for unloading a buffer after vimgrep searched the buffer
2306+
%bwipe
2307+
Xvimgrep /Editor/j Xtestfile*
2308+
call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
2309+
call assert_equal([], getbufinfo('Xtestfile2'))
2310+
23052311
call delete('Xtestfile1')
23062312
call delete('Xtestfile2')
23072313
endfunc

0 commit comments

Comments
 (0)