mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 06:58:35 +00:00
refactor(option.c): factor out loop code from do_set()
This commit is contained in:
@@ -1164,64 +1164,21 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
|
|||||||
*argp = arg;
|
*argp = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse 'arg' for option settings.
|
static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf,
|
||||||
///
|
size_t errbuflen, char **errmsg)
|
||||||
/// 'arg' may be IObuff, but only when no errors can be present and option
|
|
||||||
/// does not need to be expanded with option_expand().
|
|
||||||
/// "opt_flags":
|
|
||||||
/// 0 for ":set"
|
|
||||||
/// OPT_GLOBAL for ":setglobal"
|
|
||||||
/// OPT_LOCAL for ":setlocal" and a modeline
|
|
||||||
/// OPT_MODELINE for a modeline
|
|
||||||
/// OPT_WINONLY to only set window-local options
|
|
||||||
/// OPT_NOWIN to skip setting window-local options
|
|
||||||
///
|
|
||||||
/// @param arg option string (may be written to!)
|
|
||||||
///
|
|
||||||
/// @return FAIL if an error is detected, OK otherwise
|
|
||||||
int do_set(char *arg, int opt_flags)
|
|
||||||
{
|
{
|
||||||
int did_show = false; // already showed one value
|
|
||||||
|
|
||||||
if (*arg == NUL) {
|
|
||||||
showoptions(0, opt_flags);
|
|
||||||
did_show = true;
|
|
||||||
goto theend;
|
|
||||||
}
|
|
||||||
|
|
||||||
char errbuf[80];
|
|
||||||
|
|
||||||
while (*arg != NUL) { // loop to process all options
|
|
||||||
char *errmsg = NULL;
|
|
||||||
char *startarg = arg; // remember for error message
|
|
||||||
|
|
||||||
if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3])
|
|
||||||
&& !(opt_flags & OPT_MODELINE)) {
|
|
||||||
// ":set all" show all options.
|
|
||||||
// ":set all&" set all options to their default value.
|
|
||||||
arg += 3;
|
|
||||||
if (*arg == '&') {
|
|
||||||
arg++;
|
|
||||||
// Only for :set command set global value of local options.
|
|
||||||
set_options_default(OPT_FREE | opt_flags);
|
|
||||||
didset_options();
|
|
||||||
didset_options2();
|
|
||||||
ui_refresh_options();
|
|
||||||
redraw_all_later(UPD_CLEAR);
|
|
||||||
} else {
|
|
||||||
showoptions(1, opt_flags);
|
|
||||||
did_show = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name
|
int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name
|
||||||
if (strncmp(arg, "no", 2) == 0) {
|
|
||||||
|
if (strncmp(*argp, "no", 2) == 0) {
|
||||||
prefix = 0;
|
prefix = 0;
|
||||||
arg += 2;
|
*argp += 2;
|
||||||
} else if (strncmp(arg, "inv", 3) == 0) {
|
} else if (strncmp(*argp, "inv", 3) == 0) {
|
||||||
prefix = 2;
|
prefix = 2;
|
||||||
arg += 3;
|
*argp += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *arg = *argp;
|
||||||
|
|
||||||
// find end of name
|
// find end of name
|
||||||
int key = 0;
|
int key = 0;
|
||||||
int len;
|
int len;
|
||||||
@@ -1238,8 +1195,8 @@ int do_set(char *arg, int opt_flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (arg[len] != '>') {
|
if (arg[len] != '>') {
|
||||||
errmsg = e_invarg;
|
*errmsg = e_invarg;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
if (arg[1] == 't' && arg[2] == '_') { // could be term code
|
if (arg[1] == 't' && arg[2] == '_') { // could be term code
|
||||||
opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
|
opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
|
||||||
@@ -1288,8 +1245,8 @@ int do_set(char *arg, int opt_flags)
|
|||||||
char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name
|
char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name
|
||||||
|
|
||||||
if (opt_idx == -1 && key == 0) { // found a mismatch: skip
|
if (opt_idx == -1 && key == 0) { // found a mismatch: skip
|
||||||
errmsg = e_unknown_option;
|
*errmsg = e_unknown_option;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags; // flags for current option
|
uint32_t flags; // flags for current option
|
||||||
@@ -1302,9 +1259,9 @@ int do_set(char *arg, int opt_flags)
|
|||||||
if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL
|
if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL
|
||||||
&& (!(options[opt_idx].flags & P_BOOL)
|
&& (!(options[opt_idx].flags & P_BOOL)
|
||||||
|| nextchar == '?')) {
|
|| nextchar == '?')) {
|
||||||
errmsg = e_unsupportedoption;
|
*errmsg = e_unsupportedoption;
|
||||||
}
|
}
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = options[opt_idx].flags;
|
flags = options[opt_idx].flags;
|
||||||
@@ -1317,24 +1274,24 @@ int do_set(char *arg, int opt_flags)
|
|||||||
// an already loaded buffer in a window).
|
// an already loaded buffer in a window).
|
||||||
if ((opt_flags & OPT_WINONLY)
|
if ((opt_flags & OPT_WINONLY)
|
||||||
&& (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
|
&& (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip all options that are window-local (used for :vimgrep).
|
// Skip all options that are window-local (used for :vimgrep).
|
||||||
if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
|
if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
|
||||||
&& options[opt_idx].var == VAR_WIN) {
|
&& options[opt_idx].var == VAR_WIN) {
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow changing some options from modelines.
|
// Disallow changing some options from modelines.
|
||||||
if (opt_flags & OPT_MODELINE) {
|
if (opt_flags & OPT_MODELINE) {
|
||||||
if (flags & (P_SECURE | P_NO_ML)) {
|
if (flags & (P_SECURE | P_NO_ML)) {
|
||||||
errmsg = e_not_allowed_in_modeline;
|
*errmsg = e_not_allowed_in_modeline;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
if ((flags & P_MLE) && !p_mle) {
|
if ((flags & P_MLE) && !p_mle) {
|
||||||
errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
|
*errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
// In diff mode some options are overruled. This avoids that
|
// In diff mode some options are overruled. This avoids that
|
||||||
// 'foldmethod' becomes "marker" instead of "diff" and that
|
// 'foldmethod' becomes "marker" instead of "diff" and that
|
||||||
@@ -1343,29 +1300,29 @@ int do_set(char *arg, int opt_flags)
|
|||||||
&& opt_idx >= 0 // shut up coverity warning
|
&& opt_idx >= 0 // shut up coverity warning
|
||||||
&& (options[opt_idx].indir == PV_FDM
|
&& (options[opt_idx].indir == PV_FDM
|
||||||
|| options[opt_idx].indir == PV_WRAP)) {
|
|| options[opt_idx].indir == PV_WRAP)) {
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow changing some options in the sandbox
|
// Disallow changing some options in the sandbox
|
||||||
if (sandbox != 0 && (flags & P_SECURE)) {
|
if (sandbox != 0 && (flags & P_SECURE)) {
|
||||||
errmsg = e_sandbox;
|
*errmsg = e_sandbox;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) {
|
if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) {
|
||||||
arg += len;
|
*argp += len;
|
||||||
if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') {
|
if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') {
|
||||||
if (arg[3] == 'm') { // "opt&vim": set to Vim default
|
if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default
|
||||||
arg += 3;
|
*argp += 3;
|
||||||
} else { // "opt&vi": set to Vi default
|
} else { // "opt&vi": set to Vi default
|
||||||
arg += 2;
|
*argp += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL
|
if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL
|
||||||
&& arg[1] != NUL && !ascii_iswhite(arg[1])) {
|
&& (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) {
|
||||||
errmsg = e_trailing;
|
*errmsg = e_trailing;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1378,11 +1335,11 @@ int do_set(char *arg, int opt_flags)
|
|||||||
&& vim_strchr("=:&<", (uint8_t)nextchar) == NULL
|
&& vim_strchr("=:&<", (uint8_t)nextchar) == NULL
|
||||||
&& !(flags & P_BOOL))) {
|
&& !(flags & P_BOOL))) {
|
||||||
// print value
|
// print value
|
||||||
if (did_show) {
|
if (*did_show) {
|
||||||
msg_putchar('\n'); // cursor below last one
|
msg_putchar('\n'); // cursor below last one
|
||||||
} else {
|
} else {
|
||||||
gotocmdline(true); // cursor at status line
|
gotocmdline(true); // cursor at status line
|
||||||
did_show = true; // remember that we did a line
|
*did_show = true; // remember that we did a line
|
||||||
}
|
}
|
||||||
if (opt_idx >= 0) {
|
if (opt_idx >= 0) {
|
||||||
showoneopt(&options[opt_idx], opt_flags);
|
showoneopt(&options[opt_idx], opt_flags);
|
||||||
@@ -1391,54 +1348,101 @@ int do_set(char *arg, int opt_flags)
|
|||||||
if (varp == (char *)options[opt_idx].var) {
|
if (varp == (char *)options[opt_idx].var) {
|
||||||
option_last_set_msg(options[opt_idx].last_set);
|
option_last_set_msg(options[opt_idx].last_set);
|
||||||
} else if ((int)options[opt_idx].indir & PV_WIN) {
|
} else if ((int)options[opt_idx].indir & PV_WIN) {
|
||||||
option_last_set_msg(curwin->w_p_script_ctx[
|
option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
|
||||||
(int)options[opt_idx].indir & PV_MASK]);
|
|
||||||
} else if ((int)options[opt_idx].indir & PV_BUF) {
|
} else if ((int)options[opt_idx].indir & PV_BUF) {
|
||||||
option_last_set_msg(curbuf->b_p_script_ctx[
|
option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
|
||||||
(int)options[opt_idx].indir & PV_MASK]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errmsg = e_key_code_not_set;
|
*errmsg = e_key_code_not_set;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
if (nextchar != '?'
|
if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) {
|
||||||
&& nextchar != NUL && !ascii_iswhite(afterchar)) {
|
*errmsg = e_trailing;
|
||||||
errmsg = e_trailing;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int value_checked = false;
|
int value_checked = false;
|
||||||
if (flags & P_BOOL) { // boolean
|
if (flags & P_BOOL) { // boolean
|
||||||
do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg);
|
do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg);
|
||||||
} else { // Numeric or string.
|
} else { // Numeric or string.
|
||||||
if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL
|
if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL
|
||||||
|| prefix != 1) {
|
|| prefix != 1) {
|
||||||
errmsg = e_invarg;
|
*errmsg = e_invarg;
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & P_NUM) { // numeric
|
if (flags & P_NUM) { // numeric
|
||||||
do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf),
|
do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg);
|
||||||
&errmsg);
|
|
||||||
} else if (opt_idx >= 0) { // String.
|
} else if (opt_idx >= 0) { // String.
|
||||||
do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf,
|
do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf,
|
||||||
sizeof(errbuf), &value_checked, &errmsg);
|
errbuflen, &value_checked, errmsg);
|
||||||
} else {
|
} else {
|
||||||
// key code option(FIXME(tarruda): Show a warning or something
|
// key code option(FIXME(tarruda): Show a warning or something
|
||||||
// similar)
|
// similar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errmsg != NULL) {
|
if (*errmsg != NULL) {
|
||||||
goto skip;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_idx >= 0) {
|
if (opt_idx >= 0) {
|
||||||
did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
|
did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse 'arg' for option settings.
|
||||||
|
///
|
||||||
|
/// 'arg' may be IObuff, but only when no errors can be present and option
|
||||||
|
/// does not need to be expanded with option_expand().
|
||||||
|
/// "opt_flags":
|
||||||
|
/// 0 for ":set"
|
||||||
|
/// OPT_GLOBAL for ":setglobal"
|
||||||
|
/// OPT_LOCAL for ":setlocal" and a modeline
|
||||||
|
/// OPT_MODELINE for a modeline
|
||||||
|
/// OPT_WINONLY to only set window-local options
|
||||||
|
/// OPT_NOWIN to skip setting window-local options
|
||||||
|
///
|
||||||
|
/// @param arg option string (may be written to!)
|
||||||
|
///
|
||||||
|
/// @return FAIL if an error is detected, OK otherwise
|
||||||
|
int do_set(char *arg, int opt_flags)
|
||||||
|
{
|
||||||
|
bool did_show = false; // already showed one value
|
||||||
|
|
||||||
|
if (*arg == NUL) {
|
||||||
|
showoptions(0, opt_flags);
|
||||||
|
did_show = true;
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
|
||||||
|
char errbuf[80];
|
||||||
|
|
||||||
|
while (*arg != NUL) { // loop to process all options
|
||||||
|
char *errmsg = NULL;
|
||||||
|
char *startarg = arg; // remember for error message
|
||||||
|
|
||||||
|
if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3])
|
||||||
|
&& !(opt_flags & OPT_MODELINE)) {
|
||||||
|
// ":set all" show all options.
|
||||||
|
// ":set all&" set all options to their default value.
|
||||||
|
arg += 3;
|
||||||
|
if (*arg == '&') {
|
||||||
|
arg++;
|
||||||
|
// Only for :set command set global value of local options.
|
||||||
|
set_options_default(OPT_FREE | opt_flags);
|
||||||
|
didset_options();
|
||||||
|
didset_options2();
|
||||||
|
ui_refresh_options();
|
||||||
|
redraw_all_later(UPD_CLEAR);
|
||||||
|
} else {
|
||||||
|
showoptions(1, opt_flags);
|
||||||
|
did_show = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
|
||||||
|
|
||||||
skip:
|
|
||||||
// Advance to next argument.
|
// Advance to next argument.
|
||||||
// - skip until a blank found, taking care of backslashes
|
// - skip until a blank found, taking care of backslashes
|
||||||
// - skip blanks
|
// - skip blanks
|
||||||
|
Reference in New Issue
Block a user