mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 23:38:17 +00:00
vim-patch:7.4.1480
Problem: Cannot add a pack direcory without loading a plugin.
Solution: Add the :packadd command.
91715873d1
This commit is contained in:
@@ -398,7 +398,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
|
||||
@@ -428,6 +428,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
|
||||
|
@@ -1854,6 +1854,12 @@ return {
|
||||
addr_type=ADDR_LINES,
|
||||
func='ex_print',
|
||||
},
|
||||
{
|
||||
command='packadd',
|
||||
flags=bit.bor(BANG, FILE1, TRLBAR, SBOXOK, CMDWIN),
|
||||
addr_type=ADDR_LINES,
|
||||
func='ex_packadd',
|
||||
},
|
||||
{
|
||||
command='pclose',
|
||||
flags=bit.bor(BANG, TRLBAR),
|
||||
|
@@ -2277,14 +2277,19 @@ static void source_callback(char_u *fname, void *cookie)
|
||||
|
||||
/// 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 source_runtime(char_u *name, int all)
|
||||
{
|
||||
return do_in_runtimepath(name, all, source_callback, NULL);
|
||||
}
|
||||
|
||||
static int do_in_path(char_u *path, char_u *name, bool all,
|
||||
#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 flags,
|
||||
DoInRuntimepathCB callback, void *cookie)
|
||||
{
|
||||
char_u *tail;
|
||||
@@ -2307,7 +2312,7 @@ static int do_in_path(char_u *path, char_u *name, bool all,
|
||||
|
||||
// Loop over all entries in 'runtimepath'.
|
||||
char_u *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, ",");
|
||||
if (name == NULL) {
|
||||
@@ -2321,7 +2326,7 @@ static int do_in_path(char_u *path, char_u *name, bool all,
|
||||
|
||||
// Loop over all patterns in "name"
|
||||
char_u *np = name;
|
||||
while (*np != NUL && (all || !did_one)) {
|
||||
while (*np != NUL && ((flags & DIP_ALL) || !did_one)) {
|
||||
// Append the pattern from "name" to buf[].
|
||||
assert(MAXPATHL >= (tail - buf));
|
||||
copy_option_part(&np, tail, (size_t)(MAXPATHL - (tail - buf)),
|
||||
@@ -2335,11 +2340,12 @@ static int do_in_path(char_u *path, char_u *name, bool all,
|
||||
|
||||
// Expand wildcards, invoke the callback for each match.
|
||||
if (gen_expand_wildcards(1, &buf, &num_files, &files,
|
||||
EW_FILE) == OK) {
|
||||
for (i = 0; i < num_files; i++) {
|
||||
(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;
|
||||
}
|
||||
}
|
||||
@@ -2372,7 +2378,7 @@ static int do_in_path(char_u *path, char_u *name, bool all,
|
||||
int do_in_runtimepath(char_u *name, bool all, DoInRuntimepathCB callback,
|
||||
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);
|
||||
}
|
||||
|
||||
// Source filetype detection scripts, if filetype.vim was already done.
|
||||
@@ -2384,47 +2390,61 @@ static void may_do_filetypes(char_u *pat)
|
||||
// when it loads.
|
||||
if (cmd != NULL && eval_to_number(cmd) > 0) {
|
||||
do_cmdline_cmd("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("augroup END");
|
||||
}
|
||||
xfree(cmd);
|
||||
}
|
||||
|
||||
static void source_pack_plugin(char_u *fname, void *cookie)
|
||||
static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
{
|
||||
char_u *p6, *p5, *p4, *p3, *p2, *p1, *p;
|
||||
char_u *new_rtp;
|
||||
char_u *ffname = (char_u *)fix_fname((char *)fname);
|
||||
bool 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)) {
|
||||
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'
|
||||
char_u c = *p6;
|
||||
*p6 = NUL;
|
||||
p = (char_u *)strstr((char *)p_rtp, (char *)fname);
|
||||
char_u 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);
|
||||
p += STRLEN(ffname);
|
||||
}
|
||||
*p6 = c;
|
||||
*p4 = c;
|
||||
|
||||
if (load_file) {
|
||||
c = *p2;
|
||||
*p2 = NUL;
|
||||
if (strstr((char *)p_rtp, (char *)fname) == NULL) {
|
||||
}
|
||||
if (strstr((char *)p_rtp, (char *)ffname) == NULL) {
|
||||
// directory not in 'runtimepath', add it
|
||||
size_t oldlen = STRLEN(p_rtp);
|
||||
size_t addlen = STRLEN(fname);
|
||||
size_t addlen = STRLEN(ffname);
|
||||
new_rtp = try_malloc(oldlen + addlen + 1);
|
||||
if (new_rtp == NULL) {
|
||||
*p2 = c;
|
||||
@@ -2433,7 +2453,7 @@ static void source_pack_plugin(char_u *fname, void *cookie)
|
||||
uintptr_t keep = (uintptr_t)(p - p_rtp);
|
||||
memmove(new_rtp, p_rtp, keep);
|
||||
new_rtp[keep] = ',';
|
||||
memmove(new_rtp + keep + 1, fname, addlen + 1);
|
||||
memmove(new_rtp + keep + 1, ffname, addlen + 1);
|
||||
if (p_rtp[keep] != NUL) {
|
||||
memmove(new_rtp + keep + 1 + addlen, p_rtp + keep,
|
||||
oldlen - keep + 1);
|
||||
@@ -2441,16 +2461,18 @@ static void source_pack_plugin(char_u *fname, void *cookie)
|
||||
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
|
||||
xfree(new_rtp);
|
||||
}
|
||||
*p2 = c;
|
||||
xfree(ffname);
|
||||
|
||||
if (load_file) {
|
||||
(void)do_source(fname, false, DOSO_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
// Source the plugins in the package directories.
|
||||
void source_packages(void)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -2463,7 +2485,7 @@ void ex_loadplugin(exarg_T *eap)
|
||||
size_t len = STRLEN(ftpat) + STRLEN(eap->arg);
|
||||
char *pat = xmallocz(len);
|
||||
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);
|
||||
@@ -2471,6 +2493,18 @@ void ex_loadplugin(exarg_T *eap)
|
||||
xfree(pat);
|
||||
}
|
||||
|
||||
/// ":packadd {name}"
|
||||
void ex_packadd(exarg_T *eap)
|
||||
{
|
||||
static const char *plugpat = "pack/*/opt/%s";
|
||||
|
||||
size_t len = STRLEN(plugpat) + STRLEN(eap->arg);
|
||||
char *pat = (char *)xmallocz(len);
|
||||
vim_snprintf(pat, len, plugpat, eap->arg);
|
||||
do_in_path(p_pp, (char_u *)pat, DIP_ALL + DIP_DIR, add_pack_plugin, NULL);
|
||||
xfree(pat);
|
||||
}
|
||||
|
||||
/// ":options"
|
||||
void ex_options(exarg_T *eap)
|
||||
{
|
||||
|
@@ -215,7 +215,7 @@ static int included_patches[] = {
|
||||
// 1483 NA
|
||||
// 1482 NA
|
||||
// 1481 NA
|
||||
// 1480,
|
||||
1480,
|
||||
1479,
|
||||
1478,
|
||||
// 1477,
|
||||
|
@@ -13,34 +13,67 @@ describe('loadplugin', function()
|
||||
clear()
|
||||
|
||||
source([=[
|
||||
func SetUp()
|
||||
let s:topdir = expand('%:p: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('%:p: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'
|
||||
|
||||
exe 'split ' . s:plugdir . '/plugin/test.vim'
|
||||
call setline(1, 'let g:plugin_works = 42')
|
||||
wq
|
||||
|
||||
exe 'split ' . plugdir . '/ftdetect/test.vim'
|
||||
exe 'split ' . s: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
|
||||
call assert_true(len(&rtp) > len(rtp))
|
||||
call assert_true(&rtp =~ (s:plugdir . '\($\|,\)'))
|
||||
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 =~ (s:plugdir . '\($\|,\)'))
|
||||
|
||||
" check the path is not added twice
|
||||
let new_rtp = &rtp
|
||||
packadd mytest
|
||||
call assert_equal(new_rtp, &rtp)
|
||||
endfunc
|
||||
]=])
|
||||
call('SetUp')
|
||||
end)
|
||||
|
||||
teardown(function()
|
||||
call('TearDown')
|
||||
end)
|
||||
|
||||
it('is working', function()
|
||||
call('Test_loadplugin')
|
||||
expected_empty()
|
||||
end)
|
||||
|
||||
it('works with packadd', function()
|
||||
call('Test_packadd')
|
||||
expected_empty()
|
||||
end)
|
||||
end)
|
||||
|
Reference in New Issue
Block a user