Skip to content

Commit 9171587

Browse files
committed
patch 7.4.1480
Problem: Cannot add a pack direcory without loading a plugin. Solution: Add the :packadd command.
1 parent 863c1a9 commit 9171587

6 files changed

Lines changed: 122 additions & 53 deletions

File tree

runtime/doc/repeat.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ A Vim package is a directory that contains one or more plugins. The
413413
advantages over normal plugins:
414414
- A package can be downloaded as an archive and unpacked in its own directory.
415415
That makes it easy to updated and/or remove.
416-
- A package can be a git, mercurial, etc. respository. That makes it really
416+
- A package can be a git, mercurial, etc. repository. That makes it really
417417
easy to update.
418418
- A package can contain multiple plugins that depend on each other.
419419
- 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
443443
If the "always" plugin kicks in and sets the 'filetype' to "always", Vim will
444444
find the syntax/always.vim file, because its directory is in 'runtimepath'.
445445

446+
Vim will also load ftdetect files, like with |:loadplugin|.
447+
446448
*load-plugin*
447449
To load an optional plugin from a pack use the `:loadplugin` command: >
448450
:loadplugin mydebug

src/ex_cmds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,9 @@ EX(CMD_ownsyntax, "ownsyntax", ex_ownsyntax,
10141014
EX(CMD_print, "print", ex_print,
10151015
RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK,
10161016
ADDR_LINES),
1017+
EX(CMD_packadd, "packadd", ex_packadd,
1018+
BANG|FILE1|TRLBAR|SBOXOK|CMDWIN,
1019+
ADDR_LINES),
10171020
EX(CMD_pclose, "pclose", ex_pclose,
10181021
BANG|TRLBAR,
10191022
ADDR_LINES),

src/ex_cmds2.c

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,7 +2918,9 @@ source_callback(char_u *fname, void *cookie UNUSED)
29182918
/*
29192919
* Source the file "name" from all directories in 'runtimepath'.
29202920
* "name" can contain wildcards.
2921-
* When "all" is TRUE, source all files, otherwise only the first one.
2921+
* When "flags" has DIP_ALL: source all files, otherwise only the first one.
2922+
* When "flags" has DIP_DIR: find directories instead of files.
2923+
*
29222924
* return FAIL when no file could be sourced, OK otherwise.
29232925
*/
29242926
int
@@ -2927,11 +2929,14 @@ source_runtime(char_u *name, int all)
29272929
return do_in_runtimepath(name, all, source_callback, NULL);
29282930
}
29292931

