vim-patch:8.2.2254: Vim9: bool option type is number

Problem:    Vim9: bool option type is number.
Solution:   Have get_option_value() return a different value for bool and
            number options. (closes vim/vim#7583)
dd1f426bd6
This commit is contained in:
zeertzjq
2022-07-25 17:37:06 +08:00
parent 3ea45a2caf
commit 2241fd3211
6 changed files with 63 additions and 47 deletions

View File

@@ -104,20 +104,20 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
long numval = 0; long numval = 0;
char *stringval = NULL; char *stringval = NULL;
int result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from, getoption_T result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type,
true, err); from, true, err);
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return rv; return rv;
} }
switch (result) { switch (result) {
case 0: case gov_string:
rv = STRING_OBJ(cstr_as_string(stringval)); rv = STRING_OBJ(cstr_as_string(stringval));
break; break;
case 1: case gov_number:
rv = INTEGER_OBJ(numval); rv = INTEGER_OBJ(numval);
break; break;
case 2: case gov_bool:
switch (numval) { switch (numval) {
case 0: case 0:
case 1: case 1:
@@ -483,8 +483,8 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
}); });
} }
static int access_option_value(char *key, long *numval, char **stringval, int opt_flags, bool get, static getoption_T access_option_value(char *key, long *numval, char **stringval, int opt_flags,
Error *err) bool get, Error *err)
{ {
if (get) { if (get) {
return get_option_value(key, numval, stringval, opt_flags); return get_option_value(key, numval, stringval, opt_flags);
@@ -501,13 +501,13 @@ static int access_option_value(char *key, long *numval, char **stringval, int op
} }
} }
static int access_option_value_for(char *key, long *numval, char **stringval, int opt_flags, static getoption_T access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
int opt_type, void *from, bool get, Error *err) int opt_type, void *from, bool get, Error *err)
{ {
bool need_switch = false; bool need_switch = false;
switchwin_T switchwin; switchwin_T switchwin;
aco_save_T aco; aco_save_T aco;
int result = 0; getoption_T result = 0;
try_start(); try_start();
switch (opt_type) { switch (opt_type) {

View File

@@ -3774,7 +3774,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
{ {
long numval; long numval;
char *stringval; char *stringval;
int opt_type; getoption_T opt_type;
bool working = (**arg == '+'); // has("+option") bool working = (**arg == '+'); // has("+option")
int ret = OK; int ret = OK;
int opt_flags; int opt_flags;
@@ -3798,26 +3798,28 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
opt_type = get_option_value(*arg, &numval, opt_type = get_option_value(*arg, &numval,
rettv == NULL ? NULL : &stringval, opt_flags); rettv == NULL ? NULL : &stringval, opt_flags);
if (opt_type == -3) { // invalid name if (opt_type == gov_unknown) {
if (rettv != NULL) { if (rettv != NULL) {
semsg(_("E113: Unknown option: %s"), *arg); semsg(_("E113: Unknown option: %s"), *arg);
} }
ret = FAIL; ret = FAIL;
} else if (rettv != NULL) { } else if (rettv != NULL) {
if (opt_type == -2) { // hidden string option if (opt_type == gov_hidden_string) {
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
} else if (opt_type == -1) { // hidden number option } else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number) {
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
} else if (opt_type == 1 || opt_type == 2) { // number or boolean option } else if (opt_type == gov_bool || opt_type == gov_number) {
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = numval; rettv->vval.v_number = numval;
} else { // string option } else { // string option
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = stringval; rettv->vval.v_string = stringval;
} }
} else if (working && (opt_type == -2 || opt_type == -1)) { } else if (working && (opt_type == gov_hidden_bool
|| opt_type == gov_hidden_number
|| opt_type == gov_hidden_string)) {
ret = FAIL; ret = FAIL;
} }

View File

@@ -620,7 +620,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
emsg(_(e_letunexp)); emsg(_(e_letunexp));
} else { } else {
varnumber_T n = 0; varnumber_T n = 0;
int opt_type; getoption_T opt_type;
long numval; long numval;
char *stringval = NULL; char *stringval = NULL;
const char *s = NULL; const char *s = NULL;
@@ -630,7 +630,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
*p = NUL; *p = NUL;
opt_type = get_option_value(arg, &numval, &stringval, opt_flags); opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
if (opt_type == 1 || opt_type == -1) { if (opt_type == gov_bool
|| opt_type == gov_number
|| opt_type == gov_hidden_bool
|| opt_type == gov_hidden_number) {
// number, possibly hidden // number, possibly hidden
n = (long)tv_get_number(tv); n = (long)tv_get_number(tv);
} }
@@ -641,12 +644,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
} }
if (op != NULL && *op != '=') { if (op != NULL && *op != '=') {
if ((opt_type == 1 && *op == '.') if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.')
|| (opt_type == 0 && *op != '.')) { || (opt_type == gov_string && *op != '.')) {
semsg(_(e_letwrong), op); semsg(_(e_letwrong), op);
failed = true; // don't set the value failed = true; // don't set the value
} else { } else {
if (opt_type == 1) { // number // number or bool
if (opt_type == gov_number || opt_type == gov_bool) {
switch (*op) { switch (*op) {
case '+': case '+':
n = numval + n; break; n = numval + n; break;
@@ -659,7 +663,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
case '%': case '%':
n = num_modulus(numval, n); break; n = num_modulus(numval, n); break;
} }
} else if (opt_type == 0 && stringval != NULL && s != NULL) { } else if (opt_type == gov_string && stringval != NULL && s != NULL) {
// string // string
char *const oldstringval = stringval; char *const oldstringval = stringval;
stringval = (char *)concat_str((const char_u *)stringval, stringval = (char *)concat_str((const char_u *)stringval,
@@ -671,7 +675,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
} }
if (!failed) { if (!failed) {
if (opt_type != 0 || s != NULL) { if (opt_type != gov_string || s != NULL) {
set_option_value(arg, n, s, opt_flags); set_option_value(arg, n, s, opt_flags);
arg_end = p; arg_end = p;
} else { } else {

View File

@@ -5046,28 +5046,29 @@ static int findoption(const char *const arg)
/// @param stringval NULL when only checking existence /// @param stringval NULL when only checking existence
/// ///
/// @returns: /// @returns:
/// Toggle option: 2, *numval gets value. /// Number option: gov_number, *numval gets value.
/// Number option: 1, *numval gets value. /// Tottle option: gov_bool, *numval gets value.
/// String option: 0, *stringval gets allocated string. /// String option: gov_string, *stringval gets allocated string.
/// Hidden Number or Toggle option: -1. /// Hidden Number option: gov_hidden_number.
/// hidden String option: -2. /// Hidden Toggle option: gov_hidden_bool.
/// unknown option: -3. /// Hidden String option: gov_hidden_string.
int get_option_value(const char *name, long *numval, char **stringval, int opt_flags) /// Unknown option: gov_unknown.
getoption_T get_option_value(const char *name, long *numval, char **stringval, int opt_flags)
{ {
if (get_tty_option(name, stringval)) { if (get_tty_option(name, stringval)) {
return 0; return gov_string;
} }
int opt_idx = findoption(name); int opt_idx = findoption(name);
if (opt_idx < 0) { // Unknown option. if (opt_idx < 0) { // option not in the table
return -3; return gov_unknown;
} }
char_u *varp = get_varp_scope(&(options[opt_idx]), opt_flags); char_u *varp = get_varp_scope(&(options[opt_idx]), opt_flags);
if (options[opt_idx].flags & P_STRING) { if (options[opt_idx].flags & P_STRING) {
if (varp == NULL) { // hidden option if (varp == NULL) { // hidden option
return -2; return gov_hidden_string;
} }
if (stringval != NULL) { if (stringval != NULL) {
if ((char_u **)varp == &p_pt) { // 'pastetoggle' if ((char_u **)varp == &p_pt) { // 'pastetoggle'
@@ -5076,26 +5077,24 @@ int get_option_value(const char *name, long *numval, char **stringval, int opt_f
*stringval = xstrdup(*(char **)(varp)); *stringval = xstrdup(*(char **)(varp));
} }
} }
return 0; return gov_string;
} }
if (varp == NULL) { // hidden option if (varp == NULL) { // hidden option
return -1; return (options[opt_idx].flags & P_NUM) ? gov_hidden_number : gov_hidden_bool;
} }
if (options[opt_idx].flags & P_NUM) { if (options[opt_idx].flags & P_NUM) {
*numval = *(long *)varp; *numval = *(long *)varp;
return 1; } else {
}
// Special case: 'modified' is b_changed, but we also want to consider // Special case: 'modified' is b_changed, but we also want to consider
// it set when 'ff' or 'fenc' changed. // it set when 'ff' or 'fenc' changed.
if ((int *)varp == &curbuf->b_changed) { if ((int *)varp == &curbuf->b_changed) {
*numval = curbufIsChanged(); *numval = curbufIsChanged();
} else { } else {
*numval = (long)*(int *)varp; // NOLINT(whitespace/cast) *numval = (long)(*(int *)varp);
} }
}
return 2; return (options[opt_idx].flags & P_NUM) ? gov_number : gov_bool;
} }
// Returns the option attributes and its value. Unlike the above function it // Returns the option attributes and its value. Unlike the above function it

View File

@@ -3,6 +3,17 @@
#include "nvim/ex_cmds_defs.h" // for exarg_T #include "nvim/ex_cmds_defs.h" // for exarg_T
/// Returned by get_option_value().
typedef enum {
gov_unknown,
gov_bool,
gov_number,
gov_string,
gov_hidden_bool,
gov_hidden_number,
gov_hidden_string,
} getoption_T;
// flags for buf_copy_options() // flags for buf_copy_options()
#define BCO_ENTER 1 // going to enter the buffer #define BCO_ENTER 1 // going to enter the buffer
#define BCO_ALWAYS 2 // always copy the options #define BCO_ALWAYS 2 // always copy the options

View File

@@ -6880,7 +6880,7 @@ void ex_spelldump(exarg_T *eap)
if (no_spell_checking(curwin)) { if (no_spell_checking(curwin)) {
return; return;
} }
get_option_value("spl", &dummy, &spl, OPT_LOCAL); (void)get_option_value("spl", &dummy, &spl, OPT_LOCAL);
// Create a new empty buffer in a new window. // Create a new empty buffer in a new window.
do_cmdline_cmd("new"); do_cmdline_cmd("new");