comparison src/option.c @ 33399:95db67c7b754 v9.0.1958

patch 9.0.1958: cannot complete option values Commit: https://github.com/vim/vim/commit/900894b09a95398dfc75599e9f0aa2ea25723384 Author: Yee Cheng Chin <ychin.git@gmail.com> Date: Fri Sep 29 20:42:32 2023 +0200 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: #13182 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
author Christian Brabandt <cb@256bit.org>
date Fri, 29 Sep 2023 20:45:04 +0200
parents 667a17904f64
children 9b35b4c6df4c
comparison
equal deleted inserted replaced
33398:a877b968e471 33399:95db67c7b754
1630 1630
1631 // Copy the string, skip over escaped chars. 1631 // Copy the string, skip over escaped chars.
1632 // For MS-DOS and WIN32 backslashes before normal file name characters 1632 // For MS-DOS and WIN32 backslashes before normal file name characters
1633 // are not removed, and keep backslash at start, for "\\machine\path", 1633 // are not removed, and keep backslash at start, for "\\machine\path",
1634 // but do remove it for "\\\\machine\\path". 1634 // but do remove it for "\\\\machine\\path".
1635 // The reverse is found in ExpandOldSetting(). 1635 // The reverse is found in escape_option_str_cmdline().
1636 while (*arg != NUL && !VIM_ISWHITE(*arg)) 1636 while (*arg != NUL && !VIM_ISWHITE(*arg))
1637 { 1637 {
1638 int i; 1638 int i;
1639 1639
1640 if (*arg == '\\' && arg[1] != NUL 1640 if (*arg == '\\' && arg[1] != NUL
1835 else if (nextchar == '<') // set to global val 1835 else if (nextchar == '<') // set to global val
1836 newval = vim_strsave(*(char_u **)get_varp_scope( 1836 newval = vim_strsave(*(char_u **)get_varp_scope(
1837 &(options[opt_idx]), OPT_GLOBAL)); 1837 &(options[opt_idx]), OPT_GLOBAL));
1838 else 1838 else
1839 { 1839 {
1840 ++arg; // jump to after the '=' or ':' 1840 ++arg; // joption_value2stringump to after the '=' or ':'
1841 1841
1842 // Set 'keywordprg' to ":help" if an empty 1842 // Set 'keywordprg' to ":help" if an empty
1843 // value was passed to :set by the user. 1843 // value was passed to :set by the user.
1844 if (varp == (char_u *)&p_kp && (*arg == NUL || *arg == ' ')) 1844 if (varp == (char_u *)&p_kp && (*arg == NUL || *arg == ' '))
1845 { 1845 {
7230 { 7230 {
7231 p_imsearch = curbuf->b_p_imsearch; 7231 p_imsearch = curbuf->b_p_imsearch;
7232 } 7232 }
7233 7233
7234 static int expand_option_idx = -1; 7234 static int expand_option_idx = -1;
7235 static int expand_option_start_col = 0;
7235 static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL}; 7236 static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL};
7236 static int expand_option_flags = 0; 7237 static int expand_option_flags = 0;
7238 static int expand_option_append = FALSE;
7237 7239
7238 void 7240 void
7239 set_context_in_set_cmd( 7241 set_context_in_set_cmd(
7240 expand_T *xp, 7242 expand_T *xp,
7241 char_u *arg, 7243 char_u *arg,
7346 return; 7348 return;
7347 } 7349 }
7348 } 7350 }
7349 } 7351 }
7350 // handle "-=" and "+=" 7352 // handle "-=" and "+="
7353 expand_option_append = FALSE;
7354 int expand_option_subtract = FALSE;
7351 if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=') 7355 if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=')
7352 { 7356 {
7357 if (nextchar == '-')
7358 expand_option_subtract = TRUE;
7359 if (nextchar == '+' || nextchar == '^')
7360 expand_option_append = TRUE;
7353 ++p; 7361 ++p;
7354 nextchar = '='; 7362 nextchar = '=';
7355 } 7363 }
7356 if ((nextchar != '=' && nextchar != ':') 7364 if ((nextchar != '=' && nextchar != ':')
7357 || xp->xp_context == EXPAND_BOOL_SETTINGS) 7365 || xp->xp_context == EXPAND_BOOL_SETTINGS)
7358 { 7366 {
7359 xp->xp_context = EXPAND_UNSUCCESSFUL; 7367 xp->xp_context = EXPAND_UNSUCCESSFUL;
7360 return; 7368 return;
7361 } 7369 }
7362 if (xp->xp_context != EXPAND_BOOL_SETTINGS && p[1] == NUL) 7370
7371 // Below are for handling expanding a specific option's value after the '='
7372 // or ':'
7373
7374 if (is_term_option)
7375 expand_option_idx = -1;
7376 else
7377 expand_option_idx = opt_idx;
7378
7379 xp->xp_pattern = p + 1;
7380 expand_option_start_col = (int)(p + 1 - xp->xp_line);
7381
7382 // Certain options currently have special case handling to reuse the
7383 // expansion logic with other commands.
7384 #ifdef FEAT_SYN_HL
7385 if (options[opt_idx].var == (char_u *)&p_syn)
7386 {
7387 xp->xp_context = EXPAND_OWNSYNTAX;
7388 return;
7389 }
7390 #endif
7391 if (options[opt_idx].var == (char_u *)&p_ft)
7392 {
7393 xp->xp_context = EXPAND_FILETYPE;
7394 return;
7395 }
7396
7397 // Now pick. If the option has a custom expander, use that. Otherwise, just
7398 // fill with the existing option value.
7399 if (expand_option_subtract)
7400 {
7401 xp->xp_context = EXPAND_SETTING_SUBTRACT;
7402 return;
7403 }
7404 else if (expand_option_idx >= 0 &&
7405 options[expand_option_idx].opt_expand_cb != NULL)
7406 {
7407 xp->xp_context = EXPAND_STRING_SETTING;
7408 }
7409 else if (*xp->xp_pattern == NUL)
7363 { 7410 {
7364 xp->xp_context = EXPAND_OLD_SETTING; 7411 xp->xp_context = EXPAND_OLD_SETTING;
7365 if (is_term_option)
7366 expand_option_idx = -1;
7367 else
7368 expand_option_idx = opt_idx;
7369 xp->xp_pattern = p + 1;
7370 return; 7412 return;
7371 } 7413 }
7372 xp->xp_context = EXPAND_NOTHING; 7414 else
7415 xp->xp_context = EXPAND_NOTHING;
7416
7373 if (is_term_option || (flags & P_NUM)) 7417 if (is_term_option || (flags & P_NUM))
7374 return; 7418 return;
7375 7419
7376 xp->xp_pattern = p + 1; 7420 // Only string options below
7377 7421
7378 #ifdef FEAT_SYN_HL 7422 // Options that have P_EXPAND are considered to all use file/dir expansion.
7379 if (options[opt_idx].var == (char_u *)&p_syn)
7380 {
7381 xp->xp_context = EXPAND_OWNSYNTAX;
7382 return;
7383 }
7384 #endif
7385
7386 if (flags & P_EXPAND) 7423 if (flags & P_EXPAND)
7387 { 7424 {
7388 p = options[opt_idx].var; 7425 p = options[opt_idx].var;
7389 if (p == (char_u *)&p_bdir 7426 if (p == (char_u *)&p_bdir
7390 || p == (char_u *)&p_dir 7427 || p == (char_u *)&p_dir
7401 if (p == (char_u *)&p_path || p == (char_u *)&p_cdpath) 7438 if (p == (char_u *)&p_path || p == (char_u *)&p_cdpath)
7402 xp->xp_backslash = XP_BS_THREE; 7439 xp->xp_backslash = XP_BS_THREE;
7403 else 7440 else
7404 xp->xp_backslash = XP_BS_ONE; 7441 xp->xp_backslash = XP_BS_ONE;
7405 } 7442 }
7406 else if (p == (char_u *)&p_ft)
7407 {
7408 xp->xp_context = EXPAND_FILETYPE;
7409 }
7410 else 7443 else
7411 { 7444 {
7412 xp->xp_context = EXPAND_FILES; 7445 xp->xp_context = EXPAND_FILES;
7413 // for 'tags' need three backslashes for a space 7446 // for 'tags' need three backslashes for a space
7414 if (p == (char_u *)&p_tags) 7447 if (p == (char_u *)&p_tags)
7416 else 7449 else
7417 xp->xp_backslash = XP_BS_ONE; 7450 xp->xp_backslash = XP_BS_ONE;
7418 } 7451 }
7419 } 7452 }
7420 7453
7421 // For an option that is a list of file names, find the start of the 7454 // For an option that is a list of file names, or comma/colon-separated
7422 // last file name. 7455 // values, split it by the delimiter and find the start of the current
7423 for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; --p) 7456 // pattern, while accounting for backslash-escaped space/commas/colons.
7424 { 7457 // Triple-backslashed escaped file names (e.g. 'path') can also be
7425 // count number of backslashes before ' ' or ',' 7458 // delimited by space.
7426 if (*p == ' ' || *p == ',') 7459 if ((flags & P_EXPAND) || (flags & P_COMMA) || (flags & P_COLON))
7427 { 7460 {
7428 s = p; 7461 for (p = arg + STRLEN(arg) - 1; p >= xp->xp_pattern; --p)
7429 while (s > xp->xp_pattern && *(s - 1) == '\\') 7462 {
7430 --s; 7463 // count number of backslashes before ' ' or ',' or ':'
7431 if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3)) 7464 if (*p == ' ' || *p == ',' ||
7432 || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0)) 7465 (*p == ':' && (flags & P_COLON)))
7433 { 7466 {
7434 xp->xp_pattern = p + 1; 7467 s = p;
7435 break; 7468 while (s > xp->xp_pattern && *(s - 1) == '\\')
7469 --s;
7470 if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3))
7471 || (*p == ',' && (flags & P_COMMA) && ((p - s) % 1) == 0)
7472 || (*p == ':' && (flags & P_COLON)))
7473 {
7474 xp->xp_pattern = p + 1;
7475 break;
7476 }
7436 } 7477 }
7437 } 7478 }
7438 7479 }
7480
7481 // An option that is a list of single-character flags should always start
7482 // at the end as we don't complete words.
7483 if (flags & P_FLAGLIST)
7484 xp->xp_pattern = arg + STRLEN(arg);
7485
7486 // Some options can either be using file/dir expansions, or custom value
7487 // expansion depending on what the user typed. Unfortunately we have to
7488 // manually handle it here to make sure we have the correct xp_context set.
7439 #ifdef FEAT_SPELL 7489 #ifdef FEAT_SPELL
7440 // for 'spellsuggest' start at "file:" 7490 if (options[opt_idx].var == (char_u *)&p_sps)
7441 if (options[opt_idx].var == (char_u *)&p_sps 7491 {
7442 && STRNCMP(p, "file:", 5) == 0) 7492 if (STRNCMP(xp->xp_pattern, "file:", 5) == 0)
7443 { 7493 {
7444 xp->xp_pattern = p + 5; 7494 xp->xp_pattern += 5;
7445 break; 7495 return;
7446 } 7496 }
7447 #endif 7497 else if (options[expand_option_idx].opt_expand_cb != NULL)
7448 } 7498 {
7499 xp->xp_context = EXPAND_STRING_SETTING;
7500 }
7501 }
7502 #endif
7449 } 7503 }
7450 7504
7451 /* 7505 /*
7452 * Returns TRUE if 'str' either matches 'regmatch' or fuzzy matches 'pat'. 7506 * Returns TRUE if 'str' either matches 'regmatch' or fuzzy matches 'pat'.
7453 * 7507 *
7462 * 'fuzzystr', then returns TRUE. Otherwise returns FALSE. 7516 * 'fuzzystr', then returns TRUE. Otherwise returns FALSE.
7463 * 7517 *
7464 * If 'test_only' is FALSE and 'fuzzy' is TRUE and if 'str' fuzzy matches 7518 * If 'test_only' is FALSE and 'fuzzy' is TRUE and if 'str' fuzzy matches
7465 * 'fuzzystr', then stores the match details in fuzmatch[idx] and returns TRUE. 7519 * 'fuzzystr', then stores the match details in fuzmatch[idx] and returns TRUE.
7466 */ 7520 */
7467 static int 7521 int
7468 match_str( 7522 match_str(
7469 char_u *str, 7523 char_u *str,
7470 regmatch_T *regmatch, 7524 regmatch_T *regmatch,
7471 char_u **matches, 7525 char_u **matches,
7472 int idx, 7526 int idx,
7709 return FAIL; 7763 return FAIL;
7710 7764
7711 return OK; 7765 return OK;
7712 } 7766 }
7713 7767
7714 int 7768 // Escape an option value that can be used on the command-line with :set.
7715 ExpandOldSetting(int *numMatches, char_u ***matches) 7769 // Caller needs to free the returned string, unless NULL is returned.
7716 { 7770 static char_u*
7717 char_u *var = NULL; // init for GCC 7771 escape_option_str_cmdline(char_u *var)
7718 char_u *buf; 7772 {
7719 7773 char_u *buf;
7720 *numMatches = 0;
7721 *matches = ALLOC_ONE(char_u *);
7722 if (*matches == NULL)
7723 return FAIL;
7724
7725 // For a terminal key code expand_option_idx is < 0.
7726 if (expand_option_idx < 0)
7727 {
7728 var = find_termcode(expand_option_name + 2);
7729 if (var == NULL)
7730 expand_option_idx = findoption(expand_option_name);
7731 }
7732
7733 if (expand_option_idx >= 0)
7734 {
7735 // put string of option value in NameBuff
7736 option_value2string(&options[expand_option_idx], expand_option_flags);
7737 var = NameBuff;
7738 }
7739 else if (var == NULL)
7740 var = (char_u *)"";
7741 7774
7742 // A backslash is required before some characters. This is the reverse of 7775 // A backslash is required before some characters. This is the reverse of
7743 // what happens in do_set(). 7776 // what happens in do_set().
7744 buf = vim_strsave_escaped(var, escape_chars); 7777 buf = vim_strsave_escaped(var, escape_chars);
7745
7746 if (buf == NULL) 7778 if (buf == NULL)
7747 { 7779 return NULL;
7748 VIM_CLEAR(*matches);
7749 return FAIL;
7750 }
7751 7780
7752 #ifdef BACKSLASH_IN_FILENAME 7781 #ifdef BACKSLASH_IN_FILENAME
7753 // For MS-Windows et al. we don't double backslashes at the start and 7782 // For MS-Windows et al. we don't double backslashes at the start and
7754 // before a file name character. 7783 // before a file name character.
7784 // The reverse is found at stropt_copy_value().
7755 for (var = buf; *var != NUL; MB_PTR_ADV(var)) 7785 for (var = buf; *var != NUL; MB_PTR_ADV(var))
7756 if (var[0] == '\\' && var[1] == '\\' 7786 if (var[0] == '\\' && var[1] == '\\'
7757 && expand_option_idx >= 0 7787 && expand_option_idx >= 0
7758 && (options[expand_option_idx].flags & P_EXPAND) 7788 && (options[expand_option_idx].flags & P_EXPAND)
7759 && vim_isfilec(var[2]) 7789 && vim_isfilec(var[2])
7760 && (var[2] != '\\' || (var == buf && var[4] != '\\'))) 7790 && (var[2] != '\\' || (var == buf && var[4] != '\\')))
7761 STRMOVE(var, var + 1); 7791 STRMOVE(var, var + 1);
7762 #endif 7792 #endif
7763 7793 return buf;
7764 *matches[0] = buf; 7794 }
7795
7796 /*
7797 * Expansion handler for :set= when we just want to fill in with the existing value.
7798 */
7799 int
7800 ExpandOldSetting(int *numMatches, char_u ***matches)
7801 {
7802 char_u *var = NULL; // init for GCC
7803 char_u *buf;
7804
7805 *numMatches = 0;
7806 *matches = ALLOC_MULT(char_u *, 1);
7807 if (*matches == NULL)
7808 return FAIL;
7809
7810 // For a terminal key code expand_option_idx is < 0.
7811 if (expand_option_idx < 0)
7812 {
7813 var = find_termcode(expand_option_name + 2);
7814 if (var == NULL)
7815 expand_option_idx = findoption(expand_option_name);
7816 }
7817
7818 if (expand_option_idx >= 0)
7819 {
7820 // put string of option value in NameBuff
7821 option_value2string(&options[expand_option_idx], expand_option_flags);
7822 var = NameBuff;
7823 }
7824 else if (var == NULL)
7825 var = (char_u *)"";
7826
7827 buf = escape_option_str_cmdline(var);
7828 if (buf == NULL)
7829 {
7830 VIM_CLEAR(*matches);
7831 return FAIL;
7832 }
7833
7834 (*matches)[0] = buf;
7765 *numMatches = 1; 7835 *numMatches = 1;
7766 return OK; 7836 return OK;
7837 }
7838
7839 /*
7840 * Expansion handler for :set=/:set+= when the option has a custom expansion handler.
7841 */
7842 int
7843 ExpandStringSetting(
7844 expand_T *xp,
7845 regmatch_T *regmatch,
7846 int *numMatches,
7847 char_u ***matches)
7848 {
7849 char_u *var = NULL; // init for GCC
7850 char_u *buf;
7851
7852 if (expand_option_idx < 0 ||
7853 options[expand_option_idx].opt_expand_cb == NULL)
7854 {
7855 // Not supposed to reach this. This function is only for options with
7856 // custom expansion callbacks.
7857 return FAIL;
7858 }
7859
7860 optexpand_T args;
7861 args.oe_varp = get_varp_scope(&options[expand_option_idx], expand_option_flags);
7862 args.oe_append = expand_option_append;
7863 args.oe_regmatch = regmatch;
7864 args.oe_xp = xp;
7865 args.oe_set_arg = xp->xp_line + expand_option_start_col;
7866 args.oe_include_orig_val =
7867 !expand_option_append &&
7868 (*args.oe_set_arg == NUL);
7869
7870 // Retrieve the existing value, but escape it as a reverse of setting it.
7871 // We technically only need to do this when oe_append or
7872 // oe_include_orig_val is true.
7873 option_value2string(&options[expand_option_idx], expand_option_flags);
7874 var = NameBuff;
7875 buf = escape_option_str_cmdline(var);
7876 if (buf == NULL)
7877 return FAIL;
7878
7879 args.oe_opt_value = buf;
7880
7881 int num_ret = options[expand_option_idx].opt_expand_cb(&args, numMatches, matches);
7882
7883 vim_free(buf);
7884 return num_ret;
7885 }
7886
7887 /*
7888 * Expansion handler for :set-=
7889 */
7890 int
7891 ExpandSettingSubtract(
7892 expand_T *xp,
7893 regmatch_T *regmatch,
7894 int *numMatches,
7895 char_u ***matches)
7896 {
7897 if (expand_option_idx < 0)
7898 // term option
7899 return ExpandOldSetting(numMatches, matches);
7900
7901 char_u *option_val = *(char_u**)get_option_varp_scope(
7902 expand_option_idx, expand_option_flags);
7903
7904 long_u option_flags = options[expand_option_idx].flags;
7905
7906 if (option_flags & P_NUM)
7907 return ExpandOldSetting(numMatches, matches);
7908 else if (option_flags & P_COMMA)
7909 {
7910 // Split the option by comma, then present each option to the user if
7911 // it matches the pattern.
7912 // This condition needs to go first, because 'whichwrap' has both
7913 // P_COMMA and P_FLAGLIST.
7914 garray_T ga;
7915
7916 char_u *item;
7917 char_u *option_copy;
7918 char_u *next_val;
7919 char_u *comma;
7920
7921 if (*option_val == NUL)
7922 return FAIL;
7923
7924 // Make a copy as we need to inject null characters destructively.
7925 option_copy = vim_strsave(option_val);
7926 if (option_copy == NULL)
7927 return FAIL;
7928 next_val = option_copy;
7929
7930 ga_init2(&ga, sizeof(char_u *), 10);
7931
7932 do
7933 {
7934 item = next_val;
7935 comma = vim_strchr(next_val, ',');
7936 while (comma != NULL && comma != next_val && *(comma - 1) == '\\')
7937 {
7938 // "\," is interpreted as a literal comma rather than option
7939 // separator when reading options in copy_option_part(). Skip
7940 // it.
7941 comma = vim_strchr(comma + 1, ',');
7942 }
7943 if (comma != NULL)
7944 {
7945 *comma = NUL; // null-terminate this value, required by later functions
7946 next_val = comma + 1;
7947 }
7948 else
7949 next_val = NULL;
7950
7951 if (*item == NUL)
7952 // empty value, don't add to list
7953 continue;
7954
7955 if (!vim_regexec(regmatch, item, (colnr_T)0))
7956 continue;
7957
7958 char_u *buf = escape_option_str_cmdline(item);
7959 if (buf == NULL)
7960 {
7961 vim_free(option_copy);
7962 ga_clear_strings(&ga);
7963 return FAIL;
7964 }
7965 if (ga_add_string(&ga, buf) != OK)
7966 {
7967 vim_free(buf);
7968 break;
7969 }
7970 } while (next_val != NULL);
7971
7972 vim_free(option_copy);
7973
7974 *matches = ga.ga_data;
7975 *numMatches = ga.ga_len;
7976 return OK;
7977 }
7978 else if (option_flags & P_FLAGLIST)
7979 {
7980 // Only present the flags that are set on the option as the other flags
7981 // are not meaningful to do set-= on.
7982
7983 if (*xp->xp_pattern != NUL)
7984 {
7985 // Don't suggest anything if cmdline is non-empty. Vim's set-=
7986 // behavior requires consecutive strings and it's usually
7987 // unintuitive to users if ther try to subtract multiple flags at
7988 // once.
7989 return FAIL;
7990 }
7991
7992 int num_flags = STRLEN(option_val);
7993 if (num_flags == 0)
7994 return FAIL;
7995
7996 *matches = ALLOC_MULT(char_u *, num_flags + 1);
7997 if (*matches == NULL)
7998 return FAIL;
7999
8000 int count = 0;
8001 char_u *p;
8002
8003 p = vim_strsave(option_val);
8004 if (p == NULL)
8005 {
8006 VIM_CLEAR(*matches);
8007 return FAIL;
8008 }
8009 (*matches)[count++] = p;
8010
8011 if (num_flags > 1)
8012 {
8013 // If more than one flags, split the flags up and expose each
8014 // character as individual choice.
8015 for (char_u *flag = option_val; *flag != NUL; flag++)
8016 {
8017 char_u *p = vim_strnsave(flag, 1);
8018 if (p == NULL)
8019 break;
8020 (*matches)[count++] = p;
8021 }
8022 }
8023
8024 *numMatches = count;
8025 return OK;
8026 }
8027
8028 return ExpandOldSetting(numMatches, matches);
7767 } 8029 }
7768 8030
7769 /* 8031 /*
7770 * Get the value for the numeric or string option *opp in a nice format into 8032 * Get the value for the numeric or string option *opp in a nice format into
7771 * NameBuff[]. Must not be called with a hidden option! 8033 * NameBuff[]. Must not be called with a hidden option!
8095 p = wp->w_p_culopt; 8357 p = wp->w_p_culopt;
8096 else 8358 else
8097 p = val; 8359 p = val;
8098 while (*p != NUL) 8360 while (*p != NUL)
8099 { 8361 {
8362 // Note: Keep this in sync with p_culopt_values.
8100 if (STRNCMP(p, "line", 4) == 0) 8363 if (STRNCMP(p, "line", 4) == 0)
8101 { 8364 {
8102 p += 4; 8365 p += 4;
8103 culopt_flags_new |= CULOPT_LINE; 8366 culopt_flags_new |= CULOPT_LINE;
8104 } 8367 }