aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_docmd.c24
-rw-r--r--src/nvim/ex_getln.c17
-rw-r--r--src/nvim/testdir/test_cmdline.vim28
-rw-r--r--src/nvim/testdir/test_ins_complete.vim18
4 files changed, 72 insertions, 15 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 641edf4610..f18ebffa0a 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -5133,9 +5133,11 @@ static void uc_list(char_u *name, size_t name_len)
ucmd_T *cmd;
int len;
uint32_t a;
- garray_T *gap;
- gap = &curbuf->b_ucmds;
+ // In cmdwin, the alternative buffer should be used.
+ garray_T *gap = (cmdwin_type != 0 && get_cmdline_type() == NUL)
+ ? &prevwin->w_buffer->b_ucmds
+ : &curbuf->b_ucmds;
for (;; ) {
for (i = 0; i < gap->ga_len; ++i) {
cmd = USER_CMD_GA(gap, i);
@@ -5984,13 +5986,21 @@ char_u *get_user_cmd_addr_type(expand_T *xp, int idx)
/*
* Function given to ExpandGeneric() to obtain the list of user command names.
*/
-char_u *get_user_commands(expand_T *xp, int idx)
+char_u *get_user_commands(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (idx < curbuf->b_ucmds.ga_len)
- return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
- idx -= curbuf->b_ucmds.ga_len;
- if (idx < ucmds.ga_len)
+ // In cmdwin, the alternative buffer should be used.
+ const buf_T *const buf = (cmdwin_type != 0 && get_cmdline_type() == NUL)
+ ? prevwin->w_buffer
+ : curbuf;
+
+ if (idx < buf->b_ucmds.ga_len) {
+ return USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
+ }
+ idx -= buf->b_ucmds.ga_len;
+ if (idx < ucmds.ga_len) {
return USER_CMD(idx)->uc_name;
+ }
return NULL;
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 9e2671ca5e..7948da5e6b 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -5008,19 +5008,24 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
hashtab_T found_ht;
hash_init(&found_ht);
for (s = path; ; s = e) {
+ e = vim_strchr(s, ENV_SEPCHAR);
+ if (e == NULL) {
+ e = s + STRLEN(s);
+ }
+
if (*s == NUL) {
if (did_curdir) {
break;
}
// Find directories in the current directory, path is empty.
did_curdir = true;
- } else if (*s == '.') {
+ flags |= EW_DIR;
+ } else if (STRNCMP(s, ".", e - s) == 0) {
did_curdir = true;
- }
-
- e = vim_strchr(s, ENV_SEPCHAR);
- if (e == NULL) {
- e = s + STRLEN(s);
+ flags |= EW_DIR;
+ } else {
+ // Do not match directories inside a $PATH item.
+ flags &= ~EW_DIR;
}
l = (size_t)(e - s);
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 0a3e6ae625..635ee7984a 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -301,7 +301,7 @@ func Test_getcompletion()
call assert_equal([], l)
let l = getcompletion('.', 'shellcmd')
- call assert_equal(['./', '../'], l[0:1])
+ call assert_equal(['./', '../'], filter(l, 'v:val =~ "\\./"'))
call assert_equal(-1, match(l[2:], '^\.\.\?/$'))
let root = has('win32') ? 'C:\\' : '/'
let l = getcompletion(root, 'shellcmd')
@@ -375,6 +375,29 @@ func Test_getcompletion()
call assert_fails('call getcompletion("", "burp")', 'E475:')
endfunc
+func Test_shellcmd_completion()
+ let save_path = $PATH
+
+ call mkdir('Xpathdir/Xpathsubdir', 'p')
+ call writefile([''], 'Xpathdir/Xfile.exe')
+ call setfperm('Xpathdir/Xfile.exe', 'rwx------')
+
+ " Set PATH to example directory without trailing slash.
+ let $PATH = getcwd() . '/Xpathdir'
+
+ " Test for the ":!<TAB>" case. Previously, this would include subdirs of
+ " dirs in the PATH, even though they won't be executed. We check that only
+ " subdirs of the PWD and executables from the PATH are included in the
+ " suggestions.
+ let actual = getcompletion('X', 'shellcmd')
+ let expected = map(filter(glob('*', 0, 1), 'isdirectory(v:val) && v:val[0] == "X"'), 'v:val . "/"')
+ call insert(expected, 'Xfile.exe')
+ call assert_equal(expected, actual)
+
+ call delete('Xpathdir', 'rf')
+ let $PATH = save_path
+endfunc
+
func Test_expand_star_star()
call mkdir('a/b', 'p')
call writefile(['asdfasdf'], 'a/b/fileXname')
@@ -492,8 +515,9 @@ func Test_cmdline_complete_user_names()
let names = system('net user')
if names =~ 'Administrator'
" Trying completion of :e ~A should complete to Administrator.
+ " There could be other names starting with "A" before Administrator.
call feedkeys(':e ~A' . "\<c-a>\<c-B>\"\<cr>", 'tx')
- call assert_match('^"e \~Administrator', @:)
+ call assert_match('^"e \~.*Administrator', @:)
endif
endif
endfunc
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 7f52481ba8..52ec281d82 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -285,3 +285,21 @@ func Test_compl_feedkeys()
bwipe!
set completeopt&
endfunc
+
+func Test_compl_in_cmdwin()
+ set wildmenu wildchar=<Tab>
+ com! -nargs=1 -complete=command GetInput let input = <q-args>
+ com! -buffer TestCommand echo 'TestCommand'
+
+ let input = ''
+ call feedkeys("q:iGetInput T\<C-x>\<C-v>\<CR>", 'tx!')
+ call assert_equal('TestCommand', input)
+
+ let input = ''
+ call feedkeys("q::GetInput T\<Tab>\<CR>:q\<CR>", 'tx!')
+ call assert_equal('T', input)
+
+ delcom TestCommand
+ delcom GetInput
+ set wildmenu& wildchar&
+endfunc