Skip to content

Commit 6bef530

Browse files
committed
patch 7.4.1551
Problem: Cannot generate help tags in all doc directories. Solution: Make ":helptags ALL" work.
1 parent 2d8f56a commit 6bef530

File tree

6 files changed

+172
-132
lines changed

6 files changed

+172
-132
lines changed

src/ex_cmds.c

Lines changed: 146 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -6575,135 +6575,9 @@ ex_viusage(exarg_T *eap UNUSED)
65756575
do_cmdline_cmd((char_u *)"help normal-index");
65766576
}
65776577

6578-
static void helptags_one(char_u *dir, char_u *ext, char_u *lang, int add_help_tags);
6579-
65806578
/*
6581-
* ":helptags"
6579+
* Generate tags in one help directory.
65826580
*/
6583-
void
6584-
ex_helptags(exarg_T *eap)
6585-
{
6586-
expand_T xpc;
6587-
char_u *dirname;
6588-
int add_help_tags = FALSE;
6589-
#ifdef FEAT_MULTI_LANG
6590-
int len;
6591-
int i, j;
6592-
garray_T ga;
6593-
char_u lang[2];
6594-
char_u ext[5];
6595-
char_u fname[8];
6596-
int filecount;
6597-
char_u **files;
6598-
#endif
6599-
6600-
/* Check for ":helptags ++t {dir}". */
6601-
if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3]))
6602-
{
6603-
add_help_tags = TRUE;
6604-
eap->arg = skipwhite(eap->arg + 3);
6605-
}
6606-
6607-
ExpandInit(&xpc);
6608-
xpc.xp_context = EXPAND_DIRECTORIES;
6609-
dirname = ExpandOne(&xpc, eap->arg, NULL,
6610-
WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
6611-
if (dirname == NULL || !mch_isdir(dirname))
6612-
{
6613-
EMSG2(_("E150: Not a directory: %s"), eap->arg);
6614-
vim_free(dirname);
6615-
return;
6616-
}
6617-
6618-
#ifdef FEAT_MULTI_LANG
6619-
/* Get a list of all files in the help directory and in subdirectories. */
6620-
STRCPY(NameBuff, dirname);
6621-
add_pathsep(NameBuff);
6622-
STRCAT(NameBuff, "**");
6623-
if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
6624-
EW_FILE|EW_SILENT) == FAIL
6625-
|| filecount == 0)
6626-
{
6627-
EMSG2("E151: No match: %s", NameBuff);
6628-
vim_free(dirname);
6629-
return;
6630-
}
6631-
6632-
/* Go over all files in the directory to find out what languages are
6633-
* present. */
6634-
ga_init2(&ga, 1, 10);
6635-
for (i = 0; i < filecount; ++i)
6636-
{
6637-
len = (int)STRLEN(files[i]);
6638-
if (len > 4)
6639-
{
6640-
if (STRICMP(files[i] + len - 4, ".txt") == 0)
6641-
{
6642-
/* ".txt" -> language "en" */
6643-
lang[0] = 'e';
6644-
lang[1] = 'n';
6645-
}
6646-
else if (files[i][len - 4] == '.'
6647-
&& ASCII_ISALPHA(files[i][len - 3])
6648-
&& ASCII_ISALPHA(files[i][len - 2])
6649-
&& TOLOWER_ASC(files[i][len - 1]) == 'x')
6650-
{
6651-
/* ".abx" -> language "ab" */
6652-
lang[0] = TOLOWER_ASC(files[i][len - 3]);
6653-
lang[1] = TOLOWER_ASC(files[i][len - 2]);
6654-
}
6655-
else
6656-
continue;
6657-
6658-
/* Did we find this language already? */
6659-
for (j = 0; j < ga.ga_len; j += 2)
6660-
if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0)
6661-
break;
6662-
if (j == ga.ga_len)
6663-
{
6664-
/* New language, add it. */
6665-
if (ga_grow(&ga, 2) == FAIL)
6666-
break;
6667-
((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
6668-
((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
6669-
}
6670-
}
6671-
}
6672-
6673-
/*
6674-
* Loop over the found languages to generate a tags file for each one.
6675-
*/
6676-
for (j = 0; j < ga.ga_len; j += 2)
6677-
{
6678-
STRCPY(fname, "tags-xx");
6679-
fname[5] = ((char_u *)ga.ga_data)[j];
6680-
fname[6] = ((char_u *)ga.ga_data)[j + 1];
6681-
if (fname[5] == 'e' && fname[6] == 'n')
6682-
{
6683-
/* English is an exception: use ".txt" and "tags". */
6684-
fname[4] = NUL;
6685-
STRCPY(ext, ".txt");
6686-
}
6687-
else
6688-
{
6689-
/* Language "ab" uses ".abx" and "tags-ab". */
6690-
STRCPY(ext, ".xxx");
6691-
ext[1] = fname[5];
6692-
ext[2] = fname[6];
6693-
}
6694-
helptags_one(dirname, ext, fname, add_help_tags);
6695-
}
6696-
6697-
ga_clear(&ga);
6698-
FreeWild(filecount, files);
6699-
6700-
#else
6701-
/* No language support, just use "*.txt" and "tags". */
6702-
helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags);
6703-
#endif
6704-
vim_free(dirname);
6705-
}
6706-
67076581
static void
67086582
helptags_one(
67096583
char_u *dir, /* doc directory */
@@ -6960,6 +6834,151 @@ helptags_one(
69606834
fclose(fd_tags); /* there is no check for an error... */
69616835
}
69626836

6837+
/*
6838+
* Generate tags in one help directory, taking care of translations.
6839+
*/
6840+
static void
6841+
do_helptags(char_u *dirname, int add_help_tags)
6842+
{
6843+
#ifdef FEAT_MULTI_LANG
6844+
int len;
6845+
int i, j;
6846+
garray_T ga;
6847+
char_u lang[2];
6848+
char_u ext[5];
6849+
char_u fname[8];
6850+
int filecount;
6851+
char_u **files;
6852+
6853+
/* Get a list of all files in the help directory and in subdirectories. */
6854+
STRCPY(NameBuff, dirname);
6855+
add_pathsep(NameBuff);
6856+
STRCAT(NameBuff, "**");
6857+
if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
6858+
EW_FILE|EW_SILENT) == FAIL
6859+
|| filecount == 0)
6860+
{
6861+
EMSG2("E151: No match: %s", NameBuff);
6862+
vim_free(dirname);
6863+
return;
6864+
}
6865+
6866+
/* Go over all files in the directory to find out what languages are
6867+
* present. */
6868+
ga_init2(&ga, 1, 10);
6869+
for (i = 0; i < filecount; ++i)
6870+
{
6871+
len = (int)STRLEN(files[i]);
6872+
if (len > 4)
6873+
{
6874+
if (STRICMP(files[i] + len - 4, ".txt") == 0)
6875+
{
6876+
/* ".txt" -> language "en" */
6877+
lang[0] = 'e';
6878+
lang[1] = 'n';
6879+
}
6880+
else if (files[i][len - 4] == '.'
6881+
&& ASCII_ISALPHA(files[i][len - 3])
6882+
&& ASCII_ISALPHA(files[i][len - 2])
6883+
&& TOLOWER_ASC(files[i][len - 1]) == 'x')
6884+
{
6885+
/* ".abx" -> language "ab" */
6886+
lang[0] = TOLOWER_ASC(files[i][len - 3]);
6887+
lang[1] = TOLOWER_ASC(files[i][len - 2]);
6888+
}
6889+
else
6890+
continue;
6891+
6892+
/* Did we find this language already? */
6893+
for (j = 0; j < ga.ga_len; j += 2)
6894+
if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0)
6895+
break;
6896+
if (j == ga.ga_len)
6897+
{
6898+
/* New language, add it. */
6899+
if (ga_grow(&ga, 2) == FAIL)
6900+
break;
6901+
((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
6902+
((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
6903+
}
6904+
}
6905+
}
6906+
6907+
/*
6908+
* Loop over the found languages to generate a tags file for each one.
6909+
*/
6910+
for (j = 0; j < ga.ga_len; j += 2)
6911+
{
6912+
STRCPY(fname, "tags-xx");
6913+
fname[5] = ((char_u *)ga.ga_data)[j];
6914+
fname[6] = ((char_u *)ga.ga_data)[j + 1];
6915+
if (fname[5] == 'e' && fname[6] == 'n')
6916+
{
6917+
/* English is an exception: use ".txt" and "tags". */
6918+
fname[4] = NUL;
6919+
STRCPY(ext, ".txt");
6920+
}
6921+
else
6922+
{
6923+
/* Language "ab" uses ".abx" and "tags-ab". */
6924+
STRCPY(ext, ".xxx");
6925+
ext[1] = fname[5];
6926+
ext[2] = fname[6];
6927+
}
6928+
helptags_one(dirname, ext, fname, add_help_tags);
6929+
}
6930+
6931+
ga_clear(&ga);
6932+
FreeWild(filecount, files);
6933+
6934+
#else
6935+
/* No language support, just use "*.txt" and "tags". */
6936+
helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags);
6937+
#endif
6938+
}
6939+
6940+
static void
6941+
helptags_cb(char_u *fname, void *cookie)
6942+
{
6943+
do_helptags(fname, *(int *)cookie);
6944+
}
6945+
6946+
/*
6947+
* ":helptags"
6948+
*/
6949+
void
6950+
ex_helptags(exarg_T *eap)
6951+
{
6952+
expand_T xpc;
6953+
char_u *dirname;
6954+
int add_help_tags = FALSE;
6955+
6956+
/* Check for ":helptags ++t {dir}". */
6957+
if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3]))
6958+
{
6959+
add_help_tags = TRUE;
6960+
eap->arg = skipwhite(eap->arg + 3);
6961+
}
6962+
6963+
if (STRCMP(eap->arg, "ALL") == 0)
6964+
{
6965+
do_in_path(p_rtp, (char_u *)"doc", DIP_ALL + DIP_DIR,
6966+
helptags_cb, &add_help_tags);
6967+
}
6968+
else
6969+
{
6970+
ExpandInit(&xpc);
6971+
xpc.xp_context = EXPAND_DIRECTORIES;
6972+
dirname = ExpandOne(&xpc, eap->arg, NULL,
6973+
WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
6974+
if (dirname == NULL || !mch_isdir(dirname))
6975+
EMSG2(_("E150: Not a directory: %s"), eap->arg);
6976+
else
6977+
do_helptags(dirname, add_help_tags);
6978+
vim_free(dirname);
6979+
}
6980+
}
6981+
69636982
#if defined(FEAT_SIGNS) || defined(PROTO)
69646983

