Skip to content

Commit a4d96f0

Browse files
zeertzjqychin
andcommitted
vim-patch:9.0.1958: cannot complete option values
Problem: cannot complete option values Solution: Add completion functions for several options Add cmdline tab-completion for setting string options Add tab-completion for setting string options on the cmdline using `:set=` (along with `:set+=` and `:set-=`). The existing tab completion for setting options currently only works when nothing is typed yet, and it only fills in with the existing value, e.g. when the user does `:set diffopt=<Tab>` it will be completed to `set diffopt=internal,filler,closeoff` and nothing else. This isn't too useful as a user usually wants auto-complete to suggest all the possible values, such as 'iblank', or 'algorithm:patience'. For set= and set+=, this adds a new optional callback function for each option that can be invoked when doing completion. This allows for each option to have control over how completion works. For example, in 'diffopt', it will suggest the default enumeration, but if `algorithm:` is selected, it will further suggest different algorithm types like 'meyers' and 'patience'. When using set=, the existing option value will be filled in as the first choice to preserve the existing behavior. When using set+= this won't happen as it doesn't make sense. For flag list options (e.g. 'mouse' and 'guioptions'), completion will take into account existing typed values (and in the case of set+=, the existing option value) to make sure it doesn't suggest duplicates. For set-=, there is a new `ExpandSettingSubtract` function which will handle flag list and comma-separated options smartly, by only suggesting values that currently exist in the option. Note that Vim has some existing code that adds special handling for 'filetype', 'syntax', and misc dir options like 'backupdir'. This change preserves them as they already work, instead of converting to the new callback API for each option. closes: vim/vim#13182 vim/vim@900894b Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
1 parent 9b30451 commit a4d96f0

File tree

20 files changed

+1359
-105
lines changed

20 files changed

+1359
-105
lines changed

runtime/doc/cmdline.txt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,16 +493,26 @@ example, to match only files that end in ".c": >
493493
:e *.c$
494494
This will not match a file ending in ".cpp". Without the "$" it does match.
495495

496-
The old value of an option can be obtained by hitting 'wildchar' just after
497-
the '='. For example, typing 'wildchar' after ":set dir=" will insert the
498-
current value of 'dir'. This overrules file name completion for the options
499-
that take a file name.
500-
501496
If you would like using <S-Tab> for CTRL-P in an xterm, put this command in
502497
your .cshrc: >
503498
xmodmap -e "keysym Tab = Tab Find"
504499
And this in your vimrc: >
505500
:cmap <Esc>[1~ <C-P>
501+
< *complete-set-option*
502+
When setting an option using |:set=|, the old value of an option can be
503+
obtained by hitting 'wildchar' just after the '='. For example, typing
504+
'wildchar' after ":set dir=" will insert the current value of 'dir'. This
505+
overrules file name completion for the options that take a file name.
506+
507+
When using |:set=|, |:set+=|, or |:set^=|, string options that have
508+
pre-defined names or syntax (e.g. 'diffopt', 'listchars') or are a list of
509+
single-character flags (e.g. 'shortmess') will also present a list of possible
510+
values for completion when using 'wildchar'.
511+
512+
When using |:set-=|, comma-separated options like 'diffopt' or 'backupdir'
513+
will show each item separately. Flag list options like 'shortmess' will show
514+
both the entire old value and the individual flags. Otherwise completion will
515+
just fill in with the entire old value.
506516

507517
==============================================================================
508518
3. Ex command-lines *cmdline-lines*

runtime/doc/options.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ achieve special effects. These options come in three forms:
5252
'lines'
5353
Warning: This may have a lot of side effects.
5454

55-
*:set-args* *E487* *E521*
55+
*:set-args* *:set=* *E487* *E521*
5656
:se[t] {option}={value} or
5757
:se[t] {option}:{value}
5858
Set string or number option to {value}.
5959
For numeric options the value can be given in decimal,
6060
hex (preceded with 0x) or octal (preceded with '0').
6161
The old value can be inserted by typing 'wildchar' (by
62-
default this is a <Tab>). See |cmdline-completion|.
62+
default this is a <Tab>). Many string options with
63+
fixed syntax also support completing known values.
64+
See |cmdline-completion| and |complete-set-option|.
6365
White space between {option} and '=' is allowed and
6466
will be ignored. White space between '=' and {value}
6567
is not allowed.
@@ -93,6 +95,9 @@ achieve special effects. These options come in three forms:
9395
When the option is a list of flags, {value} must be
9496
exactly as they appear in the option. Remove flags
9597
one by one to avoid problems.
98+
The individual values from a comma separated list or
99+
list of flags can be inserted by typing 'wildchar'.
100+
See |complete-set-option|.
96101
Also see |:set-args| above.
97102

