0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 7.4.1480

Problem:    Cannot add a pack direcory without loading a plugin.
Solution:   Add the :packadd command.
This commit is contained in:
Bram Moolenaar
2016-03-03 17:13:03 +01:00
parent 863c1a9079
commit 91715873d1
6 changed files with 123 additions and 54 deletions

View File

@@ -413,7 +413,7 @@ A Vim package is a directory that contains one or more plugins. The
advantages over normal plugins: advantages over normal plugins:
- A package can be downloaded as an archive and unpacked in its own directory. - A package can be downloaded as an archive and unpacked in its own directory.
That makes it easy to updated and/or remove. 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. easy to update.
- A package can contain multiple plugins that depend on each other. - A package can contain multiple plugins that depend on each other.
- A package can contain plugins that are automatically loaded on startup and - 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 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'. find the syntax/always.vim file, because its directory is in 'runtimepath'.
Vim will also load ftdetect files, like with |:loadplugin|.
*load-plugin* *load-plugin*
To load an optional plugin from a pack use the `:loadplugin` command: > To load an optional plugin from a pack use the `:loadplugin` command: >
:loadplugin mydebug :loadplugin mydebug

View File

@@ -1014,6 +1014,9 @@ EX(CMD_ownsyntax, "ownsyntax", ex_ownsyntax,
EX(CMD_print, "print", ex_print, EX(CMD_print, "print", ex_print,
RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK, RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK,
ADDR_LINES), ADDR_LINES),
EX(CMD_packadd, "packadd", ex_packadd,
BANG|FILE1|TRLBAR|SBOXOK|CMDWIN,
ADDR_LINES),
EX(CMD_pclose, "pclose", ex_pclose, EX(CMD_pclose, "pclose", ex_pclose,
BANG|TRLBAR, BANG|TRLBAR,
ADDR_LINES), ADDR_LINES),

View File

@@ -2918,7 +2918,9 @@ source_callback(char_u *fname, void *cookie UNUSED)
/* /*
* Source the file "name" from all directories in 'runtimepath'. * Source the file "name" from all directories in 'runtimepath'.
* "name" can contain wildcards. * "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. * return FAIL when no file could be sourced, OK otherwise.
*/ */
int int
@@ -2927,11 +2929,14 @@ source_runtime(char_u *name, int all)
return do_in_runtimepath(name, all, source_callback, NULL); return do_in_runtimepath(name, all, source_callback, NULL);
} }
#define DIP_ALL 1 /* all matches, not just the first one */
#define DIP_DIR 2 /* find directories instead of files. */
static int static int
do_in_path( do_in_path(
char_u *path, char_u *path,
char_u *name, char_u *name,
int all, int flags,
void (*callback)(char_u *fname, void *ck), void (*callback)(char_u *fname, void *ck),
void *cookie) void *cookie)
{ {
@@ -2968,7 +2973,7 @@ do_in_path(
/* Loop over all entries in 'runtimepath'. */ /* Loop over all entries in 'runtimepath'. */
rtp = rtp_copy; 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 the path from 'runtimepath' to buf[]. */
copy_option_part(&rtp, buf, MAXPATHL, ","); copy_option_part(&rtp, buf, MAXPATHL, ",");
@@ -2985,7 +2990,7 @@ do_in_path(
/* Loop over all patterns in "name" */ /* Loop over all patterns in "name" */
np = name; np = name;
while (*np != NUL && (all || !did_one)) while (*np != NUL && ((flags & DIP_ALL) || !did_one))
{ {
/* Append the pattern from "name" to buf[]. */ /* Append the pattern from "name" to buf[]. */
copy_option_part(&np, tail, (int)(MAXPATHL - (tail - 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. */ /* Expand wildcards, invoke the callback for each match. */
if (gen_expand_wildcards(1, &buf, &num_files, &files, 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) for (i = 0; i < num_files; ++i)
{ {
(*callback)(files[i], cookie); (*callback)(files[i], cookie);
did_one = TRUE; did_one = TRUE;
if (!all) if (!(flags & DIP_ALL))
break; break;
} }
FreeWild(num_files, files); FreeWild(num_files, files);
@@ -3049,7 +3054,7 @@ do_in_runtimepath(
void (*callback)(char_u *fname, void *ck), void (*callback)(char_u *fname, void *ck),
void *cookie) 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) if (cmd != NULL && eval_to_number(cmd) > 0)
{ {
do_cmdline_cmd((char_u *)"augroup filetypedetect"); 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"); do_cmdline_cmd((char_u *)"augroup END");
} }
vim_free(cmd); vim_free(cmd);
} }
static void 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; char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
int c; int c;
char_u *new_rtp; char_u *new_rtp;
int keep; int keep;
int oldlen; int oldlen;
int addlen; int addlen;
char_u *ffname = fix_fname(fname);
int load_file = cookie != NULL;
p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(fname); if (ffname == NULL)
return;
p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(ffname);
for (p = p1; *p; mb_ptr_adv(p)) for (p = p1; *p; mb_ptr_adv(p))
if (vim_ispathsep_nocolon(*p)) if (vim_ispathsep_nocolon(*p))
{ {
p6 = p5; p5 = p4; p4 = p3; p3 = p2; p2 = p1; p1 = 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 * rtp/pack/name/ever/name/plugin/name.vim
* p6 p5 p4 p3 p2 p1 * 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' */ /* find the part up to "pack" in 'runtimepath' */
c = *p6; c = *p4;
*p6 = NUL; *p4 = NUL;
p = (char_u *)strstr((char *)p_rtp, (char *)fname); p = (char_u *)strstr((char *)p_rtp, (char *)ffname);
if (p == NULL) if (p == NULL)
/* not found, append at the end */ /* not found, append at the end */
p = p_rtp + STRLEN(p_rtp); p = p_rtp + STRLEN(p_rtp);
else else
/* append after the matching directory. */ /* append after the matching directory. */
p += STRLEN(fname); p += STRLEN(ffname);
*p6 = c; *p4 = c;
c = *p2; if (load_file)
*p2 = NUL; {
if (strstr((char *)p_rtp, (char *)fname) == NULL) c = *p2;
*p2 = NUL;
}
if (strstr((char *)p_rtp, (char *)ffname) == NULL)
{ {
/* directory not in 'runtimepath', add it */ /* directory not in 'runtimepath', add it */
oldlen = (int)STRLEN(p_rtp); oldlen = (int)STRLEN(p_rtp);
addlen = (int)STRLEN(fname); addlen = (int)STRLEN(ffname);
new_rtp = alloc(oldlen + addlen + 2); new_rtp = alloc(oldlen + addlen + 2);
if (new_rtp == NULL) if (new_rtp == NULL)
{ {
@@ -3121,16 +3139,17 @@ source_pack_plugin(char_u *fname, void *cookie UNUSED)
keep = (int)(p - p_rtp); keep = (int)(p - p_rtp);
mch_memmove(new_rtp, p_rtp, keep); mch_memmove(new_rtp, p_rtp, keep);
new_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) if (p_rtp[keep] != NUL)
mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep, mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep,
oldlen - keep + 1); oldlen - keep + 1);
set_option_value((char_u *)"rtp", 0L, new_rtp, 0); set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
vim_free(new_rtp); 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() source_packages()
{ {
do_in_path(p_pp, (char_u *)"pack/*/ever/*/plugin/*.vim", 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"); may_do_filetypes((char_u *)"pack/*/ever/*/ftdetect/*.vim");
} }
@@ -3160,7 +3179,7 @@ ex_loadplugin(exarg_T *eap)
if (pat == NULL) if (pat == NULL)
return; return;
vim_snprintf(pat, len, plugpat, eap->arg); 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); vim_snprintf(pat, len, ftpat, eap->arg);
may_do_filetypes((char_u *)pat); may_do_filetypes((char_u *)pat);
@@ -3168,6 +3187,25 @@ ex_loadplugin(exarg_T *eap)
vim_free(pat); 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) #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
/* /*
* ":options" * ":options"

View File

@@ -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); int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie);
void source_packages(void); void source_packages(void);
void ex_loadplugin(exarg_T *eap); void ex_loadplugin(exarg_T *eap);
void ex_packadd(exarg_T *eap);
void ex_options(exarg_T *eap); void ex_options(exarg_T *eap);
void ex_source(exarg_T *eap); void ex_source(exarg_T *eap);
linenr_T *source_breakpoint(void *cookie); linenr_T *source_breakpoint(void *cookie);

View File

@@ -1,25 +1,48 @@
" Tests for :loadplugin " Tests for :loadplugin
func Test_loadplugin() func SetUp()
let topdir = expand('%:h') . '/Xdir' let s:topdir = expand('%:h') . '/Xdir'
exe 'set packpath=' . topdir exe 'set packpath=' . s:topdir
let plugdir = topdir . '/pack/mine/opt/mytest' let s:plugdir = s:topdir . '/pack/mine/opt/mytest'
call mkdir(plugdir . '/plugin', 'p') endfunc
call mkdir(plugdir . '/ftdetect', 'p')
filetype on func TearDown()
try call delete(s:topdir, 'rf')
exe 'split ' . plugdir . '/plugin/test.vim' endfunc
call setline(1, 'let g:plugin_works = 42')
wq func Test_loadplugin()
call mkdir(s:plugdir . '/plugin', 'p')
exe 'split ' . plugdir . '/ftdetect/test.vim' call mkdir(s:plugdir . '/ftdetect', 'p')
call setline(1, 'let g:ftdetect_works = 17') set rtp&
wq let rtp = &rtp
filetype on
loadplugin mytest
call assert_true(42, g:plugin_works) exe 'split ' . s:plugdir . '/plugin/test.vim'
call assert_true(17, g:ftdetect_works) call setline(1, 'let g:plugin_works = 42')
finally wq
call delete(topdir, 'rf')
endtry 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 endfunc

View File

@@ -743,6 +743,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1480,
/**/ /**/
1479, 1479,
/**/ /**/