# HG changeset patch # User Christian Brabandt # Date 1457021705 -3600 # Node ID e448f2a5d45b5143a834374ca28f3887ffac6416 # Parent 3d5a49fe23bf4c61c0f26e223047f93e1f53a825 commit https://github.com/vim/vim/commit/91715873d19a1859c08eeded7848113596e2f2bd Author: Bram Moolenaar Date: Thu Mar 3 17:13:03 2016 +0100 patch 7.4.1480 Problem: Cannot add a pack direcory without loading a plugin. Solution: Add the :packadd command. diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -413,7 +413,7 @@ A Vim package is a directory that contai 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/al 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 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -1014,6 +1014,9 @@ EX(CMD_ownsyntax, "ownsyntax", ex_ownsyn 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 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -2918,7 +2918,9 @@ source_callback(char_u *fname, void *coo /* * 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; - - c = *p2; - *p2 = NUL; - if (strstr((char *)p_rtp, (char *)fname) == NULL) + p += STRLEN(ffname); + *p4 = c; + + 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 * 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; - - (void)do_source(fname, FALSE, DOSO_NONE); + vim_free(ffname); + + if (load_file) + (void)do_source(fname, FALSE, DOSO_NONE); } /* @@ -3140,7 +3159,7 @@ source_pack_plugin(char_u *fname, void * 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 --- 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 --- 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 ' . 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 - exe 'split ' . plugdir . '/ftdetect/test.vim' - call setline(1, 'let g:ftdetect_works = 17') - wq + 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 - loadplugin mytest - call assert_true(42, g:plugin_works) - call assert_true(17, g:ftdetect_works) - finally - call delete(topdir, 'rf') - endtry +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 --- 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,