]> granicus.if.org Git - vim/commitdiff
patch 8.2.3315: cannot use single quote in a float number for readability v8.2.3315
authorBram Moolenaar <Bram@vim.org>
Sun, 8 Aug 2021 13:43:34 +0000 (15:43 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 8 Aug 2021 13:43:34 +0000 (15:43 +0200)
Problem:    Cannot use single quote in a float number for readability.
Solution:   Support single quotes like in numbers. (closes #8713)

src/float.c
src/json.c
src/proto/float.pro
src/testdir/test_float_func.vim
src/typval.c
src/version.c
src/viminfo.c

index 898095fd4b6274b7c43f774c4a611489329a094d..ee0ceda72ea3c1437276ba656b26e77803f34f6b 100644 (file)
@@ -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;
index 4b9a2e825ad2968488aaac64a220350663d09090..a8d3a090fc77f6f77f308debf5a848fadd578e46 100644 (file)
@@ -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
index 806eba1f613a29289328bc11763794411bb9407b..cceb157870fd01341dc82d58c83a195e60340a3f 100644 (file)
@@ -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);
index ba15ecfc7f916069253786232751165b3d27ac0b..628bbb0c068101e944a9640c6b5d6b0894e9f91e 100644 (file)
@@ -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))
index e8ce4ea364ea971e2819b6daa6c664c18c953bf3..389ca3427365c3bab168beacd1ab002a12c5456e 100644 (file)
@@ -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)
index 06c89b32d167dc21f6e67a02df6379c5c243ae0e..5a5f69b1868451734b9dc55cf9ccd831ac3c1d7b 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3315,
 /**/
     3314,
 /**/
index 6b92cc64abfd884ebba8d3005662c0a5bffdd47e..1d3bac15e9ce20d0ffb91114f9137f73b6363e95 100644 (file)
@@ -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
                {