vim-patch:9.1.1340: cannot complete :filetype arguments (#33602)

Problem:  cannot complete :filetype arguments (Phạm Bình An)
Solution: add :filetype ex command completion, add "filetypecmd"
          completion type for getcompletion()

fixes: vim/vim#17165
closes: vim/vim#17167

a3422aa317

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2025-04-24 08:50:33 +08:00
committed by GitHub
parent 63689deb45
commit ac8ae1596c
7 changed files with 118 additions and 0 deletions

View File

@ -3401,6 +3401,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
file file and directory names
file_in_path file and directory names in |'path'|
filetype filetype names |'filetype'|
filetypecmd |:filetype| suboptions
function function name
help help subjects
highlight highlight groups

View File

@ -3048,6 +3048,7 @@ function vim.fn.getcmdwintype() end
--- file file and directory names
--- file_in_path file and directory names in |'path'|
--- filetype filetype names |'filetype'|
--- filetypecmd |:filetype| suboptions
--- function function name
--- help help subjects
--- highlight highlight groups

View File

@ -110,6 +110,7 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp)
&& xp->xp_context != EXPAND_FILES
&& xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE
&& xp->xp_context != EXPAND_FILETYPECMD
&& xp->xp_context != EXPAND_FINDFUNC
&& xp->xp_context != EXPAND_HELP
&& xp->xp_context != EXPAND_KEYMAP
@ -1764,6 +1765,19 @@ static const char *set_context_in_lang_cmd(expand_T *xp, const char *arg)
return NULL;
}
static enum {
EXP_FILETYPECMD_ALL, ///< expand all :filetype values
EXP_FILETYPECMD_PLUGIN, ///< expand plugin on off
EXP_FILETYPECMD_INDENT, ///< expand indent on off
EXP_FILETYPECMD_ONOFF, ///< expand on off
} filetype_expand_what;
enum {
EXPAND_FILETYPECMD_PLUGIN = 0x01,
EXPAND_FILETYPECMD_INDENT = 0x02,
EXPAND_FILETYPECMD_ONOFF = 0x04,
};
static enum {
EXP_BREAKPT_ADD, ///< expand ":breakadd" sub-commands
EXP_BREAKPT_DEL, ///< expand ":breakdel" sub-commands
@ -1836,6 +1850,47 @@ static const char *set_context_in_scriptnames_cmd(expand_T *xp, const char *arg)
return NULL;
}
/// Set the completion context for the :filetype command. Always returns NULL.
static const char *set_context_in_filetype_cmd(expand_T *xp, const char *arg)
{
xp->xp_context = EXPAND_FILETYPECMD;
xp->xp_pattern = (char *)arg;
filetype_expand_what = EXP_FILETYPECMD_ALL;
char *p = skipwhite(arg);
if (*p == NUL) {
return NULL;
}
int val = 0;
while (true) {
if (strncmp(p, "plugin", 6) == 0) {
val |= EXPAND_FILETYPECMD_PLUGIN;
p = skipwhite(p + 6);
continue;
}
if (strncmp(p, "indent", 6) == 0) {
val |= EXPAND_FILETYPECMD_INDENT;
p = skipwhite(p + 6);
continue;
}
break;
}
if ((val & EXPAND_FILETYPECMD_PLUGIN) && (val & EXPAND_FILETYPECMD_INDENT)) {
filetype_expand_what = EXP_FILETYPECMD_ONOFF;
} else if ((val & EXPAND_FILETYPECMD_PLUGIN)) {
filetype_expand_what = EXP_FILETYPECMD_INDENT;
} else if ((val & EXPAND_FILETYPECMD_INDENT)) {
filetype_expand_what = EXP_FILETYPECMD_PLUGIN;
}
xp->xp_pattern = p;
return NULL;
}
/// Set the completion context in "xp" for command "cmd" with index "cmdidx".
/// The argument to the command is "arg" and the argument flags is "argt".
/// For user-defined commands and for environment variables, "context" has the
@ -2198,6 +2253,9 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
case CMD_scriptnames:
return set_context_in_scriptnames_cmd(xp, arg);
case CMD_filetype:
return set_context_in_filetype_cmd(xp, arg);
case CMD_lua:
case CMD_equal:
xp->xp_context = EXPAND_LUA;
@ -2565,6 +2623,30 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int *
return ret;
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":filetype {plugin,indent}" command.
static char *get_filetypecmd_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
{
char *opts_all[] = { "indent", "plugin", "on", "off" };
char *opts_plugin[] = { "plugin", "on", "off" };
char *opts_indent[] = { "indent", "on", "off" };
char *opts_onoff[] = { "on", "off" };
if (filetype_expand_what == EXP_FILETYPECMD_ALL && idx < 4) {
return opts_all[idx];
}
if (filetype_expand_what == EXP_FILETYPECMD_PLUGIN && idx < 3) {
return opts_plugin[idx];
}
if (filetype_expand_what == EXP_FILETYPECMD_INDENT && idx < 3) {
return opts_indent[idx];
}
if (filetype_expand_what == EXP_FILETYPECMD_ONOFF && idx < 2) {
return opts_onoff[idx];
}
return NULL;
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":breakadd {expr, file, func, here}" command.
/// ":breakdel {func, file, here}" command.
@ -2660,6 +2742,7 @@ static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches
int escaped;
} tab[] = {
{ EXPAND_COMMANDS, get_command_name, false, true },
{ EXPAND_FILETYPECMD, get_filetypecmd_arg, true, true },
{ EXPAND_MAPCLEAR, get_mapclear_arg, true, true },
{ EXPAND_MESSAGES, get_messages_arg, true, true },
{ EXPAND_HISTORY, get_history_arg, true, true },
@ -3643,6 +3726,9 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
set_context_for_wildcard_arg(NULL, xpc.xp_pattern, false, &xpc, &context);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
if (xpc.xp_context == EXPAND_FILETYPECMD) {
filetype_expand_what = EXP_FILETYPECMD_ALL;
}
theend:
if (xpc.xp_context == EXPAND_LUA) {

View File

@ -108,6 +108,7 @@ enum {
EXPAND_DIRS_IN_CDPATH,
EXPAND_SHELLCMDLINE,
EXPAND_FINDFUNC,
EXPAND_FILETYPECMD,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};

View File

@ -3831,6 +3831,7 @@ M.funcs = {
file file and directory names
file_in_path file and directory names in |'path'|
filetype filetype names |'filetype'|
filetypecmd |:filetype| suboptions
function function name
help help subjects
highlight highlight groups

View File

@ -72,6 +72,7 @@ static const char *command_complete[] = {
[EXPAND_FILES] = "file",
[EXPAND_FILES_IN_PATH] = "file_in_path",
[EXPAND_FILETYPE] = "filetype",
[EXPAND_FILETYPECMD] = "filetypecmd",
[EXPAND_FUNCTIONS] = "function",
[EXPAND_HELP] = "help",
[EXPAND_HIGHLIGHT] = "highlight",

View File

@ -548,6 +548,13 @@ func Test_getcompletion()
let l = getcompletion('kill', 'expression')
call assert_equal([], l)
let l = getcompletion('', 'filetypecmd')
call assert_equal(["indent", "off", "on", "plugin"], l)
let l = getcompletion('not', 'filetypecmd')
call assert_equal([], l)
let l = getcompletion('o', 'filetypecmd')
call assert_equal(['off', 'on'], l)
let l = getcompletion('tag', 'function')
call assert_true(index(l, 'taglist(') >= 0)
let l = getcompletion('paint', 'function')
@ -3240,6 +3247,26 @@ func Test_fuzzy_completion_behave()
set wildoptions&
endfunc
" :filetype suboptions completion
func Test_completion_filetypecmd()
set wildoptions&
call feedkeys(":filetype \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype indent off on plugin', @:)
call feedkeys(":filetype plugin \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype plugin indent off on', @:)
call feedkeys(":filetype indent \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype indent off on plugin', @:)
call feedkeys(":filetype i\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype indent', @:)
call feedkeys(":filetype p\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype plugin', @:)
call feedkeys(":filetype o\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype off on', @:)
call feedkeys(":filetype indent of\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"filetype indent off', @:)
set wildoptions&
endfunc
" " colorscheme name fuzzy completion - NOT supported
" func Test_fuzzy_completion_colorscheme()
" endfunc