summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-08-08 15:43:34 +0200
committerBram Moolenaar <Bram@vim.org>2021-08-08 15:43:34 +0200
commit2950065e18649d234b16e60dd0e3d75adeca4513 (patch)
tree022aa2da8ed1f6588ac02d9be71a1d69df89c73b
parent267359902c8792fed13543ddeb56c6df0ae74957 (diff)
downloadvim-git-2950065e18649d234b16e60dd0e3d75adeca4513.tar.gz
patch 8.2.3315: cannot use single quote in a float number for readabilityv8.2.3315
Problem: Cannot use single quote in a float number for readability. Solution: Support single quotes like in numbers. (closes #8713)
-rw-r--r--src/float.c34
-rw-r--r--src/json.c5
-rw-r--r--src/proto/float.pro2
-rw-r--r--src/testdir/test_float_func.vim17
-rw-r--r--src/typval.c20
-rw-r--r--src/version.c2
-rw-r--r--src/viminfo.c2
7 files changed, 72 insertions, 10 deletions
diff --git a/src/float.c b/src/float.c
index 898095fd4..ee0ceda72 100644
--- a/src/float.c
+++ b/src/float.c
@@ -29,7 +29,8 @@
int
string2float(
char_u *text,
- float_T *value) // result stored here
+ float_T *value, // result stored here
+ int skip_quotes)
{
char *s = (char *)text;
float_T f;
@@ -50,6 +51,32 @@ string2float(
*value = NAN;
return 3;
}
+ if (skip_quotes && vim_strchr((char_u *)s, '\'') != NULL)
+ {
+ char_u buf[100];
+ char_u *p = buf;
+ int quotes = 0;
+
+ vim_strncpy(buf, (char_u *)s, 99);
+ p = buf;
+ for (;;)
+ {
+ // remove single quotes between digits, not in the exponent
+ if (*p == '\'')
+ {
+ ++quotes;
+ mch_memmove(p, p + 1, STRLEN(p));
+ }
+ if (!vim_isdigit(*p))
+ break;
+ p = skipdigits(p);
+ }
+ s = (char *)buf;
+ f = strtod(s, &s);
+ *value = f;
+ return (int)((char_u *)s - buf) + quotes;
+ }
+
f = strtod(s, &s);
*value = f;
return (int)((char_u *)s - text);
@@ -488,16 +515,19 @@ f_str2float(typval_T *argvars, typval_T *rettv)
{
char_u *p;
int isneg;
+ int skip_quotes;
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
return;
+ skip_quotes = argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]);
+
p = skipwhite(tv_get_string_strict(&argvars[0]));
isneg = (*p == '-');
if (*p == '+' || *p == '-')
p = skipwhite(p + 1);
- (void)string2float(p, &rettv->vval.v_float);
+ (void)string2float(p, &rettv->vval.v_float, skip_quotes);
if (isneg)
rettv->vval.v_float *= -1;
rettv->v_type = VAR_FLOAT;
diff --git a/src/json.c b/src/json.c
index 4b9a2e825..a8d3a090f 100644
--- a/src/json.c
+++ b/src/json.c
@@ -791,12 +791,13 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
{
float_T f;
- len = string2float(p, &f);
+ len = string2float(p, &f, FALSE);
}
else
{
cur_item->v_type = VAR_FLOAT;
- len = string2float(p, &cur_item->vval.v_float);
+ len = string2float(p, &cur_item->vval.v_float,
+ FALSE);
}
}
else
diff --git a/src/proto/float.pro b/src/proto/float.pro
index 806eba1f6..cceb15787 100644
--- a/src/proto/float.pro
+++ b/src/proto/float.pro
@@ -1,5 +1,5 @@
/* float.c */
-int string2float(char_u *text, float_T *value);
+int string2float(char_u *text, float_T *value, int skip_quotes);
void f_abs(typval_T *argvars, typval_T *rettv);
void f_acos(typval_T *argvars, typval_T *rettv);
void f_asin(typval_T *argvars, typval_T *rettv);
diff --git a/src/testdir/test_float_func.vim b/src/testdir/test_float_func.vim
index ba15ecfc7..628bbb0c0 100644
--- a/src/testdir/test_float_func.vim
+++ b/src/testdir/test_float_func.vim
@@ -239,13 +239,28 @@ func Test_str2float()
call assert_equal('nan', string(str2float('NaN')))
call assert_equal('nan', string(str2float(' nan ')))
- call assert_equal(1.2, str2float(1.2))
+ call assert_equal('123456.789', string(str2float("123'456.789", 1)))
+ call assert_equal('123456.789', string(str2float("12'34'56.789", 1)))
+ call assert_equal('123456.789', string(str2float("1'2'3'4'5'6.789", 1)))
+ call assert_equal('1.0', string(str2float("1''2.3", 1)))
+ call assert_equal('123456.7', string(str2float("123'456.7'89", 1)))
+
+ call assert_equal(1.2, str2float(1.2, 0))
call CheckDefAndScriptFailure2(['str2float(1.2)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1')
call assert_fails("call str2float([])", 'E730:')
call assert_fails("call str2float({})", 'E731:')
call assert_fails("call str2float(function('string'))", 'E729:')
endfunc
+def Test_float_quotes()
+ call assert_equal('123456.789', string(123'456.789))
+ call assert_equal('123456.789', string(12'34'56.789))
+ call assert_equal('123456.789', string(1'2'3'4'5'6.789))
+
+ call assert_fails("echo string(1''2.3)", 'E116:')
+ call assert_fails("echo string(123'456.7'89)", 'E116:')
+enddef
+
func Test_float2nr()
call assert_equal(1, float2nr(1.234))
call assert_equal(123, float2nr(1.234e2))
diff --git a/src/typval.c b/src/typval.c
index e8ce4ea36..389ca3427 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -1704,6 +1704,7 @@ eval_number(
int want_string UNUSED)
{
int len;
+ int skip_quotes = current_sctx.sc_version >= 4;
#ifdef FEAT_FLOAT
char_u *p;
int get_float = FALSE;
@@ -1718,7 +1719,20 @@ eval_number(
if (**arg == '.')
p = *arg;
else
- p = skipdigits(*arg + 1);
+ {
+ p = *arg + 1;
+ if (skip_quotes)
+ for (;;)
+ {
+ if (*p == '\'')
+ ++p;
+ if (!vim_isdigit(*p))
+ break;
+ p = skipdigits(p);
+ }
+ else
+ p = skipdigits(p);
+ }
if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
{
get_float = TRUE;
@@ -1740,7 +1754,7 @@ eval_number(
{
float_T f;
- *arg += string2float(*arg, &f);
+ *arg += string2float(*arg, &f, skip_quotes);
if (evaluate)
{
rettv->v_type = VAR_FLOAT;
@@ -1784,7 +1798,7 @@ eval_number(
varnumber_T n;
// decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
+ vim_str2nr(*arg, NULL, &len, skip_quotes
? STR2NR_NO_OCT + STR2NR_QUOTE
: STR2NR_ALL, &n, NULL, 0, TRUE);
if (len == 0)
diff --git a/src/version.c b/src/version.c
index 06c89b32d..5a5f69b18 100644
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3315,
+/**/
3314,
/**/
3313,
diff --git a/src/viminfo.c b/src/viminfo.c
index 6b92cc64a..1d3bac15e 100644
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -1247,7 +1247,7 @@ read_viminfo_varlist(vir_T *virp, int writing)
(int)(tab - virp->vir_line + 1), TRUE);
#ifdef FEAT_FLOAT
else if (type == VAR_FLOAT)
- (void)string2float(tab + 1, &tv.vval.v_float);
+ (void)string2float(tab + 1, &tv.vval.v_float, FALSE);
#endif
else
{