aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2016-07-09 06:58:27 -0400
committerGitHub <noreply@github.com>2016-07-09 06:58:27 -0400
commitadaacdd71a70b76bc686113eaece47a6264701a5 (patch)
tree4be6079a8571316cbd89e3f310981b080f2815a4 /src
parent6cee9d1a17177f4ccdf34283c6ed3ffaa98b32cc (diff)
parent059e9785dc2fea0a15344162de4a5a7c8da6f491 (diff)
downloadrneovim-adaacdd71a70b76bc686113eaece47a6264701a5.tar.gz
rneovim-adaacdd71a70b76bc686113eaece47a6264701a5.tar.bz2
rneovim-adaacdd71a70b76bc686113eaece47a6264701a5.zip
Merge #4648 from jamessan/packages
packages (vim-patch:7.4.{1384,1388,1396,1478,1479,1480,1486,1492,1499,1528,1550,1551,1552,1553,1554,1596,1649,1712,1840,1973,1986})
Diffstat (limited to 'src')
-rw-r--r--src/nvim/digraph.c4
-rw-r--r--src/nvim/eval.c8
-rw-r--r--src/nvim/ex_cmds.c251
-rw-r--r--src/nvim/ex_cmds.lua12
-rw-r--r--src/nvim/ex_cmds2.c295
-rw-r--r--src/nvim/ex_docmd.c84
-rw-r--r--src/nvim/ex_getln.c96
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/hardcopy.c3
-rw-r--r--src/nvim/main.c5
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/option_defs.h149
-rw-r--r--src/nvim/options.lua10
-rw-r--r--src/nvim/spell.c12
-rw-r--r--src/nvim/syntax.c37
-rw-r--r--src/nvim/tag.c5
-rw-r--r--src/nvim/version.c36
-rw-r--r--src/nvim/vim.h9
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 */