98103
The {option} arguments to ":set" may be repeated. For example: >

src/nvim/autocmd.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,6 +2213,13 @@ char *expand_get_event_name(expand_T *xp, int idx)
22132213
return event_names[idx - next_augroup_id].name;
22142214
}
22152215

2216+
/// Function given to ExpandGeneric() to obtain the list of event names. Don't
2217+
/// include groups.
2218+
char *get_event_name_no_group(expand_T *xp FUNC_ATTR_UNUSED, int idx)
2219+
{
2220+
return event_names[idx].name;
2221+
}
2222+
22162223
/// Check whether given autocommand is supported
22172224
///
22182225
/// @param[in] event Event to check.

src/nvim/cmdexpand.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,6 @@
6969
#include "nvim/vim.h"
7070
#include "nvim/window.h"
7171

72-
/// Type used by ExpandGeneric()
73-
typedef char *(*CompleteListItemGetter)(expand_T *, int);
74-
7572
/// Type used by call_user_expand_func
7673
typedef void *(*user_expand_func_T)(const char *, int, typval_T *);
7774

@@ -107,6 +104,8 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp)
107104
&& xp->xp_context != EXPAND_HELP
108105
&& xp->xp_context != EXPAND_LUA
109106
&& xp->xp_context != EXPAND_OLD_SETTING
107+
&& xp->xp_context != EXPAND_STRING_SETTING
108+
&& xp->xp_context != EXPAND_SETTING_SUBTRACT
110109
&& xp->xp_context != EXPAND_OWNSYNTAX
111110
&& xp->xp_context != EXPAND_PACKADD
112111
&& xp->xp_context != EXPAND_RUNTIME
@@ -2694,8 +2693,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
26942693
return OK;
26952694
}
26962695
if (xp->xp_context == EXPAND_OLD_SETTING) {
2697-
ExpandOldSetting(numMatches, matches);
2698-
return OK;
2696+
return ExpandOldSetting(numMatches, matches);
26992697
}
27002698
if (xp->xp_context == EXPAND_BUFFERS) {
27012699
return ExpandBufnames(pat, numMatches, matches, options);
@@ -2762,9 +2760,12 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
27622760
regmatch.rm_ic = ignorecase(pat);
27632761
}
27642762

