aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/ex_getln.c43
-rw-r--r--src/nvim/version.c2
-rw-r--r--src/nvim/vim.h1
-rw-r--r--test/functional/legacy/packadd_spec.lua64
5 files changed, 113 insertions, 3 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index ad17d4dcbd..80dad3605a 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3316,6 +3316,11 @@ set_one_cmd_context (
xp->xp_pattern = arg;
break;
+ case CMD_packadd:
+ xp->xp_context = EXPAND_PACKADD;
+ xp->xp_pattern = arg;
+ break;
+
#ifdef HAVE_WORKING_LIBINTL
case CMD_language:
p = skiptowhite(arg);
@@ -4688,6 +4693,7 @@ static struct {
{EXPAND_OWNSYNTAX, "syntax"},
{EXPAND_SYNTIME, "syntime"},
{EXPAND_SETTINGS, "option"},
+ {EXPAND_PACKADD, "packadd"},
{EXPAND_SHELLCMD, "shellcmd"},
{EXPAND_SIGN, "sign"},
{EXPAND_TAGS, "tag"},
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 65144dace8..688be3c67c 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -3440,6 +3440,7 @@ addstar (
|| context == EXPAND_COMPILER
|| context == EXPAND_OWNSYNTAX
|| context == EXPAND_FILETYPE
+ || context == EXPAND_PACKADD
|| (context == EXPAND_TAGS && fname[0] == '/'))
retval = vim_strnsave(fname, len);
else {
@@ -3809,8 +3810,12 @@ ExpandFromContext (
char *directories[] = {"syntax", "indent", "ftplugin", NULL};
return ExpandRTDir(pat, num_file, file, directories);
}
- if (xp->xp_context == EXPAND_USER_LIST)
+ if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, num_file, file);
+ }
+ if (xp->xp_context == EXPAND_PACKADD) {
+ return ExpandPackAddDir(pat, num_file, file);
+ }
regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
if (regmatch.regprog == NULL)
@@ -4241,6 +4246,42 @@ static int ExpandRTDir(char_u *pat, int *num_file, char_u ***file, char *dirname
return OK;
}
+/// Expand loadplugin names:
+/// 'packpath'/pack/ * /opt/{pat}
+static int ExpandPackAddDir(char_u *pat, int *num_file, char_u ***file)
+{
+ garray_T ga;
+
+ *num_file = 0;
+ *file = NULL;
+ size_t pat_len = STRLEN(pat);
+ ga_init(&ga, (int)sizeof(char *), 10);
+
+ char_u *s = xmalloc((unsigned)(pat_len + 26));
+ sprintf((char *)s, "pack/*/opt/%s*", pat);
+ globpath(p_pp, s, &ga, 0);
+ xfree(s);
+
+ for (int i = 0; i < ga.ga_len; ++i) {
+ char_u *match = ((char_u **)ga.ga_data)[i];
+ s = path_tail(match);
+ char_u *e = s + STRLEN(s);
+ memmove(match, s, e - s + 1);
+ }
+
+ if (GA_EMPTY(&ga)) {
+ return FAIL;
+ }
+
+ // Sort and remove duplicates which can happen when specifying multiple
+ // directories in dirnames.
+ ga_remove_duplicate_strings(&ga);
+
+ *file = ga.ga_data;
+ *num_file = ga.ga_len;
+ return OK;
+}
+
/// Expand `file` for all comma-separated directories in `path`.
/// Adds matches to `ga`.
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 569a755429..36f9fecf64 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -203,7 +203,7 @@ static int included_patches[] = {
// 1495 NA
// 1494,
// 1493 NA
- // 1492,
+ 1492,
// 1491,
// 1490 NA
// 1489 NA
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 165a44a148..c2f0a0ebd3 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -174,6 +174,7 @@ enum {
EXPAND_USER,
EXPAND_SYNTIME,
EXPAND_USER_ADDR_TYPE,
+ EXPAND_PACKADD,
};
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index 94b5336b9f..9ca7c4e723 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -1,8 +1,9 @@
-- Tests for 'packpath' and :packadd
local helpers = require('test.functional.helpers')(after_each)
-local clear, source = helpers.clear, helpers.source
+local clear, source, execute = helpers.clear, helpers.source, helpers.execute
local call, eq, nvim = helpers.call, helpers.eq, helpers.meths
+local feed = helpers.feed
local function expected_empty()
eq({}, nvim.get_vvar('errors'))
@@ -85,4 +86,65 @@ describe('packadd', function()
call('Test_packadd_noload')
expected_empty()
end)
+
+ describe('command line completion', function()
+ local Screen = require('test.functional.ui.screen')
+ local screen
+
+ before_each(function()
+ screen = Screen.new(30, 5)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {
+ foreground = Screen.colors.Black,
+ background = Screen.colors.Yellow,
+ },
+ [2] = {bold = true, reverse = true}
+ })
+ local NonText = Screen.colors.Blue
+ screen:set_default_attr_ignore({{}, {bold=true, foreground=NonText}})
+
+ execute([[let optdir1 = &packpath . '/pack/mine/opt']])
+ execute([[let optdir2 = &packpath . '/pack/candidate/opt']])
+ execute([[call mkdir(optdir1 . '/pluginA', 'p')]])
+ execute([[call mkdir(optdir1 . '/pluginC', 'p')]])
+ execute([[call mkdir(optdir2 . '/pluginB', 'p')]])
+ execute([[call mkdir(optdir2 . '/pluginC', 'p')]])
+ end)
+
+ it('works', function()
+ feed(':packadd <Tab>')
+ screen:expect([=[
+ |
+ ~ |
+ ~ |
+ {1:pluginA}{2: pluginB pluginC }|
+ :packadd pluginA^ |
+ ]=])
+ feed('<Tab>')
+ screen:expect([=[
+ |
+ ~ |
+ ~ |
+ {2:pluginA }{1:pluginB}{2: pluginC }|
+ :packadd pluginB^ |
+ ]=])
+ feed('<Tab>')
+ screen:expect([=[
+ |
+ ~ |
+ ~ |
+ {2:pluginA pluginB }{1:pluginC}{2: }|
+ :packadd pluginC^ |
+ ]=])
+ feed('<Tab>')
+ screen:expect([=[
+ |
+ ~ |
+ ~ |
+ {2:pluginA pluginB pluginC }|
+ :packadd ^ |
+ ]=])
+ end)
+ end)
end)