diff options
Diffstat (limited to 'src/optionstr.c')
-rw-r--r-- | src/optionstr.c | 1118 |
1 files changed, 1117 insertions, 1 deletions
diff --git a/src/optionstr.c b/src/optionstr.c index 9b4464d85c..010bec769f 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -24,8 +24,21 @@ static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete", "hangul", "insertmode", "lang", "mess", "showmatch", "operator", "register", "shell", "spell", "term", "wildmode", NULL}; +#if defined(FEAT_LINEBREAK) +// Note: Keep this in sync with briopt_check() +static char *(p_briopt_values[]) = {"shift:", "min:", "sbr", "list:", "column:", NULL}; +#endif +#if defined(FEAT_DIFF) +// Note: Keep this in sync with diffopt_changed() +static char *(p_dip_values[]) = {"filler", "context:", "iblank", "icase", "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", "indent-heuristic", "algorithm:", NULL}; +static char *(p_dip_algorithm_values[]) = {"myers", "minimal", "patience", "histogram", NULL}; +#endif static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", NULL}; static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; +#ifdef FEAT_CLIPBOARD +// Note: Keep this in sync with did_set_clipboard() +static char *(p_cb_values[]) = {"unnamed", "unnamedplus", "autoselect", "autoselectplus", "autoselectml", "html", "exclude:", NULL}; +#endif #ifdef FEAT_CRYPT static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", # ifdef FEAT_SODIUM @@ -34,6 +47,10 @@ static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL}; #endif static char *(p_cmp_values[]) = {"internal", "keepascii", NULL}; +#ifdef FEAT_SYN_HL +// Note: Keep this in sync with fill_culopt_flags() +static char *(p_culopt_values[]) = {"line", "screenline", "number", "both", NULL}; +#endif static char *(p_dy_values[]) = {"lastline", "truncate", "uhex", NULL}; static char *(p_jop_values[]) = {"stack", NULL}; #ifdef FEAT_FOLDING @@ -41,6 +58,18 @@ static char *(p_fdo_values[]) = {"all", "block", "hor", "mark", "percent", "quickfix", "search", "tag", "insert", "undo", "jump", NULL}; #endif +// Note: Keep this in sync with match_keyprotocol() +static char *(p_kpc_protocol_values[]) = {"none", "mok2", "kitty", NULL}; +#ifdef FEAT_PROP_POPUP +// Note: Keep this in sync with parse_popup_option() +static char *(p_popup_option_values[]) = {"height:", "width:", "highlight:", "border:", "align:", NULL}; +static char *(p_popup_option_border_values[]) = {"on", "off", NULL}; +static char *(p_popup_option_align_values[]) = {"item", "menu", NULL}; +#endif +#if defined(FEAT_SPELL) +// Note: Keep this in sync with spell_check_sps() +static char *(p_sps_values[]) = {"best", "fast", "double", "expr:", "file:", "timeout:", NULL}; +#endif #ifdef FEAT_SESSION // Also used for 'viewoptions'! Keep in sync with SSOP_ flags. static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize", @@ -62,6 +91,8 @@ static char *(p_tbis_values[]) = {"tiny", "small", "medium", "large", "huge", "g static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", "urxvt", "sgr", NULL}; #endif static char *(p_ve_values[]) = {"block", "insert", "all", "onemore", "none", "NONE", NULL}; +// Note: Keep this in sync with check_opt_wim() +static char *(p_wim_values[]) = {"full", "longest", "list", "lastused", NULL}; static char *(p_wop_values[]) = {"fuzzy", "tagfile", "pum", NULL}; #ifdef FEAT_WAK static char *(p_wak_values[]) = {"yes", "menu", "no", NULL}; @@ -700,6 +731,198 @@ did_set_option_listflag(char_u *val, char_u *flags, char *errbuf) } /* + * Expand an option that accepts a list of string values. + */ + int +expand_set_opt_string( + optexpand_T *args, + char **values, + int numValues, + int *numMatches, + char_u ***matches) +{ + char_u *p; + regmatch_T *regmatch = args->oe_regmatch; + int include_orig_val = args->oe_include_orig_val; + char_u *option_val = args->oe_opt_value; + + // Assume numValues is small since they are fixed enums, so just allocate + // upfront instead of needing two passes to calculate output size. + *matches = ALLOC_MULT(char_u *, numValues + 1); + if (*matches == NULL) + return FAIL; + + int count = 0; + + if (include_orig_val && *option_val != NUL) + { + p = vim_strsave(option_val); + if (p == NULL) + { + VIM_CLEAR(*matches); + return FAIL; + } + (*matches)[count++] = p; + } + + for (char **val = values; *val != NULL; val++) + { + if (include_orig_val && *option_val != NUL) + { + if (STRCMP((char_u*)*val, option_val) == 0) + continue; + } + if (vim_regexec(regmatch, (char_u*)(*val), (colnr_T)0)) + { + p = vim_strsave((char_u*)*val); + if (p == NULL) + { + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + else + break; + } + (*matches)[count++] = p; + } + } + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + +static char_u *set_opt_callback_orig_option = NULL; +static char_u *((*set_opt_callback_func)(expand_T *, int)); + +/* + * Callback used by expand_set_opt_generic to also include the original value. + */ + static char_u * +expand_set_opt_callback(expand_T *xp, int idx) +{ + if (idx == 0) + { + if (set_opt_callback_orig_option != NULL) + return set_opt_callback_orig_option; + else + return (char_u *)""; // empty strings are ignored + } + return set_opt_callback_func(xp, idx - 1); +} + +/* + * Expand an option with a callback that iterates through a list of possible names. + */ + int +expand_set_opt_generic( + optexpand_T *args, + char_u *((*func)(expand_T *, int)), + int *numMatches, + char_u ***matches) +{ + int ret; + + set_opt_callback_orig_option = args->oe_include_orig_val ? + args->oe_opt_value : NULL; + set_opt_callback_func = func; + + ret = ExpandGeneric( + (char_u*)"", // not using fuzzy as currently EXPAND_STRING_SETTING doesn't use it + args->oe_xp, + args->oe_regmatch, + matches, + numMatches, + expand_set_opt_callback, + FALSE); + + set_opt_callback_orig_option = NULL; + set_opt_callback_func = NULL; + return ret; +} + + +/* + * Expand an option which is a list of flags. + */ + int +expand_set_opt_listflag( + optexpand_T *args, + char_u *flags, + int *numMatches, + char_u ***matches) +{ + char_u *p; + char_u *option_val = args->oe_opt_value; + char_u *cmdline_val = args->oe_set_arg; + int append = args->oe_append; + int include_orig_val = args->oe_include_orig_val && (*option_val != NUL); + + int num_flags = STRLEN(flags); + + // Assume we only have small number of flags, so just allocate max size. + *matches = ALLOC_MULT(char_u *, num_flags + 1); + if (*matches == NULL) + return FAIL; + + int count = 0; + + if (include_orig_val) + { + p = vim_strsave(option_val); + if (p == NULL) + { + VIM_CLEAR(*matches); + return FAIL; + } + (*matches)[count++] = p; + } + + for (char_u *flag = flags; *flag != NUL; flag++) + { + if (append && vim_strchr(option_val, *flag) != NULL) + continue; + + if (vim_strchr(cmdline_val, *flag) == NULL) + { + if (include_orig_val + && option_val[1] == NUL + && *flag == option_val[0]) + { + // This value is already used as the first choice as it's the + // existing flag. Just skip it to avoid duplicate. + continue; + } + p = vim_strnsave(flag, 1); + if (p == NULL) + { + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + else + break; + } + (*matches)[count++] = p; + } + } + + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; +} + +/* * The 'ambiwidth' option is changed. */ char * @@ -711,6 +934,17 @@ did_set_ambiwidth(optset_T *args UNUSED) return check_chars_options(); } + int +expand_set_ambiwidth(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_ambw_values, + sizeof(p_ambw_values) / sizeof(p_ambw_values[0]) - 1, + numMatches, + matches); +} + /* * The 'background' option is changed. */ @@ -747,6 +981,17 @@ did_set_background(optset_T *args UNUSED) return NULL; } + int +expand_set_background(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bg_values, + sizeof(p_bg_values) / sizeof(p_bg_values[0]) - 1, + numMatches, + matches); +} + /* * The 'backspace' option is changed. */ @@ -764,6 +1009,17 @@ did_set_backspace(optset_T *args UNUSED) return NULL; } + int +expand_set_backspace(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bs_values, + sizeof(p_bs_values) / sizeof(p_bs_values[0]) - 1, + numMatches, + matches); +} + /* * The 'backupcopy' option is changed. */ @@ -801,6 +1057,17 @@ did_set_backupcopy(optset_T *args) return errmsg; } + int +expand_set_backupcopy(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bkc_values, + sizeof(p_bkc_values) / sizeof(p_bkc_values[0]) - 1, + numMatches, + matches); +} + /* * The 'backupext' or the 'patchmode' option is changed. */ @@ -823,6 +1090,17 @@ did_set_belloff(optset_T *args UNUSED) return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, TRUE); } + int +expand_set_belloff(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bo_values, + sizeof(p_bo_values) / sizeof(p_bo_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_LINEBREAK) || defined(PROTO) /* * The 'breakindentopt' option is changed. @@ -840,6 +1118,17 @@ did_set_breakindentopt(optset_T *args UNUSED) return errmsg; } + + int +expand_set_breakindentopt(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_briopt_values, + sizeof(p_briopt_values) / sizeof(p_briopt_values[0]) - 1, + numMatches, + matches); +} #endif #if defined(FEAT_BROWSE) || defined(PROTO) @@ -855,6 +1144,17 @@ did_set_browsedir(optset_T *args UNUSED) return NULL; } + + int +expand_set_browsedir(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bsdir_values, + sizeof(p_bsdir_values) / sizeof(p_bsdir_values[0]) - 1, + numMatches, + matches); +} #endif /* @@ -866,6 +1166,17 @@ did_set_bufhidden(optset_T *args UNUSED) return did_set_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE); } + int +expand_set_bufhidden(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_bufhidden_values, + sizeof(p_bufhidden_values) / sizeof(p_bufhidden_values[0]) - 1, + numMatches, + matches); +} + /* * The 'buftype' option is changed. */ @@ -886,6 +1197,17 @@ did_set_buftype(optset_T *args UNUSED) return NULL; } + int +expand_set_buftype(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_buftype_values, + sizeof(p_buftype_values) / sizeof(p_buftype_values[0]) - 1, + numMatches, + matches); +} + /* * The 'casemap' option is changed. */ @@ -895,6 +1217,30 @@ did_set_casemap(optset_T *args UNUSED) return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE); } + int +expand_set_casemap(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_cmp_values, + sizeof(p_cmp_values) / sizeof(p_cmp_values[0]) - 1, + numMatches, + matches); +} + +#if defined(FEAT_CLIPBOARD) || defined(PROTO) + int +expand_set_clipboard(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_cb_values, + sizeof(p_cb_values) / sizeof(p_cb_values[0]) - 1, + numMatches, + matches); +} +#endif + /* * The global 'listchars' or 'fillchars' option is changed. */ @@ -967,6 +1313,21 @@ did_set_chars_option(optset_T *args) } /* + * Expand 'fillchars' or 'listchars' option value. + */ + int +expand_set_chars_option(optexpand_T *args, int *numMatches, char_u ***matches) +{ + char_u **varp = (char_u **)args->oe_varp; + int is_lcs = (varp == &p_lcs || varp == &curwin->w_p_lcs); + return expand_set_opt_generic( + args, + is_lcs ? get_listchars_name : get_fillchars_name, + numMatches, + matches); +} + +/* * The 'cinoptions' option is changed. */ char * @@ -1091,6 +1452,20 @@ did_set_complete(optset_T *args) return NULL; } + int +expand_set_complete(optexpand_T *args, int *numMatches, char_u ***matches) +{ + static char *(p_cpt_values[]) = { + ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", + NULL}; + return expand_set_opt_string( + args, + p_cpt_values, + sizeof(p_cpt_values) / sizeof(p_cpt_values[0]) - 1, + numMatches, + matches); +} + /* * The 'completeopt' option is changed. */ @@ -1104,6 +1479,17 @@ did_set_completeopt(optset_T *args UNUSED) return NULL; } + int +expand_set_completeopt(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_cot_values, + sizeof(p_cot_values) / sizeof(p_cot_values[0]) - 1, + numMatches, + matches); +} + #if (defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX)) || defined(PROTO) /* * The 'completepopup' option is changed. @@ -1132,6 +1518,17 @@ did_set_completeslash(optset_T *args UNUSED) return NULL; } + + int +expand_set_completeslash(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_csl_values, + sizeof(p_csl_values) / sizeof(p_csl_values[0]) - 1, + numMatches, + matches); +} #endif #if defined(FEAT_CONCEAL) || defined(PROTO) @@ -1145,6 +1542,12 @@ did_set_concealcursor(optset_T *args) return did_set_option_listflag(*varp, (char_u *)COCU_ALL, args->os_errbuf); } + + int +expand_set_concealcursor(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_listflag(args, (char_u*)COCU_ALL, numMatches, matches); +} #endif /* @@ -1158,6 +1561,12 @@ did_set_cpoptions(optset_T *args) return did_set_option_listflag(*varp, (char_u *)CPO_ALL, args->os_errbuf); } + int +expand_set_cpoptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_listflag(args, (char_u*)CPO_ALL, numMatches, matches); +} + #if defined(FEAT_CRYPT) || defined(PROTO) /* * The 'cryptkey' option is changed. @@ -1244,6 +1653,17 @@ did_set_cryptmethod(optset_T *args) } return NULL; } + + int +expand_set_cryptmethod(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_cm_values, + sizeof(p_cm_values) / sizeof(p_cm_values[0]) - 1, + numMatches, + matches); +} #endif #if (defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)) || defined(PROTO) @@ -1285,11 +1705,23 @@ did_set_cursorlineopt(optset_T *args) { char_u **varp = (char_u **)args->os_varp; + // This could be changed to use opt_strings_flags() instead. if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) return e_invalid_argument; return NULL; } + + int +expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_culopt_values, + sizeof(p_culopt_values) / sizeof(p_culopt_values[0]) - 1, + numMatches, + matches); +} #endif /* @@ -1301,6 +1733,17 @@ did_set_debug(optset_T *args UNUSED) return did_set_opt_strings(p_debug, p_debug_values, TRUE); } + int +expand_set_debug(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_debug_values, + sizeof(p_debug_values) / sizeof(p_debug_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_DIFF) || defined(PROTO) /* * The 'diffopt' option is changed. @@ -1313,6 +1756,36 @@ did_set_diffopt(optset_T *args UNUSED) return NULL; } + + int +expand_set_diffopt(optexpand_T *args, int *numMatches, char_u ***matches) +{ + expand_T *xp = args->oe_xp; + + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':') + { + // Within "algorithm:", we have a subgroup of possible options. + int algo_len = STRLEN("algorithm:"); + if (xp->xp_pattern - args->oe_set_arg >= algo_len && + STRNCMP(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0) + { + return expand_set_opt_string( + args, + p_dip_algorithm_values, + sizeof(p_dip_algorithm_values) / sizeof(p_dip_algorithm_values[0]) - 1, + numMatches, + matches); + } + return FAIL; + } + + return expand_set_opt_string( + args, + p_dip_values, + sizeof(p_dip_values) / sizeof(p_dip_values[0]) - 1, + numMatches, + matches); +} #endif /* @@ -1328,6 +1801,17 @@ did_set_display(optset_T *args UNUSED) return NULL; } + int +expand_set_display(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_dy_values, + sizeof(p_dy_values) / sizeof(p_dy_values[0]) - 1, + numMatches, + matches); +} + /* * The 'eadirection' option is changed. */ @@ -1337,6 +1821,17 @@ did_set_eadirection(optset_T *args UNUSED) return did_set_opt_strings(p_ead, p_ead_values, FALSE); } + int +expand_set_eadirection(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_ead_values, + sizeof(p_ead_values) / sizeof(p_ead_values[0]) - 1, + numMatches, + matches); +} + /* * One of the 'encoding', 'fileencoding', 'termencoding' or 'makeencoding' * options is changed. @@ -1430,6 +1925,16 @@ did_set_encoding(optset_T *args) return errmsg; } + int +expand_set_encoding(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_generic( + args, + get_encoding_name, + numMatches, + matches); +} + /* * The 'eventignore' option is changed. */ @@ -1441,6 +1946,26 @@ did_set_eventignore(optset_T *args UNUSED) return NULL; } + static char_u * +get_eventignore_name(expand_T *xp, int idx) +{ + // 'eventignore' allows special keyword "all" in addition to + // all event names. + if (idx == 0) + return (char_u *)"all"; + return get_event_name_no_group(xp, idx - 1); +} + + int +expand_set_eventignore(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_generic( + args, + get_eventignore_name, + numMatches, + matches); +} + /* * The 'fileformat' option is changed. */ @@ -1470,6 +1995,17 @@ did_set_fileformat(optset_T *args) return NULL; } + int +expand_set_fileformat(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_ff_values, + sizeof(p_ff_values) / sizeof(p_ff_values[0]) - 1, + numMatches, + matches); +} + /* * The 'fileformats' option is changed. */ @@ -1517,6 +2053,17 @@ did_set_foldclose(optset_T *args UNUSED) { return did_set_opt_strings(p_fcl, p_fcl_values, TRUE); } + + int +expand_set_foldclose(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_fcl_values, + sizeof(p_fcl_values) / sizeof(p_fcl_values[0]) - 1, + numMatches, + matches); +} #endif #if (defined(FEAT_EVAL) && defined(FEAT_FOLDING)) || defined(PROTO) @@ -1583,6 +2130,17 @@ did_set_foldmethod(optset_T *args) return NULL; } + int +expand_set_foldmethod(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_fdm_values, + sizeof(p_fdm_values) / sizeof(p_fdm_values[0]) - 1, + numMatches, + matches); +} + /* * The 'foldopen' option is changed. */ @@ -1591,6 +2149,17 @@ did_set_foldopen(optset_T *args UNUSED) { return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE); } + + int +expand_set_foldopen(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_fdo_values, + sizeof(p_fdo_values) / sizeof(p_fdo_values[0]) - 1, + numMatches, + matches); +} #endif /* @@ -1604,6 +2173,12 @@ did_set_formatoptions(optset_T *args) return did_set_option_listflag(*varp, (char_u *)FO_ALL, args->os_errbuf); } + int +expand_set_formatoptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_listflag(args, (char_u*)FO_ALL, numMatches, matches); +} + #if defined(CURSOR_SHAPE) || defined(PROTO) /* * The 'guicursor' option is changed. @@ -1722,6 +2297,12 @@ did_set_guioptions(optset_T *args) gui_init_which_components(args->os_oldval.string); return NULL; } + + int +expand_set_guioptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_listflag(args, (char_u*)GO_ALL, numMatches, matches); +} #endif #if defined(FEAT_GUI_TABLINE) || defined(PROTO) @@ -1788,6 +2369,125 @@ did_set_highlight(optset_T *args UNUSED) } /* + * Expand 'highlight' option. + */ + int +expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches) +{ + char_u *p; + expand_T *xp = args->oe_xp; + static char_u hl_flags[HLF_COUNT] = HL_FLAGS; + int i; + int count = 0; + + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':') + { + // Right after a ':', meaning we just return all highlight names. + return expand_set_opt_generic( + args, + get_highlight_name, + numMatches, + matches); + } + + if (*xp->xp_pattern == NUL) + { + // At beginning of a comma-separated list. Return the specific list of + // supported occasions. + *matches = ALLOC_MULT(char_u *, HLF_COUNT + 1); + if (*matches == NULL) + return FAIL; + + // We still want to return the full option if it's requested. + if (args->oe_include_orig_val) + { + p = vim_strsave(args->oe_opt_value); + if (p == NULL) + { + VIM_CLEAR(*matches); + return FAIL; + } + (*matches)[count++] = p; + } + + for (i = 0; i < HLF_COUNT; i++) + { + p = vim_strnsave(&hl_flags[i], 1); + if (p == NULL) + { + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + else + break; + } + (*matches)[count++] = p; + } + + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + return OK; + } + + // We are after the initial character (which indicates the occasion). We + // already made sure we are not matching after a ':' above, so now we want + // to match against display mode modifiers. + // Since the xp_pattern starts from the beginning, we need to include it in + // the returned match. + + // Note: Keep this in sync with highlight_changed() + static char p_hl_mode_values[] = + {':', 'b', 'i', '-', 'n', 'r', 's', 'u', 'c', '2', 'd', '=', 't'}; + int num_hl_modes = sizeof(p_hl_mode_values) / sizeof(p_hl_mode_values[0]); + + *matches = ALLOC_MULT(char_u *, num_hl_modes); + if (*matches == NULL) + return FAIL; + + int pattern_len = STRLEN(xp->xp_pattern); + + for (i = 0; i < num_hl_modes; i++) + { + // Don't allow duplicates as these are unique flags + if (vim_strchr(xp->xp_pattern + 1, p_hl_mode_values[i]) != NULL) + continue; + + // ':' only works by itself, not with other flags. + if (pattern_len > 1 && p_hl_mode_values[i] == ':') + continue; + + p = vim_strnsave(xp->xp_pattern, pattern_len + 1); + if (p == NULL) + { + if (i == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + else + break; + } + p[pattern_len] = p_hl_mode_values[i]; + p[pattern_len + 1] = NUL; + (*matches)[count++] = p; + } + if (count == 0) + { + VIM_CLEAR(*matches); + return FAIL; + } + *numMatches = count; + + return OK; +} + +/* * The 'titlestring' or the 'iconstring' option is changed. */ static char * @@ -1866,6 +2566,17 @@ did_set_jumpoptions(optset_T *args UNUSED) return NULL; } + int +expand_set_jumpoptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_jop_values, + sizeof(p_jop_values) / sizeof(p_jop_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_KEYMAP) || defined(PROTO) /* * The 'keymap' option is changed. @@ -1939,6 +2650,17 @@ did_set_keymodel(optset_T *args UNUSED) return NULL; } + int +expand_set_keymodel(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_km_values, + sizeof(p_km_values) / sizeof(p_km_values[0]) - 1, + numMatches, + matches); +} + /* * The 'keyprotocol' option is changed. */ @@ -1955,6 +2677,27 @@ did_set_keyprotocol(optset_T *args UNUSED) return NULL; } + int +expand_set_keyprotocol(optexpand_T *args, int *numMatches, char_u ***matches) +{ + expand_T *xp = args->oe_xp; + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':') + { + // 'keyprotocol' only has well-defined terms for completion for the + // protocol part after the colon. + return expand_set_opt_string( + args, + p_kpc_protocol_values, + sizeof(p_kpc_protocol_values) / sizeof(p_kpc_protocol_values[0]) - 1, + numMatches, + matches); + } + // Use expand_set_opt_string instead of returning FAIL so that we can + // include the original value if args->oe_include_orig_val is set. + static char *(empty[]) = {NULL}; + return expand_set_opt_string(args, empty, 0, numMatches, matches); +} + /* * The 'lispoptions' option is changed. */ @@ -1971,6 +2714,18 @@ did_set_lispoptions(optset_T *args) return NULL; } + int +expand_set_lispoptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + static char *(p_lop_values[]) = {"expr:0", "expr:1", NULL}; + return expand_set_opt_string( + args, + p_lop_values, + sizeof(p_lop_values) / sizeof(p_lop_values[0]) - 1, + numMatches, + matches); +} + /* * The 'matchpairs' option is changed. */ @@ -2042,6 +2797,12 @@ did_set_mouse(optset_T *args) args->os_errbuf); } + int +expand_set_mouse(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_listflag(args, (char_u*)MOUSE_ALL, numMatches, matches); +} + /* * The 'mousemodel' option is changed. */ @@ -2060,6 +2821,17 @@ did_set_mousemodel(optset_T *args UNUSED) return NULL; } + int +expand_set_mousemodel(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_mousem_values, + sizeof(p_mousem_values) / sizeof(p_mousem_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_MOUSESHAPE) || defined(PROTO) char * did_set_mouseshape(optset_T *args UNUSED) @@ -2084,6 +2856,17 @@ did_set_nrformats(optset_T *args) return did_set_opt_strings(*varp, p_nf_values, TRUE); } + int +expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_nf_values, + sizeof(p_nf_values) / sizeof(p_nf_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_EVAL) || defined(PROTO) /* * One of the '*expr' options is changed: 'balloonexpr', 'diffexpr', @@ -2144,6 +2927,58 @@ did_set_previewpopup(optset_T *args UNUSED) return NULL; } + + int +expand_set_popupoption(optexpand_T *args, int *numMatches, char_u ***matches) +{ + expand_T *xp = args->oe_xp; + + if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':') + { + // Within "highlight:"/"border:"/"align:", we have a subgroup of possible options. + int border_len = STRLEN("border:"); + if (xp->xp_pattern - args->oe_set_arg >= border_len && + STRNCMP(xp->xp_pattern - border_len, "border:", border_len) == 0) + { + return expand_set_opt_string( + args, + p_popup_option_border_values, + sizeof(p_popup_option_border_values) / sizeof(p_popup_option_border_values[0]) - 1, + numMatches, + matches); + } + int align_len = STRLEN("align:"); + if (xp->xp_pattern - args->oe_set_arg >= align_len && + STRNCMP(xp->xp_pattern - align_len, "align:", align_len) == 0) + { + return expand_set_opt_string( + args, + p_popup_option_align_values, + sizeof(p_popup_option_align_values) / sizeof(p_popup_option_align_values[0]) - 1, + numMatches, + matches); + } + int highlight_len = STRLEN("highlight:"); + if (xp->xp_pattern - args->oe_set_arg >= highlight_len && + STRNCMP(xp->xp_pattern - highlight_len, "highlight:", highlight_len) == 0) + { + // Return the list of all highlight names + return expand_set_opt_generic( + args, + get_highlight_name, + numMatches, + matches); + } + return FAIL; + } + + return expand_set_opt_string( + args, + p_popup_option_values, + sizeof(p_popup_option_values) / sizeof(p_popup_option_values[0]) - 1, + numMatches, + matches); +} #endif #if defined(FEAT_POSTSCRIPT) || defined(PROTO) @@ -2178,6 +3013,30 @@ did_set_printencoding(optset_T *args UNUSED) } #endif +#if defined(FEAT_PRINTER) || defined(PROTO) + + static char_u * +get_printoptions_names(expand_T *xp UNUSED, int idx) +{ + if (idx >= (int)(sizeof(printer_opts) / sizeof(printer_opts[0]))) + return NULL; + return (char_u*)printer_opts[idx].name; +} + +/* + * Expand 'printoptions' option + */ + int +expand_set_printoptions(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_generic( + args, + get_printoptions_names, + numMatches, + matches); +} +#endif + #if defined(FEAT_STL_OPT) || defined(PROTO) /* * The 'statusline' or the 'tabline' or the 'rulerformat' option is changed. @@ -2244,6 +3103,18 @@ did_set_rightleftcmd(optset_T *args) return NULL; } + + int +expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char_u ***matches) +{ + static char *(p_rlc_values[]) = {"search", NULL}; + return expand_set_opt_string( + args, + p_rlc_values, + sizeof(p_rlc_values) / sizeof(p_rlc_values[0]) - 1, + numMatches, + matches); +} #endif #if defined(FEAT_STL_OPT) || defined(PROTO) @@ -2266,6 +3137,17 @@ did_set_scrollopt(optset_T *args UNUSED) return did_set_opt_strings(p_sbo, p_scbopt_values, TRUE); } + int +expand_set_scrollopt(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_scbopt_values, + sizeof(p_scbopt_values) / sizeof(p_scbopt_values[0]) - 1, + numMatches, + matches); +} + /* * The 'selection' option is changed. */ @@ -2278,6 +3160,17 @@ did_set_selection(optset_T *args UNUSED) return NULL; } + int +expand_set_selection(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_sel_values, + sizeof(p_sel_values) / sizeof(p_sel_values[0]) - 1, + numMatches, + matches); +} + /* * The 'selectmode' option is changed. */ @@ -2287,6 +3180,17 @@ did_set_selectmode(optset_T *args UNUSED) return did_set_opt_strings(p_slm, p_slm_values, TRUE); } + int +expand_set_selectmode(optexpand_T *args, int *numMatches, char_u ***matches) +{ + return expand_set_opt_string( + args, + p_slm_values, + sizeof(p_slm_values) / sizeof(p_slm_values[0]) - 1, + numMatches, + matches); +} + #if defined(FEAT_SESSION) || defined(PROTO) /* |