mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 06:48:17 +00:00
vim-patch:7.4.1551
Problem: Cannot generate help tags in all doc directories.
Solution: Make ":helptags ALL" work.
6bef5306e4
This commit is contained in:
@@ -4796,115 +4796,7 @@ void ex_viusage(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/// Generate tags in one help directory
|
||||||
* ":helptags"
|
|
||||||
*/
|
|
||||||
void ex_helptags(exarg_T *eap)
|
|
||||||
{
|
|
||||||
garray_T ga;
|
|
||||||
int len;
|
|
||||||
char_u lang[2];
|
|
||||||
expand_T xpc;
|
|
||||||
char_u *dirname;
|
|
||||||
char_u ext[5];
|
|
||||||
char_u fname[8];
|
|
||||||
int filecount;
|
|
||||||
char_u **files;
|
|
||||||
int add_help_tags = FALSE;
|
|
||||||
|
|
||||||
/* Check for ":helptags ++t {dir}". */
|
|
||||||
if (STRNCMP(eap->arg, "++t", 3) == 0 && ascii_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 || !os_isdir(dirname)) {
|
|
||||||
EMSG2(_("E150: Not a directory: %s"), eap->arg);
|
|
||||||
xfree(dirname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a list of all files in the help directory and in subdirectories. */
|
|
||||||
STRCPY(NameBuff, dirname);
|
|
||||||
add_pathsep((char *)NameBuff);
|
|
||||||
STRCAT(NameBuff, "**");
|
|
||||||
|
|
||||||
// Note: We cannot just do `&NameBuff` because it is a statically sized array
|
|
||||||
// so `NameBuff == &NameBuff` according to C semantics.
|
|
||||||
char_u *buff_list[1] = {NameBuff};
|
|
||||||
if (gen_expand_wildcards(1, buff_list, &filecount, &files,
|
|
||||||
EW_FILE|EW_SILENT) == FAIL
|
|
||||||
|| filecount == 0) {
|
|
||||||
EMSG2("E151: No match: %s", NameBuff);
|
|
||||||
xfree(dirname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Go over all files in the directory to find out what languages are
|
|
||||||
* present. */
|
|
||||||
ga_init(&ga, 1, 10);
|
|
||||||
for (int i = 0; i < filecount; ++i) {
|
|
||||||
len = (int)STRLEN(files[i]);
|
|
||||||
if (len <= 4) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
int j;
|
|
||||||
/* 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. */
|
|
||||||
ga_grow(&ga, 2);
|
|
||||||
((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 (int 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);
|
|
||||||
|
|
||||||
xfree(dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
helptags_one (
|
helptags_one (
|
||||||
char_u *dir, /* doc directory */
|
char_u *dir, /* doc directory */
|
||||||
@@ -5111,6 +5003,132 @@ helptags_one (
|
|||||||
fclose(fd_tags); /* there is no check for an error... */
|
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)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
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((char *)NameBuff);
|
||||||
|
STRCAT(NameBuff, "**");
|
||||||
|
|
||||||
|
// Note: We cannot just do `&NameBuff` because it is a statically sized array
|
||||||
|
// so `NameBuff == &NameBuff` according to C semantics.
|
||||||
|
char_u *buff_list[1] = {NameBuff};
|
||||||
|
if (gen_expand_wildcards(1, buff_list, &filecount, &files,
|
||||||
|
EW_FILE|EW_SILENT) == FAIL
|
||||||
|
|| filecount == 0) {
|
||||||
|
EMSG2("E151: No match: %s", NameBuff);
|
||||||
|
xfree(dirname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go over all files in the directory to find out what languages are
|
||||||
|
* present. */
|
||||||
|
int j;
|
||||||
|
ga_init(&ga, 1, 10);
|
||||||
|
for (int i = 0; i < filecount; ++i)
|
||||||
|
{
|
||||||
|
len = (int)STRLEN(files[i]);
|
||||||
|
if (len <= 4) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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. */
|
||||||
|
ga_grow(&ga, 2);
|
||||||
|
((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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
helptags_cb(char_u *fname, void *cookie)
|
||||||
|
{
|
||||||
|
do_helptags(fname, *(bool *)cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ":helptags"
|
||||||
|
*/
|
||||||
|
void ex_helptags(exarg_T *eap)
|
||||||
|
{
|
||||||
|
expand_T xpc;
|
||||||
|
char_u *dirname;
|
||||||
|
bool add_help_tags = false;
|
||||||
|
|
||||||
|
/* Check for ":helptags ++t {dir}". */
|
||||||
|
if (STRNCMP(eap->arg, "++t", 3) == 0 && ascii_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 || !os_isdir(dirname)) {
|
||||||
|
EMSG2(_("E150: Not a directory: %s"), eap->arg);
|
||||||
|
} else {
|
||||||
|
do_helptags(dirname, add_help_tags);
|
||||||
|
}
|
||||||
|
xfree(dirname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sign
|
struct sign
|
||||||
{
|
{
|
||||||
sign_T *sn_next; /* next sign in list */
|
sign_T *sn_next; /* next sign in list */
|
||||||
|
@@ -2285,10 +2285,6 @@ int source_runtime(char_u *name, int all)
|
|||||||
return do_in_runtimepath(name, all, source_callback, NULL);
|
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
|
/// Find the file "name" in all directories in "path" and invoke
|
||||||
/// "callback(fname, cookie)".
|
/// "callback(fname, cookie)".
|
||||||
/// "name" can contain wildcards.
|
/// "name" can contain wildcards.
|
||||||
@@ -2297,7 +2293,7 @@ int source_runtime(char_u *name, int all)
|
|||||||
/// When "flags" has DIP_ERR: give an error message if there is no match.
|
/// When "flags" has DIP_ERR: give an error message if there is no match.
|
||||||
///
|
///
|
||||||
/// return FAIL when no file could be sourced, OK otherwise.
|
/// return FAIL when no file could be sourced, OK otherwise.
|
||||||
static int do_in_path(char_u *path, char_u *name, int flags,
|
int do_in_path(char_u *path, char_u *name, int flags,
|
||||||
DoInRuntimepathCB callback, void *cookie)
|
DoInRuntimepathCB callback, void *cookie)
|
||||||
{
|
{
|
||||||
char_u *tail;
|
char_u *tail;
|
||||||
|
@@ -144,7 +144,7 @@ static int included_patches[] = {
|
|||||||
// 1554,
|
// 1554,
|
||||||
// 1553,
|
// 1553,
|
||||||
// 1552,
|
// 1552,
|
||||||
// 1551,
|
1551,
|
||||||
1550,
|
1550,
|
||||||
// 1549,
|
// 1549,
|
||||||
// 1548,
|
// 1548,
|
||||||
|
@@ -308,4 +308,9 @@ enum {
|
|||||||
# define SET_NO_HLSEARCH(flag) no_hlsearch = (flag); set_vim_var_nr( \
|
# define SET_NO_HLSEARCH(flag) no_hlsearch = (flag); set_vim_var_nr( \
|
||||||
VV_HLSEARCH, !no_hlsearch && p_hls)
|
VV_HLSEARCH, !no_hlsearch && p_hls)
|
||||||
|
|
||||||
|
// 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 /* NVIM_VIM_H */
|
#endif /* NVIM_VIM_H */
|
||||||
|
@@ -90,6 +90,23 @@ describe('packadd', function()
|
|||||||
packloadall!
|
packloadall!
|
||||||
call assert_equal(4321, g:plugin_bar_number)
|
call assert_equal(4321, g:plugin_bar_number)
|
||||||
endfunc
|
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
|
||||||
]=])
|
]=])
|
||||||
call('SetUp')
|
call('SetUp')
|
||||||
end)
|
end)
|
||||||
@@ -113,6 +130,11 @@ describe('packadd', function()
|
|||||||
expected_empty()
|
expected_empty()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('works with helptags', function()
|
||||||
|
call('Test_helptags')
|
||||||
|
expected_empty()
|
||||||
|
end)
|
||||||
|
|
||||||
describe('command line completion', function()
|
describe('command line completion', function()
|
||||||
local Screen = require('test.functional.ui.screen')
|
local Screen = require('test.functional.ui.screen')
|
||||||
local screen
|
local screen
|
||||||
|
Reference in New Issue
Block a user