mirror of
https://github.com/vim/vim.git
synced 2025-10-01 04:54:07 -04:00
patch 9.0.1283: the code for setting options is too complicated
Problem: The code for setting options is too complicated. Solution: Refactor the do_set() function. (Yegappan Lakshmanan, Lewis Russell, closes #11945)
This commit is contained in:
committed by
Bram Moolenaar
parent
c8ef30bc2e
commit
c72078b631
764
src/option.c
764
src/option.c
@@ -1211,6 +1211,9 @@ ex_set(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* :set operator types
|
||||||
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_NONE = 0,
|
OP_NONE = 0,
|
||||||
OP_ADDING, // "opt+=arg"
|
OP_ADDING, // "opt+=arg"
|
||||||
@@ -1218,6 +1221,181 @@ typedef enum {
|
|||||||
OP_REMOVING, // "opt-=arg"
|
OP_REMOVING, // "opt-=arg"
|
||||||
} set_op_T;
|
} set_op_T;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PREFIX_NO = 0, // "no" prefix
|
||||||
|
PREFIX_NONE, // no prefix
|
||||||
|
PREFIX_INV, // "inv" prefix
|
||||||
|
} set_prefix_T;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the prefix type for the option name in *argp.
|
||||||
|
*/
|
||||||
|
static set_prefix_T
|
||||||
|
get_option_prefix(char_u **argp)
|
||||||
|
{
|
||||||
|
int prefix = PREFIX_NONE;
|
||||||
|
char_u *arg = *argp;
|
||||||
|
|
||||||
|
if (STRNCMP(arg, "no", 2) == 0 && STRNCMP(arg, "novice", 6) != 0)
|
||||||
|
{
|
||||||
|
prefix = PREFIX_NO;
|
||||||
|
arg += 2;
|
||||||
|
}
|
||||||
|
else if (STRNCMP(arg, "inv", 3) == 0)
|
||||||
|
{
|
||||||
|
prefix = PREFIX_INV;
|
||||||
|
arg += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
*argp = arg;
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the option name in "arg" and return the option index in "*opt_idxp",
|
||||||
|
* and the option name length in "*lenp". For a <t_xx> option, return the key
|
||||||
|
* number in "*keyp".
|
||||||
|
*
|
||||||
|
* Returns FAIL if an option starting with "<" doesn't end with a ">",
|
||||||
|
* otherwise returns OK.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_option_name(char_u *arg, int *opt_idxp, int *lenp, int *keyp)
|
||||||
|
{
|
||||||
|
int key = 0;
|
||||||
|
int len;
|
||||||
|
int opt_idx;
|
||||||
|
|
||||||
|
if (*arg == '<')
|
||||||
|
{
|
||||||
|
opt_idx = -1;
|
||||||
|
// look out for <t_>;>
|
||||||
|
if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
|
||||||
|
len = 5;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = 1;
|
||||||
|
while (arg[len] != NUL && arg[len] != '>')
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
if (arg[len] != '>')
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
arg[len] = NUL; // put NUL after name
|
||||||
|
if (arg[1] == 't' && arg[2] == '_') // could be term code
|
||||||
|
opt_idx = findoption(arg + 1);
|
||||||
|
arg[len++] = '>'; // restore '>'
|
||||||
|
if (opt_idx == -1)
|
||||||
|
key = find_key_option(arg + 1, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int nextchar; // next non-white char after option name
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
/*
|
||||||
|
* The two characters after "t_" may not be alphanumeric.
|
||||||
|
*/
|
||||||
|
if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
|
||||||
|
len = 4;
|
||||||
|
else
|
||||||
|
while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
|
||||||
|
++len;
|
||||||
|
nextchar = arg[len];
|
||||||
|
arg[len] = NUL; // put NUL after name
|
||||||
|
opt_idx = findoption(arg);
|
||||||
|
arg[len] = nextchar; // restore nextchar
|
||||||
|
if (opt_idx == -1)
|
||||||
|
key = find_key_option(arg, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
*keyp = key;
|
||||||
|
*lenp = len;
|
||||||
|
*opt_idxp = opt_idx;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the option operator (+=, ^=, -=).
|
||||||
|
*/
|
||||||
|
static set_op_T
|
||||||
|
get_opt_op(char_u *arg)
|
||||||
|
{
|
||||||
|
set_op_T op = OP_NONE;
|
||||||
|
|
||||||
|
if (*arg != NUL && *(arg + 1) == '=')
|
||||||
|
{
|
||||||
|
if (*arg == '+')
|
||||||
|
op = OP_ADDING; // "+="
|
||||||
|
else if (*arg == '^')
|
||||||
|
op = OP_PREPENDING; // "^="
|
||||||
|
else if (*arg == '-')
|
||||||
|
op = OP_REMOVING; // "-="
|
||||||
|
}
|
||||||
|
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate whether the value of the option in "opt_idx" can be changed.
|
||||||
|
* Returns FAIL if the option can be skipped or cannot be changed. Returns OK
|
||||||
|
* if it can be changed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
validate_opt_idx(int opt_idx, int opt_flags, long_u flags, char **errmsg)
|
||||||
|
{
|
||||||
|
// Skip all options that are not window-local (used when showing
|
||||||
|
// an already loaded buffer in a window).
|
||||||
|
if ((opt_flags & OPT_WINONLY)
|
||||||
|
&& (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// Skip all options that are window-local (used for :vimgrep).
|
||||||
|
if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
|
||||||
|
&& options[opt_idx].var == VAR_WIN)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// Disallow changing some options from modelines.
|
||||||
|
if (opt_flags & OPT_MODELINE)
|
||||||
|
{
|
||||||
|
if (flags & (P_SECURE | P_NO_ML))
|
||||||
|
{
|
||||||
|
*errmsg = e_not_allowed_in_modeline;
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if ((flags & P_MLE) && !p_mle)
|
||||||
|
{
|
||||||
|
*errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
#ifdef FEAT_DIFF
|
||||||
|
// In diff mode some options are overruled. This avoids that
|
||||||
|
// 'foldmethod' becomes "marker" instead of "diff" and that
|
||||||
|
// "wrap" gets set.
|
||||||
|
if (curwin->w_p_diff
|
||||||
|
&& opt_idx >= 0 // shut up coverity warning
|
||||||
|
&& (
|
||||||
|
# ifdef FEAT_FOLDING
|
||||||
|
options[opt_idx].indir == PV_FDM ||
|
||||||
|
# endif
|
||||||
|
options[opt_idx].indir == PV_WRAP))
|
||||||
|
return FAIL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SANDBOX
|
||||||
|
// Disallow changing some options in the sandbox
|
||||||
|
if (sandbox != 0 && (flags & P_SECURE))
|
||||||
|
{
|
||||||
|
*errmsg = e_not_allowed_in_sandbox;
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Part of do_set() for string options.
|
* Part of do_set() for string options.
|
||||||
* Returns FAIL on failure, do not process further options.
|
* Returns FAIL on failure, do not process further options.
|
||||||
@@ -1636,6 +1814,263 @@ do_set_string(
|
|||||||
return *errmsg == NULL ? OK : FAIL;
|
return *errmsg == NULL ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a boolean option
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
do_set_option_bool(
|
||||||
|
int opt_idx,
|
||||||
|
int opt_flags,
|
||||||
|
set_prefix_T prefix,
|
||||||
|
long_u flags,
|
||||||
|
char_u *varp,
|
||||||
|
int nextchar,
|
||||||
|
int afterchar,
|
||||||
|
int cp_val)
|
||||||
|
|
||||||
|
{
|
||||||
|
varnumber_T value;
|
||||||
|
|
||||||
|
if (nextchar == '=' || nextchar == ':')
|
||||||
|
return e_invalid_argument;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ":set opt!": invert
|
||||||
|
* ":set opt&": reset to default value
|
||||||
|
* ":set opt<": reset to global value
|
||||||
|
*/
|
||||||
|
if (nextchar == '!')
|
||||||
|
value = *(int *)(varp) ^ 1;
|
||||||
|
else if (nextchar == '&')
|
||||||
|
value = (int)(long)(long_i)options[opt_idx].def_val[
|
||||||
|
((flags & P_VI_DEF) || cp_val) ? VI_DEFAULT : VIM_DEFAULT];
|
||||||
|
else if (nextchar == '<')
|
||||||
|
{
|
||||||
|
// For 'autoread' -1 means to use global value.
|
||||||
|
if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL)
|
||||||
|
value = -1;
|
||||||
|
else
|
||||||
|
value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* ":set invopt": invert
|
||||||
|
* ":set opt" or ":set noopt": set or reset
|
||||||
|
*/
|
||||||
|
if (nextchar != NUL && !VIM_ISWHITE(afterchar))
|
||||||
|
return e_trailing_characters;
|
||||||
|
if (prefix == PREFIX_INV)
|
||||||
|
value = *(int *)(varp) ^ 1;
|
||||||
|
else
|
||||||
|
value = prefix == PREFIX_NO ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_bool_option(opt_idx, varp, (int)value, opt_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a numeric option
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
do_set_option_numeric(
|
||||||
|
int opt_idx,
|
||||||
|
int opt_flags,
|
||||||
|
char_u **argp,
|
||||||
|
int nextchar,
|
||||||
|
set_op_T op,
|
||||||
|
long_u flags,
|
||||||
|
int cp_val,
|
||||||
|
char_u *varp,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbuflen)
|
||||||
|
{
|
||||||
|
char_u *arg = *argp;
|
||||||
|
varnumber_T value;
|
||||||
|
int i;
|
||||||
|
char *errmsg = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Different ways to set a number option:
|
||||||
|
* & set to default value
|
||||||
|
* < set to global value
|
||||||
|
* <xx> accept special key codes for 'wildchar'
|
||||||
|
* c accept any non-digit for 'wildchar'
|
||||||
|
* [-]0-9 set number
|
||||||
|
* other error
|
||||||
|
*/
|
||||||
|
++arg;
|
||||||
|
if (nextchar == '&')
|
||||||
|
value = (long)(long_i)options[opt_idx].def_val[
|
||||||
|
((flags & P_VI_DEF) || cp_val) ? VI_DEFAULT : VIM_DEFAULT];
|
||||||
|
else if (nextchar == '<')
|
||||||
|
{
|
||||||
|
// For 'undolevels' NO_LOCAL_UNDOLEVEL means to
|
||||||
|
// use the global value.
|
||||||
|
if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL)
|
||||||
|
value = NO_LOCAL_UNDOLEVEL;
|
||||||
|
else
|
||||||
|
value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
|
||||||
|
}
|
||||||
|
else if (((long *)varp == &p_wc || (long *)varp == &p_wcm)
|
||||||
|
&& (*arg == '<'
|
||||||
|
|| *arg == '^'
|
||||||
|
|| (*arg != NUL
|
||||||
|
&& (!arg[1] || VIM_ISWHITE(arg[1]))
|
||||||
|
&& !VIM_ISDIGIT(*arg))))
|
||||||
|
{
|
||||||
|
value = string_to_key(arg, FALSE);
|
||||||
|
if (value == 0 && (long *)varp != &p_wcm)
|
||||||
|
{
|
||||||
|
errmsg = e_invalid_argument;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*arg == '-' || VIM_ISDIGIT(*arg))
|
||||||
|
{
|
||||||
|
// Allow negative (for 'undolevels'), octal and hex numbers.
|
||||||
|
vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, TRUE);
|
||||||
|
if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
|
||||||
|
{
|
||||||
|
errmsg = e_number_required_after_equal;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errmsg = e_number_required_after_equal;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == OP_ADDING)
|
||||||
|
value = *(long *)varp + value;
|
||||||
|
else if (op == OP_PREPENDING)
|
||||||
|
value = *(long *)varp * value;
|
||||||
|
else if (op == OP_REMOVING)
|
||||||
|
value = *(long *)varp - value;
|
||||||
|
|
||||||
|
errmsg = set_num_option(opt_idx, varp, value, errbuf, errbuflen,
|
||||||
|
opt_flags);
|
||||||
|
|
||||||
|
skip:
|
||||||
|
*argp = arg;
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a key code (t_xx) option
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
do_set_option_keycode(char_u **argp, char_u *key_name, int nextchar)
|
||||||
|
{
|
||||||
|
char_u *arg = *argp;
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
if (nextchar == '&')
|
||||||
|
{
|
||||||
|
if (add_termcap_entry(key_name, TRUE) == FAIL)
|
||||||
|
return e_not_found_in_termcap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++arg; // jump to after the '=' or ':'
|
||||||
|
for (p = arg; *p && !VIM_ISWHITE(*p); ++p)
|
||||||
|
if (*p == '\\' && p[1] != NUL)
|
||||||
|
++p;
|
||||||
|
nextchar = *p;
|
||||||
|
*p = NUL;
|
||||||
|
add_termcode(key_name, arg, FALSE);
|
||||||
|
*p = nextchar;
|
||||||
|
}
|
||||||
|
if (full_screen)
|
||||||
|
ttest(FALSE);
|
||||||
|
redraw_all_later(UPD_CLEAR);
|
||||||
|
|
||||||
|
*argp = arg;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set an option to a new value.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
do_set_option_value(
|
||||||
|
int opt_idx,
|
||||||
|
int opt_flags,
|
||||||
|
char_u **argp,
|
||||||
|
set_prefix_T prefix,
|
||||||
|
set_op_T op,
|
||||||
|
long_u flags,
|
||||||
|
char_u *varp,
|
||||||
|
char_u *key_name,
|
||||||
|
int nextchar,
|
||||||
|
int afterchar,
|
||||||
|
int cp_val,
|
||||||
|
int *stopopteval,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbuflen)
|
||||||
|
{
|
||||||
|
int value_checked = FALSE;
|
||||||
|
char *errmsg = NULL;
|
||||||
|
char_u *arg = *argp;
|
||||||
|
|
||||||
|
if (flags & P_BOOL)
|
||||||
|
{
|
||||||
|
// boolean option
|
||||||
|
errmsg = do_set_option_bool(opt_idx, opt_flags, prefix, flags, varp,
|
||||||
|
nextchar, afterchar, cp_val);
|
||||||
|
if (errmsg != NULL)
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// numeric or string option
|
||||||
|
if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
|
||||||
|
|| prefix != PREFIX_NONE)
|
||||||
|
{
|
||||||
|
errmsg = e_invalid_argument;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & P_NUM)
|
||||||
|
{
|
||||||
|
// numeric option
|
||||||
|
errmsg = do_set_option_numeric(opt_idx, opt_flags, &arg, nextchar,
|
||||||
|
op, flags, cp_val, varp,
|
||||||
|
errbuf, errbuflen);
|
||||||
|
if (errmsg != NULL)
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
else if (opt_idx >= 0)
|
||||||
|
{
|
||||||
|
// string option
|
||||||
|
if (do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags,
|
||||||
|
cp_val, varp, errbuf, &value_checked,
|
||||||
|
&errmsg) == FAIL)
|
||||||
|
{
|
||||||
|
if (errmsg != NULL)
|
||||||
|
goto skip;
|
||||||
|
*stopopteval = TRUE;
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// key code option
|
||||||
|
errmsg = do_set_option_keycode(&arg, key_name, nextchar);
|
||||||
|
if (errmsg != NULL)
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_idx >= 0)
|
||||||
|
did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
|
||||||
|
|
||||||
|
skip:
|
||||||
|
*argp = arg;
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set an option to a new value.
|
* Set an option to a new value.
|
||||||
* Return NULL if OK, return an untranslated error message when something is
|
* Return NULL if OK, return an untranslated error message when something is
|
||||||
@@ -1652,78 +2087,27 @@ do_set_option(
|
|||||||
char *errbuf,
|
char *errbuf,
|
||||||
size_t errbuflen)
|
size_t errbuflen)
|
||||||
{
|
{
|
||||||
char *errmsg = NULL;
|
|
||||||
int prefix; // 1: nothing, 0: "no", 2: "inv" in front of name
|
|
||||||
int nextchar; // next non-white char after option name
|
|
||||||
int afterchar; // character just after option name
|
|
||||||
char_u *arg = *argp;
|
|
||||||
int key;
|
|
||||||
int opt_idx;
|
int opt_idx;
|
||||||
int len;
|
char_u *arg;
|
||||||
set_op_T op = 0;
|
set_prefix_T prefix; // no prefix, "no" prefix or "inv" prefix
|
||||||
long_u flags; // flags for current option
|
set_op_T op;
|
||||||
char_u *varp = NULL; // pointer to variable for current option
|
long_u flags; // flags for current option
|
||||||
|
char_u *varp; // pointer to variable for current option
|
||||||
char_u key_name[2];
|
char_u key_name[2];
|
||||||
int cp_val = 0;
|
int nextchar; // next non-white char after option name
|
||||||
varnumber_T value;
|
int afterchar; // character just after option name
|
||||||
int i;
|
int cp_val;
|
||||||
|
char *errmsg = NULL;
|
||||||
|
int key;
|
||||||
|
int len;
|
||||||
|
|
||||||
prefix = 1;
|
prefix = get_option_prefix(argp);
|
||||||
if (STRNCMP(arg, "no", 2) == 0 && STRNCMP(arg, "novice", 6) != 0)
|
arg = *argp;
|
||||||
{
|
|
||||||
prefix = 0;
|
|
||||||
arg += 2;
|
|
||||||
}
|
|
||||||
else if (STRNCMP(arg, "inv", 3) == 0)
|
|
||||||
{
|
|
||||||
prefix = 2;
|
|
||||||
arg += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find end of name
|
// find end of name
|
||||||
key = 0;
|
key = 0;
|
||||||
if (*arg == '<')
|
if (parse_option_name(arg, &opt_idx, &len, &key) == FAIL)
|
||||||
{
|
return e_invalid_argument;
|
||||||
opt_idx = -1;
|
|
||||||
// look out for <t_>;>
|
|
||||||
if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
|
|
||||||
len = 5;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len = 1;
|
|
||||||
while (arg[len] != NUL && arg[len] != '>')
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
if (arg[len] != '>')
|
|
||||||
{
|
|
||||||
errmsg = e_invalid_argument;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
arg[len] = NUL; // put NUL after name
|
|
||||||
if (arg[1] == 't' && arg[2] == '_') // could be term code
|
|
||||||
opt_idx = findoption(arg + 1);
|
|
||||||
arg[len++] = '>'; // restore '>'
|
|
||||||
if (opt_idx == -1)
|
|
||||||
key = find_key_option(arg + 1, TRUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len = 0;
|
|
||||||
/*
|
|
||||||
* The two characters after "t_" may not be alphanumeric.
|
|
||||||
*/
|
|
||||||
if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
|
|
||||||
len = 4;
|
|
||||||
else
|
|
||||||
while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
|
|
||||||
++len;
|
|
||||||
nextchar = arg[len];
|
|
||||||
arg[len] = NUL; // put NUL after name
|
|
||||||
opt_idx = findoption(arg);
|
|
||||||
arg[len] = nextchar; // restore nextchar
|
|
||||||
if (opt_idx == -1)
|
|
||||||
key = find_key_option(arg, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember character after option name
|
// remember character after option name
|
||||||
afterchar = arg[len];
|
afterchar = arg[len];
|
||||||
@@ -1748,25 +2132,10 @@ do_set_option(
|
|||||||
while (VIM_ISWHITE(arg[len]))
|
while (VIM_ISWHITE(arg[len]))
|
||||||
++len;
|
++len;
|
||||||
|
|
||||||
op = OP_NONE;
|
op = get_opt_op(arg + len);
|
||||||
if (arg[len] != NUL && arg[len + 1] == '=')
|
if (op != OP_NONE)
|
||||||
{
|
len++;
|
||||||
if (arg[len] == '+')
|
|
||||||
{
|
|
||||||
op = OP_ADDING; // "+="
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
else if (arg[len] == '^')
|
|
||||||
{
|
|
||||||
op = OP_PREPENDING; // "^="
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
else if (arg[len] == '-')
|
|
||||||
{
|
|
||||||
op = OP_REMOVING; // "-="
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextchar = arg[len];
|
nextchar = arg[len];
|
||||||
|
|
||||||
if (opt_idx == -1 && key == 0) // found a mismatch: skip
|
if (opt_idx == -1 && key == 0) // found a mismatch: skip
|
||||||
@@ -1810,54 +2179,10 @@ do_set_option(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip all options that are not window-local (used when showing
|
// Make sure the option value can be changed.
|
||||||
// an already loaded buffer in a window).
|
if (validate_opt_idx(opt_idx, opt_flags, flags, &errmsg) == FAIL)
|
||||||
if ((opt_flags & OPT_WINONLY)
|
|
||||||
&& (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
|
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
// Skip all options that are window-local (used for :vimgrep).
|
|
||||||
if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
|
|
||||||
&& options[opt_idx].var == VAR_WIN)
|
|
||||||
goto skip;
|
|
||||||
|
|
||||||
// Disallow changing some options from modelines.
|
|
||||||
if (opt_flags & OPT_MODELINE)
|
|
||||||
{
|
|
||||||
if (flags & (P_SECURE | P_NO_ML))
|
|
||||||
{
|
|
||||||
errmsg = e_not_allowed_in_modeline;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
if ((flags & P_MLE) && !p_mle)
|
|
||||||
{
|
|
||||||
errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
#ifdef FEAT_DIFF
|
|
||||||
// In diff mode some options are overruled. This avoids that
|
|
||||||
// 'foldmethod' becomes "marker" instead of "diff" and that
|
|
||||||
// "wrap" gets set.
|
|
||||||
if (curwin->w_p_diff
|
|
||||||
&& opt_idx >= 0 // shut up coverity warning
|
|
||||||
&& (
|
|
||||||
#ifdef FEAT_FOLDING
|
|
||||||
options[opt_idx].indir == PV_FDM ||
|
|
||||||
#endif
|
|
||||||
options[opt_idx].indir == PV_WRAP))
|
|
||||||
goto skip;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SANDBOX
|
|
||||||
// Disallow changing some options in the sandbox
|
|
||||||
if (sandbox != 0 && (flags & P_SECURE))
|
|
||||||
{
|
|
||||||
errmsg = e_not_allowed_in_sandbox;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
|
if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
|
||||||
{
|
{
|
||||||
arg += len;
|
arg += len;
|
||||||
@@ -1888,7 +2213,7 @@ do_set_option(
|
|||||||
* allows only one '=' character per "set" command line. grrr. (jw)
|
* allows only one '=' character per "set" command line. grrr. (jw)
|
||||||
*/
|
*/
|
||||||
if (nextchar == '?'
|
if (nextchar == '?'
|
||||||
|| (prefix == 1
|
|| (prefix == PREFIX_NONE
|
||||||
&& vim_strchr((char_u *)"=:&<", nextchar) == NULL
|
&& vim_strchr((char_u *)"=:&<", nextchar) == NULL
|
||||||
&& !(flags & P_BOOL)))
|
&& !(flags & P_BOOL)))
|
||||||
{
|
{
|
||||||
@@ -1939,177 +2264,10 @@ do_set_option(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int value_checked = FALSE;
|
errmsg = do_set_option_value(opt_idx, opt_flags, &arg, prefix, op,
|
||||||
|
flags, varp, key_name, nextchar,
|
||||||
if (flags & P_BOOL) // boolean
|
afterchar, cp_val, stopopteval, errbuf,
|
||||||
{
|
errbuflen);
|
||||||
if (nextchar == '=' || nextchar == ':')
|
|
||||||
{
|
|
||||||
errmsg = e_invalid_argument;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ":set opt!": invert
|
|
||||||
* ":set opt&": reset to default value
|
|
||||||
* ":set opt<": reset to global value
|
|
||||||
*/
|
|
||||||
if (nextchar == '!')
|
|
||||||
value = *(int *)(varp) ^ 1;
|
|
||||||
else if (nextchar == '&')
|
|
||||||
value = (int)(long)(long_i)options[opt_idx].def_val[
|
|
||||||
((flags & P_VI_DEF) || cp_val)
|
|
||||||
? VI_DEFAULT : VIM_DEFAULT];
|
|
||||||
else if (nextchar == '<')
|
|
||||||
{
|
|
||||||
// For 'autoread' -1 means to use global value.
|
|
||||||
if ((int *)varp == &curbuf->b_p_ar
|
|
||||||
&& opt_flags == OPT_LOCAL)
|
|
||||||
value = -1;
|
|
||||||
else
|
|
||||||
value = *(int *)get_varp_scope(&(options[opt_idx]),
|
|
||||||
OPT_GLOBAL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* ":set invopt": invert
|
|
||||||
* ":set opt" or ":set noopt": set or reset
|
|
||||||
*/
|
|
||||||
if (nextchar != NUL && !VIM_ISWHITE(afterchar))
|
|
||||||
{
|
|
||||||
errmsg = e_trailing_characters;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
if (prefix == 2) // inv
|
|
||||||
value = *(int *)(varp) ^ 1;
|
|
||||||
else
|
|
||||||
value = prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
errmsg = set_bool_option(opt_idx, varp, (int)value,
|
|
||||||
opt_flags);
|
|
||||||
}
|
|
||||||
else // numeric or string
|
|
||||||
{
|
|
||||||
if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
|
|
||||||
|| prefix != 1)
|
|
||||||
{
|
|
||||||
errmsg = e_invalid_argument;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & P_NUM) // numeric
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Different ways to set a number option:
|
|
||||||
* & set to default value
|
|
||||||
* < set to global value
|
|
||||||
* <xx> accept special key codes for 'wildchar'
|
|
||||||
* c accept any non-digit for 'wildchar'
|
|
||||||
* [-]0-9 set number
|
|
||||||
* other error
|
|
||||||
*/
|
|
||||||
++arg;
|
|
||||||
if (nextchar == '&')
|
|
||||||
value = (long)(long_i)options[opt_idx].def_val[
|
|
||||||
((flags & P_VI_DEF) || cp_val)
|
|
||||||
? VI_DEFAULT : VIM_DEFAULT];
|
|
||||||
else if (nextchar == '<')
|
|
||||||
{
|
|
||||||
// For 'undolevels' NO_LOCAL_UNDOLEVEL means to
|
|
||||||
// use the global value.
|
|
||||||
if ((long *)varp == &curbuf->b_p_ul
|
|
||||||
&& opt_flags == OPT_LOCAL)
|
|
||||||
value = NO_LOCAL_UNDOLEVEL;
|
|
||||||
else
|
|
||||||
value = *(long *)get_varp_scope(
|
|
||||||
&(options[opt_idx]), OPT_GLOBAL);
|
|
||||||
}
|
|
||||||
else if (((long *)varp == &p_wc
|
|
||||||
|| (long *)varp == &p_wcm)
|
|
||||||
&& (*arg == '<'
|
|
||||||
|| *arg == '^'
|
|
||||||
|| (*arg != NUL
|
|
||||||
&& (!arg[1] || VIM_ISWHITE(arg[1]))
|
|
||||||
&& !VIM_ISDIGIT(*arg))))
|
|
||||||
{
|
|
||||||
value = string_to_key(arg, FALSE);
|
|
||||||
if (value == 0 && (long *)varp != &p_wcm)
|
|
||||||
{
|
|
||||||
errmsg = e_invalid_argument;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*arg == '-' || VIM_ISDIGIT(*arg))
|
|
||||||
{
|
|
||||||
// Allow negative (for 'undolevels'), octal and
|
|
||||||
// hex numbers.
|
|
||||||
vim_str2nr(arg, NULL, &i, STR2NR_ALL,
|
|
||||||
&value, NULL, 0, TRUE);
|
|
||||||
if (i == 0 || (arg[i] != NUL
|
|
||||||
&& !VIM_ISWHITE(arg[i])))
|
|
||||||
{
|
|
||||||
errmsg = e_number_required_after_equal;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
errmsg = e_number_required_after_equal;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op == OP_ADDING)
|
|
||||||
value = *(long *)varp + value;
|
|
||||||
else if (op == OP_PREPENDING)
|
|
||||||
value = *(long *)varp * value;
|
|
||||||
else if (op == OP_REMOVING)
|
|
||||||
value = *(long *)varp - value;
|
|
||||||
errmsg = set_num_option(opt_idx, varp, value,
|
|
||||||
errbuf, errbuflen, opt_flags);
|
|
||||||
}
|
|
||||||
else if (opt_idx >= 0) // string
|
|
||||||
{
|
|
||||||
if (do_set_string(opt_idx, opt_flags, &arg, nextchar,
|
|
||||||
op, flags, cp_val, varp, errbuf,
|
|
||||||
&value_checked, &errmsg) == FAIL)
|
|
||||||
{
|
|
||||||
if (errmsg != NULL)
|
|
||||||
goto skip;
|
|
||||||
*stopopteval = TRUE;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // key code option
|
|
||||||
{
|
|
||||||
char_u *p;
|
|
||||||
|
|
||||||
if (nextchar == '&')
|
|
||||||
{
|
|
||||||
if (add_termcap_entry(key_name, TRUE) == FAIL)
|
|
||||||
errmsg = e_not_found_in_termcap;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++arg; // jump to after the '=' or ':'
|
|
||||||
for (p = arg; *p && !VIM_ISWHITE(*p); ++p)
|
|
||||||
if (*p == '\\' && p[1] != NUL)
|
|
||||||
++p;
|
|
||||||
nextchar = *p;
|
|
||||||
*p = NUL;
|
|
||||||
add_termcode(key_name, arg, FALSE);
|
|
||||||
*p = nextchar;
|
|
||||||
}
|
|
||||||
if (full_screen)
|
|
||||||
ttest(FALSE);
|
|
||||||
redraw_all_later(UPD_CLEAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_idx >= 0)
|
|
||||||
did_set_option(
|
|
||||||
opt_idx, opt_flags, op == OP_NONE, value_checked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1283,
|
||||||
/**/
|
/**/
|
||||||
1282,
|
1282,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user