69656984
/*

src/ex_cmds2.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2928,10 +2928,6 @@ source_runtime(char_u *name, int all)
29282928
return do_in_runtimepath(name, all, source_callback, NULL);
29292929
}
29302930

2931-
#define DIP_ALL 1 /* all matches, not just the first one */
2932-
#define DIP_DIR 2 /* find directories instead of files. */
2933-
#define DIP_ERR 4 /* give an error message when none found. */
2934-
29352931
/*
29362932
* Find the file "name" in all directories in "path" and invoke
29372933
* "callback(fname, cookie)".
@@ -2942,7 +2938,7 @@ source_runtime(char_u *name, int all)
29422938
*
29432939
* return FAIL when no file could be sourced, OK otherwise.
29442940
*/
2945-
static int
2941+
int
29462942
do_in_path(
29472943
char_u *path,
29482944
char_u *name,

src/proto/ex_cmds2.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void ex_listdo(exarg_T *eap);
6161
void ex_compiler(exarg_T *eap);
6262
void ex_runtime(exarg_T *eap);
6363
int source_runtime(char_u *name, int all);
64+
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
6465
int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie);
6566
void ex_packloadall(exarg_T *eap);
6667
void ex_packadd(exarg_T *eap);

src/testdir/test_packadd.vim

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,20 @@ func Test_packloadall()
9797
packloadall!
9898
call assert_equal(4321, g:plugin_bar_number)
9999
endfunc
100+
101+
func Test_helptags()
102+
let docdir1 = &packpath . '/pack/mine/start/foo/doc'
103+
let docdir2 = &packpath . '/pack/mine/start/bar/doc'
104+
call mkdir(docdir1, 'p')
105+
call mkdir(docdir2, 'p')
106+
call writefile(['look here: *look-here*'], docdir1 . '/bar.txt')
107+
call writefile(['look away: *look-away*'], docdir2 . '/foo.txt')
108+
exe 'set rtp=' . &packpath . '/pack/mine/start/foo,' . &packpath . '/pack/mine/start/bar'
109+
110+
helptags ALL
111+
112+
let tags1 = readfile(docdir1 . '/tags')
113+
call assert_true(tags1[0] =~ 'look-here')
114+
let tags2 = readfile(docdir2 . '/tags')
115+
call assert_true(tags2[0] =~ 'look-away')
116+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1551,
746748
/**/
747749
1550,
748750
/**/

src/vim.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,4 +2288,9 @@ typedef int VimClipboard; /* This is required for the prototypes. */
22882288
int vim_main2(int argc, char **argv);
22892289
#endif
22902290

2291+
/* Used for flags of do_in_path() */
2292+
#define DIP_ALL 1 /* all matches, not just the first one */
2293+
#define DIP_DIR 2 /* find directories instead of files. */
2294+
#define DIP_ERR 4 /* give an error message when none found. */
2295+
22912296
#endif /* VIM__H */

0 commit comments

Comments
 (0)