summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-03-03 17:13:03 +0100
committerBram Moolenaar <Bram@vim.org>2016-03-03 17:13:03 +0100
commit91715873d19a1859c08eeded7848113596e2f2bd (patch)
tree59e2fa6c902756d7831f05c7ffdbce45d9a7a573
parent863c1a9079fa340d663ccafb011729a29186d73e (diff)
downloadvim-git-91715873d19a1859c08eeded7848113596e2f2bd.tar.gz
patch 7.4.1480v7.4.1480
Problem: Cannot add a pack direcory without loading a plugin. Solution: Add the :packadd command.
-rw-r--r--runtime/doc/repeat.txt4
-rw-r--r--src/ex_cmds.h3
-rw-r--r--src/ex_cmds2.c102
-rw-r--r--src/proto/ex_cmds2.pro1
-rw-r--r--src/testdir/test_loadplugin.vim63
-rw-r--r--src/version.c2
6 files changed, 122 insertions, 53 deletions
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 711b13890..a6ebf7118 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -413,7 +413,7 @@ A Vim package is a directory that contains one or more plugins. The
advantages over normal plugins:
- A package can be downloaded as an archive and unpacked in its own directory.
That makes it easy to updated and/or remove.
-- A package can be a git, mercurial, etc. respository. That makes it really
+- A package can be a git, mercurial, etc. repository. That makes it really
easy to update.
- A package can contain multiple plugins that depend on each other.
- A package can contain plugins that are automatically loaded on startup and
@@ -443,6 +443,8 @@ In the example Vim will find "my/ever/always/plugin/always.vim" and adds
If the "always" plugin kicks in and sets the 'filetype' to "always", Vim will
find the syntax/always.vim file, because its directory is in 'runtimepath'.
+Vim will also load ftdetect files, like with |:loadplugin|.
+
*load-plugin*
To load an optional plugin from a pack use the `:loadplugin` command: >
:loadplugin mydebug
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index d17f4d54e..94c2816e2 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1014,6 +1014,9 @@ EX(CMD_ownsyntax, "ownsyntax", ex_ownsyntax,
EX(CMD_print, "print", ex_print,
RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK,
ADDR_LINES),
+EX(CMD_packadd, "packadd", ex_packadd,
+ BANG|FILE1|TRLBAR|SBOXOK|CMDWIN,
+ ADDR_LINES),
EX(CMD_pclose, "pclose", ex_pclose,
BANG|TRLBAR,
ADDR_LINES),
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 52575bf0a..73172cb08 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -2918,7 +2918,9 @@ source_callback(char_u *fname, void *cookie UNUSED)
/*
* 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.
+ * When "flags" has DIP_DIR: find directories instead of files.
+ *
* return FAIL when no file could be sourced, OK otherwise.
*/
int
@@ -2927,11 +2929,14 @@ source_runtime(char_u *name, int all)
return do_in_runtimepath(name, all, source_callback, NULL);
}
+#define DIP_ALL 1 /* all matches, not just the first one */
+#define DIP_DIR 2 /* find directories instead of files. */
+
static int
do_in_path(
char_u *path,
char_u *name,
- int all,
+ int flags,
void (*callback)(char_u *fname, void *ck),
void *cookie)
{
@@ -2968,7 +2973,7 @@ do_in_path(
/* Loop over all entries in 'runtimepath'. */
rtp = rtp_copy;
- while (*rtp != NUL && (all || !did_one))
+ while (*rtp != NUL && ((flags & DIP_ALL) || !did_one))
{
/* Copy the path from 'runtimepath' to buf[]. */
copy_option_part(&rtp, buf, MAXPATHL, ",");
@@ -2985,7 +2990,7 @@ do_in_path(
/* Loop over all patterns in "name" */
np = name;
- while (*np != NUL && (all || !did_one))
+ while (*np != NUL && ((flags & DIP_ALL) || !did_one))
{
/* Append the pattern from "name" to buf[]. */
copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
@@ -3000,13 +3005,13 @@ do_in_path(
/* 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;
}
FreeWild(num_files, files);
@@ -3049,7 +3054,7 @@ do_in_runtimepath(
void (*callback)(char_u *fname, void *ck),
void *cookie)
{
- return do_in_path(p_rtp, name, all, callback, cookie);
+ return do_in_path(p_rtp, name, all ? DIP_ALL : 0, callback, cookie);
}
/*
@@ -3065,53 +3070,66 @@ may_do_filetypes(char_u *pat)
if (cmd != NULL && eval_to_number(cmd) > 0)
{
do_cmdline_cmd((char_u *)"augroup filetypedetect");
- do_in_path(p_pp, pat, TRUE, source_callback, NULL);
+ do_in_path(p_pp, pat, DIP_ALL, source_callback, NULL);
do_cmdline_cmd((char_u *)"augroup END");
}
vim_free(cmd);
}
static void
-source_pack_plugin(char_u *fname, void *cookie UNUSED)
+add_pack_plugin(char_u *fname, void *cookie)
{
- char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
- int c;
- char_u *new_rtp;
- int keep;
- int oldlen;
- int addlen;
-
- p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(fname);
+ char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
+ int c;
+ char_u *new_rtp;
+ int keep;
+ int oldlen;
+ int addlen;
+ char_u *ffname = fix_fname(fname);
+ int load_file = cookie != NULL;
+
+ if (ffname == NULL)
+ return;
+ p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(ffname);
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:
+ /* now we have, load_file == TRUE:
* rtp/pack/name/ever/name/plugin/name.vim
* p6 p5 p4 p3 p2 p1
+ *
+ * with load_file == FALSE:
+ * rtp/pack/name/ever/name
+ * p4 p3 p2 p1
*/
+ if (load_file)
+ p4 = p6;
/* find the part up to "pack" in 'runtimepath' */
- c = *p6;
- *p6 = NUL;
- p = (char_u *)strstr((char *)p_rtp, (char *)fname);
+ c = *p4;
+ *p4 = NUL;
+ p = (char_u *)strstr((char *)p_rtp, (char *)ffname);
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;
+ p += STRLEN(ffname);
+ *p4 = c;
- c = *p2;
- *p2 = NUL;
- if (strstr((char *)p_rtp, (char *)fname) == NULL)
+ if (load_file)
+ {
+ c = *p2;
+ *p2 = NUL;
+ }
+ if (strstr((char *)p_rtp, (char *)ffname) == NULL)
{
/* directory not in 'runtimepath', add it */
oldlen = (int)STRLEN(p_rtp);
- addlen = (int)STRLEN(fname);
+ addlen = (int)STRLEN(ffname);
new_rtp = alloc(oldlen + addlen + 2);
if (new_rtp == NULL)
{
@@ -3121,16 +3139,17 @@ source_pack_plugin(char_u *fname, void *cookie UNUSED)
keep = (int)(p - p_rtp);
mch_memmove(new_rtp, p_rtp, keep);
new_rtp[keep] = ',';
- mch_memmove(new_rtp + keep + 1, fname, addlen + 1);
+ mch_memmove(new_rtp + keep + 1, ffname, addlen + 1);
if (p_rtp[keep] != NUL)
mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep,
oldlen - keep + 1);
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
vim_free(new_rtp);
}
- *p2 = c;
+ vim_free(ffname);
- (void)do_source(fname, FALSE, DOSO_NONE);
+ if (load_file)
+ (void)do_source(fname, FALSE, DOSO_NONE);
}
/*
@@ -3140,7 +3159,7 @@ source_pack_plugin(char_u *fname, void *cookie UNUSED)
source_packages()
{
do_in_path(p_pp, (char_u *)"pack/*/ever/*/plugin/*.vim",
- TRUE, source_pack_plugin, NULL);
+ DIP_ALL, add_pack_plugin, p_pp);
may_do_filetypes((char_u *)"pack/*/ever/*/ftdetect/*.vim");
}
@@ -3160,7 +3179,7 @@ ex_loadplugin(exarg_T *eap)
if (pat == NULL)
return;
vim_snprintf(pat, len, plugpat, eap->arg);
- do_in_path(p_pp, (char_u *)pat, TRUE, source_pack_plugin, NULL);
+ do_in_path(p_pp, (char_u *)pat, DIP_ALL, add_pack_plugin, p_pp);
vim_snprintf(pat, len, ftpat, eap->arg);
may_do_filetypes((char_u *)pat);
@@ -3168,6 +3187,25 @@ ex_loadplugin(exarg_T *eap)
vim_free(pat);
}
+/*
+ * ":packadd {name}"
+ */
+ void
+ex_packadd(exarg_T *eap)
+{
+ static char *plugpat = "pack/*/opt/%s";
+ int len;
+ char *pat;
+
+ len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg);
+ pat = (char *)alloc(len);
+ if (pat == NULL)
+ return;
+ vim_snprintf(pat, len, plugpat, eap->arg);
+ do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR, add_pack_plugin, NULL);
+ vim_free(pat);
+}
+
#if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
/*
* ":options"
diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro
index 3eabcbdb5..e10f07241 100644
--- a/src/proto/ex_cmds2.pro
+++ b/src/proto/ex_cmds2.pro
@@ -64,6 +64,7 @@ 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_packadd(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/testdir/test_loadplugin.vim b/src/testdir/test_loadplugin.vim
index 25c671538..431dd4a45 100644
--- a/src/testdir/test_loadplugin.vim
+++ b/src/testdir/test_loadplugin.vim
@@ -1,25 +1,48 @@
" Tests for :loadplugin
+func SetUp()
+ let s:topdir = expand('%:h') . '/Xdir'
+ exe 'set packpath=' . s:topdir
+ let s:plugdir = s:topdir . '/pack/mine/opt/mytest'
+endfunc
+
+func TearDown()
+ call delete(s:topdir, 'rf')
+endfunc
+
func Test_loadplugin()
- let topdir = expand('%:h') . '/Xdir'
- exe 'set packpath=' . topdir
- let plugdir = topdir . '/pack/mine/opt/mytest'
- call mkdir(plugdir . '/plugin', 'p')
- call mkdir(plugdir . '/ftdetect', 'p')
+ call mkdir(s:plugdir . '/plugin', 'p')
+ call mkdir(s:plugdir . '/ftdetect', 'p')
+ set rtp&
+ let rtp = &rtp
filetype on
- try
- exe 'split ' . plugdir . '/plugin/test.vim'
- call setline(1, 'let g:plugin_works = 42')
- wq
-
- exe 'split ' . plugdir . '/ftdetect/test.vim'
- call setline(1, 'let g:ftdetect_works = 17')
- wq
-
- loadplugin mytest
- call assert_true(42, g:plugin_works)
- call assert_true(17, g:ftdetect_works)
- finally
- call delete(topdir, 'rf')
- endtry
+
+ exe 'split ' . s:plugdir . '/plugin/test.vim'
+ call setline(1, 'let g:plugin_works = 42')
+ wq
+
+ exe 'split ' . s:plugdir . '/ftdetect/test.vim'
+ call setline(1, 'let g:ftdetect_works = 17')
+ wq
+
+ loadplugin mytest
+
+ call assert_equal(42, g:plugin_works)
+ call assert_equal(17, g:ftdetect_works)
+ call assert_true(len(&rtp) > len(rtp))
+ call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
+endfunc
+
+func Test_packadd()
+ call mkdir(s:plugdir . '/syntax', 'p')
+ set rtp&
+ let rtp = &rtp
+ packadd mytest
+ call assert_true(len(&rtp) > len(rtp))
+ call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
+
+ " check the path is not added twice
+ let new_rtp = &rtp
+ packadd mytest
+ call assert_equal(new_rtp, &rtp)
endfunc
diff --git a/src/version.c b/src/version.c
index d13f47afa..76ce46207 100644
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1480,
+/**/
1479,
/**/
1478,