Skip to content

Commit 989426b

Browse files
ychinchrisbra
authored andcommitted
patch 9.0.2025: no cmdline completion for ++opt args
Problem: no cmdline completion for ++opt args Solution: Add cmdline completion for :e ++opt=arg and :terminal [++options] closes: #13319 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
1 parent bd734c3 commit 989426b

File tree

12 files changed

+335
-8
lines changed

12 files changed

+335
-8
lines changed

runtime/doc/cmdline.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ When editing the command-line, a few commands can be used to complete the
387387
word before the cursor. This is available for:
388388

389389
- Command names: At the start of the command-line.
390+
- |++opt| values.
390391
- Tags: Only after the ":tag" command.
391392
- File names: Only after a command that accepts a file name or a setting for
392393
an option that can be set to a file name. This is called file name

src/cmdexpand.c

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,45 @@ set_context_for_wildcard_arg(
17681768
}
17691769
}
17701770

1771+
/*
1772+
* Set the completion context for the "++opt=arg" argument. Always returns
1773+
* NULL.
1774+
*/
1775+
static char_u *
1776+
set_context_in_argopt(expand_T *xp, char_u *arg)
1777+
{
1778+
char_u *p;
1779+
1780+
p = vim_strchr(arg, '=');
1781+
if (p == NULL)
1782+
xp->xp_pattern = arg;
1783+
else
1784+
xp->xp_pattern = p + 1;
1785+
1786+
xp->xp_context = EXPAND_ARGOPT;
1787+
return NULL;
1788+
}
1789+
1790+
#ifdef FEAT_TERMINAL
1791+
/*
1792+
* Set the completion context for :terminal's [options]. Always returns NULL.
1793+
*/
1794+
static char_u *
1795+
set_context_in_terminalopt(expand_T *xp, char_u *arg)
1796+
{
1797+
char_u *p;
1798+
1799+
p = vim_strchr(arg, '=');
1800+
if (p == NULL)
1801+
xp->xp_pattern = arg;
1802+
else
1803+
xp->xp_pattern = p + 1;
1804+
1805+
xp->xp_context = EXPAND_TERMINALOPT;
1806+
return NULL;
1807+
}
1808+
#endif
1809+
17711810
/*
17721811
* Set the completion context for the :filter command. Returns a pointer to the
17731812
* next command after the :filter command.
@@ -2491,13 +2530,28 @@ set_one_cmd_context(
24912530

24922531
arg = skipwhite(p);
24932532

2494-
// Skip over ++argopt argument
2495-
if ((ea.argt & EX_ARGOPT) && *arg != NUL && STRNCMP(arg, "++", 2) == 0)
2533+
// Does command allow "++argopt" argument?
2534+
if ((ea.argt & EX_ARGOPT) || ea.cmdidx == CMD_terminal)
24962535
{
2497-
p = arg;
2498-
while (*p && !vim_isspace(*p))
2499-
MB_PTR_ADV(p);
2500-
arg = skipwhite(p);
2536+
while (*arg != NUL && STRNCMP(arg, "++", 2) == 0)
2537+
{
2538+
p = arg + 2;
2539+
while (*p && !vim_isspace(*p))
2540+
MB_PTR_ADV(p);
2541+
2542+
// Still touching the command after "++"?
2543+
if (*p == NUL)
2544+
{
2545+
if (ea.argt & EX_ARGOPT)
2546+
return set_context_in_argopt(xp, arg + 2);
2547+
#ifdef FEAT_TERMINAL
2548+
if (ea.cmdidx == CMD_terminal)
2549+
return set_context_in_terminalopt(xp, arg + 2);
2550+
#endif
2551+
}
2552+
2553+
arg = skipwhite(p);
2554+
}
25012555
}
25022556

25032557
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
@@ -3120,6 +3174,12 @@ ExpandFromContext(
31203174
ret = ExpandSettingSubtract(xp, &regmatch, numMatches, matches);
31213175
else if (xp->xp_context == EXPAND_MAPPINGS)
31223176
ret = ExpandMappings(pat, &regmatch, numMatches, matches);
3177+
else if (xp->xp_context == EXPAND_ARGOPT)
3178+
ret = expand_argopt(pat, xp, &regmatch, matches, numMatches);
3179+
#if defined(FEAT_TERMINAL)
3180+
else if (xp->xp_context == EXPAND_TERMINALOPT)
3181+
ret = expand_terminal_opt(pat, xp, &regmatch, matches, numMatches);
3182+
#endif
31233183
#if defined(FEAT_EVAL)
31243184
else if (xp->xp_context == EXPAND_USER_DEFINED)
31253185
ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
@@ -3253,7 +3313,9 @@ ExpandGeneric(
32533313
if (!fuzzy && xp->xp_context != EXPAND_MENUNAMES
32543314
&& xp->xp_context != EXPAND_STRING_SETTING
32553315
&& xp->xp_context != EXPAND_MENUS
3256-
&& xp->xp_context != EXPAND_SCRIPTNAMES)
3316+
&& xp->xp_context != EXPAND_SCRIPTNAMES
3317+
&& xp->xp_context != EXPAND_ARGOPT
3318+
&& xp->xp_context != EXPAND_TERMINALOPT)
32573319
sort_matches = TRUE;
32583320

32593321
// <SNR> functions should be sorted to the end.

src/ex_docmd.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5407,6 +5407,25 @@ get_bad_opt(char_u *p, exarg_T *eap)
54075407
return OK;
54085408
}
54095409

5410+
/*
5411+
* Function given to ExpandGeneric() to obtain the list of bad= names.
5412+
*/
5413+
static char_u *
5414+
get_bad_name(expand_T *xp UNUSED, int idx)
5415+
{
5416+
// Note: Keep this in sync with getargopt.
5417+
static char *(p_bad_values[]) =
5418+
{
5419+
"?",
5420+
"keep",
5421+
"drop",
5422+
};
5423+
5424+
if (idx < (int)ARRAY_LENGTH(p_bad_values))
5425+
return (char_u*)p_bad_values[idx];
5426+
return NULL;
5427+
}
5428+
54105429
/*
54115430
* Get "++opt=arg" argument.
54125431
* Return FAIL or OK.
@@ -5419,6 +5438,8 @@ getargopt(exarg_T *eap)
54195438
int bad_char_idx;
54205439
char_u *p;
54215440

5441+
// Note: Keep this in sync with get_argopt_name.
5442+
54225443
// ":edit ++[no]bin[ary] file"
54235444
if (STRNCMP(arg, "bin", 3) == 0 || STRNCMP(arg, "nobin", 5) == 0)
54245445
{
@@ -5499,6 +5520,96 @@ getargopt(exarg_T *eap)
54995520
return OK;
55005521
}
55015522

5523+
/*
5524+
* Function given to ExpandGeneric() to obtain the list of ++opt names.
5525+
*/
5526+
static char_u *
5527+
get_argopt_name(expand_T *xp UNUSED, int idx)
5528+
{
5529+
// Note: Keep this in sync with getargopt.
5530+
static char *(p_opt_values[]) =
5531+
{
5532+
"fileformat=",
5533+
"encoding=",
5534+
"binary",
5535+
"nobinary",
5536+
"bad=",
5537+
"edit",
5538+
};
5539+
5540+
if (idx < (int)ARRAY_LENGTH(p_opt_values))
5541+
return (char_u*)p_opt_values[idx];
5542+
return NULL;
5543+
}
5544+
5545+
/*
5546+
* Command-line expansion for ++opt=name.
5547+
*/
5548+
int
5549+
expand_argopt(
5550+
char_u *pat,
5551+
expand_T *xp,
5552+
regmatch_T *rmp,
5553+
char_u ***matches,
5554+
int *numMatches)
5555+
{
5556+
if (xp->xp_pattern > xp->xp_line && *(xp->xp_pattern-1) == '=')
5557+
{
5558+
char_u *(*cb)(expand_T *, int) = NULL;
5559+
5560+
char_u *name_end = xp->xp_pattern - 1;
5561+
if (name_end - xp->xp_line >= 2
5562+
&& STRNCMP(name_end - 2, "ff", 2) == 0)
5563+
cb = get_fileformat_name;
5564+
else if (name_end - xp->xp_line >= 10
5565+
&& STRNCMP(name_end - 10, "fileformat", 10) == 0)
5566+
cb = get_fileformat_name;
5567+
else if (name_end - xp->xp_line >= 3
5568+
&& STRNCMP(name_end - 3, "enc", 3) == 0)
5569+
cb = get_encoding_name;
5570+
else if (name_end - xp->xp_line >= 8
5571+
&& STRNCMP(name_end - 8, "encoding", 8) == 0)
5572+
cb = get_encoding_name;
5573+
else if (name_end - xp->xp_line >= 3
5574+
&& STRNCMP(name_end - 3, "bad", 3) == 0)
5575+
cb = get_bad_name;
5576+
5577+
if (cb != NULL)
5578+
{
5579+
return ExpandGeneric(
5580+
pat,
5581+
xp,
5582+
rmp,
5583+
matches,
5584+
numMatches,
5585+
cb,
5586+
FALSE);
5587+
}
5588+
return FAIL;
5589+
}
5590+
5591+
// Special handling of "ff" which acts as a short form of
5592+
// "fileformat", as "ff" is not a substring of it.
5593+
if (STRCMP(xp->xp_pattern, "ff") == 0)
5594+
{
5595+
*matches = ALLOC_MULT(char_u *, 1);
5596+
if (*matches == NULL)
5597+
return FAIL;
5598+
*numMatches = 1;
5599+
(*matches)[0] = vim_strsave((char_u*)"fileformat=");
5600+
return OK;
5601+
}
5602+
5603+
return ExpandGeneric(
5604+
pat,
5605+
xp,
5606+
rmp,
5607+
matches,
5608+
numMatches,
5609+
get_argopt_name,
5610+
FALSE);
5611+
}
5612+
55025613
static void
55035614
ex_autocmd(exarg_T *eap)
55045615
{

src/optionstr.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,19 @@ expand_set_fileformat(optexpand_T *args, int *numMatches, char_u ***matches)
21042104
matches);
21052105
}
21062106

