patch 7.4.1384
Problem:    It is not easy to use a set of plugins and their dependencies.
Solution:   Add packages, ":loadopt", 'packpath'.
diff --git a/src/eval.c b/src/eval.c
index bb9a4c5..0d38e11 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -13785,6 +13785,7 @@
 #ifdef FEAT_OLE
 	"ole",
 #endif
+	"packages",
 #ifdef FEAT_PATH_EXTRA
 	"path_extra",
 #endif
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index fa26824..23c26fa 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -810,6 +810,9 @@
 EX(CMD_loadkeymap,	"loadkeymap",	ex_loadkeymap,
 			CMDWIN,
 			ADDR_LINES),
+EX(CMD_loadplugin,	"loadplugin",	ex_loadplugin,
+			BANG|FILE1|TRLBAR|SBOXOK|CMDWIN,
+			ADDR_LINES),
 EX(CMD_lockmarks,	"lockmarks",	ex_wrongmodifier,
 			NEEDARG|EXTRA|NOTRLCOM,
 			ADDR_LINES),
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 3b18ece..e26069d 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -2905,8 +2905,6 @@
     source_runtime(eap->arg, eap->forceit);
 }
 
-static void source_callback(char_u *fname, void *cookie);
-
     static void
 source_callback(char_u *fname, void *cookie UNUSED)
 {
@@ -2925,19 +2923,9 @@
     return do_in_runtimepath(name, all, 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(
+    static int
+do_in_path(
+    char_u	*path,
     char_u	*name,
     int		all,
     void	(*callback)(char_u *fname, void *ck),
@@ -2962,7 +2950,7 @@
 
     /* Make a copy of 'runtimepath'.  Invoking the callback may change the
      * value. */
-    rtp_copy = vim_strsave(p_rtp);
+    rtp_copy = vim_strsave(path);
     buf = alloc(MAXPATHL);
     if (buf != NULL && rtp_copy != NULL)
     {
@@ -2970,7 +2958,7 @@
 	{
 	    verbose_enter();
 	    smsg((char_u *)_("Searching for \"%s\" in \"%s\""),
-						 (char *)name, (char *)p_rtp);
+						 (char *)name, (char *)path);
 	    verbose_leave();
 	}
 
@@ -3039,6 +3027,120 @@
     return did_one ? OK : FAIL;
 }
 
+/*
+ * 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,
+    void	(*callback)(char_u *fname, void *ck),
+    void	*cookie)
+{
+    return do_in_path(p_rtp, name, all, callback, cookie);
+}
+
+    static void
+source_pack_plugin(char_u *fname, void *cookie UNUSED)
+{
+    char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
+    int c;
+    char_u *new_rtp;
+    int keep;
+    int oldlen;
+    int addlen;
+
+    p4 = p3 = p2 = p1 = get_past_head(fname);
+    for (p = p1; *p; mb_ptr_adv(p))
+    {
+	if (vim_ispathsep_nocolon(*p))
+	{
+	    p6 = p5; p5 = p4; p4 = p3; p3 = p2; p2 = p1; p1 = p;
+	}
+    }
+
+    /* now we have:
+     * rtp/pack/name/ever/name/plugin/name.vim
+     *    p6   p5   p4   p3   p2     p1
+     */
+
+    /* find the part up to "pack" in 'runtimepath' */
+    c = *p6;
+    *p6 = NUL;
+    p = (char_u *)strstr((char *)p_rtp, (char *)fname);
+    if (p == NULL)
+	/* not found, append at the end */
+	p = p_rtp + STRLEN(p_rtp);
+    else
+	/* append after the matching directory. */
+	p += STRLEN(fname);
+    *p6 = c;
+
+    c = *p2;
+    *p2 = NUL;
+    if (strstr((char *)p_rtp, (char *)fname) == NULL)
+    {
+	/* directory not in 'runtimepath', add it */
+	oldlen = STRLEN(p_rtp);
+	addlen = STRLEN(fname);
+	new_rtp = alloc(oldlen + addlen + 2);
+	if (new_rtp == NULL)
+	{
+	    *p2 = c;
+	    return;
+	}
+	keep = (int)(p - p_rtp);
+	mch_memmove(new_rtp, p_rtp, keep);
+	new_rtp[keep] = ',';
+	mch_memmove(new_rtp + keep + 1, fname, addlen + 1);
+	if (p_rtp[keep] != NUL)
+	    mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep,
+							   oldlen - keep + 1);
+	free_string_option(p_rtp);
+	p_rtp = new_rtp;
+    }
+    *p2 = c;
+
+    (void)do_source(fname, FALSE, DOSO_NONE);
+}
+
+/*
+ * Source the plugins in the package directories.
+ */
+    void
+source_packages()
+{
+    do_in_path(p_pp, (char_u *)"pack/*/ever/*/plugin/*.vim",
+					      TRUE, source_pack_plugin, NULL);
+}
+
+/*
+ * ":loadplugin {name}"
+ */
+    void
+ex_loadplugin(exarg_T *eap)
+{
+    static char *pattern = "pack/*/opt/%s/plugin/*.vim";
+    int		len;
+    char	*pat;
+
+    len = STRLEN(pattern) + STRLEN(eap->arg);
+    pat = (char *)alloc(len);
+    if (pat == NULL)
+	return;
+    vim_snprintf(pat, len, pattern, eap->arg);
+    do_in_path(p_pp, (char_u *)pat, TRUE, source_pack_plugin, NULL);
+    vim_free(pat);
+}
+
 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
 /*
  * ":options"
diff --git a/src/main.c b/src/main.c
index 57aeeed..f19ea1d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -637,6 +637,9 @@
 	source_runtime((char_u *)"plugin/**/*.vim", TRUE);
 # endif
 	TIME_MSG("loading plugins");
+
+	source_packages();
+	TIME_MSG("loading packages");
     }
 #endif
 