2932+
#define DIP_ALL 1 /* all matches, not just the first one */
2933+
#define DIP_DIR 2 /* find directories instead of files. */
2934+
29302935
static int
29312936
do_in_path(
29322937
char_u *path,
29332938
char_u *name,
2934-
int all,
2939+
int flags,
29352940
void (*callback)(char_u *fname, void *ck),
29362941
void *cookie)
29372942
{
@@ -2968,7 +2973,7 @@ do_in_path(
29682973

29692974
/* Loop over all entries in 'runtimepath'. */
29702975
rtp = rtp_copy;
2971-
while (*rtp != NUL && (all || !did_one))
2976+
while (*rtp != NUL && ((flags & DIP_ALL) || !did_one))
29722977
{
29732978
/* Copy the path from 'runtimepath' to buf[]. */
29742979
copy_option_part(&rtp, buf, MAXPATHL, ",");
@@ -2985,7 +2990,7 @@ do_in_path(
29852990

29862991
/* Loop over all patterns in "name" */
29872992
np = name;
2988-
while (*np != NUL && (all || !did_one))
2993+
while (*np != NUL && ((flags & DIP_ALL) || !did_one))
29892994
{
29902995
/* Append the pattern from "name" to buf[]. */
29912996
copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)),
@@ -3000,13 +3005,13 @@ do_in_path(
30003005

30013006
/* Expand wildcards, invoke the callback for each match. */
30023007
if (gen_expand_wildcards(1, &buf, &num_files, &files,
3003-
EW_FILE) == OK)
3008+
(flags & DIP_DIR) ? EW_DIR : EW_FILE) == OK)
30043009
{
30053010
for (i = 0; i < num_files; ++i)
30063011
{
30073012
(*callback)(files[i], cookie);
30083013
did_one = TRUE;
3009-
if (!all)
3014+
if (!(flags & DIP_ALL))
30103015
break;
30113016
}
30123017
FreeWild(num_files, files);
@@ -3049,7 +3054,7 @@ do_in_runtimepath(
30493054
void (*callback)(char_u *fname, void *ck),
30503055
void *cookie)
30513056
{
3052-
return do_in_path(p_rtp, name, all, callback, cookie);
3057+
return do_in_path(p_rtp, name, all ? DIP_ALL : 0, callback, cookie);
30533058
}
30543059

30553060
/*
@@ -3065,53 +3070,66 @@ may_do_filetypes(char_u *pat)
30653070
if (cmd != NULL && eval_to_number(cmd) > 0)
30663071
{
30673072
do_cmdline_cmd((char_u *)"augroup filetypedetect");
3068-
do_in_path(p_pp, pat, TRUE, source_callback, NULL);
3073+
do_in_path(p_pp, pat, DIP_ALL, source_callback, NULL);
30693074
do_cmdline_cmd((char_u *)"augroup END");
30703075
}
30713076
vim_free(cmd);
30723077
}
30733078

30743079
static void
3075-
source_pack_plugin(char_u *fname, void *cookie UNUSED)
3080+
add_pack_plugin(char_u *fname, void *cookie)
30763081
{
3077-
char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
3078-
int c;
3079-
char_u *new_rtp;
3080-
int keep;
3081-
int oldlen;
3082-
int addlen;
3083-
3084-
p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(fname);
3082+
char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
3083+
int c;
3084+
char_u *new_rtp;
3085+
int keep;
3086+
int oldlen;
3087+
int addlen;
3088+
char_u *ffname = fix_fname(fname);
3089+
int load_file = cookie != NULL;
3090+
3091+
if (ffname == NULL)
3092+
return;
3093+
p6 = p5 = p4 = p3 = p2 = p1 = get_past_head(ffname);
30853094
for (p = p1; *p; mb_ptr_adv(p))
30863095
if (vim_ispathsep_nocolon(*p))
30873096
{
30883097
p6 = p5; p5 = p4; p4 = p3; p3 = p2; p2 = p1; p1 = p;
30893098
}
30903099

3091-
/* now we have:
3100+
/* now we have, load_file == TRUE:
30923101
* rtp/pack/name/ever/name/plugin/name.vim
30933102
* p6 p5 p4 p3 p2 p1
3103+
*
3104+
* with load_file == FALSE:
3105+
* rtp/pack/name/ever/name
3106+
* p4 p3 p2 p1
30943107
*/
3108+
if (load_file)
3109+
p4 = p6;
30953110

30963111
/* find the part up to "pack" in 'runtimepath' */
3097-
c = *p6;
3098-
*p6 = NUL;
3099-
p = (char_u *)strstr((char *)p_rtp, (char *)fname);
3112+
c = *p4;
3113+
*p4 = NUL;
3114+
p = (char_u *)strstr((char *)p_rtp, (char *)ffname);
31003115
if (p == NULL)
31013116
/* not found, append at the end */
31023117
p = p_rtp + STRLEN(p_rtp);
31033118
else
31043119
/* append after the matching directory. */
3105-
p += STRLEN(fname);
3106-
*p6 = c;
3120+
p += STRLEN(ffname);
3121+
*p4 = c;
31073122

3108-
c = *p2;
3109-
*p2 = NUL;
3110-
if (strstr((char *)p_rtp, (char *)fname) == NULL)
3123+
if (load_file)
3124+
{
3125+
c = *p2;
3126+
*p2 = NUL;
3127+
}
3128+
if (strstr((char *)p_rtp, (char *)ffname) == NULL)
31113129
{
31123130
/* directory not in 'runtimepath', add it */
31133131
oldlen = (int)STRLEN(p_rtp);
3114-
addlen = (int)STRLEN(fname);
3132+
addlen = (int)STRLEN(ffname);
31153133
new_rtp = alloc(oldlen + addlen + 2);
31163134
if (new_rtp == NULL)
31173135
{
@@ -3121,16 +3139,17 @@ source_pack_plugin(char_u *fname, void *cookie UNUSED)
31213139
keep = (int)(p - p_rtp);
31223140
mch_memmove(new_rtp, p_rtp, keep);
31233141
new_rtp[keep] = ',';
3124-
mch_memmove(new_rtp + keep + 1, fname, addlen + 1);
3142+
mch_memmove(new_rtp + keep + 1, ffname, addlen + 1);
31253143
if (p_rtp[keep] != NUL)
31263144
mch_memmove(new_rtp + keep + 1 + addlen, p_rtp + keep,
31273145
oldlen - keep + 1);
31283146
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
31293147
vim_free(new_rtp);
31303148
}
3131-
*p2 = c;
3149+
vim_free(ffname);
31323150

3133-
(void)do_source(fname, FALSE, DOSO_NONE);
3151+
if (load_file)
3152+
(void)do_source(fname, FALSE, DOSO_NONE);
31343153
}
31353154

31363155
/*
@@ -3140,7 +3159,7 @@ source_pack_plugin(char_u *fname, void *cookie UNUSED)
31403159
source_packages()
31413160
{
31423161
do_in_path(p_pp, (char_u *)"pack/*/ever/*/plugin/*.vim",
3143-
TRUE, source_pack_plugin, NULL);
3162+
DIP_ALL, add_pack_plugin, p_pp);
31443163
may_do_filetypes((char_u *)"pack/*/ever/*/ftdetect/*.vim");
31453164
}
31463165

@@ -3160,14 +3179,33 @@ ex_loadplugin(exarg_T *eap)
31603179
if (pat == NULL)
31613180
return;
31623181
vim_snprintf(pat, len, plugpat, eap->arg);
3163-
do_in_path(p_pp, (char_u *)pat, TRUE, source_pack_plugin, NULL);
3182+
do_in_path(p_pp, (char_u *)pat, DIP_ALL, add_pack_plugin, p_pp);
31643183

31653184
vim_snprintf(pat, len, ftpat, eap->arg);
31663185
may_do_filetypes((char_u *)pat);
31673186

31683187
vim_free(pat);
31693188
}
31703189

3190+
/*
3191+
* ":packadd {name}"
3192+
*/
3193+
void
3194+
ex_packadd(exarg_T *eap)
3195+
{
3196+
static char *plugpat = "pack/*/opt/%s";
3197+
int len;
3198+
char *pat;
3199+
3200+
len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg);
3201+
pat = (char *)alloc(len);
3202+
if (pat == NULL)
3203+
return;
3204+
vim_snprintf(pat, len, plugpat, eap->arg);
3205+
do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR, add_pack_plugin, NULL);
3206+
vim_free(pat);
3207+
}
3208+
31713209
#if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
31723210
/*
31733211
* ":options"

src/proto/ex_cmds2.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ int source_runtime(char_u *name, int all);
6464
int do_in_runtimepath(char_u *name, int all, void (*callback)(char_u *fname, void *ck), void *cookie);
6565
void source_packages(void);
6666
void ex_loadplugin(exarg_T *eap);
67+
void ex_packadd(exarg_T *eap);
6768
void ex_options(exarg_T *eap);
6869
void ex_source(exarg_T *eap);
6970
linenr_T *source_breakpoint(void *cookie);

src/testdir/test_loadplugin.vim

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
11
" Tests for :loadplugin
22

3+
func SetUp()
4+
let s:topdir = expand('%:h') . '/Xdir'
5+
exe 'set packpath=' . s:topdir
6+
let s:plugdir = s:topdir . '/pack/mine/opt/mytest'
7+
endfunc
8+
9+
func TearDown()
10+
call delete(s:topdir, 'rf')
11+
endfunc
12+
313
func Test_loadplugin()
4-
let topdir = expand('%:h') . '/Xdir'
5-
exe 'set packpath=' . topdir
6-
let plugdir = topdir . '/pack/mine/opt/mytest'
7-
call mkdir(plugdir . '/plugin', 'p')
8-
call mkdir(plugdir . '/ftdetect', 'p')
14+
call mkdir(s:plugdir . '/plugin', 'p')
15+
call mkdir(s:plugdir . '/ftdetect', 'p')
16+
set rtp&
17+
let rtp = &rtp
918
filetype on
10-
try
11-
exe 'split ' . plugdir . '/plugin/test.vim'
12-
call setline(1, 'let g:plugin_works = 42')
13-
wq
14-
15-
exe 'split ' . plugdir . '/ftdetect/test.vim'
16-
call setline(1, 'let g:ftdetect_works = 17')
17-
wq
18-
19-
loadplugin mytest
20-
call assert_true(42, g:plugin_works)
21-
call assert_true(17, g:ftdetect_works)
22-
finally
23-
call delete(topdir, 'rf')
24-
endtry
19+
20+
exe 'split ' . s:plugdir . '/plugin/test.vim'
21+
call setline(1, 'let g:plugin_works = 42')
22+
wq
23+
24+
exe 'split ' . s:plugdir . '/ftdetect/test.vim'
25+
call setline(1, 'let g:ftdetect_works = 17')
26+
wq
27+
28+
loadplugin mytest
29+
30+
call assert_equal(42, g:plugin_works)
31+
call assert_equal(17, g:ftdetect_works)
32+
call assert_true(len(&rtp) > len(rtp))
33+
call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
34+
endfunc
35+
36+
func Test_packadd()
37+
call mkdir(s:plugdir . '/syntax', 'p')
38+
set rtp&
39+
let rtp = &rtp
40+
packadd mytest
41+
call assert_true(len(&rtp) > len(rtp))
42+
call assert_true(&rtp =~ 'testdir/Xdir/pack/mine/opt/mytest\($\|,\)')
43+
44+
" check the path is not added twice
45+
let new_rtp = &rtp
46+
packadd mytest
47+
call assert_equal(new_rtp, &rtp)
2548
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1480,
746748
/**/
747749
1479,
748750
/**/

0 commit comments

Comments
 (0)