forked from aniani/vim
patch 9.1.0770: current command line completion is a bit limited
Problem: current command completion is a bit limited
Solution: Add the shellcmdline completion type and getmdcomplpat()
function (Ruslan Russkikh).
closes: #15823
Signed-off-by: Ruslan Russkikh <dvrussk@yandex.ru>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
347d43bd33
commit
0407d621bb
@@ -59,6 +59,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
|
||||
&& xp->xp_context != EXPAND_PACKADD
|
||||
&& xp->xp_context != EXPAND_RUNTIME
|
||||
&& xp->xp_context != EXPAND_SHELLCMD
|
||||
&& xp->xp_context != EXPAND_SHELLCMDLINE
|
||||
&& xp->xp_context != EXPAND_TAGS
|
||||
&& xp->xp_context != EXPAND_TAGS_LISTFILES
|
||||
&& xp->xp_context != EXPAND_USER_LIST);
|
||||
@@ -1754,7 +1755,7 @@ set_context_for_wildcard_arg(
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
|
||||
// For a shell command more chars need to be escaped.
|
||||
if (usefilter || eap->cmdidx == CMD_bang || eap->cmdidx == CMD_terminal)
|
||||
if (usefilter || eap->cmdidx == CMD_bang || eap->cmdidx == CMD_terminal || *complp == EXPAND_SHELLCMDLINE)
|
||||
{
|
||||
#ifndef BACKSLASH_IN_FILENAME
|
||||
xp->xp_shell = TRUE;
|
||||
|
||||
@@ -2091,6 +2091,8 @@ static funcentry_T global_functions[] =
|
||||
ret_dict_any, f_getcharsearch},
|
||||
{"getcharstr", 0, 1, 0, arg1_bool,
|
||||
ret_string, f_getcharstr},
|
||||
{"getcmdcomplpat", 0, 0, 0, NULL,
|
||||
ret_string, f_getcmdcomplpat},
|
||||
{"getcmdcompltype", 0, 0, 0, NULL,
|
||||
ret_string, f_getcmdcompltype},
|
||||
{"getcmdline", 0, 0, 0, NULL,
|
||||
|
||||
@@ -4204,6 +4204,40 @@ get_cmdline_str(void)
|
||||
return vim_strnsave(p->cmdbuff, p->cmdlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current command-line completion pattern.
|
||||
*/
|
||||
static char_u *
|
||||
get_cmdline_completion_pattern(void)
|
||||
{
|
||||
cmdline_info_T *p;
|
||||
int xp_context;
|
||||
|
||||
if (cmdline_star > 0)
|
||||
return NULL;
|
||||
|
||||
p = get_ccline_ptr();
|
||||
if (p == NULL || p->xpc == NULL)
|
||||
return NULL;
|
||||
|
||||
xp_context = p->xpc->xp_context;
|
||||
if (xp_context == EXPAND_NOTHING)
|
||||
{
|
||||
set_expand_context(p->xpc);
|
||||
xp_context = p->xpc->xp_context;
|
||||
p->xpc->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
if (xp_context == EXPAND_UNSUCCESSFUL)
|
||||
return NULL;
|
||||
|
||||
char_u *compl_pat = p->xpc->xp_pattern;
|
||||
|
||||
if (compl_pat == NULL)
|
||||
return NULL;
|
||||
|
||||
return vim_strsave(compl_pat);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current command-line completion type.
|
||||
*/
|
||||
@@ -4247,6 +4281,16 @@ get_cmdline_completion(void)
|
||||
return vim_strsave(cmd_compl);
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdcomplpat()" function
|
||||
*/
|
||||
void
|
||||
f_getcmdcomplpat(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = get_cmdline_completion_pattern();
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdcompltype()" function
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@ char_u *vim_strsave_fnameescape(char_u *fname, int what);
|
||||
void escape_fname(char_u **pp);
|
||||
void tilde_replace(char_u *orig_pat, int num_files, char_u **files);
|
||||
cmdline_info_T *get_cmdline_info(void);
|
||||
void f_getcmdcomplpat(typval_T *argvars, typval_T *rettv);
|
||||
void f_getcmdcompltype(typval_T *argvars, typval_T *rettv);
|
||||
void f_getcmdline(typval_T *argvars, typval_T *rettv);
|
||||
void f_getcmdpos(typval_T *argvars, typval_T *rettv);
|
||||
|
||||
@@ -1078,6 +1078,16 @@ func Test_cmdline_complete_user_names()
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func Test_cmdline_complete_shellcmdline()
|
||||
CheckExecutable whoami
|
||||
command -nargs=1 -complete=shellcmdline MyCmd
|
||||
|
||||
call feedkeys(":MyCmd whoam\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_match('^".*\<whoami\>', @:)
|
||||
|
||||
delcommand MyCmd
|
||||
endfunc
|
||||
|
||||
func Test_cmdline_complete_bang()
|
||||
CheckExecutable whoami
|
||||
call feedkeys(":!whoam\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||
@@ -3631,6 +3641,52 @@ func Test_cmdline_complete_substitute_short()
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" Test for shellcmdline command argument completion
|
||||
func Test_cmdline_complete_shellcmdline_argument()
|
||||
command -nargs=+ -complete=shellcmdline MyCmd
|
||||
|
||||
set wildoptions=fuzzy
|
||||
|
||||
call feedkeys(":MyCmd vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim test_cmdline.vim', @:)
|
||||
|
||||
call feedkeys(":MyCmd vim nonexistentfile\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim nonexistentfile', @:)
|
||||
|
||||
let compl1 = getcompletion('', 'file')[0]
|
||||
let compl2 = getcompletion('', 'file')[1]
|
||||
call feedkeys(":MyCmd vim \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1, @:)
|
||||
|
||||
call feedkeys(":MyCmd vim \<Tab> \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1 .. ' ' .. compl1, @:)
|
||||
|
||||
let compl = getcompletion('', 'file')[1]
|
||||
call feedkeys(":MyCmd vim \<Tab> \<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1 .. ' ' .. compl2, @:)
|
||||
|
||||
set wildoptions&
|
||||
call feedkeys(":MyCmd vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim test_cmdline.vim', @:)
|
||||
|
||||
call feedkeys(":MyCmd vim nonexistentfile\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim nonexistentfile', @:)
|
||||
|
||||
let compl1 = getcompletion('', 'file')[0]
|
||||
let compl2 = getcompletion('', 'file')[1]
|
||||
call feedkeys(":MyCmd vim \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1, @:)
|
||||
|
||||
call feedkeys(":MyCmd vim \<Tab> \<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1 .. ' ' .. compl1, @:)
|
||||
|
||||
let compl = getcompletion('', 'file')[1]
|
||||
call feedkeys(":MyCmd vim \<Tab> \<Tab>\<Tab>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"MyCmd vim ' .. compl1 .. ' ' .. compl2, @:)
|
||||
|
||||
delcommand MyCmd
|
||||
endfunc
|
||||
|
||||
" Test for :! shell command argument completion
|
||||
func Test_cmdline_complete_bang_cmd_argument()
|
||||
set wildoptions=fuzzy
|
||||
@@ -3642,30 +3698,32 @@ func Test_cmdline_complete_bang_cmd_argument()
|
||||
endfunc
|
||||
|
||||
func Call_cmd_funcs()
|
||||
return [getcmdpos(), getcmdscreenpos(), getcmdcompltype()]
|
||||
return [getcmdpos(), getcmdscreenpos(), getcmdcompltype(), getcmdcomplpat()]
|
||||
endfunc
|
||||
|
||||
func Test_screenpos_and_completion()
|
||||
call assert_equal(0, getcmdpos())
|
||||
call assert_equal(0, getcmdscreenpos())
|
||||
call assert_equal('', getcmdcompltype())
|
||||
call assert_equal('', getcmdcomplpat())
|
||||
|
||||
cnoremap <expr> <F2> string(Call_cmd_funcs())
|
||||
call feedkeys(":let a\<F2>\<C-B>\"\<CR>", "xt")
|
||||
call assert_equal("\"let a[6, 7, 'var']", @:)
|
||||
call assert_equal("\"let a[6, 7, 'var', 'a']", @:)
|
||||
call feedkeys(":quit \<F2>\<C-B>\"\<CR>", "xt")
|
||||
call assert_equal("\"quit [6, 7, '']", @:)
|
||||
call assert_equal("\"quit [6, 7, '', '']", @:)
|
||||
call feedkeys(":nosuchcommand \<F2>\<C-B>\"\<CR>", "xt")
|
||||
call assert_equal("\"nosuchcommand [15, 16, '']", @:)
|
||||
call assert_equal("\"nosuchcommand [15, 16, '', '']", @:)
|
||||
|
||||
" Check that getcmdcompltype() doesn't interfere with cmdline completion.
|
||||
" Check that getcmdcompltype() and getcmdcomplpat() don't interfere with
|
||||
" cmdline completion.
|
||||
let g:results = []
|
||||
cnoremap <F2> <Cmd>let g:results += [[getcmdline()] + Call_cmd_funcs()]<CR>
|
||||
call feedkeys(":sign un\<Tab>\<F2>\<Tab>\<F2>\<Tab>\<F2>\<C-C>", "xt")
|
||||
call assert_equal([
|
||||
\ ['sign undefine', 14, 15, 'sign'],
|
||||
\ ['sign unplace', 13, 14, 'sign'],
|
||||
\ ['sign un', 8, 9, 'sign']], g:results)
|
||||
\ ['sign undefine', 14, 15, 'sign', 'undefine'],
|
||||
\ ['sign unplace', 13, 14, 'sign', 'unplace'],
|
||||
\ ['sign un', 8, 9, 'sign', 'un']], g:results)
|
||||
|
||||
unlet g:results
|
||||
cunmap <F2>
|
||||
|
||||
@@ -92,6 +92,7 @@ static keyvalue_T command_complete_tab[] =
|
||||
KEYVALUE_ENTRY(EXPAND_SCRIPTNAMES, "scriptnames"),
|
||||
#endif
|
||||
KEYVALUE_ENTRY(EXPAND_SHELLCMD, "shellcmd"),
|
||||
KEYVALUE_ENTRY(EXPAND_SHELLCMDLINE, "shellcmdline"),
|
||||
#if defined(FEAT_SIGNS)
|
||||
KEYVALUE_ENTRY(EXPAND_SIGN, "sign"),
|
||||
#endif
|
||||
@@ -328,7 +329,6 @@ set_context_in_user_cmdarg(
|
||||
if (argt & EX_XFILE)
|
||||
{
|
||||
// EX_XFILE: file names are handled before this call
|
||||
xp->xp_context = context;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -850,7 +850,7 @@ parse_compl_arg(
|
||||
*complp = entry->key;
|
||||
if (*complp == EXPAND_BUFFERS)
|
||||
*argt |= EX_BUFNAME;
|
||||
else if (*complp == EXPAND_DIRECTORIES || *complp == EXPAND_FILES)
|
||||
else if (*complp == EXPAND_DIRECTORIES || *complp == EXPAND_FILES || *complp == EXPAND_SHELLCMDLINE)
|
||||
*argt |= EX_XFILE;
|
||||
|
||||
if (
|
||||
|
||||
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
770,
|
||||
/**/
|
||||
769,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user