diff options
-rw-r--r-- | src/nvim/ex_docmd.c | 6 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 43 | ||||
-rw-r--r-- | src/nvim/version.c | 2 | ||||
-rw-r--r-- | src/nvim/vim.h | 1 | ||||
-rw-r--r-- | test/functional/legacy/packadd_spec.lua | 64 |
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) |