# HG changeset patch # User Christian Brabandt # Date 1457814604 -3600 # Node ID 721e8d6cb7b5c6a13dd1dba9c2b78ddc9614cf04 # Parent 2f5f0cb8790693af8c027ee6831b6869dd520dfa commit https://github.com/vim/vim/commit/6bef5306e4f2cacb3a93667992c2312d4b293c9d Author: Bram Moolenaar Date: Sat Mar 12 21:28:26 2016 +0100 patch 7.4.1551 Problem: Cannot generate help tags in all doc directories. Solution: Make ":helptags ALL" work. diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -6575,135 +6575,9 @@ ex_viusage(exarg_T *eap UNUSED) do_cmdline_cmd((char_u *)"help normal-index"); } -static void helptags_one(char_u *dir, char_u *ext, char_u *lang, int add_help_tags); - /* - * ":helptags" + * Generate tags in one help directory. */ - void -ex_helptags(exarg_T *eap) -{ - expand_T xpc; - char_u *dirname; - int add_help_tags = FALSE; -#ifdef FEAT_MULTI_LANG - int len; - int i, j; - garray_T ga; - char_u lang[2]; - char_u ext[5]; - char_u fname[8]; - int filecount; - char_u **files; -#endif - - /* Check for ":helptags ++t {dir}". */ - if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3])) - { - add_help_tags = TRUE; - eap->arg = skipwhite(eap->arg + 3); - } - - ExpandInit(&xpc); - xpc.xp_context = EXPAND_DIRECTORIES; - dirname = ExpandOne(&xpc, eap->arg, NULL, - WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); - if (dirname == NULL || !mch_isdir(dirname)) - { - EMSG2(_("E150: Not a directory: %s"), eap->arg); - vim_free(dirname); - return; - } - -#ifdef FEAT_MULTI_LANG - /* Get a list of all files in the help directory and in subdirectories. */ - STRCPY(NameBuff, dirname); - add_pathsep(NameBuff); - STRCAT(NameBuff, "**"); - if (gen_expand_wildcards(1, &NameBuff, &filecount, &files, - EW_FILE|EW_SILENT) == FAIL - || filecount == 0) - { - EMSG2("E151: No match: %s", NameBuff); - vim_free(dirname); - return; - } - - /* Go over all files in the directory to find out what languages are - * present. */ - ga_init2(&ga, 1, 10); - for (i = 0; i < filecount; ++i) - { - len = (int)STRLEN(files[i]); - if (len > 4) - { - if (STRICMP(files[i] + len - 4, ".txt") == 0) - { - /* ".txt" -> language "en" */ - lang[0] = 'e'; - lang[1] = 'n'; - } - else if (files[i][len - 4] == '.' - && ASCII_ISALPHA(files[i][len - 3]) - && ASCII_ISALPHA(files[i][len - 2]) - && TOLOWER_ASC(files[i][len - 1]) == 'x') - { - /* ".abx" -> language "ab" */ - lang[0] = TOLOWER_ASC(files[i][len - 3]); - lang[1] = TOLOWER_ASC(files[i][len - 2]); - } - else - continue; - - /* Did we find this language already? */ - for (j = 0; j < ga.ga_len; j += 2) - if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0) - break; - if (j == ga.ga_len) - { - /* New language, add it. */ - if (ga_grow(&ga, 2) == FAIL) - break; - ((char_u *)ga.ga_data)[ga.ga_len++] = lang[0]; - ((char_u *)ga.ga_data)[ga.ga_len++] = lang[1]; - } - } - } - - /* - * Loop over the found languages to generate a tags file for each one. - */ - for (j = 0; j < ga.ga_len; j += 2) - { - STRCPY(fname, "tags-xx"); - fname[5] = ((char_u *)ga.ga_data)[j]; - fname[6] = ((char_u *)ga.ga_data)[j + 1]; - if (fname[5] == 'e' && fname[6] == 'n') - { - /* English is an exception: use ".txt" and "tags". */ - fname[4] = NUL; - STRCPY(ext, ".txt"); - } - else - { - /* Language "ab" uses ".abx" and "tags-ab". */ - STRCPY(ext, ".xxx"); - ext[1] = fname[5]; - ext[2] = fname[6]; - } - helptags_one(dirname, ext, fname, add_help_tags); - } - - ga_clear(&ga); - FreeWild(filecount, files); - -#else - /* No language support, just use "*.txt" and "tags". */ - helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags); -#endif - vim_free(dirname); -} - static void helptags_one( char_u *dir, /* doc directory */ @@ -6960,6 +6834,151 @@ helptags_one( fclose(fd_tags); /* there is no check for an error... */ } +/* + * Generate tags in one help directory, taking care of translations. + */ + static void +do_helptags(char_u *dirname, int add_help_tags) +{ +#ifdef FEAT_MULTI_LANG + int len; + int i, j; + garray_T ga; + char_u lang[2]; + char_u ext[5]; + char_u fname[8]; + int filecount; + char_u **files; + + /* Get a list of all files in the help directory and in subdirectories. */ + STRCPY(NameBuff, dirname); + add_pathsep(NameBuff); + STRCAT(NameBuff, "**"); + if (gen_expand_wildcards(1, &NameBuff, &filecount, &files, + EW_FILE|EW_SILENT) == FAIL + || filecount == 0) + { + EMSG2("E151: No match: %s", NameBuff); + vim_free(dirname); + return; + } + + /* Go over all files in the directory to find out what languages are + * present. */ + ga_init2(&ga, 1, 10); + for (i = 0; i < filecount; ++i) + { + len = (int)STRLEN(files[i]); + if (len > 4) + { + if (STRICMP(files[i] + len - 4, ".txt") == 0) + { + /* ".txt" -> language "en" */ + lang[0] = 'e'; + lang[1] = 'n'; + } + else if (files[i][len - 4] == '.' + && ASCII_ISALPHA(files[i][len - 3]) + && ASCII_ISALPHA(files[i][len - 2]) + && TOLOWER_ASC(files[i][len - 1]) == 'x') + { + /* ".abx" -> language "ab" */ + lang[0] = TOLOWER_ASC(files[i][len - 3]); + lang[1] = TOLOWER_ASC(files[i][len - 2]); + } + else + continue; + + /* Did we find this language already? */ + for (j = 0; j < ga.ga_len; j += 2) + if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0) + break; + if (j == ga.ga_len) + { + /* New language, add it. */ + if (ga_grow(&ga, 2) == FAIL) + break; + ((char_u *)ga.ga_data)[ga.ga_len++] = lang[0]; + ((char_u *)ga.ga_data)[ga.ga_len++] = lang[1]; + } + } + } + + /* + * Loop over the found languages to generate a tags file for each one. + */ + for (j = 0; j < ga.ga_len; j += 2) + { + STRCPY(fname, "tags-xx"); + fname[5] = ((char_u *)ga.ga_data)[j]; + fname[6] = ((char_u *)ga.ga_data)[j + 1]; + if (fname[5] == 'e' && fname[6] == 'n') + { + /* English is an exception: use ".txt" and "tags". */ + fname[4] = NUL; + STRCPY(ext, ".txt"); + } + else + { + /* Language "ab" uses ".abx" and "tags-ab". */ + STRCPY(ext, ".xxx"); + ext[1] = fname[5]; + ext[2] = fname[6]; + } + helptags_one(dirname, ext, fname, add_help_tags); + } + + ga_clear(&ga); + FreeWild(filecount, files); + +#else + /* No language support, just use "*.txt" and "tags". */ + helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags); +#endif +} + + static void +helptags_cb(char_u *fname, void *cookie) +{ + do_helptags(fname, *(int *)cookie); +} + +/* + * ":helptags" + */ + void +ex_helptags(exarg_T *eap) +{ + expand_T xpc; + char_u *dirname; + int add_help_tags = FALSE; + + /* Check for ":helptags ++t {dir}". */ + if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3])) + { + add_help_tags = TRUE; + eap->arg = skipwhite(eap->arg + 3); + } + + if (STRCMP(eap->arg, "ALL") == 0) + { + do_in_path(p_rtp, (char_u *)"doc", DIP_ALL + DIP_DIR, + helptags_cb, &add_help_tags); + } + else + { + ExpandInit(&xpc); + xpc.xp_context = EXPAND_DIRECTORIES; + dirname = ExpandOne(&xpc, eap->arg, NULL, + WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); + if (dirname == NULL || !mch_isdir(dirname)) + EMSG2(_("E150: Not a directory: %s"), eap->arg); + else + do_helptags(dirname, add_help_tags); + vim_free(dirname); + } +} + #if defined(FEAT_SIGNS) || defined(PROTO) /* diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -2928,10 +2928,6 @@ source_runtime(char_u *name, int all) return do_in_runtimepath(name, all, source_callback, NULL); } -#define DIP_ALL 1 /* all matches, not just the first one */ -#define DIP_DIR 2 /* find directories instead of files. */ -#define DIP_ERR 4 /* give an error message when none found. */ - /* * Find the file "name" in all directories in "path" and invoke * "callback(fname, cookie)". @@ -2942,7 +2938,7 @@ source_runtime(char_u *name, int all) * * return FAIL when no file could be sourced, OK otherwise. */ - static int + int do_in_path( char_u *path, char_u *name, diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -61,6 +61,7 @@ void ex_listdo(exarg_T *eap); void ex_compiler(exarg_T *eap); void ex_runtime(exarg_T *eap); int source_runtime(char_u *name, int all); +int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie); void ex_packloadall(exarg_T *eap); void ex_packadd(exarg_T *eap); diff --git a/src/testdir/test_packadd.vim b/src/testdir/test_packadd.vim --- a/src/testdir/test_packadd.vim +++ b/src/testdir/test_packadd.vim @@ -97,3 +97,20 @@ func Test_packloadall() packloadall! call assert_equal(4321, g:plugin_bar_number) endfunc + +func Test_helptags() + let docdir1 = &packpath . '/pack/mine/start/foo/doc' + let docdir2 = &packpath . '/pack/mine/start/bar/doc' + call mkdir(docdir1, 'p') + call mkdir(docdir2, 'p') + call writefile(['look here: *look-here*'], docdir1 . '/bar.txt') + call writefile(['look away: *look-away*'], docdir2 . '/foo.txt') + exe 'set rtp=' . &packpath . '/pack/mine/start/foo,' . &packpath . '/pack/mine/start/bar' + + helptags ALL + + let tags1 = readfile(docdir1 . '/tags') + call assert_true(tags1[0] =~ 'look-here') + let tags2 = readfile(docdir2 . '/tags') + call assert_true(tags2[0] =~ 'look-away') +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -744,6 +744,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1551, +/**/ 1550, /**/ 1549, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -2288,4 +2288,9 @@ typedef int VimClipboard; /* This is req int vim_main2(int argc, char **argv); #endif +/* Used for flags of do_in_path() */ +#define DIP_ALL 1 /* all matches, not just the first one */ +#define DIP_DIR 2 /* find directories instead of files. */ +#define DIP_ERR 4 /* give an error message when none found. */ + #endif /* VIM__H */