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 #7583)
diff --git a/src/evalvars.c b/src/evalvars.c
index f7982f7..f9b3c48 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1354,7 +1354,7 @@
else
{
long n = 0;
- int opt_type;
+ getoption_T opt_type;
long numval;
char_u *stringval = NULL;
char_u *s = NULL;
@@ -1364,7 +1364,10 @@
*p = NUL;
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)
&& (tv->v_type != VAR_STRING || !in_vim9script()))
// number, possibly hidden
n = (long)tv_get_number(tv);
@@ -1377,8 +1380,9 @@
if (op != NULL && *op != '=')
{
- if ((opt_type == 1 && *op == '.')
- || (opt_type == 0 && *op != '.'))
+ if (((opt_type == gov_bool || opt_type == gov_number)
+ && *op == '.')
+ || (opt_type == gov_string && *op != '.'))
{
semsg(_(e_letwrong), op);
failed = TRUE; // don't set the value
@@ -1386,7 +1390,9 @@
}
else
{
- if (opt_type == 1) // number
+ // number, in legacy script also bool
+ if (opt_type == gov_number
+ || (opt_type == gov_bool && !in_vim9script()))
{
switch (*op)
{
@@ -1397,7 +1403,8 @@
case '%': n = (long)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
s = concat_str(stringval, s);
@@ -1409,7 +1416,7 @@
if (!failed)
{
- if (opt_type != 0 || s != NULL)
+ if (opt_type != gov_string || s != NULL)
{
set_option_value(arg, n, s, opt_flags);
arg_end = p;
diff --git a/src/if_mzsch.c b/src/if_mzsch.c
index 7b52936..58b1692 100644
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -1712,7 +1712,7 @@
Vim_Prim *prim = (Vim_Prim *)data;
long value;
char *strval;
- int rc;
+ getoption_T rc;
Scheme_Object *rval = NULL;
Scheme_Object *name = NULL;
int opt_flags = 0;
@@ -1754,27 +1754,30 @@
scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv);
}
- rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval, opt_flags);
+ rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval,
+ opt_flags);
curbuf = save_curb;
curwin = save_curw;
switch (rc)
{
- case 1:
+ case gov_bool:
+ case gov_number:
MZ_GC_UNREG();
return scheme_make_integer_value(value);
- case 0:
+ case gov_string:
rval = scheme_make_byte_string(strval);
MZ_GC_CHECK();
vim_free(strval);
MZ_GC_UNREG();
return rval;
- case -1:
- case -2:
+ case gov_hidden_bool:
+ case gov_hidden_number:
+ case gov_hidden_string:
MZ_GC_UNREG();
raise_vim_exn(_("hidden option"));
//NOTREACHED
- case -3:
+ case gov_unknown:
MZ_GC_UNREG();
raise_vim_exn(_("unknown option"));
//NOTREACHED
diff --git a/src/if_ruby.c b/src/if_ruby.c
index 3751025..9e58902 100644
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -865,13 +865,11 @@
vim_str2rb_enc_str(const char *s)
{
#if RUBY_VERSION >= 19
- int isnum;
long lval;
char_u *sval;
rb_encoding *enc;
- isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
- if (isnum == 0)
+ if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
{
enc = rb_enc_find((char *)sval);
vim_free(sval);
@@ -886,14 +884,12 @@
eval_enc_string_protect(const char *str, int *state)
{
#if RUBY_VERSION >= 19
- int isnum;
long lval;
char_u *sval;
rb_encoding *enc;
VALUE v;
- isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
- if (isnum == 0)
+ if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
{
enc = rb_enc_find((char *)sval);
vim_free(sval);
diff --git a/src/option.c b/src/option.c
index dd09e0e..ca6fadb 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3834,13 +3834,15 @@
* Get the value for an option.
*
* Returns:
- * Number or Toggle option: 1, *numval gets value.
- * String option: 0, *stringval gets allocated string.
- * Hidden Number or Toggle option: -1.
- * hidden String option: -2.
- * unknown option: -3.
+ * Number option: gov_number, *numval gets value.
+ * Tottle option: gov_bool, *numval gets value.
+ * String option: gov_string, *stringval gets allocated string.
+ * Hidden Number option: gov_hidden_number.
+ * Hidden Toggle option: gov_hidden_bool.
+ * Hidden String option: gov_hidden_string.
+ * Unknown option: gov_unknown.
*/
- int
+ getoption_T
get_option_value(
char_u *name,
long *numval,
@@ -3851,16 +3853,17 @@
char_u *varp;
opt_idx = findoption(name);
- if (opt_idx < 0) // unknown option
+ if (opt_idx < 0) // option not in the table
{
int key;
if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
- && (key = find_key_option(name, FALSE)) != 0)
+ && (key = find_key_option(name, FALSE)) != 0)
{
char_u key_name[2];
char_u *p;
+ // check for a terminal option
if (key < 0)
{
key_name[0] = KEY2TERMCAP0(key);
@@ -3876,10 +3879,10 @@
{
if (stringval != NULL)
*stringval = vim_strsave(p);
- return 0;
+ return gov_string;
}
}
- return -3;
+ return gov_unknown;
}
varp = get_varp_scope(&(options[opt_idx]), opt_flags);
@@ -3887,7 +3890,7 @@
if (options[opt_idx].flags & P_STRING)
{
if (varp == NULL) // hidden option
- return -2;
+ return gov_hidden_string;
if (stringval != NULL)
{
#ifdef FEAT_CRYPT
@@ -3899,11 +3902,12 @@
#endif
*stringval = vim_strsave(*(char_u **)(varp));
}
- return 0;
+ return gov_string;
}
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)
*numval = *(long *)varp;
else
@@ -3915,7 +3919,7 @@
else
*numval = (long) *(int *)varp;
}
- return 1;
+ return (options[opt_idx].flags & P_NUM) ? gov_number : gov_bool;
}
#endif
diff --git a/src/option.h b/src/option.h
index 421ee7a..4bc189c 100644
--- a/src/option.h
+++ b/src/option.h
@@ -60,6 +60,17 @@
#define P_RWINONLY 0x10000000L // only redraw current window
#define P_MLE 0x20000000L // under control of 'modelineexpr'
+// 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;
+
/*
* Default values for 'errorformat'.
* The "%f|%l| %m" one is used for when the contents of the quickfix window is
diff --git a/src/proto/option.pro b/src/proto/option.pro
index 1c7c3b2..8d672aa 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -24,7 +24,7 @@
void set_term_option_sctx_idx(char *name, int opt_idx);
void check_redraw(long_u flags);
int findoption(char_u *arg);
-int get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags);
+getoption_T get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags);
int get_option_value_strict(char_u *name, long *numval, char_u **stringval, int opt_type, void *from);
char_u *option_iter_next(void **option, int opt_type);
long_u get_option_flags(int opt_idx);
diff --git a/src/spell.c b/src/spell.c
index b474a38..d430566 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -3813,7 +3813,7 @@
if (no_spell_checking(curwin))
return;
- get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
+ (void)get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd((char_u *)"new");
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index ea344fe..3e14b58 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -45,6 +45,9 @@
assert_equal(true, flag)
flag = 1 && false
assert_equal(false, flag)
+
+ var cp: bool = &cp
+ var fen: bool = &l:fen
END
CheckScriptSuccess(lines)
CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
@@ -118,6 +121,8 @@
assert_equal('new', s:newVar)
set ts=7
+ var ts: number = &ts
+ assert_equal(7, ts)
&ts += 1
assert_equal(8, &ts)
&ts -= 3
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index ed0c7dd..2017846 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -590,7 +590,7 @@
unlet g:readFile
noswapfile edit XnoSwap
- assert_equal(0, &l:swapfile)
+ assert_equal(false, &l:swapfile)
bwipe!
var caught = false
diff --git a/src/typval.c b/src/typval.c
index df3bc92..421e62a 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -1083,7 +1083,7 @@
char_u *option_end;
long numval;
char_u *stringval;
- int opt_type;
+ getoption_T opt_type;
int c;
int working = (**arg == '+'); // has("+option")
int ret = OK;
@@ -1109,7 +1109,7 @@
opt_type = get_option_value(*arg, &numval,
rettv == NULL ? NULL : &stringval, opt_flags);
- if (opt_type == -3) // invalid name
+ if (opt_type == gov_unknown)
{
if (rettv != NULL)
semsg(_(e_unknown_option), *arg);
@@ -1117,20 +1117,29 @@
}
else if (rettv != NULL)
{
- if (opt_type == -2) // hidden string option
+ if (opt_type == gov_hidden_string)
{
rettv->v_type = VAR_STRING;
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 = in_vim9script() && opt_type == gov_hidden_bool
+ ? VAR_BOOL : VAR_NUMBER;
rettv->vval.v_number = 0;
}
- else if (opt_type == 1) // number option
+ else if (opt_type == gov_bool || opt_type == gov_number)
{
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = numval;
+ if (in_vim9script() && opt_type == gov_bool)
+ {
+ rettv->v_type = VAR_BOOL;
+ rettv->vval.v_number = numval ? VVAL_TRUE : VVAL_FALSE;
+ }
+ else
+ {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = numval;
+ }
}
else // string option
{
@@ -1138,7 +1147,9 @@
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;
*option_end = c; // put back for error messages
diff --git a/src/version.c b/src/version.c
index a8e1a89..d23afb2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2254,
+/**/
2253,
/**/
2252,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 5602ff5..c2c3fc9 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5191,9 +5191,9 @@
if (*name == '&')
{
- int cc;
- long numval;
- int opt_type;
+ int cc;
+ long numval;
+ getoption_T opt_type;
*dest = dest_option;
if (cmdidx == CMD_final || cmdidx == CMD_const)
@@ -5214,15 +5214,24 @@
opt_type = get_option_value(skip_option_env_lead(name),
&numval, NULL, *opt_flags);
*p = cc;
- if (opt_type == -3)
+ switch (opt_type)
{
- semsg(_(e_unknown_option), name);
- return FAIL;
+ case gov_unknown:
+ semsg(_(e_unknown_option), name);
+ return FAIL;
+ case gov_string:
+ case gov_hidden_string:
+ *type = &t_string;
+ break;
+ case gov_bool:
+ case gov_hidden_bool:
+ *type = &t_bool;
+ break;
+ case gov_number:
+ case gov_hidden_number:
+ *type = &t_number;
+ break;
}
- if (opt_type == -2 || opt_type == 0)
- *type = &t_string;
- else
- *type = &t_number; // both number and boolean option
}
else if (*name == '$')
{