2107+
/*
2108+
* Function given to ExpandGeneric() to obtain the possible arguments of the
2109+
* fileformat options.
2110+
*/
2111+
char_u *
2112+
get_fileformat_name(expand_T *xp UNUSED, int idx)
2113+
{
2114+
if (idx >= (int)ARRAY_LENGTH(p_ff_values))
2115+
return NULL;
2116+
2117+
return (char_u*)p_ff_values[idx];
2118+
}
2119+
21072120
/*
21082121
* The 'fileformats' option is changed.
21092122
*/

src/proto/ex_docmd.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
3030
void separate_nextcmd(exarg_T *eap, int keep_backslash);
3131
char_u *skip_cmd_arg(char_u *p, int rembs);
3232
int get_bad_opt(char_u *p, exarg_T *eap);
33+
int expand_argopt(char_u *pat, expand_T *xp, regmatch_T *rmp, char_u ***matches, int *numMatches);
3334
int ends_excmd(int c);
3435
int ends_excmd2(char_u *cmd_start, char_u *cmd);
3536
char_u *find_nextcmd(char_u *p);

src/proto/optionstr.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ int expand_set_wildoptions(optexpand_T *args, int *numMatches, char_u ***matches
189189
int expand_set_winaltkeys(optexpand_T *args, int *numMatches, char_u ***matches);
190190
int expand_set_wincolor(optexpand_T *args, int *numMatches, char_u ***matches);
191191
int check_ff_value(char_u *p);
192+
char_u *get_fileformat_name(expand_T *xp, int idx);
192193
void save_clear_shm_value(void);
193194
void restore_shm_value(void);
194195
/* vim: set ft=c : */

src/proto/terminal.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
void init_job_options(jobopt_T *opt);
33
buf_T *term_start(typval_T *argvar, char **argv, jobopt_T *opt, int flags);
44
void ex_terminal(exarg_T *eap);
5+
int expand_terminal_opt(char_u *pat, expand_T *xp, regmatch_T *rmp, char_u ***matches, int *numMatches);
56
int term_write_session(FILE *fd, win_T *wp, hashtab_T *terminal_bufs);
67
int term_should_restore(buf_T *buf);
78
void free_terminal(buf_T *buf);

src/structs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ typedef enum {
603603
*/
604604
typedef struct expand
605605
{
606-
char_u *xp_pattern; // start of item to expand
606+
char_u *xp_pattern; // start of item to expand, guaranteed
607+
// to be part of xp_line
607608
int xp_context; // type of expansion
608609
int xp_pattern_len; // bytes in xp_pattern before cursor
609610
xp_prefix_T xp_prefix;

0 commit comments

Comments
 (0)