0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.0.1754: ex_helpgrep() is too long

Problem:    ex_helpgrep() is too long.
Solution:   Refactor the function. (Yegappan Lakshmanan, closes #2766)
This commit is contained in:
Bram Moolenaar
2018-04-24 15:48:11 +02:00
parent 1c17ffa461
commit 2225ebb486
3 changed files with 221 additions and 138 deletions

View File

@@ -5942,53 +5942,14 @@ ex_cexpr(exarg_T *eap)
#endif #endif
/* /*
* ":helpgrep {pattern}" * Get the location list for ":lhelpgrep"
*/ */
void static qf_info_T *
ex_helpgrep(exarg_T *eap) hgr_get_ll(int *new_ll)
{ {
regmatch_T regmatch;
char_u *save_cpo;
char_u *p;
int fcount;
char_u **fnames;
FILE *fd;
int fi;
long lnum;
#ifdef FEAT_MULTI_LANG
char_u *lang;
#endif
qf_info_T *qi = &ql_info;
int new_qi = FALSE;
win_T *wp; win_T *wp;
char_u *au_name = NULL; qf_info_T *qi;
#ifdef FEAT_MULTI_LANG
/* Check for a specified language */
lang = check_help_lang(eap->arg);
#endif
switch (eap->cmdidx)
{
case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break;
case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break;
default: break;
}
if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
curbuf->b_fname, TRUE, curbuf))
{
#ifdef FEAT_EVAL
if (aborting())
return;
#endif
}
/* Make 'cpoptions' empty, the 'l' flag should not be used here. */
save_cpo = p_cpo;
p_cpo = empty_option;
if (eap->cmdidx == CMD_lhelpgrep)
{
/* If the current window is a help window, then use it */ /* If the current window is a help window, then use it */
if (bt_help(curwin->w_buffer)) if (bt_help(curwin->w_buffer))
wp = curwin; wp = curwin;
@@ -6007,56 +5968,32 @@ ex_helpgrep(exarg_T *eap)
{ {
/* Allocate a new location list for help text matches */ /* Allocate a new location list for help text matches */
if ((qi = ll_new_list()) == NULL) if ((qi = ll_new_list()) == NULL)
return; return NULL;
new_qi = TRUE; *new_ll = TRUE;
}
} }
regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING); return qi;
regmatch.rm_ic = FALSE; }
if (regmatch.regprog != NULL)
{ /*
* Search for a pattern in a help file.
*/
static void
hgr_search_file(
qf_info_T *qi,
char_u *fname,
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
vimconv_T vc; vimconv_T *p_vc,
/* Help files are in utf-8 or latin1, convert lines when 'encoding'
* differs. */
vc.vc_type = CONV_NONE;
if (!enc_utf8)
convert_setup(&vc, (char_u *)"utf-8", p_enc);
#endif #endif
regmatch_T *p_regmatch)
{
FILE *fd;
long lnum;
/* create a new quickfix list */ fd = mch_fopen((char *)fname, "r");
qf_new_list(qi, *eap->cmdlinep); if (fd == NULL)
return;
/* Go through all directories in 'runtimepath' */
p = p_rtp;
while (*p != NUL && !got_int)
{
copy_option_part(&p, NameBuff, MAXPATHL, ",");
/* Find all "*.txt" and "*.??x" files in the "doc" directory. */
add_pathsep(NameBuff);
STRCAT(NameBuff, "doc/*.\\(txt\\|??x\\)");
if (gen_expand_wildcards(1, &NameBuff, &fcount,
&fnames, EW_FILE|EW_SILENT) == OK
&& fcount > 0)
{
for (fi = 0; fi < fcount && !got_int; ++fi)
{
#ifdef FEAT_MULTI_LANG
/* 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))
continue;
#endif
fd = mch_fopen((char *)fnames[fi], "r");
if (fd != NULL)
{
lnum = 1; lnum = 1;
while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
{ {
@@ -6064,16 +6001,16 @@ ex_helpgrep(exarg_T *eap)
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
/* Convert a line if 'encoding' is not utf-8 and /* Convert a line if 'encoding' is not utf-8 and
* the line contains a non-ASCII character. */ * the line contains a non-ASCII character. */
if (vc.vc_type != CONV_NONE if (p_vc->vc_type != CONV_NONE
&& has_non_ascii(IObuff)) && has_non_ascii(IObuff))
{ {
line = string_convert(&vc, IObuff, NULL); line = string_convert(p_vc, IObuff, NULL);
if (line == NULL) if (line == NULL)
line = IObuff; line = IObuff;
} }
#endif #endif
if (vim_regexec(&regmatch, line, (colnr_T)0)) if (vim_regexec(p_regmatch, line, (colnr_T)0))
{ {
int l = (int)STRLEN(line); int l = (int)STRLEN(line);
@@ -6084,11 +6021,11 @@ ex_helpgrep(exarg_T *eap)
if (qf_add_entry(qi, if (qf_add_entry(qi,
qi->qf_curlist, qi->qf_curlist,
NULL, /* dir */ NULL, /* dir */
fnames[fi], fname,
0, 0,
line, line,
lnum, lnum,
(int)(regmatch.startp[0] - line) (int)(p_regmatch->startp[0] - line)
+ 1, /* col */ + 1, /* col */
FALSE, /* vis_col */ FALSE, /* vis_col */
NULL, /* search pattern */ NULL, /* search pattern */
@@ -6113,17 +6050,155 @@ ex_helpgrep(exarg_T *eap)
line_breakcheck(); line_breakcheck();
} }
fclose(fd); fclose(fd);
} }
/*
* Search for a pattern in all the help files in the doc directory under
* the given directory.
*/
static void
hgr_search_files_in_dir(
qf_info_T *qi,
char_u *dirname,
regmatch_T *p_regmatch
#ifdef FEAT_MBYTE
, vimconv_T *p_vc
#endif
#ifdef FEAT_MULTI_LANG
, char_u *lang
#endif
)
{
int fcount;
char_u **fnames;
int fi;
/* Find all "*.txt" and "*.??x" files in the "doc" directory. */
add_pathsep(dirname);
STRCAT(dirname, "doc/*.\\(txt\\|??x\\)");
if (gen_expand_wildcards(1, &dirname, &fcount,
&fnames, EW_FILE|EW_SILENT) == OK
&& fcount > 0)
{
for (fi = 0; fi < fcount && !got_int; ++fi)
{
#ifdef FEAT_MULTI_LANG
/* 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))
continue;
#endif
hgr_search_file(qi, fnames[fi],
#ifdef FEAT_MBYTE
p_vc,
#endif
p_regmatch);
} }
FreeWild(fcount, fnames); FreeWild(fcount, fnames);
} }
}
/*
* Search for a pattern in all the help files in the 'runtimepath'.
*/
static void
hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg)
{
char_u *p;
#ifdef FEAT_MULTI_LANG
char_u *lang;
#endif
#ifdef FEAT_MBYTE
vimconv_T vc;
/* Help files are in utf-8 or latin1, convert lines when 'encoding'
* differs. */
vc.vc_type = CONV_NONE;
if (!enc_utf8)
convert_setup(&vc, (char_u *)"utf-8", p_enc);
#endif
#ifdef FEAT_MULTI_LANG
/* Check for a specified language */
lang = check_help_lang(arg);
#endif
/* Go through all directories in 'runtimepath' */
p = p_rtp;
while (*p != NUL && !got_int)
{
copy_option_part(&p, NameBuff, MAXPATHL, ",");
hgr_search_files_in_dir(qi, NameBuff, p_regmatch
#ifdef FEAT_MBYTE
, &vc
#endif
#ifdef FEAT_MULTI_LANG
, lang
#endif
);
} }
vim_regfree(regmatch.regprog);
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (vc.vc_type != CONV_NONE) if (vc.vc_type != CONV_NONE)
convert_setup(&vc, NULL, NULL); convert_setup(&vc, NULL, NULL);
#endif #endif
}
/*
* ":helpgrep {pattern}"
*/
void
ex_helpgrep(exarg_T *eap)
{
regmatch_T regmatch;
char_u *save_cpo;
qf_info_T *qi = &ql_info;
int new_qi = FALSE;
char_u *au_name = NULL;
switch (eap->cmdidx)
{
case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break;
case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break;
default: break;
}
if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
curbuf->b_fname, TRUE, curbuf))
{
#ifdef FEAT_EVAL
if (aborting())
return;
#endif
}
/* Make 'cpoptions' empty, the 'l' flag should not be used here. */
save_cpo = p_cpo;
p_cpo = empty_option;
if (eap->cmdidx == CMD_lhelpgrep)
{
qi = hgr_get_ll(&new_qi);
if (qi == NULL)
return;
}
regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
regmatch.rm_ic = FALSE;
if (regmatch.regprog != NULL)
{
/* create a new quickfix list */
qf_new_list(qi, *eap->cmdlinep);
hgr_search_in_rtp(qi, &regmatch, eap->arg);
vim_regfree(regmatch.regprog);
qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_ptr =

View File

@@ -2302,6 +2302,12 @@ func XvimgrepTests(cchar)
call assert_equal('Xtestfile2', bufname('')) call assert_equal('Xtestfile2', bufname(''))
call assert_equal('Editor:Emacs EmAcS', l[0].text) call assert_equal('Editor:Emacs EmAcS', l[0].text)
" Test for unloading a buffer after vimgrep searched the buffer
%bwipe
Xvimgrep /Editor/j Xtestfile*
call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded)
call assert_equal([], getbufinfo('Xtestfile2'))
call delete('Xtestfile1') call delete('Xtestfile1')
call delete('Xtestfile2') call delete('Xtestfile2')
endfunc endfunc

View File

@@ -761,6 +761,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1754,
/**/ /**/
1753, 1753,
/**/ /**/