diff --git a/src/option.c b/src/option.c
index 8daba63..4f73c0b 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1978,6 +1978,11 @@
     {"osfiletype",  "oft",  P_STRING|P_ALLOCED|P_VI_DEF,
 			    (char_u *)NULL, PV_NONE,
 			    {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
+    {"packpath",    "pp",   P_STRING|P_VI_DEF|P_EXPAND|P_ONECOMMA|P_NODUP
+								    |P_SECURE,
+			    (char_u *)&p_pp, PV_NONE,
+			    {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L}
+			    SCRIPTID_INIT},
     {"paragraphs",  "para", P_STRING|P_VI_DEF,
 			    (char_u *)&p_para, PV_NONE,
 			    {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp",
@@ -11045,6 +11050,7 @@
 	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
 #ifdef FEAT_SEARCHPATH
 		|| p == (char_u *)&p_cdpath
diff --git a/src/option.h b/src/option.h
index f178ea7..24e4184 100644
--- a/src/option.h
+++ b/src/option.h
@@ -723,6 +723,7 @@
 #ifdef FEAT_STL_OPT
 EXTERN char_u	*p_ruf;		/* 'rulerformat' */
 #endif
+EXTERN char_u	*p_pp;		/* 'packpath' */
 EXTERN char_u	*p_rtp;		/* 'runtimepath' */
 EXTERN long	p_sj;		/* 'scrolljump' */
 EXTERN long	p_so;		/* 'scrolloff' */
diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro
index a73e10f..3eabcbd 100644
--- a/src/proto/ex_cmds2.pro
+++ b/src/proto/ex_cmds2.pro
@@ -62,6 +62,8 @@
 void ex_runtime(exarg_T *eap);
 int source_runtime(char_u *name, int all);
 int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie);
+void source_packages(void);
+void ex_loadplugin(exarg_T *eap);
 void ex_options(exarg_T *eap);
 void ex_source(exarg_T *eap);
 linenr_T *source_breakpoint(void *cookie);
diff --git a/src/version.c b/src/version.c
index 27d8c92..81e4617 100644
--- a/src/version.c
+++ b/src/version.c
@@ -462,6 +462,7 @@
 	"-ole",
 # endif
 #endif
+	"+packages",
 #ifdef FEAT_PATH_EXTRA
 	"+path_extra",
 #else
@@ -748,6 +749,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1384,
+/**/
     1383,
 /**/
     1382,