diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/digraph.c | 4 | ||||
-rw-r--r-- | src/nvim/eval.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 251 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 12 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 295 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 84 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 96 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/hardcopy.c | 3 | ||||
-rw-r--r-- | src/nvim/main.c | 5 | ||||
-rw-r--r-- | src/nvim/option.c | 6 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 149 | ||||
-rw-r--r-- | src/nvim/options.lua | 10 | ||||
-rw-r--r-- | src/nvim/spell.c | 12 | ||||
-rw-r--r-- | src/nvim/syntax.c | 37 | ||||
-rw-r--r-- | src/nvim/tag.c | 5 | ||||
-rw-r--r-- | src/nvim/version.c | 36 | ||||
-rw-r--r-- | src/nvim/vim.h | 9 |
18 files changed, 694 insertions, 330 deletions
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 9525024c1b..aad145b3e5 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1757,12 +1757,12 @@ char_u* keymap_init(void) vim_snprintf(buf, buflen, "keymap/%s_%s.vim", curbuf->b_p_keymap, p_enc); - if (source_runtime((char_u *)buf, FALSE) == FAIL) { + if (source_runtime((char_u *)buf, 0) == FAIL) { // try finding "keymap/'keymap'.vim" in 'runtimepath' vim_snprintf(buf, buflen, "keymap/%s.vim", curbuf->b_p_keymap); - if (source_runtime((char_u *)buf, FALSE) == FAIL) { + if (source_runtime((char_u *)buf, 0) == FAIL) { xfree(buf); return (char_u *)N_("E544: Keymap file not found"); } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9a86c5765c..591ed50cfd 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -10782,6 +10782,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "mouse", "multi_byte", "multi_lang", + "packages", "path_extra", "persistent_undo", "postscript", @@ -20497,9 +20498,10 @@ script_autoload ( tofree = NULL; } - /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ - if (source_runtime(scriptname, FALSE) == OK) - ret = TRUE; + // Try loading the package from $VIMRUNTIME/autoload/<name>.vim + if (source_runtime(scriptname, 0) == OK) { + ret = true; + } } xfree(tofree); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index d0661b6b9b..da64533708 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -4796,122 +4796,15 @@ void ex_viusage(exarg_T *eap) } -/* - * ":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 -helptags_one ( - char_u *dir, /* doc directory */ - char_u *ext, /* suffix, ".txt", ".itx", ".frx", etc. */ - char_u *tagfname, /* "tags" for English, "tags-fr" for French. */ - int add_help_tags /* add "help-tags" tag */ -) +/// Generate tags in one help directory +/// +/// @param dir Path to the doc directory +/// @param ext Suffix of the help files (".txt", ".itx", ".frx", etc.) +/// @param tagname Name of the tags file ("tags" for English, "tags-fr" for +/// French) +/// @param add_help_tags Whether to add the "help-tags" tag +static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, + bool add_help_tags) { FILE *fd_tags; FILE *fd; @@ -5111,6 +5004,132 @@ 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, bool 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 { sign_T *sn_next; /* next sign in list */ diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 6c58879d58..76191d5a56 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1849,6 +1849,18 @@ return { func='ex_print', }, { + command='packadd', + flags=bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN), + addr_type=ADDR_LINES, + func='ex_packadd', + }, + { + command='packloadall', + flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN), + addr_type=ADDR_LINES, + func='ex_packloadall', + }, + { command='pclose', flags=bit.bor(BANG, TRLBAR), addr_type=ADDR_LINES, diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 40074f726c..b56b1cf013 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -2237,7 +2237,7 @@ void ex_compiler(exarg_T *eap) do_unlet((char_u *)"b:current_compiler", true); snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg); - if (source_runtime(buf, true) == FAIL) { + if (source_runtime(buf, DIP_ALL) == FAIL) { EMSG2(_("E666: compiler not supported: %s"), eap->arg); } xfree(buf); @@ -2263,10 +2263,29 @@ void ex_compiler(exarg_T *eap) } } -/// ":runtime {name}" +/// ":runtime [what] {name}" void ex_runtime(exarg_T *eap) { - source_runtime(eap->arg, eap->forceit); + char_u *arg = eap->arg; + char_u *p = skiptowhite(arg); + ptrdiff_t len = p - arg; + int flags = eap->forceit ? DIP_ALL : 0; + + if (STRNCMP(arg, "START", len) == 0) { + flags += DIP_START + DIP_NORTP; + arg = skipwhite(arg + len); + } else if (STRNCMP(arg, "OPT", len) == 0) { + flags += DIP_OPT + DIP_NORTP; + arg = skipwhite(arg + len); + } else if (STRNCMP(arg, "PACK", len) == 0) { + flags += DIP_START + DIP_OPT + DIP_NORTP; + arg = skipwhite(arg + len); + } else if (STRNCMP(arg, "ALL", len) == 0) { + flags += DIP_START + DIP_OPT; + arg = skipwhite(arg + len); + } + + source_runtime(arg, flags); } @@ -2277,28 +2296,25 @@ static void source_callback(char_u *fname, void *cookie) /// Source the file "name" from all directories in 'runtimepath'. /// "name" can contain wildcards. -/// When "all" is true, source all files, otherwise only the first one. +/// When "flags" has DIP_ALL: source all files, otherwise only the first one. +/// /// return FAIL when no file could be sourced, OK otherwise. -int source_runtime(char_u *name, int all) +int source_runtime(char_u *name, int flags) { - return do_in_runtimepath(name, all, source_callback, NULL); + return do_in_runtimepath(name, flags, source_callback, NULL); } -/// Find "name" in 'runtimepath'. When found, invoke the callback function for -/// it: callback(fname, "cookie") -/// When "all" is true repeat for all matches, otherwise only the first one is -/// used. -/// Returns OK when at least one match found, FAIL otherwise. -/// If "name" is NULL calls callback for each entry in runtimepath. Cookie is -/// passed by reference in this case, setting it to NULL indicates that callback -/// has done its job. -int do_in_runtimepath(char_u *name, int all, DoInRuntimepathCB callback, - void *cookie) +/// Find the file "name" in all directories in "path" and invoke +/// "callback(fname, cookie)". +/// "name" can contain wildcards. +/// When "flags" has DIP_ALL: source all files, otherwise only the first one. +/// When "flags" has DIP_DIR: find directories instead of files. +/// When "flags" has DIP_ERR: give an error message if there is no match. +/// +/// return FAIL when no file could be sourced, OK otherwise. +int do_in_path(char_u *path, char_u *name, int flags, + DoInRuntimepathCB callback, void *cookie) { - char_u *rtp; - char_u *np; - char_u *buf; - char_u *rtp_copy; char_u *tail; int num_files; char_u **files; @@ -2307,19 +2323,19 @@ int do_in_runtimepath(char_u *name, int all, DoInRuntimepathCB callback, // Make a copy of 'runtimepath'. Invoking the callback may change the // value. - rtp_copy = vim_strsave(p_rtp); - buf = xmallocz(MAXPATHL); + char_u *rtp_copy = vim_strsave(path); + char_u *buf = xmallocz(MAXPATHL); { if (p_verbose > 1 && name != NULL) { verbose_enter(); smsg(_("Searching for \"%s\" in \"%s\""), - (char *)name, (char *)p_rtp); + (char *)name, (char *)path); verbose_leave(); } // Loop over all entries in 'runtimepath'. - rtp = rtp_copy; - while (*rtp != NUL && (all || !did_one)) { + char_u *rtp = rtp_copy; + while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) { // Copy the path from 'runtimepath' to buf[]. copy_option_part(&rtp, buf, MAXPATHL, ","); if (name == NULL) { @@ -2332,8 +2348,8 @@ int do_in_runtimepath(char_u *name, int all, DoInRuntimepathCB callback, tail = buf + STRLEN(buf); // Loop over all patterns in "name" - np = name; - while (*np != NUL && (all || !did_one)) { + char_u *np = name; + while (*np != NUL && ((flags & DIP_ALL) || !did_one)) { // Append the pattern from "name" to buf[]. assert(MAXPATHL >= (tail - buf)); copy_option_part(&np, tail, (size_t)(MAXPATHL - (tail - buf)), @@ -2347,11 +2363,12 @@ int do_in_runtimepath(char_u *name, int all, DoInRuntimepathCB callback, // Expand wildcards, invoke the callback for each match. if (gen_expand_wildcards(1, &buf, &num_files, &files, - EW_FILE) == OK) { + (flags & DIP_DIR) ? EW_DIR + : EW_FILE) == OK) { for (i = 0; i < num_files; i++) { (*callback)(files[i], cookie); did_one = true; - if (!all) { + if (!(flags & DIP_ALL)) { break; } } @@ -2363,16 +2380,228 @@ int do_in_runtimepath(char_u *name, int all, DoInRuntimepathCB callback, } xfree(buf); xfree(rtp_copy); - if (p_verbose > 0 && !did_one && name != NULL) { - verbose_enter(); - smsg(_("not found in 'runtimepath': \"%s\""), name); - verbose_leave(); + if (!did_one && name != NULL) { + char *basepath = path == p_rtp ? "runtimepath" : "packpath"; + + if (flags & DIP_ERR) { + EMSG3(_(e_dirnotf), basepath, name); + } else if (p_verbose > 0) { + verbose_enter(); + smsg(_("not found in '%s': \"%s\""), basepath, name); + verbose_leave(); + } } return did_one ? OK : FAIL; } +/// Find "name" in 'runtimepath'. When found, invoke the callback function for +/// it: callback(fname, "cookie") +/// When "flags" has DIP_ALL repeat for all matches, otherwise only the first +/// one is used. +/// Returns OK when at least one match found, FAIL otherwise. +/// If "name" is NULL calls callback for each entry in runtimepath. Cookie is +/// passed by reference in this case, setting it to NULL indicates that callback +/// has done its job. +int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, + void *cookie) +{ + int done = FAIL; + + if ((flags & DIP_NORTP) == 0) { + done = do_in_path(p_rtp, name, flags, callback, cookie); + } + + if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) { + char *start_dir = "pack/*/start/*/%s"; // NOLINT + size_t len = STRLEN(start_dir) + STRLEN(name); + char_u *s = xmallocz(len); + + vim_snprintf((char *)s, len, start_dir, name); + done = do_in_path(p_pp, s, flags, callback, cookie); + + xfree(s); + } + + if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT)) { + char *opt_dir = "pack/*/opt/*/%s"; // NOLINT + size_t len = STRLEN(opt_dir) + STRLEN(name); + char_u *s = xmallocz(len); + + vim_snprintf((char *)s, len, opt_dir, name); + done = do_in_path(p_pp, s, flags, callback, cookie); + + xfree(s); + } + + return done; +} + +// Expand wildcards in "pat" and invoke do_source() for each match. +static void source_all_matches(char_u *pat) +{ + int num_files; + char_u **files; + + if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) { + for (int i = 0; i < num_files; i++) { + (void)do_source(files[i], false, DOSO_NONE); + } + FreeWild(num_files, files); + } +} + +// used for "cookie" of add_pack_plugin() +static int APP_ADD_DIR; +static int APP_LOAD; +static int APP_BOTH; + +static void add_pack_plugin(char_u *fname, void *cookie) +{ + char_u *p4, *p3, *p2, *p1, *p; + char_u *new_rtp; + char_u *ffname = (char_u *)fix_fname((char *)fname); + + if (ffname == NULL) { + return; + } + + if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) { + // directory is not yet in 'runtimepath', add it + p4 = p3 = p2 = p1 = get_past_head(ffname); + for (p = p1; *p; mb_ptr_adv(p)) { + if (vim_ispathsep_nocolon(*p)) { + p4 = p3; p3 = p2; p2 = p1; p1 = p; + } + } + + // now we have: + // rtp/pack/name/start/name + // p4 p3 p2 p1 + // + // find the part up to "pack" in 'runtimepath' + char_u c = *p4; + *p4 = NUL; + + // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences + size_t fname_len = STRLEN(ffname); + char_u *insp = p_rtp; + for (;;) { + if (vim_fnamencmp(insp, ffname, fname_len) == 0) { + break; + } + insp = vim_strchr(insp, ','); + if (insp == NULL) { + break; + } + insp++; + } + + if (insp == NULL) { + // not found, append at the end + insp = p_rtp + STRLEN(p_rtp); + } else { + // append after the matching directory. + insp += STRLEN(ffname); + while (*insp != NUL && *insp != ',') { + insp++; + } + } + *p4 = c; + + // check if rtp/pack/name/start/name/after exists + char *afterdir = concat_fnames((char *)ffname, "after", true); + size_t afterlen = 0; + if (os_isdir((char_u *)afterdir)) { + afterlen = STRLEN(afterdir) + 1; // add one for comma + } + + size_t oldlen = STRLEN(p_rtp); + size_t addlen = STRLEN(ffname) + 1; // add one for comma + new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL + if (new_rtp == NULL) { + goto theend; + } + uintptr_t keep = (uintptr_t)(insp - p_rtp); + memmove(new_rtp, p_rtp, keep); + new_rtp[keep] = ','; + memmove(new_rtp + keep + 1, ffname, addlen); + if (p_rtp[keep] != NUL) { + memmove(new_rtp + keep + addlen, p_rtp + keep, + oldlen - keep + 1); + } + if (afterlen > 0) { + STRCAT(new_rtp, ","); + STRCAT(new_rtp, afterdir); + } + set_option_value((char_u *)"rtp", 0L, new_rtp, 0); + xfree(new_rtp); + xfree(afterdir); + } + + if (cookie != &APP_ADD_DIR) { + static const char *plugpat = "%s/plugin/*.vim"; // NOLINT + static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT + + size_t len = STRLEN(ffname) + STRLEN(ftpat); + char_u *pat = try_malloc(len + 1); + if (pat == NULL) { + goto theend; + } + vim_snprintf((char *)pat, len, plugpat, ffname); + source_all_matches(pat); + + char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes"); + + // If runtime/filetype.vim wasn't loaded yet, the scripts will be + // found when it loads. + if (eval_to_number(cmd) > 0) { + do_cmdline_cmd("augroup filetypedetect"); + vim_snprintf((char *)pat, len, ftpat, ffname); + source_all_matches(pat); + do_cmdline_cmd("augroup END"); + } + xfree(cmd); + xfree(pat); + } + +theend: + xfree(ffname); +} + +static bool did_source_packages = false; + +// ":packloadall" +// Find plugins in the package directories and source them. +void ex_packloadall(exarg_T *eap) +{ + if (!did_source_packages || (eap != NULL && eap->forceit)) { + did_source_packages = true; + + // First do a round to add all directories to 'runtimepath', then load + // the plugins. This allows for plugins to use an autoload directory + // of another plugin. + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_ADD_DIR); + do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT + add_pack_plugin, &APP_LOAD); + } +} + +/// ":packadd[!] {name}" +void ex_packadd(exarg_T *eap) +{ + static const char *plugpat = "pack/*/opt/%s"; // NOLINT + + size_t len = STRLEN(plugpat) + STRLEN(eap->arg); + char *pat = (char *)xmallocz(len); + vim_snprintf(pat, len, plugpat, eap->arg); + do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR + DIP_ERR, add_pack_plugin, + eap->forceit ? &APP_ADD_DIR : &APP_BOTH); + xfree(pat); +} + /// ":options" void ex_options(exarg_T *eap) { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index ad17d4dcbd..9bc7ec39da 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -3316,6 +3316,11 @@ set_one_cmd_context ( xp->xp_pattern = arg; break; + case CMD_packadd: + xp->xp_context = EXPAND_PACKADD; + xp->xp_pattern = arg; + break; + #ifdef HAVE_WORKING_LIBINTL case CMD_language: p = skiptowhite(arg); @@ -4660,41 +4665,42 @@ static struct { char *name; } command_complete[] = { - {EXPAND_AUGROUP, "augroup"}, - {EXPAND_BEHAVE, "behave"}, - {EXPAND_BUFFERS, "buffer"}, - {EXPAND_COLORS, "color"}, - {EXPAND_COMMANDS, "command"}, - {EXPAND_COMPILER, "compiler"}, - {EXPAND_CSCOPE, "cscope"}, - {EXPAND_USER_DEFINED, "custom"}, - {EXPAND_USER_LIST, "customlist"}, - {EXPAND_DIRECTORIES, "dir"}, - {EXPAND_ENV_VARS, "environment"}, - {EXPAND_EVENTS, "event"}, - {EXPAND_EXPRESSION, "expression"}, - {EXPAND_FILES, "file"}, - {EXPAND_FILES_IN_PATH, "file_in_path"}, - {EXPAND_FILETYPE, "filetype"}, - {EXPAND_FUNCTIONS, "function"}, - {EXPAND_HELP, "help"}, - {EXPAND_HIGHLIGHT, "highlight"}, - {EXPAND_HISTORY, "history"}, + { EXPAND_AUGROUP, "augroup" }, + { EXPAND_BEHAVE, "behave" }, + { EXPAND_BUFFERS, "buffer" }, + { EXPAND_COLORS, "color" }, + { EXPAND_COMMANDS, "command" }, + { EXPAND_COMPILER, "compiler" }, + { EXPAND_CSCOPE, "cscope" }, + { EXPAND_USER_DEFINED, "custom" }, + { EXPAND_USER_LIST, "customlist" }, + { EXPAND_DIRECTORIES, "dir" }, + { EXPAND_ENV_VARS, "environment" }, + { EXPAND_EVENTS, "event" }, + { EXPAND_EXPRESSION, "expression" }, + { EXPAND_FILES, "file" }, + { EXPAND_FILES_IN_PATH, "file_in_path" }, + { EXPAND_FILETYPE, "filetype" }, + { EXPAND_FUNCTIONS, "function" }, + { EXPAND_HELP, "help" }, + { EXPAND_HIGHLIGHT, "highlight" }, + { EXPAND_HISTORY, "history" }, #ifdef HAVE_WORKING_LIBINTL - {EXPAND_LOCALES, "locale"}, + { EXPAND_LOCALES, "locale" }, #endif - {EXPAND_MAPPINGS, "mapping"}, - {EXPAND_MENUS, "menu"}, - {EXPAND_OWNSYNTAX, "syntax"}, - {EXPAND_SYNTIME, "syntime"}, - {EXPAND_SETTINGS, "option"}, - {EXPAND_SHELLCMD, "shellcmd"}, - {EXPAND_SIGN, "sign"}, - {EXPAND_TAGS, "tag"}, - {EXPAND_TAGS_LISTFILES, "tag_listfiles"}, - {EXPAND_USER, "user"}, - {EXPAND_USER_VARS, "var"}, - {0, NULL} + { EXPAND_MAPPINGS, "mapping" }, + { EXPAND_MENUS, "menu" }, + { EXPAND_OWNSYNTAX, "syntax" }, + { EXPAND_SYNTIME, "syntime" }, + { EXPAND_SETTINGS, "option" }, + { EXPAND_PACKADD, "packadd" }, + { EXPAND_SHELLCMD, "shellcmd" }, + { EXPAND_SIGN, "sign" }, + { EXPAND_TAGS, "tag" }, + { EXPAND_TAGS_LISTFILES, "tag_listfiles" }, + { EXPAND_USER, "user" }, + { EXPAND_USER_VARS, "var" }, + { 0, NULL } }; static void uc_list(char_u *name, size_t name_len) @@ -9330,14 +9336,14 @@ static void ex_filetype(exarg_T *eap) } if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0) { if (*arg == 'o' || !filetype_detect) { - source_runtime((char_u *)FILETYPE_FILE, true); + source_runtime((char_u *)FILETYPE_FILE, DIP_ALL); filetype_detect = kTrue; if (plugin) { - source_runtime((char_u *)FTPLUGIN_FILE, true); + source_runtime((char_u *)FTPLUGIN_FILE, DIP_ALL); filetype_plugin = kTrue; } if (indent) { - source_runtime((char_u *)INDENT_FILE, true); + source_runtime((char_u *)INDENT_FILE, DIP_ALL); filetype_indent = kTrue; } } @@ -9348,15 +9354,15 @@ static void ex_filetype(exarg_T *eap) } else if (STRCMP(arg, "off") == 0) { if (plugin || indent) { if (plugin) { - source_runtime((char_u *)FTPLUGOF_FILE, true); + source_runtime((char_u *)FTPLUGOF_FILE, DIP_ALL); filetype_plugin = kFalse; } if (indent) { - source_runtime((char_u *)INDOFF_FILE, true); + source_runtime((char_u *)INDOFF_FILE, DIP_ALL); filetype_indent = kFalse; } } else { - source_runtime((char_u *)FTOFF_FILE, true); + source_runtime((char_u *)FTOFF_FILE, DIP_ALL); filetype_detect = kFalse; } } else diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 65144dace8..cd28554970 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3440,6 +3440,7 @@ addstar ( || context == EXPAND_COMPILER || context == EXPAND_OWNSYNTAX || context == EXPAND_FILETYPE + || context == EXPAND_PACKADD || (context == EXPAND_TAGS && fname[0] == '/')) retval = vim_strnsave(fname, len); else { @@ -3794,23 +3795,27 @@ ExpandFromContext ( || xp->xp_context == EXPAND_TAGS_LISTFILES) return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file); if (xp->xp_context == EXPAND_COLORS) { - char *directories[] = {"colors", NULL}; - return ExpandRTDir(pat, num_file, file, directories); + char *directories[] = { "colors", NULL }; + return ExpandRTDir(pat, DIP_START + DIP_OPT, num_file, file, directories); } if (xp->xp_context == EXPAND_COMPILER) { - char *directories[] = {"compiler", NULL}; - return ExpandRTDir(pat, num_file, file, directories); + char *directories[] = { "compiler", NULL }; + return ExpandRTDir(pat, 0, num_file, file, directories); } if (xp->xp_context == EXPAND_OWNSYNTAX) { - char *directories[] = {"syntax", NULL}; - return ExpandRTDir(pat, num_file, file, directories); + char *directories[] = { "syntax", NULL }; + return ExpandRTDir(pat, 0, num_file, file, directories); } if (xp->xp_context == EXPAND_FILETYPE) { - char *directories[] = {"syntax", "indent", "ftplugin", NULL}; - return ExpandRTDir(pat, num_file, file, directories); + char *directories[] = { "syntax", "indent", "ftplugin", NULL }; + return ExpandRTDir(pat, 0, num_file, file, directories); } - if (xp->xp_context == EXPAND_USER_LIST) + if (xp->xp_context == EXPAND_USER_LIST) { return ExpandUserList(xp, num_file, file); + } + if (xp->xp_context == EXPAND_PACKADD) { + return ExpandPackAddDir(pat, num_file, file); + } regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0); if (regmatch.regprog == NULL) @@ -4190,12 +4195,16 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) return OK; } -/* - * Expand color scheme, compiler or filetype names: - * 'runtimepath'/{dirnames}/{pat}.vim - * "dirnames" is an array with one or more directory names. - */ -static int ExpandRTDir(char_u *pat, int *num_file, char_u ***file, char *dirnames[]) +/// Expand color scheme, compiler or filetype names. +/// Search from 'runtimepath': +/// 'runtimepath'/{dirnames}/{pat}.vim +/// When "flags" has DIP_START: search also from 'start' of 'packpath': +/// 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim +/// When "flags" has DIP_OPT: search also from 'opt' of 'packpath': +/// 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim +/// "dirnames" is an array with one or more directory names. +static int ExpandRTDir(char_u *pat, int flags, int *num_file, char_u ***file, + char *dirnames[]) { *num_file = 0; *file = NULL; @@ -4212,6 +4221,26 @@ static int ExpandRTDir(char_u *pat, int *num_file, char_u ***file, char *dirname xfree(s); } + if (flags & DIP_START) { + for (int i = 0; dirnames[i] != NULL; i++) { + size_t size = STRLEN(dirnames[i]) + pat_len + 22; + char_u *s = xmalloc(size); + snprintf((char *)s, size, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT + globpath(p_pp, s, &ga, 0); + xfree(s); + } + } + + if (flags & DIP_OPT) { + for (int i = 0; dirnames[i] != NULL; i++) { + size_t size = STRLEN(dirnames[i]) + pat_len + 20; + char_u *s = xmalloc(size); + snprintf((char *)s, size, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT + globpath(p_pp, s, &ga, 0); + xfree(s); + } + } + for (int i = 0; i < ga.ga_len; i++) { char_u *match = ((char_u **)ga.ga_data)[i]; char_u *s = match; @@ -4241,6 +4270,43 @@ static int ExpandRTDir(char_u *pat, int *num_file, char_u ***file, char *dirname return OK; } +/// Expand loadplugin names: +/// 'packpath'/pack/ * /opt/{pat} +static int ExpandPackAddDir(char_u *pat, int *num_file, char_u ***file) +{ + garray_T ga; + + *num_file = 0; + *file = NULL; + size_t pat_len = STRLEN(pat); + ga_init(&ga, (int)sizeof(char *), 10); + + size_t buflen = pat_len + 26; + char_u *s = xmalloc(buflen); + snprintf((char *)s, buflen, "pack/*/opt/%s*", pat); // NOLINT + globpath(p_pp, s, &ga, 0); + xfree(s); + + for (int i = 0; i < ga.ga_len; i++) { + char_u *match = ((char_u **)ga.ga_data)[i]; + s = path_tail(match); + char_u *e = s + STRLEN(s); + memmove(match, s, e - s + 1); + } + + if (GA_EMPTY(&ga)) { + return FAIL; + } + + // Sort and remove duplicates which can happen when specifying multiple + // directories in dirnames. + ga_remove_duplicate_strings(&ga); + + *file = ga.ga_data; + *num_file = ga.ga_len; + return OK; +} + /// Expand `file` for all comma-separated directories in `path`. /// Adds matches to `ga`. diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 7f91903106..ed9862a264 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1223,6 +1223,8 @@ EXTERN char_u e_invalpat[] INIT(= N_( EXTERN char_u e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); EXTERN char_u e_notset[] INIT(= N_("E764: Option '%s' is not set")); EXTERN char_u e_invalidreg[] INIT(= N_("E850: Invalid register name")); +EXTERN char_u e_dirnotf[] INIT(= N_( + "E919: Directory not found in '%s': \"%s\"")); EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported")); diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index 916d27a964..1c9b8e18ef 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -1526,8 +1526,7 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource) vim_strcat(buffer, (char_u *)name, MAXPATHL); vim_strcat(buffer, (char_u *)".ps", MAXPATHL); resource->filename[0] = NUL; - retval = (do_in_runtimepath(buffer, FALSE, prt_resource_name, - resource->filename) + retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename) && resource->filename[0] != NUL); xfree(buffer); return retval; diff --git a/src/nvim/main.c b/src/nvim/main.c index 5cd1dbb467..64b5de8663 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1241,8 +1241,11 @@ static void set_window_layout(mparm_T *paramp) static void load_plugins(void) { if (p_lpl) { - source_runtime((char_u *)"plugin/**/*.vim", TRUE); + source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL); // NOLINT TIME_MSG("loading plugins"); + + ex_packloadall(NULL); + TIME_MSG("loading packages"); } } diff --git a/src/nvim/option.c b/src/nvim/option.c index a844c4ed80..81f57522b3 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3187,8 +3187,9 @@ did_set_string_option ( for (p = q; *p != NUL; ++p) if (vim_strchr((char_u *)"_.,", *p) != NULL) break; - vim_snprintf((char *)fname, 200, "spell/%.*s.vim", (int)(p - q), q); - source_runtime(fname, TRUE); + vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim", + (int)(p - q), q); + source_runtime(fname, DIP_ALL); } } @@ -5839,6 +5840,7 @@ set_context_in_set_cmd ( if (p == (char_u *)&p_bdir || p == (char_u *)&p_dir || p == (char_u *)&p_path + || p == (char_u *)&p_pp || p == (char_u *)&p_rtp || p == (char_u *)&p_cdpath || p == (char_u *)&p_vdir diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index b1a2b00bdb..8d6f42e088 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -456,80 +456,81 @@ EXTERN int p_hid; // 'hidden' // Use P_HID to check if a buffer is to be hidden when it is no longer // visible in a window. # define P_HID(buf) (buf_hide(buf)) -EXTERN char_u *p_hl; /* 'highlight' */ -EXTERN int p_hls; /* 'hlsearch' */ -EXTERN long p_hi; /* 'history' */ -EXTERN int p_hkmap; /* 'hkmap' */ -EXTERN int p_hkmapp; /* 'hkmapp' */ -EXTERN int p_fkmap; /* 'fkmap' */ -EXTERN int p_altkeymap; /* 'altkeymap' */ -EXTERN int p_arshape; /* 'arabicshape' */ -EXTERN int p_icon; /* 'icon' */ -EXTERN char_u *p_iconstring; /* 'iconstring' */ -EXTERN int p_ic; /* 'ignorecase' */ -EXTERN int p_is; /* 'incsearch' */ -EXTERN int p_im; /* 'insertmode' */ -EXTERN char_u *p_isf; /* 'isfname' */ -EXTERN char_u *p_isi; /* 'isident' */ -EXTERN char_u *p_isp; /* 'isprint' */ -EXTERN int p_js; /* 'joinspaces' */ -EXTERN char_u *p_kp; /* 'keywordprg' */ -EXTERN char_u *p_km; /* 'keymodel' */ -EXTERN char_u *p_langmap; /* 'langmap'*/ -EXTERN int p_lnr; /* 'langnoremap'*/ -EXTERN char_u *p_lm; /* 'langmenu' */ -EXTERN char_u *p_lispwords; /* 'lispwords' */ -EXTERN long p_ls; /* 'laststatus' */ -EXTERN long p_stal; /* 'showtabline' */ -EXTERN char_u *p_lcs; /* 'listchars' */ - -EXTERN int p_lz; /* 'lazyredraw' */ -EXTERN int p_lpl; /* 'loadplugins' */ -EXTERN int p_magic; /* 'magic' */ -EXTERN char_u *p_mef; /* 'makeef' */ -EXTERN char_u *p_mp; /* 'makeprg' */ -EXTERN char_u *p_cc; /* 'colorcolumn' */ -EXTERN int p_cc_cols[256]; /* array for 'colorcolumn' columns */ -EXTERN long p_mat; /* 'matchtime' */ -EXTERN long p_mco; /* 'maxcombine' */ -EXTERN long p_mfd; /* 'maxfuncdepth' */ -EXTERN long p_mmd; /* 'maxmapdepth' */ -EXTERN long p_mm; /* 'maxmem' */ -EXTERN long p_mmp; /* 'maxmempattern' */ -EXTERN long p_mmt; /* 'maxmemtot' */ -EXTERN long p_mis; /* 'menuitems' */ -EXTERN char_u *p_msm; /* 'mkspellmem' */ -EXTERN long p_mls; /* 'modelines' */ -EXTERN char_u *p_mouse; /* 'mouse' */ -EXTERN char_u *p_mousem; /* 'mousemodel' */ -EXTERN long p_mouset; /* 'mousetime' */ -EXTERN int p_more; /* 'more' */ -EXTERN char_u *p_opfunc; /* 'operatorfunc' */ -EXTERN char_u *p_para; /* 'paragraphs' */ -EXTERN int p_paste; /* 'paste' */ -EXTERN char_u *p_pt; /* 'pastetoggle' */ -EXTERN char_u *p_pex; /* 'patchexpr' */ -EXTERN char_u *p_pm; /* 'patchmode' */ -EXTERN char_u *p_path; /* 'path' */ -EXTERN char_u *p_cdpath; /* 'cdpath' */ -EXTERN long p_rdt; /* 'redrawtime' */ -EXTERN int p_remap; /* 'remap' */ -EXTERN long p_re; /* 'regexpengine' */ -EXTERN long p_report; /* 'report' */ -EXTERN long p_pvh; /* 'previewheight' */ -EXTERN int p_ari; /* 'allowrevins' */ -EXTERN int p_ri; /* 'revins' */ -EXTERN int p_ru; /* 'ruler' */ -EXTERN char_u *p_ruf; /* 'rulerformat' */ -EXTERN char_u *p_rtp; /* 'runtimepath' */ -EXTERN long p_sj; /* 'scrolljump' */ -EXTERN long p_so; /* 'scrolloff' */ -EXTERN char_u *p_sbo; /* 'scrollopt' */ -EXTERN char_u *p_sections; /* 'sections' */ -EXTERN int p_secure; /* 'secure' */ -EXTERN char_u *p_sel; /* 'selection' */ -EXTERN char_u *p_slm; /* 'selectmode' */ -EXTERN char_u *p_ssop; /* 'sessionoptions' */ +EXTERN char_u *p_hl; // 'highlight' +EXTERN int p_hls; // 'hlsearch' +EXTERN long p_hi; // 'history' +EXTERN int p_hkmap; // 'hkmap' +EXTERN int p_hkmapp; // 'hkmapp' +EXTERN int p_fkmap; // 'fkmap' +EXTERN int p_altkeymap; // 'altkeymap' +EXTERN int p_arshape; // 'arabicshape' +EXTERN int p_icon; // 'icon' +EXTERN char_u *p_iconstring; // 'iconstring' +EXTERN int p_ic; // 'ignorecase' +EXTERN int p_is; // 'incsearch' +EXTERN int p_im; // 'insertmode' +EXTERN char_u *p_isf; // 'isfname' +EXTERN char_u *p_isi; // 'isident' +EXTERN char_u *p_isp; // 'isprint' +EXTERN int p_js; // 'joinspaces' +EXTERN char_u *p_kp; // 'keywordprg' +EXTERN char_u *p_km; // 'keymodel' +EXTERN char_u *p_langmap; // 'langmap'*/ +EXTERN int p_lnr; // 'langnoremap'*/ +EXTERN char_u *p_lm; // 'langmenu' +EXTERN char_u *p_lispwords; // 'lispwords' +EXTERN long p_ls; // 'laststatus' +EXTERN long p_stal; // 'showtabline' +EXTERN char_u *p_lcs; // 'listchars' + +EXTERN int p_lz; // 'lazyredraw' +EXTERN int p_lpl; // 'loadplugins' +EXTERN int p_magic; // 'magic' +EXTERN char_u *p_mef; // 'makeef' +EXTERN char_u *p_mp; // 'makeprg' +EXTERN char_u *p_cc; // 'colorcolumn' +EXTERN int p_cc_cols[256]; // array for 'colorcolumn' columns +EXTERN long p_mat; // 'matchtime' +EXTERN long p_mco; // 'maxcombine' +EXTERN long p_mfd; // 'maxfuncdepth' +EXTERN long p_mmd; // 'maxmapdepth' +EXTERN long p_mm; // 'maxmem' +EXTERN long p_mmp; // 'maxmempattern' +EXTERN long p_mmt; // 'maxmemtot' +EXTERN long p_mis; // 'menuitems' +EXTERN char_u *p_msm; // 'mkspellmem' +EXTERN long p_mls; // 'modelines' +EXTERN char_u *p_mouse; // 'mouse' +EXTERN char_u *p_mousem; // 'mousemodel' +EXTERN long p_mouset; // 'mousetime' +EXTERN int p_more; // 'more' +EXTERN char_u *p_opfunc; // 'operatorfunc' +EXTERN char_u *p_para; // 'paragraphs' +EXTERN int p_paste; // 'paste' +EXTERN char_u *p_pt; // 'pastetoggle' +EXTERN char_u *p_pex; // 'patchexpr' +EXTERN char_u *p_pm; // 'patchmode' +EXTERN char_u *p_path; // 'path' +EXTERN char_u *p_cdpath; // 'cdpath' +EXTERN long p_rdt; // 'redrawtime' +EXTERN int p_remap; // 'remap' +EXTERN long p_re; // 'regexpengine' +EXTERN long p_report; // 'report' +EXTERN long p_pvh; // 'previewheight' +EXTERN int p_ari; // 'allowrevins' +EXTERN int p_ri; // 'revins' +EXTERN int p_ru; // 'ruler' +EXTERN char_u *p_ruf; // 'rulerformat' +EXTERN char_u *p_pp; // 'packpath' +EXTERN char_u *p_rtp; // 'runtimepath' +EXTERN long p_sj; // 'scrolljump' +EXTERN long p_so; // 'scrolloff' +EXTERN char_u *p_sbo; // 'scrollopt' +EXTERN char_u *p_sections; // 'sections' +EXTERN int p_secure; // 'secure' +EXTERN char_u *p_sel; // 'selection' +EXTERN char_u *p_slm; // 'selectmode' +EXTERN char_u *p_ssop; // 'sessionoptions' EXTERN unsigned ssop_flags; # ifdef IN_OPTION_C /* Also used for 'viewoptions'! */ diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 218e34f595..d19af4f73f 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1640,6 +1640,16 @@ return { defaults={if_true={vi=""}} }, { + full_name='packpath', abbreviation='pp', + type='string', list='onecomma', scope={'global'}, + deny_duplicates=true, + secure=true, + vi_def=true, + expand=true, + varname='p_pp', + defaults={if_true={vi=''}} + }, + { full_name='paragraphs', abbreviation='para', type='string', scope={'global'}, vi_def=true, diff --git a/src/nvim/spell.c b/src/nvim/spell.c index fba6fac821..610fb660e7 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2317,16 +2317,14 @@ static void spell_load_lang(char_u *lang) for (round = 1; round <= 2; ++round) { // Find the first spell file for "lang" in 'runtimepath' and load it. vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, - "spell/%s.%s.spl", - lang, spell_enc()); - r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); + "spell/%s.%s.spl", lang, spell_enc()); + r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl); if (r == FAIL && *sl.sl_lang != NUL) { // Try loading the ASCII version. vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, - "spell/%s.ascii.spl", - lang); - r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); + "spell/%s.ascii.spl", lang); + r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl); if (r == FAIL && *sl.sl_lang != NUL && round == 1 && apply_autocmds(EVENT_SPELLFILEMISSING, lang, @@ -2354,7 +2352,7 @@ static void spell_load_lang(char_u *lang) } else if (sl.sl_slang != NULL) { // At least one file was loaded, now load ALL the additions. STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl"); - do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl); + do_in_runtimepath(fname_enc, DIP_ALL, spell_load_cb, &sl); } } diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 05141eaf1e..27855184df 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -4207,9 +4207,10 @@ static void syn_cmd_include(exarg_T *eap, int syncing) current_syn_inc_tag = ++running_syn_inc_tag; prev_toplvl_grp = curwin->w_s->b_syn_topgrp; curwin->w_s->b_syn_topgrp = sgl_id; - if (source ? do_source(eap->arg, FALSE, DOSO_NONE) == FAIL - : source_runtime(eap->arg, TRUE) == FAIL) + if (source ? do_source(eap->arg, false, DOSO_NONE) == FAIL + : source_runtime(eap->arg, DIP_ALL) == FAIL) { EMSG2(_(e_notopen), eap->arg); + } curwin->w_s->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; } @@ -6023,12 +6024,12 @@ init_highlight ( if (get_var_value((char_u *)"g:syntax_on") != NULL) { static int recursive = 0; - if (recursive >= 5) + if (recursive >= 5) { EMSG(_("E679: recursive loop loading syncolor.vim")); - else { - ++recursive; - (void)source_runtime((char_u *)"syntax/syncolor.vim", TRUE); - --recursive; + } else { + recursive++; + (void)source_runtime((char_u *)"syntax/syncolor.vim", DIP_ALL); + recursive--; } } } @@ -6041,22 +6042,24 @@ int load_colors(char_u *name) { char_u *buf; int retval = FAIL; - static int recursive = FALSE; + static int recursive = false; - /* When being called recursively, this is probably because setting - * 'background' caused the highlighting to be reloaded. This means it is - * working, thus we should return OK. */ - if (recursive) + // When being called recursively, this is probably because setting + // 'background' caused the highlighting to be reloaded. This means it is + // working, thus we should return OK. + if (recursive) { return OK; + } - recursive = TRUE; - buf = xmalloc(STRLEN(name) + 12); - sprintf((char *)buf, "colors/%s.vim", name); - retval = source_runtime(buf, FALSE); + recursive = true; + size_t buflen = STRLEN(name) + 12; + buf = xmalloc(buflen); + snprintf((char *)buf, buflen, "colors/%s.vim", name); + retval = source_runtime(buf, DIP_START + DIP_OPT); xfree(buf); apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf); - recursive = FALSE; + recursive = false; ui_refresh(); return retval; diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 5d15196784..dfecfb776d 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2023,9 +2023,8 @@ get_tagfname ( if (first) { ga_clear_strings(&tag_fnames); ga_init(&tag_fnames, (int)sizeof(char_u *), 10); - do_in_runtimepath((char_u *) - "doc/tags doc/tags-??" - , TRUE, found_tagfile_cb, NULL); + do_in_runtimepath((char_u *)"doc/tags doc/tags-??", DIP_ALL, + found_tagfile_cb, NULL); } if (tnp->tn_hf_idx >= tag_fnames.ga_len) { diff --git a/src/nvim/version.c b/src/nvim/version.c index 278255c904..8aa3071395 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -75,7 +75,9 @@ static char *features[] = { // clang-format off static int included_patches[] = { + 1973, 1960, + 1840, 1832, 1831, 1809, @@ -87,9 +89,11 @@ static int included_patches[] = { 1753, 1728, 1716, + 1712, 1695, 1654, 1652, + 1649, 1643, 1641, // 1624 NA @@ -98,7 +102,7 @@ static int included_patches[] = { // 1599 NA // 1598 NA // 1597 NA - // 1596, + 1596, // 1595 NA // 1594 NA // 1593 NA @@ -141,11 +145,11 @@ static int included_patches[] = { // 1557, // 1556 NA // 1555 NA - // 1554, - // 1553, - // 1552, - // 1551, - // 1550, + 1554, + 1553, + 1552, + 1551, + 1550, // 1549, // 1548, // 1547, @@ -167,7 +171,7 @@ static int included_patches[] = { // 1531 NA // 1530 NA // 1529 NA - // 1528, + 1528, // 1527 NA // 1526 NA // 1525 NA @@ -196,28 +200,28 @@ static int included_patches[] = { // 1502 NA // 1501 NA 1500, - // 1499, + 1499, // 1498 NA // 1497 NA // 1496 NA // 1495 NA // 1494, // 1493 NA - // 1492, + 1492, // 1491, // 1490 NA // 1489 NA // 1488 NA // 1487 NA - // 1486, + 1486, // 1485 NA // 1484 NA // 1483 NA // 1482 NA // 1481 NA - // 1480, - // 1479, - // 1478, + 1480, + 1479, + 1478, // 1477, // 1476 NA // 1475 NA @@ -299,7 +303,7 @@ static int included_patches[] = { // 1399 NA // 1398 NA 1397, - // 1396, + 1396, // 1395 NA 1394, // 1393 NA @@ -307,11 +311,11 @@ static int included_patches[] = { // 1391 NA // 1390 NA // 1389 NA - // 1388, + 1388, // 1387 NA // 1386 NA // 1385 NA - // 1384, + 1384, // 1383 NA // 1382 NA // 1381 NA diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 165a44a148..09e9e850a7 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -174,6 +174,7 @@ enum { EXPAND_USER, EXPAND_SYNTIME, EXPAND_USER_ADDR_TYPE, + EXPAND_PACKADD, }; @@ -307,4 +308,12 @@ enum { # define SET_NO_HLSEARCH(flag) no_hlsearch = (flag); set_vim_var_nr( \ VV_HLSEARCH, !no_hlsearch && p_hls) +// Used for flags in do_in_path() +#define DIP_ALL 0x01 // all matches, not just the first one +#define DIP_DIR 0x02 // find directories instead of files +#define DIP_ERR 0x04 // give an error message when none found +#define DIP_START 0x08 // also use "start" directory in 'packpath' +#define DIP_OPT 0x10 // also use "opt" directory in 'packpath' +#define DIP_NORTP 0x20 // do not use 'runtimepath' + #endif /* NVIM_VIM_H */ |