2765-
if (xp->xp_context == EXPAND_SETTINGS
2766-
|| xp->xp_context == EXPAND_BOOL_SETTINGS) {
2763+
if (xp->xp_context == EXPAND_SETTINGS || xp->xp_context == EXPAND_BOOL_SETTINGS) {
27672764
ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches, fuzzy);
2765+
} else if (xp->xp_context == EXPAND_STRING_SETTING) {
2766+
ret = ExpandStringSetting(xp, &regmatch, numMatches, matches);
2767+
} else if (xp->xp_context == EXPAND_SETTING_SUBTRACT) {
2768+
ret = ExpandSettingSubtract(xp, &regmatch, numMatches, matches);
27682769
} else if (xp->xp_context == EXPAND_MAPPINGS) {
27692770
ret = ExpandMappings(pat, &regmatch, numMatches, matches);
27702771
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
@@ -2788,9 +2789,8 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
27882789
/// program. Matching strings are copied into an array, which is returned.
27892790
///
27902791
/// @param func returns a string from the list
2791-
static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch,
2792-
char ***matches, int *numMatches, CompleteListItemGetter func,
2793-
int escaped)
2792+
void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch, char ***matches,
2793+
int *numMatches, CompleteListItemGetter func, bool escaped)
27942794
{
27952795
const bool fuzzy = cmdline_fuzzy_complete(pat);
27962796
*matches = NULL;
@@ -2863,6 +2863,7 @@ static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regma
28632863
// in the specified order.
28642864
const bool sort_matches = !fuzzy
28652865
&& xp->xp_context != EXPAND_MENUNAMES
2866+
&& xp->xp_context != EXPAND_STRING_SETTING
28662867
&& xp->xp_context != EXPAND_MENUS
28672868
&& xp->xp_context != EXPAND_SCRIPTNAMES;
28682869

@@ -3221,8 +3222,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
32213222

32223223
char **p;
32233224
int num_p = 0;
3224-
(void)ExpandFromContext(&xpc, buf, &p, &num_p,
3225-
WILD_SILENT | expand_options);
3225+
(void)ExpandFromContext(&xpc, buf, &p, &num_p, WILD_SILENT | expand_options);
32263226
if (num_p > 0) {
32273227
ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT | expand_options);
32283228

src/nvim/cmdexpand.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ enum {
4141
BUF_DIFF_FILTER = 0x2000,
4242
};
4343

44+
/// Type used by ExpandGeneric()
45+
typedef char *(*CompleteListItemGetter)(expand_T *, int);
46+
4447
#ifdef INCLUDE_GENERATED_DECLARATIONS
4548
# include "cmdexpand.h.generated.h"
4649
#endif

src/nvim/diff.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,6 +2467,7 @@ int diffopt_changed(void)
24672467

24682468
char *p = p_dip;
24692469
while (*p != NUL) {
2470+
// Note: Keep this in sync with p_dip_values
24702471
if (strncmp(p, "filler", 6) == 0) {
24712472
p += 6;
24722473
diff_flags_new |= DIFF_FILLER;
@@ -2513,6 +2514,7 @@ int diffopt_changed(void)
25132514
p += 8;
25142515
diff_flags_new |= DIFF_INTERNAL;
25152516
} else if (strncmp(p, "algorithm:", 10) == 0) {
2517+
// Note: Keep this in sync with p_dip_algorithm_values.
25162518
p += 10;
25172519
if (strncmp(p, "myers", 5) == 0) {
25182520
p += 5;

src/nvim/ex_getln.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,6 +2766,7 @@ int check_opt_wim(void)
27662766
}
27672767

27682768
for (char *p = p_wim; *p; p++) {
2769+
// Note: Keep this in sync with p_wim_values.
27692770
for (i = 0; ASCII_ISALPHA(p[i]); i++) {}
27702771
if (p[i] != NUL && p[i] != ',' && p[i] != ':') {
27712772
return FAIL;

src/nvim/generators/gen_options.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ local redraw_flags={
3535
local list_flags={
3636
comma='P_COMMA',
3737
onecomma='P_ONECOMMA',
38+
commacolon='P_COMMA|P_COLON',
39+
onecommacolon='P_ONECOMMA|P_COLON',
3840
flags='P_FLAGLIST',
3941
flagscomma='P_COMMA|P_FLAGLIST',
4042
}
@@ -166,6 +168,9 @@ local function dump_option(i, o)
166168
if o.cb then
167169
w(' .opt_did_set_cb=' .. o.cb)
168170
end
171+
if o.expand_cb then
172+
w(' .opt_expand_cb=' .. o.expand_cb)
173+
end
169174
if o.enable_if then
170175
w('#else')
171176
w(' .var=NULL')

src/nvim/indent.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ bool briopt_check(win_T *wp)
760760

761761
char *p = wp->w_p_briopt;
762762
while (*p != NUL) {
763+
// Note: Keep this in sync with p_briopt_values
763764
if (strncmp(p, "shift:", 6) == 0
764765
&& ((p[6] == '-' && ascii_isdigit(p[7])) || ascii_isdigit(p[6]))) {
765766
p += 6;

src/nvim/mbyte.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,3 +2830,14 @@ void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
28302830
}
28312831
rettv->vval.v_number = mb_get_class(argvars[0].vval.v_string);
28322832
}
2833+
2834+
/// Function given to ExpandGeneric() to obtain the possible arguments of the
2835+
/// encoding options.
2836+
char *get_encoding_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
2837+
{
2838+
if (idx >= (int)ARRAY_SIZE(enc_canon_table)) {
2839+
return NULL;
2840+
}
2841+
2842+
return (char *)enc_canon_table[idx].name;
2843+
}

0 commit comments

Comments
 (0)